Home > Software design >  The language changes automatically when I change the night mode
The language changes automatically when I change the night mode

Time:11-07

I added day/night mode option in my android app as explained here. But when I change it, the language changes automatically.

This is my function

public void enableDarkMode(boolean enable){
    Log.d(""  this.TAG, "Dark Mode = " enable);
    this.editorDarkMode.putBoolean(IS_DARK_MODE_ON, enable);
    this.editorDarkMode.commit();
    if (enable){
        AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
    }else {
        AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
    }
}

I searched a lot but didn't achieve any solution yet.

Edit1: this is how I store the lang.

public void setLanguage(String lang){
    this.editorLang.putString("Language", "" lang);
    this.editorLang.commit();
    Locale locale = new Locale(""  lang);
    Locale.setDefault(locale);
    Configuration configuration = new Configuration();
    configuration.locale = locale;
    this.context.getResources().updateConfiguration(configuration,this.context.getResources().getDisplayMetrics());
}

CodePudding user response:

The problem that when you change the dark mode, the activity restarts with the default settings (default language), so you need to explicitly force the user's language.

But setting that explicitly every time you change the dark mode could be boilerplate, and this also could require a one more restart of the activity to apply the language.

Instead of that, you can use a customized ContextWrapper where you can apply the preferred language at the very beginning of your app in the attachBaseContext() activity callback by wrapping this customized ContextWrapper:

The custom context wrapper:

public class MyContextWrapper extends ContextWrapper {

    public MyContextWrapper(Context base) {
        super(base);
    }

    public static ContextWrapper wrap(Context context, String language) {
        Configuration config = context.getResources().getConfiguration();
        Locale sysLocale;
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) {
            sysLocale = getSystemLocale(config);
        } else {
            sysLocale = getSystemLocaleLegacy(config);
        }
        if (!language.equals("") && !sysLocale.getLanguage().equals(language)) {
            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.N) {
            context = context.createConfigurationContext(config);
        } else {
            context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());
        }
        return new MyContextWrapper(context);
    }

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

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

Override attachBaseContext() in the activity:

@Override
protected void attachBaseContext(Context context) {
    sharedPreferences = context.getSharedPreferences("prefs", MODE_PRIVATE); // adjust the name of the SharedPreference to yours
    String language = sharedPreferences.getString("Language", "en");
    super.attachBaseContext(MyContextWrapper.wrap(context, language));
    Locale locale = new Locale(language);
    Resources resources = getBaseContext().getResources();
    Configuration conf = resources.getConfiguration();
    conf.locale = locale;
    resources.updateConfiguration(conf, resources.getDisplayMetrics());
}
  • Related