Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
a quick Context wraper to change locale of android app in runtime, supporting changes in direction (RTL <-> LTR)
package com.mu.tools;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.res.Configuration;
import android.os.Build;
import java.util.Locale;
/**
* Created by Muhammad on 07/01/2017.
* Main idea came from http://stackoverflow.com/questions/40221711/android-context-getresources-updateconfiguration-deprecated/40704077#40704077
*/
public class LocaleHelper extends ContextWrapper {
public LocaleHelper(Context base) {
super(base);
}
@SuppressWarnings("deprecation")
public static ContextWrapper wrap(Context context, String language) {
Configuration config = context.getResources().getConfiguration();
if (!language.equals("")) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
setSystemLocale(config, locale);
} else {
setSystemLocaleLegacy(config, locale);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
config.setLayoutDirection(locale);
context = context.createConfigurationContext(config);
} else {
context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());
}
}
return new LocaleHelper(context);
}
@SuppressWarnings("deprecation")
public static Locale getSystemLocaleLegacy(Configuration config){
return config.locale;
}
@TargetApi(Build.VERSION_CODES.N)
public static Locale getSystemLocale(Configuration config){
return config.getLocales().get(0);
}
@SuppressWarnings("deprecation")
public static void setSystemLocaleLegacy(Configuration config, Locale locale){
config.locale = locale;
}
@TargetApi(Build.VERSION_CODES.N)
public static void setSystemLocale(Configuration config, Locale locale){
config.setLocale(locale);
}
}
@muhammad-naderi
Copy link
Author

muhammad-naderi commented Jan 7, 2017

need to wrap your activities Context:

@Override
protected void attachBaseContext(Context newBase) {
    super.attachBaseContext(MyContextWrapper.wrap(newBase,"fa"));
}

Loading

@alicoskun
Copy link

alicoskun commented Jan 13, 2017

Hi,
Thanks for the solution.
How do you store chosen language?
It's not possible to use SharedPreferences in attachBaseContext method.

Loading

@gorodechnyj
Copy link

gorodechnyj commented Jan 31, 2017

You should correct this and use android.view.ContextThemeWrapper instead of android.content.ContextWrapper.

Constructor will look like this:
public LocaleHelper(Context base) { super(base, R.style.<your-app-theme-here>); }

<your-app-theme-here> is usually set in AndroidManifest.xml in <application> tag, see android:theme

Otherwise you loose colors, strings and other referenced by your current theme. In my case this leads to NullPointerException in SwitchCompat, because some configuration strings, turnOn and turnOff are referenced in theme's parent, Theme.AppCompat

Loading

@rmr356
Copy link

rmr356 commented Mar 2, 2017

This is not working for me, it goes back to default language whenever I restart the app, and some activities don't respond to the language change. Why could it be?

Loading

@PoojaB26
Copy link

PoojaB26 commented Jun 12, 2017

List adapters don't respond to the language change immediately. It is reflected only on recreating the activity

Loading

@mjalijani
Copy link

mjalijani commented Oct 24, 2018

this solution not worked in Google Nexus 5 . Texts are not Translated ! but Direction has changed !

Loading

@podcoder
Copy link

podcoder commented Feb 4, 2019

Hi,
Thanks for the solution.
How do you store chosen language?
It's not possible to use SharedPreferences in attachBaseContext method.

I know it is late to reply, but this might help someone else looking for the same.
Let say you have a DialogInterface menu from which you choose the languages.
@Override public void onClick(DialogInterface dialog, int which) { SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(Your_Context); SharedPreferences.Editor editor = sharedPreferences.edit(); switch (which) { case 0: editor.putString("language","en");; break; case 1: editor.putString("language","fr"); break; case 2: editor.putString("language","fa"); break; default: editor.putString("language","en"); } editor.commit(); recreate(); dialog.dismiss(); }
and then while calling the @Override protected void attachBaseContext(Context newBase) { SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(newBase); String lang = sharedPreferences.getString("language", "en"); super.attachBaseContext(MyContextWrapper.wrap(newBase,lang)); }

Loading

@musso
Copy link

musso commented Nov 7, 2020

any jetpack compose version ?

Loading

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment