Android 应用内多语言切换

p.p1 { margin: 0.0px 0.0px 12.0px 0.0px; line-height: 18.0px; font: 12.0px ".PingFang SC"; color: #000000 }
p.p3 { margin: 0.0px 0.0px 13.9px 0.0px; line-height: 18.0px; font: 16.8px "PT Sans"; color: #000000 }
p.p4 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 12.0px Courier; color: #000000 }
p.p5 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 12.0px Courier; color: #000000; min-height: 14.0px }
p.p6 { margin: 0.0px 0.0px 12.0px 0.0px; line-height: 18.0px; font: 12.0px Courier; color: #000000 }
p.p7 { margin: 0.0px 0.0px 14.4px 0.0px; line-height: 18.0px; font: 14.4px "PT Sans"; color: #000000 }
li.li1 { margin: 0.0px 0.0px 12.0px 0.0px; line-height: 18.0px; font: 12.0px ".PingFang SC"; color: #000000 }
li.li2 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 12.0px ".PingFang SC"; color: #000000 }
li.li4 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 12.0px Courier; color: #000000 }
li.li6 { margin: 0.0px 0.0px 12.0px 0.0px; line-height: 18.0px; font: 12.0px Courier; color: #000000 }
span.s1 { }
span.s2 { font: 12.0px Courier }
span.s3 { font: 12.0px ".PingFang SC" }
span.s4 { font: 12.0px ".PingFang SC" }
span.s5 { font: 12.0px Courier }
span.s6 { text-decoration: underline; color: #0000ee }
ol.ol1 { list-style-type: decimal }

最近公司的 App 里需要用到多语言切换,简单来说,就是如果用户没有选择语言选项时,App 默认跟随系统语言,如果用户在 App 内进行了语言设置,那么就使用用户设置的语言。当然,你会发现,App 的语言切换也会导致加载的其它资源文件进行切换

上述内容大概可以分为以下几块:

  1. 获取系统默认的语言和地区(注意地区,后面会讲述这里的坑)
  2. 更改 App 的语言

Android 应用资源国际化

在正式开始之前,先来讲解一下 Android 应用资源国际化的知识。对于资源文件的国际化,我们一般是在 Android src/main/res/ 目录下,建立对应语言文件夹,格式一般为:values-语言代号-地区代号,默认的资源是不包含语言代号和地区代号的。一般情况下,应用资源是没有做任何适配的,所以不管如何切换语言和地区设置,应用显示的资源都不会发生任何改变。

配置选项包括语言代号地区代号。表示中文和中国的配置选项是 zh-rCN(zh表示中文,CN表示中国)。表示英文和美国的配置选项是 en-rUS(en表示英文,US表示美国)。同一语言代号可以有多个地区代号,用 r 表示区分。

常见的国际化资源表示形式:

中文(中国):values-zh-rCN

中文(台湾):values-zh-rTW

中文(香港):values-zh-rHK

维吾尔文(中国):values-ug-rCN

英语(美国):values-en-rUS

英语(英国):values-en-rGB

英文(澳大利亚):values-en-rAU

英文(加拿大):values-en-rCA

英文(爱尔兰):values-en-rIE

英文(印度):values-en-rIN

英文(新西兰):values-en-rNZ

英文(新加坡):values-en-rSG

英文(南非):values-en-rZA

阿拉伯文(埃及):values-ar-rEG

阿拉伯文(以色列):values-ar-rIL

保加利亚文:  values-bg-rBG

加泰罗尼亚文:values-ca-rES

捷克文:values-cs-rCZ

丹麦文:values-da-rDK

德文(奥地利):values-de-rAT

德文(瑞士):values-de-rCH

德文(德国):values-de-rDE

德文(列支敦士登):values-de-rLI

希腊文:values-el-rGR

西班牙文(西班牙):values-es-rES

西班牙文(美国):values-es-rUS

芬兰文(芬兰):values-fi-rFI

法文(比利时):values-fr-rBE

法文(加拿大):values-fr-rCA

法文(瑞士):values-fr-rCH

法文(法国):values-fr-rFR

希伯来文:values-iw-rIL

印地文:values-hi-rIN

克罗里亚文:values-hr-rHR

匈牙利文:values-hu-rHU

印度尼西亚文:values-in-rID

意大利文(瑞士):values-it-rCH

意大利文(意大利):values-it-rIT

日文:values-ja-rJP

韩文:values-ko-rKR

立陶宛文:valueslt-rLT

拉脱维亚文:values-lv-rLV

挪威博克马尔文:values-nb-rNO

荷兰文(比利时):values-nl-BE

荷兰文(荷兰):values-nl-rNL

波兰文:values-pl-rPL

葡萄牙文(巴西):values-pt-rBR

葡萄牙文(葡萄牙):values-pt-rPT

罗马尼亚文:values-ro-rRO

俄文:values-ru-rRU

斯洛伐克文:values-sk-rSK

斯洛文尼亚文:values-sl-rSI

塞尔维亚文:values-sr-rRS

瑞典文:values-sv-rSE

泰文:values-th-rTH

塔加洛语:values-tl-rPH

土耳其文:values–r-rTR

乌克兰文:values-uk-rUA

越南文:values-vi-rVN

获取系统默认的语言和地区

总的来说,获取语言和地区有三种方法:

  1. 通过 Java 自带的接口来实现,即:Locale locale = Locale.getLocale();
  2. String language = locale.getLanguage();
  3. String country = locale.getCountry();
  4. 通过 Configuration 来获取//方法1,该方法已废弃,如果在 API >= 17 的版本上使用 方法2
  5. Locale locale = context.getResources().getConfiguration().locale;
  6. //方法2,在 API >= 17 的版本上可以使用
  7. Locale locale = context.getResources().getConfiguration().getLocales().get(0);
  8. String language = locale.getLanguage();
  9. String country = locale.getCountry();
  10. 其中, context.getResources() 也可以用 Resources.getSystem() 来代替,前者获取的是应用内部的语言和地区设置,后者获取的是系统的语言地区设置,默认情况下,前者跟随系统设置。

更改 App 的语言设置

通过上述分析,我们已经知道怎么获取系统和应用的语言地区设置了。接下来,我们来讲一下如何实现 Android App 的多语言切换。在前面我们已经使用到了 Configuration ,这个类保存了 Android 应用的所有设备信息,详见 Configuration。要实现应用的多语言切换,我们所要做的就是更新 Configuration 中关于语言地区的属性。

Resources resources = context.getResources();

DisplayMetrics metrics = resources.getDisplayMetrics();

Configuration configuration = resources.getConfiguration();

//API >= 17 可以使用

configuration.setLocale(locale);

//该方法已经废弃,官方建议使用 Context.createConfigurationContext(Configuration)

resources.updateConfiguration(configuration, metrics);

资源目录结构大致如下:

│   └── res

│       ├── drawable

│       ├── drawable-xhdpi

│       │   └── icon_test.png

│       ├── drawable-zh-rCN-xhdpi//图标适配

│       │   └── icon_test.png

│       ├── layout

│       │   └── activity_main.xml

│       ├── mipmap-hdpi

│       │   └── ic_launcher.png

│       ├── mipmap-mdpi

│       │   └── ic_launcher.png

│       ├── mipmap-xhdpi

│       │   └── ic_launcher.png

│       ├── mipmap-xxhdpi

│       │   └── ic_launcher.png

│       ├── mipmap-xxxhdpi

│       │   └── ic_launcher.png

│       ├── values

│       │   ├── colors.xml

│       │   ├── strings.xml

│       │   └── styles.xml

│       ├── values-en-rWW

│       │   └── strings.xml

│       ├── values-ja-rJP

│       │   └── strings.xml

│       ├── values-ko-rKR

│       │   └── strings.xml

│       └── values-zh-rCN

│           └── strings.xml

重新加载资源

看到这里,你是不是觉得就结束了?不,当然不是,更新 Configuration 之后,如果不重启 Activity,应用的资源就不会被重新加载。

Intent intent = new Intent(this, MainActivity.class);

//开始新的activity同时移除之前所有的activity

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

startActivity(intent);

持久化存储设置

经过上述步骤,我们已经可以看到应用显示的资源发生了改变,但是当应用被杀掉重启后,之前所有的设置都已经失效,应用的语言地区又变成了系统默认的,这是因为我们对应用所做的变更只是保存在内存中,当应用被杀掉,在内存中的数据也随之被释放,再次启动应用的时候,应用读取的是系统的 Configuration ,语言地区也随之变成系统默认的。

当应用需要保存用户更改的操作,就需要对用户的选择进行持久化,并在应用重启的时候,从配置中读取并应用该配置。

public class MyApplication extends Application {

@Override

public void onCreate() {

super.onCreate();

//一般在 Application 的 onCreate() 方法中更新 Configuration

LanguageUtil.changeAppLanguage(this, Locale.SIMPLIFIED_CHINESE, true);

}

}

LanguageUtil.java

/**

* 更改应用语言

*

* @param context

* @param locale 语言地区

* @param persistence 是否持久化

*/

public static void changeAppLanguage(Context context, Locale locale,

boolean persistence) {

Resources resources = context.getResources();

DisplayMetrics metrics = resources.getDisplayMetrics();

Configuration configuration = resources.getConfiguration();

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

configuration.setLocale(locale);

} else {

configuration.locale = locale;

}

resources.updateConfiguration(configuration, metrics);

if (persistence) {

saveLanguageSetting(context, locale);

}

}

private static void saveLanguageSetting(Context context, Locale locale) {

String name = context.getPackageName() + "_" + LANGUAGE;

SharedPreferences preferences =

context.getSharedPreferences(name, Context.MODE_PRIVATE);

preferences.edit().putString(LANGUAGE, locale.getLanguage()).apply();

preferences.edit().putString(COUNTRY, locale.getCountry()).apply();

}

这样,Android 应用内多语言切换基本完工。接下来,分享一下我在多语言切换过程中遇到的坑。

多语言切换中遇到的坑

  1. 以静态变量的方式,在 Application 初始化时初始化网络请求错误提示语,然后再系统中切换语言后,网络请求错误提示语未更新。解决办法:使用时直接通过 getString() 方法获取
  2. App 多语言切换设置持久化后,在应用启动时, Application 的 onCreate() 中也进行了多语言切换。然后去系统设置中切换语言,App 也会随之跟随系统语言。原因:在我们改变系统的语言时,应用的 Configuration 也随之跟随系统改变,而不是我们启动应用时的设置了解决办法:监听 Activity 的生命周期,在 Activty 的 onCreate() 中判断应用当前的语言设置是否与用户设置值相同,否则强制更新应用语言设置。因为,当系统切换语言选项的时候,系统会重启 Activity,就如前文所说,我们需要重启 Activity 才能实现资源的重新加载一样。这里也有两种方案:
    1. 创建一个基类 BaseActivity ,在其 onCreate() 方法中做处理
    2. 使用 ActivityLifecycleCallbacks ,在其回调 onActivityCreated() 中做处理
  3. 对比一下,上述两种方案,第一种只能针对继承自 BaseActivity 的才有效,第二种则是监听所以 Activity 的生命周期。所以相对而言,第二种方案更好点。/**
  4. * 判断是否与设定的语言相同.
  5. *
  6. * @param context
  7. * @return
  8. */
  9. public static boolean isSameWithSetting(Context context) {
  10. Locale current = context.getResources().getConfiguration().locale;
  11. return current.equals(getAppLocale(context));
  12. }
  13. public class App extends Application {
  14. @Override
  15. public void onCreate() {
  16. super.onCreate();
  17. LanguageUtil.init(this);
  18. //注册Activity生命周期监听回调
  19. registerActivityLifecycleCallbacks(callbacks);
  20. }
  21. ActivityLifecycleCallbacks callbacks = new ActivityLifecycleCallbacks() {
  22. @Override
  23. public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
  24. //强制修改应用语言
  25. if (!LanguageUtil.isSameWithSetting(activity)) {
  26. LanguageUtil.changeAppLanguage(activity,
  27. LanguageUtil.getAppLocale(activity));
  28. }
  29. }
  30. //Activity 其它生命周期的回调
  31. };
  32. }
  33. 对于在 AndroidManifest.xml 中配置 launchMode 为 singleInstance 的 Activity,使用Intent intent = new Intent(this, MainActivity.class);
  34. //开始新的activity同时移除之前所有的activity
  35. intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
  36. startActivity(intent);
  37. 资源文件不更新。原因:launchMode 为 singleInstance 的 Activity 与当前应用时不在同一个 Task 栈解决方法:将 launchMode 改为其它模式或者杀掉应用重新启动
  38. 资源文件夹为 values-zh-rCN时,将应用 Locale 设置为 Locale.CHINESE 时,找不到对应的资源文件。原因:values-zh-rCN 对应的 Locale 为 Locale.SIMPLIFIED_CHINESE解决办法:将 Locale 设置为 Locale.SIMPLIFIED_CHINESE 或者将资源文件改为 values-zh这是踩得最惨的一个坑,浪费了大量时间,所以才会有开头 Android 应用资源国际化 那么一小节插曲。

代码已上传 Git,欢迎大家 Star 和 Fork

时间: 2024-08-01 18:11:14

Android 应用内多语言切换的相关文章

Android应用实现多语言切换

关于Android应用实现多语言切换,有好几种办法,网上也搜到很多资料,这里有个简单有效的办法. 步骤如下: 在资源文件中新建一个文件夹values-en,在里面新建一个strings.xml,把默认values文件夹中的strings.xml中的内容拷贝一份到values-en中的strings.xml,再把该文件夹中的中文内容转换为英文,例如<string name="set">设置</string>转换为<string name="set&

Android app应用多语言切换功能实现

最近在做一个多语言切换的功能,类似于微信的语言切换,搜了下资料基本上都是以下这种: 1. 实现的效果 和微信类似,在设置界面打开切换语言的界面,选择语言后重启 HomeActivity,语言切换完成,下次重新打开 App ,也是用户设置的语言. 2. 实现步骤 1. 添加多语言文件 在不同的 value 文件夹下(例如 value .value-en.values-zh-rTW 文件夹)添加不同语言的 string.xml 文件,我们的项目添加了英文.简体中文.繁体中文三种语言,如下图所示: 其

Android应用内语言切换实现

自定义控件系列结束了,打个回马枪,补上前段时间埋下的一个坑---"应用内语言切换".APP语言改变是一个Configuration,但是这个Configuration和android手机屏幕旋转有点不大一样.屏幕旋转的时候,会destroy当前页面,并进行重新绘制.而切换语言后不会重新绘制页面,所以这种情况的出现造成了网上的一知半解小伙伴们哀声一片,不是在咒骂api的坑爹,就是在卖力的另辟蹊径想尽办法解决问题.思路都是很好的,目的也是坚决的,可是方向是错误的,把哥哥我也给带进了坑了,爬

Android 应用内切换语言

extends :http://bbs.51cto.com/thread-1075165-1.html,http://www.cnblogs.com/loulijun/p/3164746.html 1. 多国语言: 在res目录下建立不同名称的values文件来调用不同的语言包Values文件汇总如下:中文(中国):values-zh-rCN中文(台湾):values-zh-rTW中文(香港):values-zh-rHK英语(美国):values-en-rUS英语(英国):values-en-r

Android应用语言切换功能

因为公司的产品大部分是销售到国外的,所以领导要求app有语言切换功能.我在网上搜了些相关知识并实现了功能,在这里做个中英文切换的demo记录下来. 先看看demo的效果: 效果就是这样子.当然也可以做成其他语言的切换,具体根据需求而定. 原理其实很简单,就是多个strings.xml进行切换然后在刷新Activity. 首先,在AndroidManifest.xml文件中的每个需要切换语言的Activity中加入android:configChanges="locale". 然后在re

android 语言切换过程分析 (zhuan)

最近在看一个bug,系统切换语言后,本来退到后台的音乐,会在通知栏上显示通知.为了解决这个bug,我学习了下android的语言切换流程,也参考了大量其他人的资料.(主要参考了http://blog.csdn.net/wqhjfree/article/details/8244520)在这里我将自己的探索记录下来,作为自己的学习记录,也希望能对有同样需要的人有个帮助.刚学android不久,如果中间有什么问题不对的请多多谅解,并指出错误,多交流,共同进步下. 1.从setting入手,我们可以知道

【Android 多语言切换简单实例分享】

一.Android多语言切换 Android应用的开发不可能只针对某一个国家或者区域使用,各国间语言文化各不相同,因此一个优秀的APP必须支持多种语言,为了实现这个特性,Android给出了一个解决方式,在res目录下通过values+语言编码来实现多国语言的支持(中间采用连字符号-连接),例如:values-es代表英文,如果你决定了你的应用要支持多国语言,那么你就必须新建多种values-XXX的多语言支持文件,下面通过一个例子来看看基本的使用方式,先看下效果图: 1.工程结构 注:主要看下

android实现多语言切换

在安卓开发中,常会遇到需要切换不同语言的情况.语言不同意味着需要进行不同语种字符的动态切换.不同布局的动态切换. 安卓实现这一功能非常的简单: 首先在res中创建其它语种对应的value.layout等文件夹,比如添加英文版和越南版,命名如value-en-US.value-vi.layout-en-US.layout-vi. 命名规则在网上可以查到,value-en-US中,en表示英文,US表示美国.国家可不写.越南版可全写为layout-vi-VN. 如此,便有了几套同名,同id,但内容属

iOS应用内语言切换功能

? 添加关注 作者 FarmGuo 2016.01.27 15:36* 写了6453字,被44人关注,获得了56个喜欢 iOS应用内语言切换功能 字数1372 阅读681 评论7 喜欢7 当我们的应用仅仅面向国内用户群,一般仅支持一种语言--中文就可以了.当面向国外用户时就需要进行国际化了,不仅仅是语言的转变,也可能包括设计风格,页面布局.交互效果的转变,如微信,微博,QQ这类应用都有着切换语言的功能. iOS常用的国际化流程 1.建立strings文件.2.在Localization勾选支持的