在Android中以编程方式更改应用语言

hpi*_*que 417 resources android localization

是否可以在使用Android资源的同时以编程方式更改应用程序的语言?

如果没有,是否可以请求特定语言的资源?

我想让用户从应用程序更改应用程序的语言.

Ale*_*voy 350

这是可能的.您可以设置区域设置.但是,我不建议这样做.我们在早期阶段尝试过它,它基本上是在与系统作斗争.

我们对更改语言有相同的要求,但决定解决UI应与手机UI相同的事实.它通过设置区域设置工作但是太多了.每次从我的经验中输入活动(每项活动)时都必须设置它.这是一个代码,如果你仍然需要这个(再次,我不建议)

Resources res = context.getResources();
// Change locale settings in the app.
DisplayMetrics dm = res.getDisplayMetrics();
android.content.res.Configuration conf = res.getConfiguration();
conf.setLocale(new Locale(language_code.toLowerCase())); // API 17+ only.
// Use conf.locale = new Locale(...) if targeting lower versions
res.updateConfiguration(conf, dm);
Run Code Online (Sandbox Code Playgroud)

如果您有特定于语言的内容 - 您可以根据设置更改该基础.

  • 无法相信Android让这么难.我真的不明白为什么手机的语言环境和应用程序之间应该存在STRICT关联.虽然我不是母语为英语的人,但我的手机总是使用英语.原因是翻译的半技术词语在我自己的语言中变得过于怪异,所以英语变得更加容易.这也让我更容易听从网络的建议.但这并不意味着我希望手机上的每个应用程序都使用英语(尽管默认情况下完全没问题).我希望能够选择!!! (289认同)
  • 如果你设置一个像"ar"这样的RTL语言环境,并希望你的-ldrtl资源文件夹也能正常工作,那么也可以调用conf.setLayoutDirection(locale); (13认同)
  • 哦,看起来像API级别17引入了`Context.createConfigurationContext()`,它可以用于使用特定于语言环境的配置包装默认上下文,然后在其上调用`getResources`而无需更新资源对象本身的配置. (8认同)
  • 你需要把它放在每个活动的onCreate()中.否则系统可能会覆盖它 - 例如,当您将设备转为横向并且使用新的(系统提供的)配置重新创建活动时. (6认同)
  • 此代码的小问题:`@deprecated 请参阅 {@link android.content.Context#createConfigurationContext(Configuration)}。` - updateConfiguration 已弃用 (4认同)
  • `updateConfiguration` 方法已被弃用,有什么解决方案吗? (4认同)
  • @ZsoltSafrany - 而不是添加对`conf.setLayoutDirection(locale)`的调用,你可以用`conf.setLocale(new Locale(...))替换`conf.locale = new Locale(...))` .它将在内部调用`setLayoutDirection`. (3认同)
  • 这个解决方案不适用于Adroid 8.有什么建议吗? (3认同)
  • 我正在使用此处所选答案中的解决方案:/sf/ask/349006381/ 我在这里链接以帮助其他人。 (3认同)
  • 它在一段时间后恢复。 (2认同)
  • 这需要在onCreate方法中的所有活动中调用吗?或者,如果我们给应用程序上下文,它应该只调用一次,而不是在所有活动中调用? (2认同)

Ali*_*iSh 167

这真的很有效:

fa =波斯语,en =英语

languageToLoad变量中输入您的语言代码:

import android.app.Activity;
import android.content.res.Configuration;
import android.os.Bundle;

public class Main extends Activity {
  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    String languageToLoad  = "fa"; // your language
    Locale locale = new Locale(languageToLoad); 
    Locale.setDefault(locale);
    Configuration config = new Configuration();
    config.locale = locale;
    getBaseContext().getResources().updateConfiguration(config, 
      getBaseContext().getResources().getDisplayMetrics());
    this.setContentView(R.layout.main);
  }
}
Run Code Online (Sandbox Code Playgroud)

你可以在这里找到一个例子

  • 不推荐使用Config.locale (8认同)
  • 这对于启动活动中的所有活动都很有效.但是,操作栏标题似乎不受影响,仍然会继续显示默认语言.知道我可能错过了什么吗? (5认同)
  • 这个解决方案不适用于Adroid 8.有什么建议吗? (3认同)
  • 我想在运行时更改语言环境,在代码中,将代码放在setContentView()方法之前.所以你的代码对我没用,所以如何在运行时更改语言,在我的应用程序中,有两个单选按钮,用于英语,另一个用于阿拉伯语, (2认同)
  • @Buffalo,它只是`Resources.updateConfiguration`方法的第二个参数.我缩进了代码以使其更清晰. (2认同)
  • 而不是"config.locale = locale;" 使用"if(Build.VERSION.SDK_INT> = 17){config.setLocale(locale);} else {config.locale = locale;} (2认同)

icy*_*sor 34

我一直在寻找一种以编程方式更改系统语言的方法.虽然我完全理解正常的应用程序永远不应该这样做,而是:

  • 用户应该(通过意图)指向系统设置以手动更改它
  • 应用程序应该自己处理它的本地化,就像Alex的答案中所描述的那样

有必要真正地改变系统的语言.

这是未记录的API,因此不应用于市场/最终用户应用程序!

无论如何,我找到了解决方案:

  Locale locale = new Locale(targetLocaleAsString);

  Class amnClass = Class.forName("android.app.ActivityManagerNative");
  Object amn = null;
  Configuration config = null;

  // amn = ActivityManagerNative.getDefault();
  Method methodGetDefault = amnClass.getMethod("getDefault");
  methodGetDefault.setAccessible(true);
  amn = methodGetDefault.invoke(amnClass);

  // config = amn.getConfiguration();
  Method methodGetConfiguration = amnClass.getMethod("getConfiguration");
  methodGetConfiguration.setAccessible(true);
  config = (Configuration) methodGetConfiguration.invoke(amn);

  // config.userSetLocale = true;
  Class configClass = config.getClass();
  Field f = configClass.getField("userSetLocale");
  f.setBoolean(config, true);

  // set the locale to the new value
  config.locale = locale;

  // amn.updateConfiguration(config);
  Method methodUpdateConfiguration = amnClass.getMethod("updateConfiguration", Configuration.class);
  methodUpdateConfiguration.setAccessible(true);
  methodUpdateConfiguration.invoke(amn, config);
Run Code Online (Sandbox Code Playgroud)

  • 我将我的应用程序放在 /system/priv-app 中以解决 Android 6.0 问题。[详情](http://stackoverflow.com/a/32216895/14870)。 (3认同)
  • API 级别 24 及以上,可以使用 [setLocales](https://developer.android.com/reference/android/content/res/Configuration.html#setLocales(android.os.LocaleList)) 设置多种语言 (3认同)
  • 给出异常调用目标异常 (2认同)

Dan*_* S. 30

如果你想保留改变所有应用程序的语言,你必须做两件事.

首先,创建一个基本活动,并使您的所有活动从此扩展:

public class BaseActivity extends AppCompatActivity {

    private Locale mCurrentLocale;

    @Override
    protected void onStart() {
        super.onStart();

        mCurrentLocale = getResources().getConfiguration().locale;
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Locale locale = getLocale(this);

        if (!locale.equals(mCurrentLocale)) {

            mCurrentLocale = locale;
            recreate();
        }
    }

    public static Locale getLocale(Context context){
        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);

        String lang = sharedPreferences.getString("language", "en");
        switch (lang) {
            case "English":
                lang = "en";
                break;
            case "Spanish":
                lang = "es";
                break;
        }
        return new Locale(lang);
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,我将新语言保存在sharedPreference中.

其次,像这样创建一个Application的扩展:

    public class App extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        setLocale();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        setLocale();
    }

    private void setLocale() {

        final Resources resources = getResources();
        final Configuration configuration = resources.getConfiguration();
        final Locale locale = getLocale(this);
        if (!configuration.locale.equals(locale)) {
            configuration.setLocale(locale);
            resources.updateConfiguration(configuration, null);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,getLocale()与上面的相同.

就这样!我希望这可以帮助别人.

  • 对于像我这样的 Android 菜鸟,来这里了解“应用程序”是什么以及如何使用。https://www.mobomo.com/2011/05/how-to-use-application-object-of-android/ (3认同)
  • `configuration.locate` 已弃用,setLocale 需要 API 17+ 且 updateConfiguration 已弃用 (2认同)

Kha*_*ela 16

根据 这篇文章.您需要下载LocaleHelper.java该文章中引用的内容.

  1. 创建MyApplication将扩展的类Application
  2. 覆盖attachBaseContext()更新语言.
  3. 在清单中注册此类.

    public class MyApplication extends Application {
       @Override
       protected void attachBaseContext(Context base) {
        super.attachBaseContext(LocaleHelper.onAttach(base, "en"));
       }
    }
    
    <application
         android:name="com.package.MyApplication"
         .../>
    
    Run Code Online (Sandbox Code Playgroud)
  4. 创建BaseActivity并覆盖onAttach()以更新语言.Android 6+需要

    public class BaseActivity extends Activity {
      @Override
      protected void attachBaseContext(Context base) {
        super.attachBaseContext(LocaleHelper.onAttach(base));
      }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  5. 使您的应用上的所有活动延伸BaseActivity.

    public class LocaleHelper {
    
    private static final String SELECTED_LANGUAGE = "Locale.Helper.Selected.Language";
    
    public static Context onAttach(Context context) {
        String lang = getPersistedData(context, Locale.getDefault().getLanguage());
        return setLocale(context, lang);
    }
    
    public static Context onAttach(Context context, String defaultLanguage) {
        String lang = getPersistedData(context, defaultLanguage);
        return setLocale(context, lang);
    }
    
    public static String getLanguage(Context context) {
        return getPersistedData(context, Locale.getDefault().getLanguage());
    }
    
    public static Context setLocale(Context context, String language) {
        persist(context, language);
    
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return updateResources(context, language);
        }
    
        return updateResourcesLegacy(context, language);
    }
    
    private static String getPersistedData(Context context, String defaultLanguage) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        return preferences.getString(SELECTED_LANGUAGE, defaultLanguage);
    }
    
    private static void persist(Context context, String language) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        SharedPreferences.Editor editor = preferences.edit();
    
        editor.putString(SELECTED_LANGUAGE, language);
        editor.apply();
    }
    
    @TargetApi(Build.VERSION_CODES.N)
    private static Context updateResources(Context context, String language) {
        Locale locale = new Locale(language);
        Locale.setDefault(locale);
    
        Configuration configuration = context.getResources().getConfiguration();
        configuration.setLocale(locale);
        configuration.setLayoutDirection(locale);
    
        return context.createConfigurationContext(configuration);
    }
    
    @SuppressWarnings("deprecation")
    private static Context updateResourcesLegacy(Context context, String language) {
        Locale locale = new Locale(language);
        Locale.setDefault(locale);
    
        Resources resources = context.getResources();
    
        Configuration configuration = resources.getConfiguration();
        configuration.locale = locale;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            configuration.setLayoutDirection(locale);
        }
    
        resources.updateConfiguration(configuration, resources.getDisplayMetrics());
    
        return context;
    }
    }
    
    Run Code Online (Sandbox Code Playgroud)

  • 你可以用一个包裹另一个。super.attachBaseContext(CalligraphyContextWrapper.wrap(LocaleHelper.onAttach(newBase))) (2认同)

tri*_*ggs 15

只是添加一个让我绊倒的额外部分.

而其他答案与"de"合作正常

String lang = "de";
Locale locale = new Locale(lang); 
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, 
    getBaseContext().getResources().getDisplayMetrics());
Run Code Online (Sandbox Code Playgroud)

以上不适用于例如"fr_BE"语言环境,因此它将使用values-fr-rBE文件夹或类似文件.

需要进行以下微小更改才能使用 "fr_BE"

String lang = "fr";

//create a string for country
String country = "BE";
//use constructor with country
Locale locale = new Locale(lang, country);

Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, 
    getBaseContext().getResources().getDisplayMetrics());
Run Code Online (Sandbox Code Playgroud)

  • 如果您想将区域设置更改应用于当前打开的活动,请调用“activity.recreate()” (2认同)

har*_*nan 14

我的应用程序启动后,我的德语语言已更改.

这是我正确的代码.任何人都希望我这样使用..(如何以编程方式更改android中的语言)

我的代码:

Configuration config ; // variable declaration in globally

// this part is given inside onCreate Method starting and before setContentView()

public void onCreate(Bundle icic) 
{
    super.onCreate(icic);
    config = new Configuration(getResources().getConfiguration());
    config.locale = Locale.GERMAN ;
    getResources().updateConfiguration(config,getResources().getDisplayMetrics());

    setContentView(R.layout.newdesign);
}
Run Code Online (Sandbox Code Playgroud)


Ani*_*rma 13

我知道现在回答很晚,但我在这里找到了这篇文章 .这很好地解释了整个过程,并为您提供结构良好的代码.

Locale Helper类:

import android.annotation.TargetApi;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.preference.PreferenceManager;

import java.util.Locale;

/**
 * This class is used to change your application locale and persist this change for the next time
 * that your app is going to be used.
 * <p/>
 * You can also change the locale of your application on the fly by using the setLocale method.
 * <p/>
 * Created by gunhansancar on 07/10/15.
 */
public class LocaleHelper {

    private static final String SELECTED_LANGUAGE = "Locale.Helper.Selected.Language";

    public static Context onAttach(Context context) {
        String lang = getPersistedData(context, Locale.getDefault().getLanguage());
        return setLocale(context, lang);
    }

    public static Context onAttach(Context context, String defaultLanguage) {
        String lang = getPersistedData(context, defaultLanguage);
        return setLocale(context, lang);
    }

    public static String getLanguage(Context context) {
        return getPersistedData(context, Locale.getDefault().getLanguage());
    }

    public static Context setLocale(Context context, String language) {
        persist(context, language);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return updateResources(context, language);
        }

        return updateResourcesLegacy(context, language);
    }

    private static String getPersistedData(Context context, String defaultLanguage) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        return preferences.getString(SELECTED_LANGUAGE, defaultLanguage);
    }

    private static void persist(Context context, String language) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        SharedPreferences.Editor editor = preferences.edit();

        editor.putString(SELECTED_LANGUAGE, language);
        editor.apply();
    }

    @TargetApi(Build.VERSION_CODES.N)
    private static Context updateResources(Context context, String language) {
        Locale locale = new Locale(language);
        Locale.setDefault(locale);

        Configuration configuration = context.getResources().getConfiguration();
        configuration.setLocale(locale);
        configuration.setLayoutDirection(locale);

        return context.createConfigurationContext(configuration);
    }

    @SuppressWarnings("deprecation")
    private static Context updateResourcesLegacy(Context context, String language) {
        Locale locale = new Locale(language);
        Locale.setDefault(locale);

        Resources resources = context.getResources();

        Configuration configuration = resources.getConfiguration();
        configuration.locale = locale;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            configuration.setLayoutDirection(locale);
        }

        resources.updateConfiguration(configuration, resources.getDisplayMetrics());

        return context;
    }
}
Run Code Online (Sandbox Code Playgroud)

您需要覆盖attachBaseContext并调用LocaleHelper.onAttach()来初始化应用程序中的区域设置.

import android.app.Application;
import android.content.Context;

import com.gunhansancar.changelanguageexample.helper.LocaleHelper;

public class MainApplication extends Application {
    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(LocaleHelper.onAttach(base, "en"));
    }
}
Run Code Online (Sandbox Code Playgroud)

你所要做的就是添加

LocaleHelper.onCreate(this, "en");
Run Code Online (Sandbox Code Playgroud)

您想要更改区域设置的任何位置.

  • onCreate 或 onAttach 调用? (2认同)

小智 12

创建类扩展Application并创建静态方法.然后你可以在之前的所有活动中调用此方法setContentView().

public class MyApp extends Application {

@Override
public void onCreate() {
    super.onCreate();
}

public static void setLocaleFa (Context context){
    Locale locale = new Locale("fa"); 
    Locale.setDefault(locale);
    Configuration config = new Configuration();
    config.locale = locale;
    context.getApplicationContext().getResources().updateConfiguration(config, null);
}

public static void setLocaleEn (Context context){
    Locale locale = new Locale("en_US"); 
    Locale.setDefault(locale);
    Configuration config = new Configuration();
    config.locale = locale;
    context.getApplicationContext().getResources().updateConfiguration(config, null);
}

}
Run Code Online (Sandbox Code Playgroud)

用于活动:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    MyApp.setLocaleFa(MainActivity.this);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.activity_main);
}
Run Code Online (Sandbox Code Playgroud)

  • 不推荐使用updateConfiguration (2认同)

PRA*_*NGH 10

Mayuri 的答案是正确的,但这只适用于 Api 33 或更高版本。这是逐步向后兼容的解决方案:

步骤1:在res/xml文件夹下创建locales_config.xml。

//res/xml/locales_config.xml
<?xml version="1.0" encoding="utf-8"?>
<locale-config xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Add your required languages -->
    <locale android:name="hi" />
    <locale android:name="en" />
</locale-config>
Run Code Online (Sandbox Code Playgroud)

步骤2:在Application下的Manifest中添加localeConfig

<manifest>
<application
    android:localeConfig="@xml/locales_config">
</application>
Run Code Online (Sandbox Code Playgroud)

步骤 3:在清单中添加此服务

<service
android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
android:enabled="false"
android:exported="false">
<meta-data
  android:name="autoStoreLocales"
  android:value="true" />
</service>
Run Code Online (Sandbox Code Playgroud)

步骤 4:使用应用程序的模块级 build.gradle 文件中的 resConfigs 属性指定相同的语言:

  android {
  defaultConfig {
      ...
      resConfigs "hi","en"
  }
  }
Run Code Online (Sandbox Code Playgroud)

(需要appCompat版本1.6.0或更高版本)

implementation 'androidx.appcompat:appcompat:1.6.0'
Run Code Online (Sandbox Code Playgroud)

第 5 步:现在您可以使用以下代码更改应用程序语言(在 android 9,10,12 和 13 上测试)

  LocaleListCompat appLocale = LocaleListCompat.forLanguageTags("hi"); //Give user selected language code 
  AppCompatDelegate.setApplicationLocales(appLocale);
Run Code Online (Sandbox Code Playgroud)


Dud*_*uda 9

对于Android 7.0 Nougat(及更低版本),请遵循以下文章:

在Android中以编程方式更改语言

旧答案
这包括RTL/LTR支持:

public static void changeLocale(Context context, Locale locale) {
    Configuration conf = context.getResources().getConfiguration();
    conf.locale = locale;
    Locale.setDefault(locale);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
       conf.setLayoutDirection(conf.locale);
    }

    context.getResources().updateConfiguration(conf, context.getResources().getDisplayMetrics());
}
Run Code Online (Sandbox Code Playgroud)


Bri*_*ani 8

如果你写

android:configChanges="locale"
Run Code Online (Sandbox Code Playgroud)

在每个活动中,每次进入时都不需要设置它Activity.

  • 如果它在清单中那么它如何构成运行时的变化,这似乎是OP想要的? (9认同)

Lak*_*hna 8

您可以要求用户在第一个屏幕中选择语言并将其保存在SharedPreferences

SharedPreferences.Editor editor = getSharedPreferences("data", MODE_PRIVATE).edit();
editor.putString("lang", "si");
editor.apply();
    
recreate();
Run Code Online (Sandbox Code Playgroud)

然后您可以将其纳入Activity您的应用程序中的每个部分。这里我设置了英语和僧伽罗语。

@Override
protected void attachBaseContext(Context base) {
    SharedPreferences prefs = base.getSharedPreferences("uinfo", MODE_PRIVATE);
    String restoredText = prefs.getString("lang", "No name defined");

    if (restoredText.equals("si")){
        super.attachBaseContext(LocaleHelper.localeUpdateResources(base, "si"));
    }else{
        super.attachBaseContext(LocaleHelper.localeUpdateResources(base, "en"));
    }
}
Run Code Online (Sandbox Code Playgroud)

这就是你的localUpdateResources方法。将其放置在LocalHelper课堂上

public class LocaleHelper {
    public static Context localeUpdateResources(Context context, String languageCode) {

        Context newContext = context;

        Locale locale = new Locale(languageCode);
        Locale.setDefault(locale);

        Resources resources = context.getResources();
        Configuration config = new Configuration(resources.getConfiguration());

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {

            config.setLocale(locale);
            newContext = context.createConfigurationContext(config);

        } else {

            config.locale = locale;
            resources.updateConfiguration(config, resources.getDisplayMetrics());
        }

        return newContext;

    }
}
Run Code Online (Sandbox Code Playgroud)


Cod*_*meo 8

Resources.updateConfiguration()已被弃用,我已解决此问题而无需创建任何自定义ContextWrapper.

首先我创建了一个扩展函数

fun Context.setAppLocale(language: String): Context {
    val locale = Locale(language)
    Locale.setDefault(locale)
    val config = resources.configuration
    config.setLocale(locale)
    config.setLayoutDirection(locale)
    return createConfigurationContext(config)
}
Run Code Online (Sandbox Code Playgroud)

然后在活动的attachBaseContext方法中,只需将上下文替换为新的上下文即可。

override fun attachBaseContext(newBase: Context) {
  super.attachBaseContext(ContextWrapper(newBase.setAppLocale("bn")))
}
Run Code Online (Sandbox Code Playgroud)

  • 这段代码完美工作:) (2认同)

Mis*_*sha 7

对我来说唯一的解决方案是Alex Volovoy的代码与应用程序重启机制的组合:

void restartApplication() {
    Intent i = new Intent(MainTabActivity.context, MagicAppRestart.class);
    i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    MainTabActivity.context.startActivity(i);
}


/** This activity shows nothing; instead, it restarts the android process */
public class MagicAppRestart extends Activity {
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        finish();
    }

    protected void onResume() {
        super.onResume();
        startActivityForResult(new Intent(this, MainTabActivity.class), 0);         
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 在区域设置更改后,您还可以调用`activity.recreate()` (2认同)

Zoe*_*Zoe 7

进行适当更新的时间。

首先,使用已弃用的API弃用的列表:

  • configuration.locale (API 17)
  • updateConfiguration(configuration, displaymetrics) (API 17)

最近没有回答的问题正确地解决了新方法的使用问题

createConfigurationContext是updateConfiguration的新方法。

有些人像这样单独使用它:

Configuration overrideConfiguration = ctx.getResources().getConfiguration();
Locale locale = new Locale("en_US");
overrideConfiguration.setLocale(locale);
createConfigurationContext(overrideConfiguration);
Run Code Online (Sandbox Code Playgroud)

...但是那行不通。为什么?该方法返回一个上下文,然后该上下文用于处理Strings.xml转换和其他本地化资源(图像,布局等)。

正确的用法是这样的:

Configuration overrideConfiguration = ctx.getResources().getConfiguration();
Locale locale = new Locale("en_US");
overrideConfiguration.setLocale(locale);
//the configuration can be used for other stuff as well
Context context  = createConfigurationContext(overrideConfiguration);
Resources resources = context.getResources();
Run Code Online (Sandbox Code Playgroud)

如果只是将其复制粘贴到IDE中,则可能会看到一条警告,提示该API要求您定位API 17或更高版本。可以通过将其放入方法并添加注释来解决此问题。@TargetApi(17)

可是等等。那旧的API呢?

您需要使用没有TargetApi批注的updateConfiguration创建另一个方法。

Resources res = YourApplication.getInstance().getResources();
// Change locale settings in the app.
DisplayMetrics dm = res.getDisplayMetrics();
android.content.res.Configuration conf = res.getConfiguration();
conf.locale = new Locale("th");
res.updateConfiguration(conf, dm);
Run Code Online (Sandbox Code Playgroud)

您无需在此处返回上下文。

现在,管理这些可能很困难。在API 17+中,您需要创建上下文(或创建的上下文中的资源)以基于本地化获取适当的资源。您如何处理?

好吧,这就是我的方法:

/**
 * Full locale list: /sf/ask/558111641/
 * @param lang language code (e.g. en_US)
 * @return the context
 * PLEASE READ: This method can be changed for usage outside an Activity. Simply add a COntext to the arguments
 */
public Context setLanguage(String lang/*, Context c*/){
    Context c = AndroidLauncher.this;//remove if the context argument is passed. This is a utility line, can be removed totally by replacing calls to c with the activity (if argument Context isn't passed)
    int API = Build.VERSION.SDK_INT;
    if(API >= 17){
        return setLanguage17(lang, c);
    }else{
        return setLanguageLegacy(lang, c);
    }
}

/**
 * Set language for API 17
 * @param lang
 * @param c
 * @return
 */
@TargetApi(17)
public Context setLanguage17(String lang, Context c){
    Configuration overrideConfiguration = c.getResources().getConfiguration();
    Locale locale = new Locale(lang);
    Locale.setDefault(locale);
    overrideConfiguration.setLocale(locale);
    //the configuration can be used for other stuff as well
    Context context  = createConfigurationContext(overrideConfiguration);//"local variable is redundant" if the below line is uncommented, it is needed
    //Resources resources = context.getResources();//If you want to pass the resources instead of a Context, uncomment this line and put it somewhere useful
    return context;
}

public Context setLanguageLegacy(String lang, Context c){
    Resources res = c.getResources();
    // Change locale settings in the app.
    DisplayMetrics dm = res.getDisplayMetrics();//Utility line
    android.content.res.Configuration conf = res.getConfiguration();

    conf.locale = new Locale(lang);//setLocale requires API 17+ - just like createConfigurationContext
    Locale.setDefault(conf.locale);
    res.updateConfiguration(conf, dm);

    //Using this method you don't need to modify the Context itself. Setting it at the start of the app is enough. As you
    //target both API's though, you want to return the context as you have no clue what is called. Now you can use the Context
    //supplied for both things
    return c;
}
Run Code Online (Sandbox Code Playgroud)

该代码通过使用一种方法来起作用,该方法可以根据API调用适当的方法。这是我使用许多不推荐使用的调用(包括Html.fromHtml)完成的。您有一个采用所需参数的方法,然后将其拆分为两个(或三个或更多)方法之一,并根据API级别返回适当的结果。由于您不必多次检查,因此它很灵活,“输入”方法可以为您完成检查。这里的进入方法是setLanguage

使用前请仔细阅读

获取资源时,需要使用返回的Context。为什么?我在这里看到了其他答案,他们使用createConfigurationContext而不使用返回的上下文。为了使其能够正常工作,必须调用updateConfiguration。不推荐使用。使用方法返回的上下文获取资源。

用法示例

构造函数或类似的地方:

ctx = getLanguage(lang);//lang is loaded or generated. How you get the String lang is not something this answer handles (nor will handle in the future)
Run Code Online (Sandbox Code Playgroud)

然后,无论您想获得什么资源,都可以这样做:

String fromResources = ctx.getString(R.string.helloworld);
Run Code Online (Sandbox Code Playgroud)

使用任何其他上下文(理论上)将打破这一点。

AFAIK您仍然必须使用活动上下文来显示对话框或Toast。为此,您可以使用活动的实例(如果您在外面)


最后,使用recreate()该活动刷新内容。不必创建刷新意图的快捷方式。


Hei*_*eli 7

对每应用语言首选项的支持刚刚添加到API 33Android 13,Tiramisu目前处于开发者预览版)。

要更改应用程序的区域设置,只需从LocaleManager调用setApplicationLocales

// Set app locale to pt-BR (Portuguese, Brazil)
getSystemService(LocaleManager::class.java)
    .applicationLocales = LocaleList(Locale.forLanguageTag("pt-BR"))
Run Code Online (Sandbox Code Playgroud)

查看更多信息https://developer.android.com/about/versions/13/features/app-languages#api-impl

我写了一篇关于此功能的文章https://proandroiddev.com/exploring-the-new-android-13-per-app-language-preferences-8d99b971b578


Ran*_*mar 6

对于阿拉伯语/RTL 支持

  1. 您必须通过 - attachBaseContext() 更新您的语言设置
  2. 对于 android 版本 N 及更高版本,您必须使用 createConfigurationContext() 和 updateConfiguration() - 否则 RTL 布局无法正常工作

 @Override
    protected void attachBaseContext(Context newBase) {
        super.attachBaseContext(updateBaseContextLocale(newBase));
    }

    public Context updateBaseContextLocale(Context context) {
        String language = SharedPreference.getInstance().getValue(context, "lan");//it return "en", "ar" like this
        if (language == null || language.isEmpty()) {
            //when first time enter into app (get the device language and set it
            language = Locale.getDefault().getLanguage();
            if (language.equals("ar")) {
                SharedPreference.getInstance().save(mContext, "lan", "ar");
            }
        }
        Locale locale = new Locale(language);
        Locale.setDefault(locale);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            updateResourcesLocale(context, locale);
            return  updateResourcesLocaleLegacy(context, locale);
        }

        return updateResourcesLocaleLegacy(context, locale);
    }

    @TargetApi(Build.VERSION_CODES.N)
    private Context updateResourcesLocale(Context context, Locale locale) {
        Configuration configuration = context.getResources().getConfiguration();
        configuration.setLocale(locale);
        return context.createConfigurationContext(configuration);
    }

    @SuppressWarnings("deprecation")
    private Context updateResourcesLocaleLegacy(Context context, Locale locale) {
        Resources resources = context.getResources();
        Configuration configuration = resources.getConfiguration();
        configuration.locale = locale;
        resources.updateConfiguration(configuration, resources.getDisplayMetrics());
        return context;
    }
Run Code Online (Sandbox Code Playgroud)

  • 这应该是正确的答案。只需测试它即可工作(22/02/2021)。谢谢,我的朋友。 (3认同)

Roc*_*ney 5

我面临同样的问题.在GitHub上,我找到了Android-LocalizationActivity库.

该库使得在运行时更改应用程序语言非常简单,如下面的代码示例所示.可以在github页面找到包含以下示例代码和更多信息的示例项目.

LocalizationActivity扩展了AppCompatActivity,因此您在使用Fragments时也可以使用它.

public class MainActivity extends LocalizationActivity implements View.OnClickListener {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_simple);

        findViewById(R.id.btn_th).setOnClickListener(this);
        findViewById(R.id.btn_en).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        if (id == R.id.btn_en) {
            setLanguage("en");
        } else if (id == R.id.btn_th) {
            setLanguage("th");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Moh*_*ari 5

首先为不同的语言创建多个string.xml;然后在方法中使用这段代码onCreate()

super.onCreate(savedInstanceState);
String languageToLoad  = "fr"; // change your language here
Locale locale = new Locale(languageToLoad); 
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, 
  getBaseContext().getResources().getDisplayMetrics());
this.setContentView(R.layout.main);
Run Code Online (Sandbox Code Playgroud)


Мак*_*люк 5

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

Configuration config = context.getResources().getConfiguration();
config.setLocale(locale);
context.createConfigurationContext(config);
Run Code Online (Sandbox Code Playgroud)

重要更新:

context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());
Run Code Online (Sandbox Code Playgroud)

注意,在SDK> = 21上,您需要调用'Resources.updateConfiguration()',否则资源将不会更新.


Pav*_*kov 5

这里列出的解决方案都没有帮助我。

如果 AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES),则语言不会在 android >= 7.0 上切换

这个 LocaleUtils 工作得很好: https://gist.github.com/GigigoGreenLabs/7d555c762ba2d3a810fe

语言环境工具

public class LocaleUtils {

public static final String LAN_SPANISH      = "es";
public static final String LAN_PORTUGUESE   = "pt";
public static final String LAN_ENGLISH      = "en";

private static Locale sLocale;

public static void setLocale(Locale locale) {
    sLocale = locale;
    if(sLocale != null) {
        Locale.setDefault(sLocale);
    }
}

public static void updateConfig(ContextThemeWrapper wrapper) {
    if(sLocale != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        Configuration configuration = new Configuration();
        configuration.setLocale(sLocale);
        wrapper.applyOverrideConfiguration(configuration);
    }
}

public static void updateConfig(Application app, Configuration configuration) {
    if(sLocale != null && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
        //Wrapping the configuration to avoid Activity endless loop
        Configuration config = new Configuration(configuration);
        config.locale = sLocale;
        Resources res = app.getBaseContext().getResources();
        res.updateConfiguration(config, res.getDisplayMetrics());
    }
}
}
Run Code Online (Sandbox Code Playgroud)

将此代码添加到应用程序中

public class App extends Application {
public void onCreate(){
    super.onCreate();

    LocaleUtils.setLocale(new Locale("iw"));
    LocaleUtils.updateConfig(this, getBaseContext().getResources().getConfiguration());
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    LocaleUtils.updateConfig(this, newConfig);
}
}
Run Code Online (Sandbox Code Playgroud)

活动中的代码

public class BaseActivity extends AppCompatActivity {
    public BaseActivity() {
        LocaleUtils.updateConfig(this);
    }
}
Run Code Online (Sandbox Code Playgroud)


May*_*ara 5

该功能是 Google 为 Android 13 正式推出的(并且也有向后支持)。Android 现在允许您为每个应用程序选择语言。

官方文档在这里 - https://developer.android.com/guide/topics/resources/app-languages

要设置用户的首选语言,您需要要求用户在语言选择器中选择区域设置,然后在系统中设置该值:

// 1. Inside an activity, in-app language picker gets an input locale "xx-YY"
// 2. App calls the API to set its locale
mContext.getSystemService(LocaleManager.class
    ).setApplicationLocales(newLocaleList(Locale.forLanguageTag("xx-YY")));
// 3. The system updates the locale and restarts the app, including any configuration updates
// 4. The app is now displayed in "xx-YY" language
Run Code Online (Sandbox Code Playgroud)

要让用户当前的首选语言显示在语言选择器中,您的应用程序可以从系统返回该值:


// 1. App calls the API to get the preferred locale
LocaleList currentAppLocales =
    mContext.getSystemService(LocaleManager.class).getApplicationLocales();
// 2. App uses the returned LocaleList to display languages to the user
Run Code Online (Sandbox Code Playgroud)