Skip to content

Instantly share code, notes, and snippets.

@muhammad-naderi
Last active November 7, 2020 09:36
Show Gist options
  • Save muhammad-naderi/0ff264e6cc07df904bc88a9f7efbe57d to your computer and use it in GitHub Desktop.
Save muhammad-naderi/0ff264e6cc07df904bc88a9f7efbe57d to your computer and use it in GitHub Desktop.
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

need to wrap your activities Context:

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

@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.

@gorodechnyj
Copy link

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

@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?

@PoojaB26
Copy link

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

@mjalijani
Copy link

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

@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)); }

@musso
Copy link

musso commented Nov 7, 2020

any jetpack compose version ?

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