Change the locale at runtime?

We have an Android app that functions as a client for a remote PC program. We’d like to add a feature so the PC can instruct the Android app to change its locale at runtime, i.e., start the app; put it in communication with the PC; sometime later the PC tells the app to switch to, say, Spanish or Chinese.

We already have all the layout and string resources set up for their respective locales. Our app is the only app the user sees so it doesn’t matter if the rest of the device stays in English.

  • Android onPreviewFrame is not called
  • How to install last version of ADT plug-in for eclipse
  • VideoView seekto() function extremely inconsistent
  • Does Android supports MVC (Model View Controller) Structure?
  • Video processing in Android
  • What is the life cycle of a public static variable in Android?
  • There is another thread on this at Change language programmatically in Android but it doesn’t seem to reach a conclusion.

    I can put . . .

    Locale locale = new Locale(sTheNewLocale);
    Locale.setDefault(locale);
    Configuration config = new Configuration();
    config.locale = locale;
    getBaseContext().getResources().updateConfiguration(config,
          getBaseContext().getResources().getDisplayMetrics());
    

    . . . in onCreate() before the setContentView() but that doesn’t really help if I want to change the locale after my screen is up and running. Is there a way to REload the content view after the Activity is already running? So is there any practical way to change locales on-the-fly reliably or do I have to tell my boss it can’t be done except for setting the whole device to the new locale before starting the app?

    Related posts:

    UNEXPECTED TOP-LEVEL EXCEPTION: com.android.dex.DexException: Multiple dex files define
    Check in the onReceivedSslError() method of a WebViewClient if a certificate is signed from a specif...
    NullPointerException at TextView.checkForRelayout() while setText()
    Accessing localhost:port from Android emulator
    Android: Click event for Status bar notification
    How to set the emulator pixel density from the command line?
  • How to use scrollVerticallyBy() with Android RecyclerView and LayoutManager?
  • Android Studio 0.2.6 update broke my project, asks me to setup jdk
  • Convert magnetic field X, Y, Z values from device into global reference frame
  • Is it possible to compress video on Android?
  • Failed to export application after upgrade to Proguard 4.8
  • MenuItem tinting on AppCompat Toolbar
  • 4 Solutions collect form web for “Change the locale at runtime?”

    Since API 11 you can use recreate so can make this method in your activity:

    private void restartInLocale(Locale locale)
    {
        Locale.setDefault(locale);
        Configuration config = new Configuration();
        config.locale = locale;
        Resources resources = getResources();
        resources.updateConfiguration(config, resources.getDisplayMetrics());
        recreate();
    }
    

    You can start a new instance of your activity and exit the old one. Here is a full (untested) example how you can store any desired language and restart your app. You just need to call restartInLanguage with your prefered language.

    public class YourMainActivity extends Activity {
        private static final String APP_SHARED_PREFS = "com.example.test";
        private SharedPreferences settings;
        private Editor editor;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            settings=getSharedPreferences(APP_SHARED_PREFS, Activity.MODE_PRIVATE);
            editor=settings.edit();
    
            Locale locale = new Locale(settings.getString("lang", "default-lang"));
            Locale.setDefault(locale);
            Configuration config = new Configuration();
            config.locale = locale;
            getResources().updateConfiguration(config, getResources().getDisplayMetrics());
    
            // your stuff...
        }
    
        public void restartInLanguage(String lang) {
            editor.putString("lang", lang);
            editor.commit();
            Intent intent = getIntent();
            finish();
            startActivity(intent);
        }
    
        // ...
    }
    

    I have combined @weston and @rekire (both +1) and extendet it to handle this use-case:

    • ActivityA => ActivityB => SettingsActivity-changeLocale

    After changeLocale in SettingsActivity the parent activities ActivityA and ActivityB should also be recreated to reflect the new locale.

    My solution: ActivityA and ActivityB inherit from LocalizedActivity which checks in onResume if the locale has changed and trigger a recreate() if necessary

    So every activity that inherits from LocalizedActivity automatically handles app specific locale change.

    /**
     * An activity that can change the locale (language) of its content.
     *
     * Inspired by http://stackoverflow.com/questions/13181847/change-the-locale-at-runtime
     *
     * Created by k3b on 07.01.2016.
     */
    public class LocalizedActivity extends Activity {
        /** if myLocale != Locale.Default : activity must be recreated in on resume */
        private Locale myLocale = null;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            fixLocale(this);
            super.onCreate(savedInstanceState);
        }
    
        @Override
        protected void onResume() {
            super.onResume();
    
            // Locale has changed by other Activity ?
            if ((myLocale != null) && (myLocale.getLanguage() != Locale.getDefault().getLanguage())) {
                myLocale = null;
                recreate();
            }
        }
    
        /**
         * Set Activity-s locale to SharedPreferences-setting.
         * Must be called before onCreate
         * @param context
         */
        public static void fixLocale(Context context)
        {
            final SharedPreferences prefs = PreferenceManager
                    .getDefaultSharedPreferences(context);
            String language = prefs.getString(Global.PREF_KEY_USER_LOCALE, "");
            Locale locale = Global.systemLocale; // in case that setting=="use android-locale"
            if ((language != null) && (!language.isEmpty())) {
                locale = new Locale(language); // overwrite "use android-locale"
            }
    
            if (locale != null) {
                Locale.setDefault(locale);
                Configuration config = new Configuration();
                config.locale = locale;
                Resources resources = context.getResources();
                resources.updateConfiguration(config, resources.getDisplayMetrics());
                // recreate();
    
                if (context instanceof LocalizedActivity) {
                    ((LocalizedActivity) context).myLocale = locale;
                }
            }
        }
    }
    

    Here is the source of LocalizedActivity.java and SettingsActivity.java that are used in my A Photo Manager project

    The solution is to use setContentView and controlLanguage (you can also call this method from a Global class) methods in EVERY activity in onResume method after setting your locale.
    Example:

    @Override
        public void onClick(View v) {
            SharedPreferences.Editor editor;
            editor = sharedPref.edit();
            Configuration config = new Configuration(getBaseContext().getResources().getConfiguration());
            String language = "";
            switch (v.getId()){
                case R.id.turkceButton:
                    editor.putString("language", "tr");
                    language="tr";
                    break;
                case R.id.englishButton:
                    editor.putString("language", "en");
                    language="en";
                    break;
            }
            Locale locale = new Locale(language);
            Locale.setDefault(locale);
            config.locale = locale;
            getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
            editor.commit();
    
    
    @Override
        protected void onResume() {
            super.onResume();
            controlLanguage(getApplicationContext(), getResources());
            setContentView(R.layout.main);
        }
    
    public void controlLanguage(Context context, Resources res){
            SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context);
            String language = sharedPref.getString("language","en");
            Locale locale = new Locale(language);
            Locale.setDefault(locale);
            res.getConfiguration().locale = locale;
            res.updateConfiguration(res.getConfiguration(), res.getDisplayMetrics());
        }
    
    Android Babe is a Google Android Fan, All about Android Phones, Android Wear, Android Dev and Android Games Apps and so on.