AndroidAndroid Utility

Android Change Language At Runtime Programmatically

This tutorial will explain you how to change the language locale of your application at runtime or dynamically.

The code explained here will show you how to convert text written in English to French language using a Helper class.

Step 1: Create Separate string.xml With Translations

Here fr is the language qualifier for french language resources.

So please create two separate String.xml under res folder with following names,

By default, we we have a string.xml file under values folder. To create new translation for french language, we need to create a separate string.xml for french language under values-fr folder.

  • values/string.xml
  • values-fr/string.xml

Add string values to both string files as follows,

string.xml

<resources>
    <string name="app_name">Change Language</string>
    <string name="hello">Hello</string>
    <string name="welcome">Welcome,</string>
</resources>

values-fr/string.xml

<resources>
    <string name="app_name">Changer de langue</string>
    <string name="hello">Bonjour</string>
    <string name="welcome">Bienvenue,</string>
</resources>

Step 2: Create Locale Helper Class

Please create a Helper class called LocaleHelper in utils package. Which has all the methods to manage the language switching functionalities.

LocaleHelper.java

package devdeeds.com.changelanguage;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.preference.PreferenceManager;

import java.util.Locale;

/**
 * Created by devdeeds.com on 18/4/17.
 * by Jayakrishnan P.M
 */

public class LocaleHelper {

    private static final String SELECTED_LANGUAGE = "Locale.Helper.Selected.Language";

    public static Context onAttach(Context context) {
        String lang = getPersistedData(context, Locale.getDefault().getLanguage());
        return setLocale(context, lang);
    }

    public static Context onAttach(Context context, String defaultLanguage) {
        String lang = getPersistedData(context, defaultLanguage);
        return setLocale(context, lang);
    }

    public static String getLanguage(Context context) {
        return getPersistedData(context, Locale.getDefault().getLanguage());
    }

    public static Context setLocale(Context context, String language) {
        persist(context, language);

        if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.N) {
            return updateResources(context, language);
        }

        return updateResourcesLegacy(context, language);
    }

    private static String getPersistedData(Context context, String defaultLanguage) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        return preferences.getString(SELECTED_LANGUAGE, defaultLanguage);
    }

    private static void persist(Context context, String language) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        SharedPreferences.Editor editor = preferences.edit();

        editor.putString(SELECTED_LANGUAGE, language);
        editor.apply();
    }

    @TargetApi(Build.VERSION_CODES.N)
    private static Context updateResources(Context context, String language) {
        Locale locale = new Locale(language);
        Locale.setDefault(locale);

        Configuration configuration = context.getResources().getConfiguration();
        configuration.setLocale(locale);

        return context.createConfigurationContext(configuration);
    }

    @SuppressWarnings("deprecation")
    private static Context updateResourcesLegacy(Context context, String language) {
        Locale locale = new Locale(language);
        Locale.setDefault(locale);

        Resources resources = context.getResources();

        Configuration configuration = resources.getConfiguration();
        configuration.locale = locale;

        resources.updateConfiguration(configuration, resources.getDisplayMetrics());

        return context;
    }
}

Step 3: Activity Layout With TextViews

Create layout file with 3 TextViews and a button to change the locale. All the strings should be referred from the resource files respectively.

res/layout/activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="devdeeds.com.changelanguage.MainActivity">

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="@string/hello"
        android:textSize="18sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHorizontal_bias="0.501"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.110000014"
        tools:layout_constraintLeft_creator="1"
        tools:layout_constraintRight_creator="1" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="368dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:gravity="center"
        android:text="@string/welcome"
        android:textSize="18sp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView2"
        tools:layout_constraintLeft_creator="1"
        tools:layout_constraintRight_creator="1" />

    <TextView
        android:id="@+id/textView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginTop="16dp"
        android:text="@string/app_name"
        android:textSize="20sp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView" />

    <Button
        android:id="@+id/btnChangeLangView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginTop="24dp"
        android:text="Switch To French"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView3" />

</android.support.constraint.ConstraintLayout>

Implementation And Usage In Activity

In this activity we added a button to change the locale from English to French language.

MainActivity.java

package devdeeds.com.changelanguage;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;

import devdeeds.com.changelanguage.utils.LocaleHelper;

/**
 * Created by devdeeds.com on 18/4/17.
 * by Jayakrishnan P.M
 */

public class MainActivity extends AppCompatActivity {

    private String mLanguageCode = "fr";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //Change English to French when user clicked the button.
        findViewById(R.id.btnChangeLangView).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //Change Application level locale
                LocaleHelper.setLocale(MainActivity.this, mLanguageCode);

                //It is required to recreate the activity to reflect the change in UI. 
                recreate();
            }
        });
    }
}

Result

GitHub-Mark-32px
About author

Rojer is a programmer by profession, but he likes to research new things and is also interested in writing. Devdeeds is his blog, where he writes all the blog posts related to technology, gadgets, mobile apps, games, and related content.

Leave a Reply

Your email address will not be published. Required fields are marked *