java 如何更改 Android O / Oreo / api 26 应用程序语言

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/47165311/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 09:31:18  来源:igfitidea点击:

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

javaandroidlocaledefault

提问by Marius Razvan Varvarei

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

我想更改应用程序的语言,这在 API 26 之前都可以正常工作。

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

对于 api > 25 我Locale.setDefault(Locale.Category.DISPLAY, mynewlanglocale);之前放过setContentView(R.layout.activity_main);但没有任何变化。

The docsdon't explain too much about this.

文档不解释太多关于这一点。

回答by Skeptiker

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:

我遇到了同样的问题:自从 Android 8.0+ 以来,我的应用程序的某些部分不再更改它们的语言。应用程序和活动上下文的更新对我有帮助。这是 MainActivity 函数的示例:

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

回答by Rajalakshmi Arumugam

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...

是的,在 android Oreo 中,本地化在使用更新配置时无法正常工作。但它在 android N 本身中已被弃用。在每个 attachcontext 中使用 createconfiguration 代替 updateconfiguration。它对我来说很好用。试试这个...

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

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

回答by Luke

updateConfigurationis deprecated and you should use createConfigurationContext. I solved it this way:

updateConfiguration已弃用,您应该使用createConfigurationContext. 我是这样解决的:

    @Override
    protected void attachBaseContext(Context newBase) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            Configuration config = newBase.getResources().getConfiguration();
            //Update your config with the Locale i. e. saved in SharedPreferences
            SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(newBase);
            String language = prefs.getString(SP_KEY_LANGUAGE, "en_US");
            Locale.setDefault(locale);
            config.setLocale(new Locale(language));
            newBase = newBase.createConfigurationContext(config);
        }
        super.attachBaseContext(newBase);
    }

回答by emilpmp

Updated For All android versions till Oreo

更新所有安卓版本,直到奥利奥

Create a class like this

创建一个这样的类

public class LocaleUtils {

@Retention(RetentionPolicy.SOURCE)
@StringDef({ENGLISH, FRENCH, SPANISH})
public @interface LocaleDef {
    String[] SUPPORTED_LOCALES = {ENGLISH, FRENCH, SPANISH};
}

public static final String ENGLISH = "en";
public static final String FRENCH = "fr";
public static final String SPANISH = "es";


public static void initialize(Context context) {
    setLocale(context, ENGLISH);
}

public static void initialize(Context context, @LocaleDef String defaultLanguage) {
    setLocale(context, defaultLanguage);
}


public static boolean setLocale(Context context, @LocaleDef String language) {
    return updateResources(context, language);
}

private static boolean updateResources(Context context, String language) {
    Locale locale = new Locale(language);
    Locale.setDefault(locale);
    Resources resources = context.getResources();
    Configuration configuration = resources.getConfiguration();
    context.createConfigurationContext(configuration);
    configuration.locale = locale;
    resources.updateConfiguration(configuration, resources.getDisplayMetrics());
    return true;
}

}

}

Now when you select the language from your app, Save the language code in Shared Preference like below

现在,当您从应用程序中选择语言时,将语言代码保存在共享首选项中,如下所示

private static SharedPreferences getDefaultSharedPreference(Context context) {
    if (PreferenceManager.getDefaultSharedPreferences(Application.getInstance().getApplicationContext()) != null)
        return PreferenceManager.getDefaultSharedPreferences(Application.getInstance().getApplicationContext());
    else
        return null;
}

 public static void setSelectedLanguageId(String id){
    final SharedPreferences prefs = getDefaultSharedPreference(Application.getInstance().getApplicationContext());
    SharedPreferences.Editor editor = prefs.edit();
    editor.putString("app_language_id", id);
    editor.apply();
}

public static String getSelectedLanguageId(){
    return getDefaultSharedPreference(Application.getInstance().getApplicationContext())
            .getString("app_language_id", "en");
}

These three functions should be written inside a Utiltiy class(your preference). Then when you select the app language from the app, call the setSelectedLanguageId() function and pass the language id as parameter.

这三个函数应该写在一个 Utiltiy 类中(你的偏好)。然后当您从应用程序中选择应用程序语言时,调用 setSelectedLanguageId() 函数并将语言 ID 作为参数传递。

This way you have saved the selected language in your app. Now in your application class write a function like this

这样你就在你的应用程序中保存了所选的语言。现在在您的应用程序类中编写这样的函数

public void initAppLanguage(Context context){
    LocaleUtils.initialize(context, PreferenceUtil.getSelectedLanguageId() );
}

Here the PreferenceUtil is my Utiltiy class. You should replace it with your utility class function.

这里的 PreferenceUtil 是我的 Utiltiy 类。您应该用您的实用程序类函数替换它。

You should also create a variable in your application class

您还应该在应用程序类中创建一个变量

private static Application applicationInstance;

and in your Application class's onCreate method, initialise applicationInstance to be the applications context like this

并在您的 Application 类的 onCreate 方法中,将 applicationInstance 初始化为这样的应用程序上下文

applicationInstance = this; 

Now write a getter function in your application class

现在在您的应用程序类中编写一个 getter 函数

public static synchronized Application getInstance() {
    return applicationInstance;
}

And now when you start your first activity, call this method in your activity's onCreate

现在当你开始你的第一个活动时,在你的活动的 onCreate 中调用这个方法

Application.getInstance().initAppLanguage(this);

Remember that we are passing the activity's context to the initAppLanguage() function, not the application context. Passing the Application context won't make it work in Oreo(atleast for me).

请记住,我们将活动的上下文传递给 initAppLanguage() 函数,而不是应用程序上下文。传递应用程序上下文不会让它在奥利奥中工作(至少对我来说)。

So when you select the language try to restart your application completely. You can acheive this by

因此,当您选择语言时,请尝试完全重新启动您的应用程序。你可以通过

Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage(getBaseContext().getPackageName());

startActivity(i);

开始活动(i);

Hope this helps you!

希望这对你有帮助!

回答by Andre Breton

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

Android 的设计使系统 UI 和您的应用程序具有相同的语言,如果您以编程方式更改它,您将与系统作斗争

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

相反,您可以做的是通过添加不同的 strings.xml 语言来启用多语言支持,这将自动更改语言

I reccommend reading through this Google Developersarticle:

我建议通读这篇Google Developers文章:

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.

SDK >= 21 需要调用'Resources.updateConfiguration()',否则资源不会更新。

Hope it helps.

希望能帮助到你。

回答by Ness Tyagi

Here is complete solution worked for kitkat, Lollipop, Marshmallow, Nougat and Oreo too. Just follow all below step.

这是适用于奇巧、棒棒糖、棉花糖、牛轧糖和奥利奥的完整解决方案。只需按照以下步骤操作即可。

First create a java class like below

首先创建一个如下所示的java类

import android.content.Context;
import android.content.res.Configuration;
import java.util.Locale;
public class LocaleUtils {
public static void updateConfig(Context mContext, String sLocale) {
    Locale locale = new Locale(sLocale);
    Locale.setDefault(locale);
    Configuration config = mContext.getResources().getConfiguration();
    config.locale = locale;
    mContext.getResources().updateConfiguration(config,
            mContext.getResources().getDisplayMetrics());
  }
}

Now add this snippet on Button click where you want to change locale

现在在按钮单击要更改区域设置的位置添加此代码段

String lang="hi";//pass your language here
SharedPreferences preferences =  PreferenceManager.getDefaultSharedPreferences(mContext);
                        SharedPreferences.Editor editor = preferences.edit();
                        editor.clear();
                        editor.putString("lang", lang");
                        editor.putBoolean("langSelected", true);
                        editor.apply();
                        LocaleUtils.updateConfig(mContext,lang);
                        Intent intent = mContext.getIntent();
                        mContext.overridePendingTransition(0, 0);
                        mContext.finish();
                        intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
                        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                        mContext.overridePendingTransition(0, 0);
                        mContext.startActivity(intent);

Finally paste the below code in Splash Activity or in Launching Activity.

最后将以下代码粘贴到 Splash Activity 或 Launching Activity 中。

SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
    String lang = preferences.getString("lang", "");
    boolean langSelected = preferences.getBoolean("langSelected", false);
    SharedPreferences.Editor editor = preferences.edit();
    if (langSelected) {
        editor.clear();
        editor.putString("lang", lang);
        editor.putBoolean("langSelected", true);
        editor.apply();
        LocaleUtils.updateConfig(this,lang);
    } else {
        LocaleUtils.updateConfig(this, Locale.getDefault().getLanguage());
        editor.clear();
        editor.putString("lang", Locale.getDefault().getLanguage());
        editor.putBoolean("langSelected", false);
        editor.apply();
    }

回答by MT Michael Michael Mao

You need to use getApplicationContext()instead of getContext()

你需要使用getApplicationContext()而不是getContext()

回答by Radesh

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

在所有来源中使用所有解决方案后,我终于找到了我的问题。这让我生气了2天。

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

每个人都知道在 Android Oreo (API 26) 中我们必须使用createConfigurationContext,但我的问题是在本地使用国家/地区名称。

Replace

代替

en_USwithen

en_USen

ar_AEwithar

ar_AEar

fa_IRwithfa

fa_IRfa

And my problem solved.

我的问题解决了。

Hope to help someone

希望能帮助某人