AFLAH ALI
AFLAH ALI

Reputation: 451

Unable to change language in Oreo

I'm trying to use Arabic and English in my app. Its working fine on devices running on android Nougat or below. But it's not working on oreo devices. Is there some new code requirement in API 26? I am using the code below.

public void changeLanguage(Context context, String language) {
    Locale locale = new Locale(language);
    Locale.setDefault(locale);
    Configuration config = context.getResources().getConfiguration();
    config.setLocale(locale);
    context.createConfigurationContext(config);
    context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());
}

and I'm passing "en" and "ar" as language argument.

Upvotes: 7

Views: 3374

Answers (5)

Zaid Mirza
Zaid Mirza

Reputation: 3719

I recently faced issue related to layout direction on Oreo. Resources were being updated but Layout direction not changing.

Below code worked for me.

 public static void setRTLSupportIfRequired(AppCompatActivity activity) {
        if(getLanguageFromPrefs(activity).equals("ar")) {
            activity.getWindow().getDecorView().setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
        }else{
            activity.getWindow().getDecorView().setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
        }

    }

Note: Previously I were using View.LAYOUT_DIRECTION_LOCALE but it was not working on Oreo

Upvotes: 2

Rajwinder Singh
Rajwinder Singh

Reputation: 11

Yes, there is issue with Android Oreo for language change(strings and layout direction in arabic,urdu and hebrew), i found the solution this will help you to solve this problem

In LanguageContextWrapper.java class

 public static ContextWrapper wrap(Context context, String language) {
            Locale locale = new Locale(language);
            Locale.setDefault(locale);
            Resources resources = context.getResources();
            Configuration configuration = resources.getConfiguration();
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                configuration.setLocale(locale);
                LocaleList localeList = new LocaleList(locale);
                LocaleList.setDefault(localeList);
                configuration.setLocales(localeList);
                configuration.setLayoutDirection(locale);
                context.createConfigurationContext(configuration);
            } else {
                configuration.locale = locale;
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                    configuration.setLayoutDirection(locale);
                }
            }
            resources.updateConfiguration(configuration, resources.getDisplayMetrics());

        return new LanguageContextWrapper(context);
    }

In activity class override following method

 override fun attachBaseContext(base: Context) {
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) {
            super.attachBaseContext(LanguageContextWrapper.wrap(base, Locale.getDefault().language))
        } else {
            super.attachBaseContext(base)
        }
    }

And after change language we have to recreate activity, we need to write following code

fun recreateActivity(){
    if (Build.VERSION.SDK_INT in 26..27) {
                    if (Locale.getDefault().language == "ar" ||
                            Locale.getDefault().language == "iw" ||
                            Locale.getDefault().language == "ur")
                        window.decorView.layoutDirection = View.LAYOUT_DIRECTION_RTL
                    else
                        window.decorView.layoutDirection = View.LAYOUT_DIRECTION_LTR
                }
                recreate()

  }

Upvotes: 1

gokhan
gokhan

Reputation: 667

I had same problem before and after some research I find out one solution. Create custom language aware context wrapper and attach on your activity's attachBaseContext() method.

@SuppressWarnings("NewApi")
public static LanguageAwareContext newLanguageAwareContext(String targetLanguage, Context context) {
    Resources resources = context.getResources();
    Configuration configuration = resources.getConfiguration();

    Locale newLocale = new Locale(targetLanguage);

    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) {
        configuration.setLocale(newLocale);
        LocaleList.setDefault(new LocaleList(newLocale));

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

    return new LanguageAwareContext(context);
}

override attachBaseContext method and change with your customized context wrapper

@Override
protected void attachBaseContext(Context newBase) {
    newBase = LanguageAwareContext.newLanguageAwareContext("en",newBase);

    super.attachBaseContext(newBase);
}

Upvotes: 1

husen
husen

Reputation: 180

Locale locale = new Locale(lang);
    Locale.setDefault(locale);
    Configuration config = new Configuration();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        config.setLocale(locale);
    } else {
        config.locale = locale;
    }
    context.getApplicationContext().getResources().updateConfiguration(config,
            context.getApplicationContext().getResources().getDisplayMetrics());

This worked for me.

Upvotes: 1

Denysole
Denysole

Reputation: 4061

When you set new Locale you should restart your Activity. You can perform it using the next snippet of code:

private void restartActivity() {
    Intent intent = getIntent();
    finish();
    startActivity(intent);
}

Then your changeLanguage() method will look in a next way:

public void changeLanguage(Context context, String language) {
    Locale locale = new Locale(language);
    Locale.setDefault(locale);
    Configuration config = context.getResources().getConfiguration();
    config.setLocale(locale);
    context.createConfigurationContext(config);
    context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());

    restartActivity();
}

Upvotes: 4

Related Questions