Set Locale programmatically

后端 未结 14 1441
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: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);
        }
    }
    

提交回复
热议问题