【问题标题】:How to change language of app when user selects language?用户选择语言时如何更改应用程序的语言?
【发布时间】:2012-10-06 04:11:22
【问题描述】:

我希望我的应用支持西班牙语、葡萄牙语和英语三种语言。并提供在应用程序中选择语言的选项。我已经做了

1) 3个可绘制文件夹drawable-es、drawable-pt、drawable。

2) 3个值文件夹values-es,values-pt,values.根据语言改变String.xml值。

我有 imageView 来选择语言。单击它时打开菜单,其中包含选项英语、西班牙语、葡萄牙语。

我在应用程序内通过此代码选择选项时设置区域设置

public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.en:
             Locale locale = new Locale("en"); 
             Locale.setDefault(locale);
             Configuration config = new Configuration();
             config.locale = locale;
             getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
             Toast.makeText(this, "Locale in English !", Toast.LENGTH_LONG).show();
             break;

        case R.id.pt:
             Locale locale2 = new Locale("pt"); 
             Locale.setDefault(locale2);
             Configuration config2 = new Configuration();
             config2.locale = locale2;
             getBaseContext().getResources().updateConfiguration(config2, getBaseContext().getResources().getDisplayMetrics());

             Toast.makeText(this, "Locale in Portugal !", Toast.LENGTH_LONG).show();
             break;

        case R.id.es:
             Locale locale3 = new Locale("es"); 
             Locale.setDefault(locale3);
             Configuration config3 = new Configuration();
             config3.locale = locale3;
             getBaseContext().getResources().updateConfiguration(config3, getBaseContext().getResources().getDisplayMetrics());

             Toast.makeText(this, "Locale in Spain !", Toast.LENGTH_LONG).show();
             break;     
    }
    return super.onOptionsItemSelected(item);
}

我已在 Manifest 中声明- android:configChanges="locale"

它工作,但它有一些问题。

问题:-

1)选中语言时,由语言选择的图像的屏幕不会改变,但其他屏幕是更改的。

2)根据手机的语言环境改变方向后应用恢复语言。

【问题讨论】:

  • 对于第二个问题,请尝试在 AndroidManifest.xml 中为您的 Activity 添加:android:configChanges="locale"
  • 我已经在我的清单中添加了每个活动。
  • 您可以使用以下库,它提供语言列表、设置屏幕的首选项并覆盖应用程序中的语言:github.com/delight-im/Android-Languages

标签: android localization


【解决方案1】:

网页摘录:http://android.programmerguru.com/android-localization-at-runtime/

当用户从语言列表中选择应用程序时,更改应用程序的语言很简单。有一个像下面这样接受语言环境作为字符串的方法(比如英语的“en”,印地语的“hi”),为您的应用程序配置语言环境并刷新您当前的活动以反映语言的变化。在您再次手动更改之前,您应用的语言环境不会更改。

public void setLocale(String lang) { 
    Locale 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); 
    finish();
    startActivity(refresh); 
} 

确保您导入了以下包:

import java.util.Locale; 
import android.os.Bundle; 
import android.app.Activity; 
import android.content.Intent; 
import android.content.res.Configuration; 
import android.content.res.Resources; 
import android.util.DisplayMetrics; 

将清单添加到活动 android:configChanges="locale|orientation"

【讨论】:

  • 一定要添加finish(),这样你的activity就不会在导航栈中有两个副本了。
  • finish() 需要在startActivity(refresh) 之前调用。否则 App 可能会退出而不是 Activity 被重新启动。
  • 嗨,我做到了,它可以工作,但是当我重新启动应用程序时,它会返回到默认语言..
  • 配置配置=新配置(newConfig); config.locale = 语言环境;就我而言,收到此消息。 API 级别 25 中已弃用的语言环境
  • 这个答案需要更新,因为现在使用的一些 API 已被弃用。
【解决方案2】:

好的解决方案在这里解释得很好。但这里还有一个。

创建您自己的 CustomContextWrapper 类扩展 ContextWrapper 并使用它来更改整个应用程序的区域设置。 Here is a GIST 有用法。

然后使用保存的语言环境标识符调用CustomContextWrapper,例如'hi' 用于活动生命周期方法中的印地语语言 attachBaseContext。这里的用法:

@Override
protected void attachBaseContext(Context newBase) {
    // fetch from shared preference also save the same when applying. Default here is en = English
    String language = MyPreferenceUtil.getInstance().getString("saved_locale", "en");
    super.attachBaseContext(MyContextWrapper.wrap(newBase, language));
}

【讨论】:

  • 感谢链接它正在工作,但我不明白一些事情,我只是在我的应用程序的一个片段的onAttach 中调用了MyContextWrapper.warp,但语言已更改为整个应用程序,但活动标题没有改变,我认为这是因为清单标题优先,但如果我在我的应用程序子类上的onAttachBaseContex 中调用相同的方法,活动标题也会更改为所选语言,但随后更改仅应用于我在 warp 方法中调用的片段,这是为什么呢?
  • @AbhinavChauhan 我不确定这是否属实。我需要检查那个。实施此解决方案时,我从未遇到过此问题。但是,已经很久了,新版本的 Android 实现可能会有一些变化。或者在这篇文章中尝试一些最新的答案。
  • 我尝试了很多解决方案,但没有一个有效,或者我实施不正确,可能你的课程对活动很好,我在片段的onAttach 中使用它warp 方法,以前我说我只需要在整个应用程序中更改 mainactivity 片段和语言,这是真的,但是对于所有其他片段,在配置更改时语言更改为英语,所以我需要输入所有片段的 onattach 而不是清单我在代码中设置操作栏标题,现在应用程序按预期工作。谢谢
  • 好的!我相信您不必对每个屏幕都执行此操作,只需在启动的第一个活动和 attachBaseContext 函数内执行此操作即可。这适用于所有屏幕。您是否为应用中的所有活动创建了“BaseActivity”?
  • 不,我试图在我的应用程序子类中执行此操作,认为它将应用于整个应用程序,然后应用于所有片段,但事实证明需要执行 wrap() 代码在每次配置更改时,我将它放在所有其他活动扩展的抽象活动中,现在它正在工作
【解决方案3】:

以上@Uday 的所有代码都很完美,但只缺少一件事(build.gradle 中的默认配置)

public void setLocale(String lang) { 
Locale 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); 
finish();
startActivity(refresh); 

}

我的不工作只是因为配置文件(build.gradle)中没有提到语言

 defaultConfig {
    resConfigs "en", "hi", "kn"
}

之后,所有语言都开始运行

【讨论】:

  • 它不工作
  • 真的需要吗?
  • @JCarlosR 是的。当我在配置文件中添加语言时,Udhay 的代码开始运行
【解决方案4】:

您应该从清单中删除 android:configChanges="locale",这将导致活动重新加载,或者覆盖 onConfigurationChanged 方法:

@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
    // your code here, you can use newConfig.locale if you need to check the language
    // or just re-set all the labels to desired string resource
}

【讨论】:

  • 从清单中删除 android:configChanges="locale" 不会阻止应用重新启动。无论是否将其添加到清单中,它都会重新启动。
  • 我并不是说从清单中删除 android:configChanges="locale" 会阻止应用程序重新启动,我说的恰恰相反。现在,对于我们在清单中有 android:configChanges="locale" 的情况,它曾经在我写这个答案时阻止应用程序重新加载,我不能肯定现在是这种情况。
【解决方案5】:

使用上下文扩展的 Kotlin 解决方案

fun Context.applyNewLocale(locale: Locale): Context {
    val config = this.resources.configuration
    val sysLocale = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        config.locales.get(0)
    } else {
        //Legacy
        config.locale
    }
    if (sysLocale.language != locale.language) {
        Locale.setDefault(locale)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            config.setLocale(locale)
        } else {
            //Legacy
            config.locale = locale
        }
        resources.updateConfiguration(config, resources.displayMetrics)
    }
    return this
}

用法

override fun attachBaseContext(newBase: Context?) {
    super.attachBaseContext(newBase?.applyNewLocale(Locale("es", "MX")))
}

【讨论】:

    【解决方案6】:

    那些遇到版本问题的人试试这个代码..

    public static void switchLocal(Context context, String lcode, Activity activity) {
            if (lcode.equalsIgnoreCase(""))
                return;
            Resources resources = context.getResources();
            Locale locale = new Locale(lcode);
            Locale.setDefault(locale);
            android.content.res.Configuration config = new 
            android.content.res.Configuration();
            config.locale = locale;
            resources.updateConfiguration(config, resources.getDisplayMetrics());
            //restart base activity 
            activity.finish();
            activity.startActivity(activity.getIntent());
        }
    

    【讨论】:

      【解决方案7】:

      Udhay 的示例代码运行良好。除了 Sofiane Hassaini 和 Chirag SolankI 的问题,对于重入来说,它不起作用。在 super.onCreate(savedInstanceState); 之前,我尝试调用 Udhay 的代码而不重启 onCreate() 中的活动。然后就OK了! 只是有点小问题,菜单字符串还是没有改成设置的Locale。

          public void setLocale(String lang) { //call this in onCreate()
            Locale 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); 
            //finish();
          } 
      

      【讨论】:

      • 菜单字符串有同样的问题。你解决问题了吗?
      • @AlexS,我没有找到解决菜单字符串问题的方法。但是发现退出app再重新进入,菜单字符串可以正常改成新的Locale。
      • 你的意思是Intent refresh = new Intent(this, ThisActivity.class); startActivity(refresh); ?
      • @AlexS,不!添加新的 Intent() 和 startActivity() 可能会使其在重新启动应用程序时返回默认语言。我的意思是如果用户退出应用程序并重新进入应用程序,菜单字符串可以更改为新的区域设置。
      【解决方案8】:
          Locale locale = new Locale(langCode);
          Locale.setDefault(locale);
          Configuration configuration = context.getResources().getConfiguration();
          configuration.locale = locale;
          configuration.setLayoutDirection(locale); // for RTL changes
          preferences.setLocalePref(langCode);
          context.getResources().updateConfiguration(configuration, context.getResources().getDisplayMetrics());
      

      这里,langCode 是必需的语言代码。您可以将语言代码保存为 sharedPreferences 中的字符串。您可以在onCreate 中调用此代码super.onCreate(savedInstanceState)

      【讨论】:

        猜你喜欢
        • 2017-09-19
        • 2016-12-13
        • 1970-01-01
        • 2015-05-09
        • 2015-06-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-28
        相关资源
        最近更新 更多