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

时间:2010-05-24 20:17:44

标签: android localization resources

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

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

我想让用户从应用中更改应用的语言。

41 个答案:

答案 0 :(得分:331)

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

我们对更改语言有相同的要求,但我们决定确定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);

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

答案 1 :(得分:155)

这真的有用:

  

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

您可以找到示例here

答案 2 :(得分:32)

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

  • 用户应指向(通过意图)系统设置以手动更改
  • 应用程序应该自行处理其本地化,就像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);

答案 3 :(得分:29)

如果您想要改变所有应用程序的语言,您必须做两件事。

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

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

请注意,我将新语言保存在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);
        }
    }
}

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

这就是全部! 我希望这可以帮助某人。

答案 4 :(得分: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());

以上内容不适用于"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());

答案 5 :(得分:13)

我的应用程序自动更改为德语。

这是我正确的代码。任何人都想为我使用这个.. (如何以编程方式更改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);
}

答案 6 :(得分:13)

我知道答案很晚但我发现this article here 。这很好地解释了整个过程,并为您提供了结构良好的代码。

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

您需要覆盖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"));
    }
}

您所要做的就是添加

LocaleHelper.onCreate(this, "en");

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

答案 7 :(得分:12)

根据 this article。您需要下载该文章中引用的LocaleHelper.java

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

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

    public class BaseActivity extends Activity {
      @Override
      protected void attachBaseContext(Context base) {
        super.attachBaseContext(LocaleHelper.onAttach(base));
      }
    }
    
  6. 让您的应用上的所有活动都延伸至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;
    }
    }
    

答案 8 :(得分:12)

创建一个类Extends 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);
}

}

活动中的用法:

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

答案 9 :(得分:9)

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

Change Language Programatically in 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());
}

答案 10 :(得分:7)

如果你写

android:configChanges="locale"

在每项活动中,每次进入Activity时都无需进行设置。

答案 11 :(得分: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);         
    }
}

答案 12 :(得分:5)

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

请注意,在SDK&gt; = 21上,您需要调用&#39; Resources.updateConfiguration()&#39; ,否则资源将不会更新。

答案 13 :(得分:5)

我遇到了同样的问题。在GitHub上我找到了Android-LocalizationActivity library

这个库使得在运行时更改应用程序语言变得非常简单,如下面的代码示例所示。可以在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");
        }
    }
}

答案 14 :(得分:4)

首先为不同的语言创建多个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);

答案 15 :(得分:4)

适时更新的时间。

首先,使用不推荐使用的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);

......但这不起作用。为什么?该方法返回一个上下文,然后用于处理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();

如果您只是将其复制粘贴到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);

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

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

嗯,这就是我这样做的方式:

/**
 * Full locale list: https://stackoverflow.com/questions/7973023/what-is-the-list-of-supported-languages-locales-on-android
 * @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;
}

此代码的工作原理是使用一种方法根据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)

然后,无论您想获得资源,还是:

String fromResources = ctx.getString(R.string.helloworld);

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

AFAIK您仍然需要使用活动上下文来显示对话框或Toasts。为此你可以使用一个活动的实例(如果你在外面)

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

答案 16 :(得分:4)

/*change language at Run-time*/
//use method like that:
//setLocale("en");
 public void setLocale(String lang) { 
  myLocale = new Locale(lang);         
  Resources res = getResources();         
  DisplayMetrics dm = res.getDisplayMetrics();         
  Configuration conf = res.getConfiguration();         
  conf.locale = myLocale;         
  res.updateConfiguration(conf, dm);         
  Intent refresh = new Intent(this, AndroidLocalize.class);         
  startActivity(refresh); 
 }

答案 17 :(得分:4)

在设置内容之前,应在每个Locale设置

configuration activity - this.setContentView(R.layout.main);

答案 18 :(得分:3)

这是一些对我有用的代码:

public class  MainActivity extends AppCompatActivity {
    public static String storeLang;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        SharedPreferences shp = PreferenceManager.getDefaultSharedPreferences(this);
        storeLang = shp.getString(getString(R.string.key_lang), "");

        // Create a new Locale object
        Locale locale = new Locale(storeLang);

        // Create a new configuration object
        Configuration config = new Configuration();
        // Set the locale of the new configuration
        config.locale = locale;
        // Update the configuration of the Accplication context
        getResources().updateConfiguration(
                config,
                getResources().getDisplayMetrics()
        );

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

来源:here

答案 19 :(得分:2)

请注意,使用updateConfiguration will not be working anymore with the Android M版本的解决方案将在几周内发布。执行此操作的新方法现在使用applyOverrideConfiguration中的ContextThemeWrapper方法 see API doc

你可以在这里找到我的完整解决方案,因为我自己遇到了这个问题: https://stackoverflow.com/a/31787201/2776572

答案 20 :(得分:2)

Alex Volovoy回答只适用于我,如果它是onCreate活动方法。

适用于所有方法的答案是在另一个线程中

Change language programmatically in Android

以下是代码的改编



    Resources standardResources = getBaseContext().getResources();

    AssetManager assets = standardResources.getAssets();

    DisplayMetrics metrics = standardResources.getDisplayMetrics();

    Configuration config = new Configuration(standardResources.getConfiguration());

    config.locale = new Locale(languageToLoad);

    Resources defaultResources = new Resources(assets, metrics, config);

希望它有所帮助。

答案 21 :(得分:1)

当按下按钮更改TextView的文本语言时,这是有效的。(values-de文件夹中的strings.xml)

String languageToLoad = "de"; // your language
Configuration config = getBaseContext().getResources().getConfiguration();
Locale locale = new Locale(languageToLoad);
Locale.setDefault(locale);
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
recreate();

答案 22 :(得分:1)

private void setLanguage(String language) {
    Locale locale = new Locale(language);
    Locale.setDefault(locale);
    Configuration config = new Configuration();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        config.setLocale(locale);
    } else {
        config.locale = locale;
    }
    getResources().updateConfiguration(config,
            getResources().getDisplayMetrics());

}

答案 23 :(得分:1)

如果有人在编译时正在寻找禁用语言,这是解决方案:

android {
    defaultConfig {
        resConfigs "en"
    }
}

这不仅是为了禁用本地化,resConfigs只是告诉构建系统要保留哪些资源。

您可以查看原始答案here

答案 24 :(得分:1)

我终于弄清楚了如何将其设置为在两个= N android版本上都可以使用。

使用您自己的抽象类扩展AppCompatActivity,例如:

abstract class MLAppCompatActivity : AppCompatActivity() {
  override fun attachBaseContext(newBase: Context?) {
    super.attachBaseContext(LocaleHelper.wrap(newBase))
  }

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
        LocaleHelper.wrap(this)
    }
  }
}
在Android> = N版本上会调用

attachBaseContext,这样活动将使用正确的上下文。在Android

class TermsActivity : MLAppCompatActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_terms)
  }
}

最后,LocaleHelper就像这样:

import android.annotation.TargetApi;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.util.DisplayMetrics;

import com.at_zone.constants.SharedPreferencesKeys;

import java.util.Locale;

public class LocaleHelper extends ContextWrapper {

    public LocaleHelper(Context base) {
        super(base);
    }

    public static Context wrap(Context context) {
        SharedPreferences sharedPreferences = context.getSharedPreferences(
                SharedPreferencesKeys.SHARED_PREFERENCES, Context.MODE_PRIVATE
        );
        String language = sharedPreferences.getString(SharedPreferencesKeys.CURRENT_LANGUAGE, "default");
        if (!language.equals("default")) {
            Configuration config = context.getResources().getConfiguration();
            if (!language.equals("")) {
                Locale locale = new Locale(language);
                Locale.setDefault(locale);
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    setSystemLocale(config, locale);
                } else {
                    setSystemLocaleLegacy(context, config, locale);
                }
                config.setLayoutDirection(locale);
                context = context.createConfigurationContext(config);
            }
            return new LocaleHelper(context);
        }
        return context;
    }

    public static String getSystemLanguage(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return getSystemLocale(context).getLanguage().toLowerCase();
        } else {
            return getSystemLocaleLegacy(context).getLanguage().toLowerCase();
        }
    }

    public static Locale getSystemLocaleLegacy(Context context) {
        Configuration config = context.getResources().getConfiguration();
        return config.locale;
    }

    @TargetApi(Build.VERSION_CODES.N)
    public static Locale getSystemLocale(Context context) {
        return context.getResources().getConfiguration().getLocales().get(0);
    }

    public static void setSystemLocaleLegacy(Context context, Configuration config, Locale locale) {
        config.locale = locale;
        Resources res = context.getResources();
        DisplayMetrics dm = res.getDisplayMetrics();
        res.updateConfiguration(config, dm);
    }

    @TargetApi(Build.VERSION_CODES.N)
    public static void setSystemLocale(Configuration config, Locale locale) {
        config.setLocale(locale);
    }

}

答案 25 :(得分:1)

https://stackoverflow.com/a/48531811/9609776

可以,但是不要将updateResources拆分为不同的版本,只需使用以下解决方案即可(kotlin)。密钥位于“ Configuration(context.resources.configuration)”中,可以进行深度复制。

API 21+的100%解决方案。我尚未测试过较低的水平,但应该可以。

private fun updateResources(context: Context, language: String): Context {
    return Configuration(context.resources.configuration).run {
        Locale.setDefault(Locale(language).also { locale ->
            setLocale(locale)
        }).let {
            context.createConfigurationContext(this)
        }
    }
}

答案 26 :(得分:0)

添加 LocaleHelper

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

活动或片段中

Context context = LocaleHelper.setLocale(this, App.getSharedPre().getLanguage());
Resource resources = context.getResources();

现在在每个文本上使用SetText

TextView tv = findViewById(R.id.tv);
tv.setText(resources.getString(R.string.tv));

答案 27 :(得分:0)

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

然后在活动的 attachBaseContext 方法中,简单地用新的上下文替换上下文。

override fun attachBaseContext(newBase: Context) {
  super.attachBaseContext(ContextWrapper(newBase.setAppLocale("bn")))
}

答案 28 :(得分:0)

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

SharedPreferences.Editor editor = getSharedPreferences("uinfo", MODE_PRIVATE).edit();
editor.putString("lang", "si");
editor.apply();
    
recreate();

然后您可以在应用程序中的每个 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"));
    }
}

这是您的 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;

    }
}

答案 29 :(得分:0)

对于 androidx.appcompat:appcompat 用户,上述解决方案在 1.3.0 版本后有效。 如here中所述。

答案 30 :(得分:0)

解决方案的Kotlin版本

private fun setLocale(activity: Activity, languageCode: String?) {
    val locale = Locale(languageCode)
    Locale.setDefault(locale)
    val resources: Resources = activity.resources
    val config: Configuration = resources.getConfiguration()
    config.setLocale(locale)
    resources.updateConfiguration(config, resources.getDisplayMetrics())

请参阅此答案以获取语言代码列表 https://stackoverflow.com/a/7989085/13139418

答案 31 :(得分:0)

对我来说,最好的解决方案是: https://www.bitcaal.com/how-to-change-the-app-language-programmatically-in-android/

package me.mehadih.multiplelanguage;

import androidx.appcompat.app.AppCompatActivity;

import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.os.Bundle;
import android.util.DisplayMetrics;

import java.util.Locale;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setApplicationLocale("az"); // short name of language. "en" for English
        setContentView(R.layout.activity_main);

    }

    private void setApplicationLocale(String locale) {
        Resources resources = getResources();
        DisplayMetrics dm = resources.getDisplayMetrics();
        Configuration config = resources.getConfiguration();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            config.setLocale(new Locale(locale.toLowerCase()));
        } else {
            config.locale = new Locale(locale.toLowerCase());
        }
        resources.updateConfiguration(config, dm);
    }
}

答案 32 :(得分:0)

获得阿拉伯语/ RTL支持

  1. 您必须通过-attachBaseContext()
  2. 更新语言设置
  3. 对于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;
    }

答案 33 :(得分:0)

类似于接受的答案,但2017版本并添加了重启(没有重新启动,有时下一个活动仍然会呈现英语):

// Inside some activity...
private void changeDisplayLanguage(String langCode) {
// Step 1. Change the locale in the app's configuration
    Resources res = getResources();
    android.content.res.Configuration conf = res.getConfiguration();
    conf.setLocale(currentLocale);
    createConfigurationContext(conf);
// Step 2. IMPORTANT! you must restart the app to make sure it works 100%
    restart();
}
private void restart() {
    PackageManager packageManager = getPackageManager();
    Intent intent = packageManager.getLaunchIntentForPackage(getPackageName());
    ComponentName componentName = intent.getComponent();
    Intent mainIntent = IntentCompat.makeRestartActivityTask(componentName);
    mainIntent.putExtra("app_restarting", true);
    PrefUtils.putBoolean("app_restarting", true);
    startActivity(mainIntent);
    System.exit(0);
}

答案 34 :(得分:0)

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

如果AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES),语言无法在android> = 7.0上打开

此LocaleUtils正常工作: https://gist.github.com/GigigoGreenLabs/7d555c762ba2d3a810fe

LocaleUtils

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

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

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

活动代码

public class BaseActivity extends AppCompatActivity {
    public BaseActivity() {
        LocaleUtils.updateConfig(this);
    }
}

答案 35 :(得分:0)

您应该实施一些步骤

首先,您需要更改配置的区域设置

$("#mapasFiltro option:not(:selected).length > 0").serialize();

其次,如果您希望更改直接应用于可见的布局,您可以直接更新视图,也可以调用activity.recreate()来重新启动当前活动。

此外,您还必须保留更改,因为在用户关闭您的应用程序后,您将失去语言更改。

我在博文Change Language Programmatically in Android

上解释了更详细的解决方案

基本上,您只需在应用程序类上调用LocaleHelper.onCreate(),如果要动态更改语言环境,可以调用LocaleHelper.setLocale()

答案 36 :(得分:0)

在示例中,我们设置了英语:

 Configuration config = GetBaseContext().getResources().getConfiguration();
 Locale locale = new Locale("en");
 Locale.setDefault(locale);
 config.locale = locale;
 GetBaseContext().getResources().updateConfiguration(config, 
            GetBaseContext().getResources().getDisplayMetrics());

请记住,只有在设备系统中找到语言时才有效,不仅仅是在应用程序中

答案 37 :(得分:0)

首先创建目录名称值 - “语言名称”,如hindi,而不是写“hi”,并且在此目录中使用相同的字符串文件名副本,并且在按钮等操作中设置下面的代码后,更改值不会更改参数...

Locale myLocale = new Locale("hi");
Resources res = getResources();
DisplayMetrics dm = res.getDisplayMetrics();
Configuration conf = res.getConfiguration();
conf.locale = myLocale;
res.updateConfiguration(conf, dm);
Intent refresh = new Intent(Home.this, Home.class);
startActivity(refresh);
finish(); 

答案 38 :(得分:-2)

只需处理方法

@Override public void onConfigurationChanged(android.content.res.Configuration newConfig).

关注Link

我认为这很有用

答案 39 :(得分:-3)

它适合我

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

答案 40 :(得分:-3)

我遇到了同样的问题:我需要将我的语言设置为我的应用程序中选择的语言。

我的解决方法是:

  1. 将您的字符串保存在XML文件中,不要将其提取到资源
  2. 制作XML的精确副本,并将其重命名为_languagecode,如 _fr(使用小写!)
  3. 将您的翻译修复为XML副本
  4. 在代码中,您可以检查应用级语言并夸大相关内容 XML
  5. 示例:

     String languageInitials = MyAppconfig.currentLanguageInitials();
            if (languageInitials.equals("NL")) {
                view = inflater.inflate(R.layout.mylayout_nl, container, false);
            } else {
                view = inflater.inflate(R.layout.fragment_mylayout_fr, container, false);
            }
    

    从这些XML中,您仍然可以将所需的字符串提取到资源。