Set Locale programmatically

后端 未结 14 1439
Happy的楠姐
Happy的楠姐 2020-11-22 05:55

My app supports 3 (soon 4) languages. Since several locales are quite similar I\'d like to give the user the option to change locale in my application, for instance an Itali

相关标签:
14条回答
  • 2020-11-22 06:21

    For people still looking for this answer, since configuration.locale was deprecated from API 24, you can now use:

    configuration.setLocale(locale);
    

    Take in consideration that the minSkdVersion for this method is API 17.

    Full example code:

    @SuppressWarnings("deprecation")
    private void setLocale(Locale locale){
        SharedPrefUtils.saveLocale(locale); // optional - Helper method to save the selected language to SharedPreferences in case you might need to attach to activity context (you will need to code this)
        Resources resources = getResources();
        Configuration configuration = resources.getConfiguration();
        DisplayMetrics displayMetrics = resources.getDisplayMetrics();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1){
            configuration.setLocale(locale);
        } else{
            configuration.locale=locale;
        }
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N){
            getApplicationContext().createConfigurationContext(configuration);
        } else {
            resources.updateConfiguration(configuration,displayMetrics);
        }
    }
    

    Don't forget that, if you change the locale with a running Activity, you will need to restart it for the changes to take effect.

    EDIT 11th MAY 2018

    As from @CookieMonster's post, you might have problems keeping the locale change in higher API versions. If so, add the following code to your Base Activity so that you update the context locale on every Activity creation:

    @Override
    protected void attachBaseContext(Context base) {
         super.attachBaseContext(updateBaseContextLocale(base));
    }
    
    private Context updateBaseContextLocale(Context context) {
        String language = SharedPrefUtils.getSavedLanguage(); // Helper method to get saved language from SharedPreferences
        Locale locale = new Locale(language);
        Locale.setDefault(locale);
    
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) {
            return updateResourcesLocale(context, locale);
        }
    
        return updateResourcesLocaleLegacy(context, locale);
    }
    
    @TargetApi(Build.VERSION_CODES.N_MR1)
    private Context updateResourcesLocale(Context context, Locale locale) {
        Configuration configuration = new Configuration(context.getResources().getConfiguration())
        configuration.setLocale(locale);
        return context.createConfigurationContext(configuration);
    }
    
    @SuppressWarnings("deprecation")
    private Context updateResourcesLocaleLegacy(Context context, Locale locale) {
        Resources resources = context.getResources();
        Configuration configuration = resources.getConfiguration();
        configuration.locale = locale;
        resources.updateConfiguration(configuration, resources.getDisplayMetrics());
        return context;
    }
    

    If you use this, don't forget to save the language to SharedPreferences when you set the locale with setLocate(locale)

    EDIT 7th APRIL 2020

    You might be experiencing issues in Android 6 and 7, and this happens due to an issue in the androidx libraries while handling the night mode. For this you will also need to override applyOverrideConfiguration in your base activity and update the configuration's locale in case a fresh new locale one is created.

    Sample code:

    @Override
    public void applyOverrideConfiguration(Configuration overrideConfiguration) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1) {
            // update overrideConfiguration with your locale  
            setLocale(overrideConfiguration) // you will need to implement this
        }
        super.applyOverrideConfiguration(overrideConfiguration);
    } 
    
    0 讨论(0)
  • 2020-11-22 06:21

    Hope this help(in onResume):

    Locale locale = new Locale("ru");
    Locale.setDefault(locale);
    Configuration config = getBaseContext().getResources().getConfiguration();
    config.locale = locale;
    getBaseContext().getResources().updateConfiguration(config,
          getBaseContext().getResources().getDisplayMetrics());
    
    0 讨论(0)
  • 2020-11-22 06:26

    Valid for API16 to API28 Just place this method some where:

    Context newContext = context;
    
    Locale locale = new Locale(languageCode);
    Locale.setDefault(locale);
    
    Resources resources = context.getResources();
    Configuration config = new Configuration(resources.getConfiguration());
    
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        config.setLocale(locale);
        newContext = context.createConfigurationContext(config);
    } else {
        config.locale = locale;
        resources.updateConfiguration(config, resources.getDisplayMetrics());
    }
    
    return newContext;
    

    Insert this code in all your activitys using:

        @Override
        protected void attachBaseContext(Context base) {
            super.attachBaseContext(localeUpdateResources(base, "<-- language code -->"));
        }
    

    or call localeUpdateResources on fragments, adapters, etc. where you need the new context.

    Credits: Yaroslav Berezanskyi

    0 讨论(0)
  • 2020-11-22 06:27

    simple and easy

    Locale locale = new Locale("en", "US");
    Resources res = getResources();
    DisplayMetrics dm = res.getDisplayMetrics();
    Configuration conf = res.getConfiguration();
    conf.locale = locale;
    res.updateConfiguration(conf, dm);
    

    where "en" is language code and "US" is country code.

    0 讨论(0)
  • 2020-11-22 06:31

    I had a problem with setting locale programmatically with devices that has Android OS N and higher. For me the solution was writing this code in my base activity:

    (if you don't have a base activity then you should make these changes in all of your activities)

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(updateBaseContextLocale(base));
    }
    
    private Context updateBaseContextLocale(Context context) {
        String language = SharedPref.getInstance().getSavedLanguage();
        Locale locale = new Locale(language);
        Locale.setDefault(locale);
    
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return updateResourcesLocale(context, locale);
        }
    
        return updateResourcesLocaleLegacy(context, locale);
    }
    
    @TargetApi(Build.VERSION_CODES.N)
    private Context updateResourcesLocale(Context context, Locale locale) {
        Configuration configuration = context.getResources().getConfiguration();
        configuration.setLocale(locale);
        return context.createConfigurationContext(configuration);
    }
    
    @SuppressWarnings("deprecation")
    private Context updateResourcesLocaleLegacy(Context context, Locale locale) {
        Resources resources = context.getResources();
        Configuration configuration = resources.getConfiguration();
        configuration.locale = locale;
        resources.updateConfiguration(configuration, resources.getDisplayMetrics());
        return context;
    }
    

    note that here it is not enough to call

    createConfigurationContext(configuration)
    

    you also need to get the context that this method returns and then to set this context in the attachBaseContext method.

    0 讨论(0)
  • 2020-11-22 06:31
     /**
     * Requests the system to update the list of system locales.
     * Note that the system looks halted for a while during the Locale migration,
     * so the caller need to take care of it.
     */
    public static void updateLocales(LocaleList locales) {
        try {
            final IActivityManager am = ActivityManager.getService();
            final Configuration config = am.getConfiguration();
    
            config.setLocales(locales);
            config.userSetLocale = true;
    
            am.updatePersistentConfiguration(config);
        } catch (RemoteException e) {
            // Intentionally left blank
        }
    }
    
    0 讨论(0)
提交回复
热议问题