Android 多语言

pexels-photo-268438

前段时间,刚换工作,因公司业务的关系,接触了 Android 多语言。

以前,从没考虑过国际化,所以对这块也是一知半解,借此机会就做一下整理。

多语言

Android 的多语言实现,大部分工作都交给了 framwork 层的资源进程调度框架,对于应用层的开发来说非常简单,得益于 Android 独特的资源文件管理方式,代码可以不和资源关联,通过 R 文件提供的索引来间接引用某一资源,所有只要在特定文件夹内提供对应的资源供系统调用就行啦。
简单来说,我们通常在 res-valuesstrings.xml 或者 arrays.xml文件中提供字符串资源,这里是提供默认资源的地方。如果需要添加台湾繁体,则需要新建 values-zh-rTW 的文件夹,以及提供台湾繁体的字符串资源文件strings.xml

多语言

values 文件夹的名称规则是 values-语言-地区 ,更多名称见下面的附录。

注意:不同语言的字符串资源的名称要一样,即索引要相同。

1
2
3
4
5
6
7
8
9
//默认的中文资源
<resources>
<string name="app_language">语言</string>
</resources>
//台湾繁体资源
<resources>
<string name="app_language">語言</string>
</resources>

如果在需要的资源目录下找不到对应的资源 ID,就会到默认文件夹内寻找,如果还找不到,就会报错。


全局查找替换

如果整个项目代码非常规范,所有的字符串资源都放在了strings.xml 或者arrays.xml中,那多语言就非常省心了。

但往往事与愿违,这个项目在我之前,已经经手四五个人了,编码风格迥异,代码规范就是没有规范,更加谈不上什么架构模式了、性能优化啦,所有东西都很随意,哎,都是泪~

说回正题,因此项目的字符串资源一部分在 strings.xml 中,更多的是散落在项目的各个角落,因此,第一步就是要将字符串资源统一整合到 strings.xml 或者 arrays.xml中。

刚开始还想着偷懒,写个脚本,寻找所有 xml 文件中的 android:text="xxxx" 然后替换,但项目中不仅仅是系统控件,还有一些自定义控件,命名空间和名称都不相同,如果是仅仅通过中文字符串匹配,那么一些注释怎样排除呢?同时代码中也有很多字符串,也有很多注释…….考虑到这么多复杂场景,如果哪位大牛能把这个脚本写出来,造福所有 Android 开发者,那就好啦~
算了,还是自己手动一个个替换吧~
打开全局搜索面板,输入 中文字符串的正则匹配

1
^((?!(\*|//)).)+[\u4e00-\u9fa5]

还可以根据需要进行过滤等操作。

全局搜索中文字符串

如果找到字符串,那么 AS 提供了非常方便的替换字符串的操作。
将光标移动到字符串位置,按下智能提示的快捷键(我的因按键冲突改过快捷键),选择Extract string resource 就能自动帮你完成操作了。这里盗了一个图,来看看效果。

extract_resource


翻译

如果将所有字符串资源都规范的整合到strings.xml 中,那么有很多插件,能帮我们一键完成翻译的工作。

比如:AndroidLocalizationerBaiduTranslationInternationalizatio
这个插件虽好,但也存在不少问题,首先是字符串中出现一些特殊字符,那么翻译出来就会大段大段错位,还是得手动一个个修改回去,非常麻烦。

因为是将简体中文翻译成繁体,所有有一个非常方便的方法,就是直接将strings.xml 中的内容扔进谷歌翻译,什么特殊字符啥的都不用担心,当然,这种方式仅限于简体转繁体。

google 翻译

当然,机器翻译都有一个问题,就是翻译都比较生硬。区域的不同导致同一个东西的叫法也有差异,比如内地人说「软件」,但台湾人习惯说「软体」。所以简繁体翻译并没有想象的那么简单,这里提供一个比较智能的简体与繁体转换的网站 简/繁体转换 ,效果比谷歌好很多。
相对于「简/繁体转换」,「中/英文转换」存在的问题就更多了,不仅仅是翻译正确与否的问题,字符串长度的变化还会引起页面排版的变化。
因此,相对好的做法就是先用机器翻译,然后人工核对翻译,最后运行起来看看排版效果,如果不行就再做调整。


多语言切换

这里的语言切换类似微信,是应用内的语言切换,和系统语言无关。

参照 Android 开发者官网 上的描述,Configuration 包含了设备的所有的配置信息,这些配置信息会影响应用获取的资源。例如 string 资源,就是根据 Configuration 的 locale 属性来判断该取哪种语言的 string 资源,默认是 value 文件夹下的。

主要代码如下:

1
2
3
4
5
Resources resources = context.getResources();
Configuration config = resources.getConfiguration();//获得设置对象
DisplayMetrics dm = resources.getDisplayMetrics();//获得屏幕参数:主要是分辨率,像素等。
config.locale = Locale.ENGLISH;//设置为英文
resources.updateConfiguration(config, dm);

在设置完语言后,并不会马上生效,必须重新启动页面。大多数都是做法是直接退出整个 APP,然后重新启动,这种做法有点粗暴,体检不好,微信的做法是重启回到主页面。

1
2
3
4
5
6
7
8
Intent intent = new Intent();
intent.setAction("android.intent.action.VIEW");
intent.setData(Uri.parse("app://trade"));
intent.setPackage(getPackageName()); //隐式启动时,最好指定包名
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | //清空当前栈
Intent.FLAG_ACTIVITY_NEW_TASK | //启动新栈
Intent.FLAG_ACTIVITY_CLEAR_TOP); // 清除当前页面
startActivity(intent);

项目因为组件化,这里采用隐式启动,但是这里有一个坑,因为保不齐,手机里面会有其符合要求的 Activity ,因此最好指定包名。

如果应用更改了语言,退出后再进来,还是会跟随系统,所有可以将语言类型用 SP 存起来,在刚刚进来时初始化语言。

我遇到一个问题是,在 application 中初始化语言不生效??? 只好又拿到 欢迎页去初始化了。
还有就是更换语言后,在 webview 页面退出来后会失效,因此只能在 onPoause() 时重新设置语言。


附录

多国语言文件夹命名对应表

国家 Folder Name
中文(中国) values-zh-rCN
中文(台湾) values-zh-rTW
中文(香港) values-zh-rHK
英语(美国) 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


参考

Android实现多语言so easy

Android-国际化(多语言)切换详解及实例

Android(国际化)多语言的实现和切换

Android App 多语言切换


坚持分享技术,但行好事,莫问前程 ~^o^~