How to change Android O / Oreo / api 26 app language

Viewed 17991

I want to change the language of the app and this works fine until API 26.

For api > 25 I put Locale.setDefault(Locale.Category.DISPLAY, mynewlanglocale); before setContentView(R.layout.activity_main); but nothing changes.

The docs don't explain too much about this.

8 Answers

I had the same problem: since Android 8.0+ some parts of my app did't change their language anymore. Updating of both application and activity context helps me. Here is an example of MainActivity function:

private void setApplicationLanguage(String newLanguage) {
    Resources activityRes = getResources();
    Configuration activityConf = activityRes.getConfiguration();
    Locale newLocale = new Locale(newLanguage);
    activityConf.setLocale(newLocale);
    activityRes.updateConfiguration(activityConf, activityRes.getDisplayMetrics());

    Resources applicationRes = getApplicationContext().getResources();
    Configuration applicationConf = applicationRes.getConfiguration();
    applicationConf.setLocale(newLocale);
    applicationRes.updateConfiguration(applicationConf, 
    applicationRes.getDisplayMetrics());
}

Yes in android Oreo localization is not working fine with updateconfiguration. But it is deprecated in android N itself. Instead of updateconfiguration use createconfiguration in each attachcontext. it is working fine for me. Try this...

In you activity add this..

@Override
protected void attachBaseContext(Context newBase) {
    if(Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) {
        super.attachBaseContext(MyContextWrapper.wrap(newBase, "ta"));
    }
    else {
        super.attachBaseContext(newBase);
    }
}

In MyContextWrapper.java

 public static ContextWrapper wrap(Context context, String language) {
    Resources res = context.getResources();
    Configuration configuration = res.getConfiguration();
    Locale newLocale = new Locale(language);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        configuration.setLocale(newLocale);
        LocaleList localeList = new LocaleList(newLocale);
        LocaleList.setDefault(localeList);
        configuration.setLocales(localeList);
        context = context.createConfigurationContext(configuration);

    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        configuration.setLocale(newLocale);
        context = context.createConfigurationContext(configuration);

    } else {
        configuration.locale = newLocale;
        res.updateConfiguration(configuration, res.getDisplayMetrics());
    }

    return new ContextWrapper(context);
}

It is possible, however i would not recommend to set the language programatically

Android is designed so the System UI and your App have the same language, if you change it programmatically you would be fighting the system

Instead what you can do is enable multilanguage support by adding different strings.xml languages, this will change the language automatically

I reccommend reading through this Google Developers article:

Supporting Different Languages and Cultures

If you really need to change it programatically you can do the following

Locale locale = new Locale("en");
Locale.setDefault(locale);

Configuration config = context.getResources().getConfiguration();
config.setLocale(locale);
context.createConfigurationContext(config);
context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());

On SDK >= 21, you need to call 'Resources.updateConfiguration()', otherwise resources will not be updated.

Hope it helps.

After use all solution in all sources finally i found my issue. That makes me angry for 2 days.

Everyone knows that in Android Oreo (API 26) we must use createConfigurationContext, But My problem is using Country name with local.

Replace

en_US with en

ar_AE with ar

fa_IR with fa

And my problem solved.

Hope to help someone

Related