简体   繁体   English

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

[英]How to change Android O / Oreo / api 26 app language

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); 对于api> 25,我放了Locale.setDefault(Locale.Category.DISPLAY, mynewlanglocale); before setContentView(R.layout.activity_main); setContentView(R.layout.activity_main);之前setContentView(R.layout.activity_main); but nothing changes. 但没有变化。

The docs don't explain too much about this. 文档没有解释太多。

Yes in android Oreo localization is not working fine with updateconfiguration. 是的在android Oreo本地化与updateconfiguration无法正常工作。 But it is deprecated in android N itself. 但它在Android N本身被弃用了。 Instead of updateconfiguration use createconfiguration in each attachcontext. 而不是更新配置使用每个attachcontext中的createconfiguration。 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 在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);
}

I had the same problem: since Android 8.0+ some parts of my app did't change their language anymore. 我有同样的问题:因为Android 8.0+我的应用程序的某些部分不再改变他们的语言。 Updating of both application and activity context helps me. 更新应用程序和活动上下文对我有帮助。 Here is an example of MainActivity function: 以下是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());
}

updateConfiguration is deprecated and you should use createConfigurationContext . 不推荐使用updateConfiguration ,您应该使用createConfigurationContext I solved it this way: 我这样解决了:

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

Updated For All android versions till Oreo 更新了所有Android版本,直到奥利奥

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). 这三个函数应该写在Utiltiy类中(您的首选项)。 Then when you select the app language from the app, call the setSelectedLanguageId() function and pass the language id as parameter. 然后,当您从应用程序中选择应用程序语言时,请调用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. 这里的PreferenceUtil是我的Utiltiy类。 You should replace it with your utility class function. 您应该用实用程序类函数替换它。

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. 请记住,我们将活动的上下文传递给initAppLanguage()函数,而不是应用程序上下文。 Passing the Application context won't make it work in Oreo(atleast for me). 传递应用程序上下文不会使它在奥利奥(至少对我来说)有效。

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); startActivity(ⅰ);

Hope this helps you! 希望这对你有所帮助!

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 Developers article: 我推荐阅读这篇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. 希望能帮助到你。

Here is complete solution worked for kitkat, Lollipop, Marshmallow, Nougat and Oreo too. 这里是kitkat,Lollipop,Marshmallow,Nougat和Oreo的完整解决方案。 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();
    }

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

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_US with en en_US with en

ar_AE with ar ar_AE with ar

fa_IR with fa fa_IR with fa

And my problem solved. 我的问题解决了。

Hope to help someone 希望能帮助别人

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在screen_on上更新android小部件的最佳方法是什么。是否支持Android Oreo(API 26) - What is the best way to update android widget on screen_on. Is it supported in Android Oreo (API 26) android中的OpenWeatherMap api如何更改描述语言 - How to change description language in OpenWeatherMap api in android 如何更改android应用程序的语言? 区域设置已弃用 - How to change language of android app ? Locale is deprecated 如何检查服务是否在Android 8(API 26)上运行? - How to check if a service is running on Android 8 (API 26)? 通知Oreo API 26-正常运行,但现在无法运行 - Notifications oreo api 26 - were working perfectly, now they're not 如何在android studio java中通过api 26杀死应用程序后创建始终运行的服务检测调用 - How to create service Detaction call always running after killed app over api 26 in android studio java 将targetSDKVersion从19更改为26时出错的Android应用 - Error Android app when change targetSDKVersion from 19 to 26 在 android 应用程序中更改语言的选项 - Option to change language in an android app 在Android中使用微调器更改应用程序语言 - Change app language with spinner in Android MethodHandle.invoke 和 MethodHandle.invokeExact 仅从 Android O (--min-api 26) 开始支持 - MethodHandle.invoke and MethodHandle.invokeExact are only supported starting with Android O (--min-api 26)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM