前段时间,刚换工作,因公司业务的关系,接触了 Android 多语言。
以前,从没考虑过国际化,所以对这块也是一知半解,借此机会就做一下整理。
Android 的多语言实现,大部分工作都交给了 framwork 层的资源进程调度框架,对于应用层的开发来说非常简单,得益于 Android 独特的资源文件管理方式,代码可以不和资源关联,通过 R 文件提供的索引来间接引用某一资源,所有只要在特定文件夹内提供对应的资源供系统调用就行啦。
简单来说,我们通常在 res-values
的strings.xml
或者 arrays.xml
文件中提供字符串资源,这里是提供默认资源的地方。如果需要添加台湾繁体,则需要新建 values-zh-rTW
的文件夹,以及提供台湾繁体的字符串资源文件strings.xml
。
values
文件夹的名称规则是 values-语言-地区
,更多名称见下面的附录。
注意:不同语言的字符串资源的名称要一样,即索引要相同。
//默认的中文资源
<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 开发者,那就好啦~
算了,还是自己手动一个个替换吧~
打开全局搜索面板,输入 中文字符串的正则匹配
^((?!(\*|//)).)+[\u4e00-\u9fa5]
还可以根据需要进行过滤等操作。
如果找到字符串,那么 AS 提供了非常方便的替换字符串的操作。
将光标移动到字符串位置,按下智能提示的快捷键(我的因按键冲突改过快捷键),选择Extract string resource
就能自动帮你完成操作了。这里盗了一个图,来看看效果。
如果将所有字符串资源都规范的整合到strings.xml
中,那么有很多插件,能帮我们一键完成翻译的工作。
比如:AndroidLocalizationer 、BaiduTranslationInternationalizatio
这个插件虽好,但也存在不少问题,首先是字符串中出现一些特殊字符,那么翻译出来就会大段大段错位,还是得手动一个个修改回去,非常麻烦。
因为是将简体中文翻译成繁体,所有有一个非常方便的方法,就是直接将strings.xml
中的内容扔进谷歌翻译,什么特殊字符啥的都不用担心,当然,这种方式仅限于简体转繁体。
当然,机器翻译都有一个问题,就是翻译都比较生硬。区域的不同导致同一个东西的叫法也有差异,比如内地人说「软件」,但台湾人习惯说「软体」。所以简繁体翻译并没有想象的那么简单,这里提供一个比较智能的简体与繁体转换的网站 简/繁体转换 ,效果比谷歌好很多。
相对于「简/繁体转换」,「中/英文转换」存在的问题就更多了,不仅仅是翻译正确与否的问题,字符串长度的变化还会引起页面排版的变化。
因此,相对好的做法就是先用机器翻译,然后人工核对翻译,最后运行起来看看排版效果,如果不行就再做调整。
这里的语言切换类似微信,是应用内的语言切换,和系统语言无关。
参照 Android 开发者官网 上的描述,Configuration 包含了设备的所有的配置信息,这些配置信息会影响应用获取的资源。例如 string 资源,就是根据 Configuration 的 locale 属性来判断该取哪种语言的 string 资源,默认是 value 文件夹下的。
主要代码如下:
Resources resources = context.getResources();
Configuration config = resources.getConfiguration();//获得设置对象
DisplayMetrics dm = resources.getDisplayMetrics();//获得屏幕参数:主要是分辨率,像素等。
config.locale = Locale.ENGLISH;//设置为英文
resources.updateConfiguration(config, dm);
在设置完语言后,并不会马上生效,必须重新启动页面。大多数都是做法是直接退出整个 APP,然后重新启动,这种做法有点粗暴,体检不好,微信的做法是重启回到主页面。
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 多语言切换