Set Locale programmatically

后端 未结 14 1454
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:11
    @SuppressWarnings("deprecation")
    public static void forceLocale(Context context, String localeCode) {
        String localeCodeLowerCase = localeCode.toLowerCase();
    
        Resources resources = context.getApplicationContext().getResources();
        Configuration overrideConfiguration = resources.getConfiguration();
        Locale overrideLocale = new Locale(localeCodeLowerCase);
    
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            overrideConfiguration.setLocale(overrideLocale);
        } else {
            overrideConfiguration.locale = overrideLocale;
        }
    
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            context.getApplicationContext().createConfigurationContext(overrideConfiguration);
        } else {
            resources.updateConfiguration(overrideConfiguration, null);
        }
    }
    

    Just use this helper method to force specific locale.

    UDPATE 22 AUG 2017. Better use this approach.

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

    Add a helper class with the following method:

    public class LanguageHelper {
        public static final void setAppLocale(String language, Activity activity) {
    
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                Resources resources = activity.getResources();
                Configuration configuration = resources.getConfiguration();
                configuration.setLocale(new Locale(language));
                activity.getApplicationContext().createConfigurationContext(configuration);
            } else {
                Locale locale = new Locale(language);
                Locale.setDefault(locale);
                Configuration config = activity.getResources().getConfiguration();
                config.locale = locale;
                activity.getResources().updateConfiguration(config,
                        activity.getResources().getDisplayMetrics());
            }
    
        }
    }
    

    And call it in your startup activity, like MainActivity.java:

    public void onCreate(Bundle savedInstanceState) {
        ...
        LanguageHelper.setAppLocale("fa", this);
        ...
    }
    
    0 讨论(0)
  • 2020-11-22 06:14

    As of 2020 language management become easy! All you have to do is:

    1. Call to Activity.applyOverrideConfiguration
    2. And call to Locale.setDefault

    You must call those from the activity constructor since you can call to applyOverrideConfiguration only once, and the system calls it pretty early.

    And watch out from app-bundles, Google will split your APK by language resources automatically when using app-bundles. Check out the new API and the workaround here.


    I created a helper class to help you with it. In my implementation G.app is the application context. Also, I need to access resources from the app context so I use the Res class for it, this one is optional, but I provide its code as well.

    Usage

    public BaseActivity(){
        LanguageUtility.init(this);
    }
    
    public void changeLanguage(Local local){
        // you must recreat your activity after you call this
        LanguageUtillity.setDefaultLanguage(local, this);
    }
    

    Source code

    public class LanguageUtility {
    
        private static Configuration configuration;
    
        public static void setDefaultLanguage(Locale locale, Context context) {
            Locale.setDefault(locale);
    
            context.getSharedPreferences("LocaleSettings", Context.MODE_PRIVATE)
                    .edit()
                    .putString("language", locale.getLanguage())
                    .putString("country", locale.getCountry())
                    .putString("variant", locale.getVariant())
                    .apply();
    
            configuration = createConfiguration(context);
            Res.updateContext();
        }
    
        /**
         * Used to update your app context in case you cache it.
         */
        public static Context createConfigurationContext(Context context) {
            return context.createConfigurationContext(getConfiguration(context));
        }
    
        public static void init(Activity activity) {
            activity.applyOverrideConfiguration(LanguageUtility.getConfiguration(G.app));
            // you can't access sharedPrefferences from activity constructor 
            // with activity context, so I used the app context.
            Locale.setDefault(getLocale(G.app));
        }
    
        @NotNull
        private static Configuration getConfiguration(Context context) {
            if (configuration == null) {
                configuration = createConfiguration(context);
            }
            return configuration;
        }
    
        @NotNull
        private static Configuration createConfiguration(Context context) {
            Locale locale = getLocale(context);
            Configuration configuration = new Configuration();
            configuration.setLocale(locale);
            LanguageUtility.configuration = configuration;
            return configuration;
        }
    
        @NotNull
        private static Locale getLocale(Context context) {
            Locale aDefault = Locale.getDefault();
            SharedPreferences preferences =
                    context.getSharedPreferences("LocaleSettings", Context.MODE_PRIVATE);
            String language = preferences.getString("language", aDefault.getLanguage());
            String country = preferences.getString("country", aDefault.getCountry());
            String variant = preferences.getString("variant", aDefault.getVariant());
            return new Locale(language, country, variant);
        }
    }
    

    An optional Res class.

    public class Res {
    
        @SuppressLint("StaticFieldLeak")
        public static Context appLocalContext = LanguageUtility.createConfigurationContext(G.app);
    
        public static void updateContext() {
            appLocalContext = LanguageUtility.createConfigurationContext(G.app);
        }
    
        public static String getString(@StringRes int id, Object... formatArgs) {
            return appLocalContext.getResources().getString(id, formatArgs);
        }
    
        public static int getColor(@ColorRes int id) {
            return G.app.getColor(id);
        }
    }
    
    0 讨论(0)
  • 2020-11-22 06:14

    Put this code in your activity

     if (id==R.id.uz)
        {
            LocaleHelper.setLocale(MainActivity.this, mLanguageCode);
    
            //It is required to recreate the activity to reflect the change in UI.
            recreate();
            return true;
        }
        if (id == R.id.ru) {
    
            LocaleHelper.setLocale(MainActivity.this, mLanguageCode);
    
            //It is required to recreate the activity to reflect the change in UI.
            recreate();
        }
    
    0 讨论(0)
  • 2020-11-22 06:18

    For those who tried everything but not not working. Please check that if you set darkmode with AppCompatDelegate.setDefaultNightMode and the system is not dark, then Configuration.setLocale will not work above Andorid 7.0.

    Add this code in your every activity to solve this issue:

    override fun applyOverrideConfiguration(overrideConfiguration: Configuration?) {
      if (overrideConfiguration != null) {
        val uiMode = overrideConfiguration.uiMode
        overrideConfiguration.setTo(baseContext.resources.configuration)
        overrideConfiguration.uiMode = uiMode
      }
      super.applyOverrideConfiguration(overrideConfiguration)
    }
    
    0 讨论(0)
  • 2020-11-22 06:19

    There is a super simple way.

    in BaseActivity, Activity or Fragment override attachBaseContext

     override fun attachBaseContext(context: Context) {
        super.attachBaseContext(context.changeLocale("tr"))
    }
    

    extension

    fun Context.changeLocale(language:String): Context {
        val locale = Locale(language)
        Locale.setDefault(locale)
        val config = this.resources.configuration
        config.setLocale(locale)
        return createConfigurationContext(config)
    }
    
    0 讨论(0)
提交回复
热议问题