用户选择语言时如何更改应用语言?


106

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

1)3个drawable文件夹drawable-es,drawable-pt,drawable。

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

我有imageView来选择语言。单击它时,将打开包含选项English,Spanish,Portuguese的菜单。

我通过此代码在选项选择中在应用内设置了语言环境

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

我在清单中声明了 android:configChanges =“ locale”

它可以工作,但是有一些问题。

问题:-

1)选择语言后,包含语言选择图像的画面不会改变,但其他画面会改变。

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


1
对于第二个问题,请尝试添加:android:configChanges="locale"在AndroidManifest.xml中添加您的Activity
Parth Doshi 2012年

我已经在清单中添加了所有活动。
mukesh 2012年

您可以使用下面的库,它提供的语言列表中,偏好设置屏幕,并覆盖在你的应用程序的语言:github.com/delight-im/Android-Languages
CAW

Answers:


172

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

当用户从语言列表中选择应用程序时,更改语言非常简单。有一种如下所示的方法,该方法将语言环境接受为String(例如,英语为“ 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”


2
当然可以。我可以提供该网页的摘录。我需要提供的地方请告诉我。谢谢。
Udhay

3
确保添加finish(),以便在导航堆栈中没有活动的两个副本。
Joel Teply 2015年

6
finish()需要先被调用startActivity(refresh)。否则,应用程序可能会退出,而不是重新启动活动。
穆罕默德·阿里

10
嗨,我做到了,它能正常工作,但是当我重新启动该应用程序时,它返回了默认语言..
Sofiane Hassaini 2016年

5
配置config =新配置(newConfig); config.locale =语言环境; 就我而言,收到此消息。API级别25中弃用的语言环境
Milon

9

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

创建您自己的CustomContextWrapper扩展类,ContextWrapper并使用它来更改整个应用程序的“语言环境”设置。 这是带有用法的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));
}

感谢您的链接它是工作,但我不明白一些事情,我只是叫MyContextWrapper.warponAttach只有一个我的应用程序的片段,但语言被改变了整个应用程序,但活动标题没有改变,我认为这是因为清单标题优先,但是如果我在onAttachBaseContex应用程序的子类上调用相同的方法,则活动标题也会更改为所选语言,但是更改仅适用于在warp方法中调用的片段,这是为什么?
Abhinav Chauhan

@AbhinavChauhan我不确定这是真的。我需要检查一下。当我实现此解决方案时,我从未遇到过这个问题。但是,已经很长时间了,对于较新版本的Android实现可能会有一些更改。或者尝试在此帖子上找到一些最新答案。
sud007

我尝试了许多解决方案,但其中任何一个都不起作用,或者我可能实施不正确,可能您的班级在活动中工作得很好,我在片段中使用它的warp方法onAttach,以前我说过,我只需要在mainactivity片段中进行操作,并更改语言整个应用程序都是正确的,但是对于所有其他片段,在配置更改时语言会更改为英语,因此我需要放入onattach所有片段,而不是清单我在代码中设置动作栏标题,现在该应用程序可以按预期运行。谢谢
Abhinav Chauhan

好的!我确定您不必在每个屏幕上都执行此操作,只需在启动的第一个活动内执行此attachBaseContext功能即可。这适用于所有屏幕。您是否为应用中的所有活动创建了“ BaseActivity”?
sud007

不,我在应用程序的子类中尝试这样做,认为它将应用于整个应用程序,然后应用于所有片段,但是事实证明,wrap()每次配置更改时都需要执行代码,因此我将其放在抽象活动将扩展其他所有活动,现在它正在运行
Abhinav Chauhan

6

您应该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”不会阻止应用重启。无论是否将其添加到清单中,它都会重新启动。
portfoliobuilder

我并不是说从清单中删除android:configChanges =“ locale”会阻止应用程序重启,而是相反。现在,对于清单中有android:configChanges =“ locale”的情况,它用来防止在我编写此答案时重新加载应用程序,我不能肯定现在就是这种情况。
Frane Poljak

6

以上所有@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"
}

之后,所有语言开始运行


3
它不起作用
Krunal Shah

真的需要吗?
JCarlosR

1
@JCarlosR是的。当我在配置文件中添加语言时,Udhay的代码开始运行
Lokesh Tiwari

3

那些获得版本问题的人可以尝试以下代码..

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

2

Udhay的示例代码效果很好。除了Sofiane Hassaini和Chirag SolankI的问题之外,对于重新进入,它是行不通的。我尝试调用Udhay的代码,而无需在super.onCreate(savedInstanceState);之前重新启动onCreate()中的活动。那就可以了!只是一个小问题,菜单字符串仍然没有更改为设置的区域设置。

    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

@AlexS,我没有找到方法来解决菜单字符串中的问题。但是发现退出应用程序然后重新输入,菜单字符串通常可以更改为新的区域设置。
费舍尔

你的意思是Intent refresh = new Intent(this, ThisActivity.class); startActivity(refresh);
AlexS

2
@AlexS,不!重新启动应用程序时,添加新的Intent()和startActivity()可能使其返回默认语言。我的意思是,如果用户退出应用程序并重新进入应用程序,则菜单字符串可以更改为新的区域设置。
Fisher
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.