AndroidStudio一键国际化方案

news/2024/11/25 15:35:51/

预研

国际化对于只做国内市场的小伙伴来说基本没有太多感觉,但是对于做国外市场特别是谷歌市场的朋友来说却是需要重视的一个知识点。因为海外市场面对的全球的客户,而如果人工翻译势必很费时费力而且低效,这时候我们需要程序化来实现这个体力活。

有几种方案,一种是自己写一个程序或者脚本,接入翻译的api,比如google或者有道实现自动化查询转换。还有一种是拿现成的,这显然不知我有这个需求,大部分大众需求网上有热心朋友会做好,于是我选择第二种。

但是对于稍微大一点的公司来说,主要考虑的是分工的问题,而且要保证结果的准确性,用线上翻译软件不见得会有多准确,多数公司对翻译要求比较高,需要单独核对,而他们核对翻译通常不是在ide中,而是希望能有一个excel文件来存放对应的翻译数据,这个时候用一件翻译不见得是好事,那就要采用另外一种方法了,这个在后面会介绍。

通过插件实现国际化

选择国际化插件

如果我们在百度或者google上搜索Android Studio国际化,会有很多文章介绍如何实现国际化,但是大部分的文章并不一定奏效。当然我们自己也可以在Android Studio带的插件市场上搜索安装,最后我锁定在AndroidLocalizationer。

通常我找一个别人做好的工具,我会关注三点:

  1. 用的人多不多
  2. 更新的频次够不够高
  3. 现在是否还在维护

当然这都是出于实用主义,道理很简单,但是这三点再给我们找三方工具上会让我们少走很多弯路。

实际上我在Android studio上安装该插件后,我按照介绍说的右击string文件,他并没有生效而是弹出了一个警示框,然后没有了。开始我以为是网络问题,于是我连续试了两个梯子,全局代理都用了,并不能解决问题,于是我开始怀疑是不是版本错误了。

幸运的是,我在github上找到这个开源库并下载了旧版的release,然后神奇的发现旧版本的是可以用的。我这里用的是1.5,大概是两年前了吧,但是确实是蛮好用的,所以有时候最新的不一定好用,因为它有一些坑,而他的新功能我们自己又不一定用得到,所以大家要注意鉴别。

各国简称对照

简称/语言简称/语言简称/语言简称/语言
aa 阿法尔语fr 法语li 林堡语se 北萨米语
ab 阿布哈兹语fy 弗里西亚语ln 林加拉语sg 桑戈语
ae 阿维斯陀语ga 爱尔兰语lo 老挝语sh 塞尔维亚-克罗地亚语
af 南非语gd 苏格兰盖尔语lt 立陶宛语si 僧加罗语
ak 阿坎语gl 加利西亚语lu 卢巴语sk 斯洛伐克语
am 阿姆哈拉语gn 瓜拉尼语lv 拉脱维亚语sl 斯洛文尼亚语
an 阿拉贡语gu 古吉拉特语mg 马达加斯加语sm 萨摩亚语
ar 阿拉伯语gv 马恩岛语mh 马绍尔语sn 绍纳语
as 阿萨姆语ha 豪萨语mi 毛利语so 索马里语
av 阿瓦尔语he 希伯来语mk 马其顿语sq 阿尔巴尼亚语
ay 艾马拉语hi 印地语ml 马拉亚拉姆语sr 塞尔维亚语
az 阿塞拜疆语ho 希里莫图语mn 蒙古语ss 斯瓦特语
ba 巴什基尔语hr 克罗地亚语mo 摩尔达维亚语st 南索托语
be 白俄罗斯语ht 海地克里奥尔语mr 马拉提语su 巽他语
bg 保加利亚语hu 匈牙利语ms 马来语sv 瑞典语
bh 比哈尔语hy 亚美尼亚语mt 马耳他语sw 斯瓦希里语
bi 比斯拉马语hz 赫雷罗语my 缅甸语ta 泰米尔语
bm 班巴拉语ia 国际语A na 瑙鲁语te 泰卢固语
bn 孟加拉语id 印尼语nb 书面挪威语tg 塔吉克斯坦语
bo 藏语ie 国际语E nd 北恩德贝勒语th 泰语
br 布列塔尼语ig 伊博语ne 尼泊尔语ti 提格里尼亚语
bs 波斯尼亚语ii 四川彝语(诺苏语) ng 恩敦加语
ca 加泰隆语ik 依努庇克语nl 荷兰语tl 他加禄语
ce 车臣语io 伊多语nn 新挪威语tn 塞茨瓦纳语
ch 查莫罗语is 冰岛语no 挪威语to 汤加语
co 科西嘉语it 意大利语nr 南恩德贝勒语tr 土耳其语
cr 克里语iu 因纽特语nv 纳瓦霍语ts 宗加语
cs 捷克语ja 日语ny 尼扬贾语tt 塔塔尔语
cu 古教会斯拉夫语jv 爪哇语oc 奥克语tw 特威语
cv 楚瓦什语ka 格鲁吉亚语oj 奥吉布瓦语ty 塔希提语
cy 威尔士语kg 刚果语om 奥洛莫语ug 维吾尔语
da 丹麦语ki 基库尤语or 奥利亚语uk 乌克兰语
de 德语kj 宽亚玛语os 奥塞梯语ur 乌尔都语
dv 迪维希语kk 哈萨克语pa 旁遮普语uz 乌兹别克语
dz 不丹语kl 格陵兰语pi 巴利语ve 文达语
ee 埃维语km 高棉语pl 波兰语vi 越南语
el 现代希腊语kn 卡纳达语ps 普什图语vo 沃拉普克语
en 英语ko 朝鲜语、韩语pt 葡萄牙语
eo 世界语kr 卡努里语qu 凯楚亚语wo 沃洛夫语
es 西班牙语ks 克什米尔语rm 罗曼什语xh 科萨语
et 爱沙尼亚语ku 库尔德语rn 基隆迪语yi 依地语
eu 巴斯克语kv 科米语ro 罗马尼亚语yo 约鲁巴语
fa 波斯语kw 康沃尔语ru 俄语za 壮语
ff 富拉语ky 吉尔吉斯语rw 卢旺达语zh 中文、汉语
fi 芬兰语la 拉丁语sa 梵语zu 祖鲁语
fj 斐济语lb 卢森堡语sc 萨丁尼亚语
fo 法罗语lg 卢干达语sd 信德语

各国语言对照

国家/地区语言代码国家/地区语言代码
简体中文(中国)zh-cn繁体中文(台湾地区)zh-tw
繁体中文(香港)zh-hk英语(香港)en-hk
英语(美国)en-us英语(英国)en-gb
英语(全球)en-ww英语(加拿大)en-ca
英语(澳大利亚)en-au英语(爱尔兰) en-ie
英语(芬兰)en-fi芬兰语(芬兰)fi-fi
英语(丹麦)en-dk丹麦语(丹麦)da-dk
英语(以色列)en-il希伯来语(以色列)he-il
英语(南非)en-za英语(印度)en-in
英语(挪威)en-no英语(新加坡)en-sg
英语(新西兰)en-nz英语(印度尼西亚)en-id
英语(菲律宾)en-ph英语(泰国)en-th
英语(马来西亚)en-my英语(阿拉伯)en-xa
韩文(韩国)ko-kr日语(日本)ja-jp
荷兰语(荷兰)nl-nl荷兰语(比利时)nl-be
葡萄牙语(葡萄牙)pt-pt葡萄牙语(巴西)pt-br
法语(法国)fr-fr法语(卢森堡)fr-lu
法语(瑞士)fr-ch法语(比利时)fr-be
法语(加拿大)fr-ca西班牙语(拉丁美洲) es-la
西班牙语(西班牙)es-es西班牙语(阿根廷)es-ar
西班牙语(美国)es-us西班牙语(墨西哥)es-mx
西班牙语(哥伦比亚)es-co 西班牙语(波多黎各) es-pr
德语(德国)de-de德语(奥地利)de-at
德语(瑞士)de-ch俄语(俄罗斯)ru-ru
意大利语(意大利)it-it 希腊语(希腊) el-gr
挪威语(挪威)no-no匈牙利语(匈牙利)hu-hu
土耳其语(土耳其)tr-tr捷克语(捷克共和国) cs-cz
斯洛文尼亚语sl-sl波兰语(波兰)pl-pl
瑞典语(瑞典)sv-se西班牙语 (智利)es-cl
越南vi_VN

执行

由于通过http实现转换,因此转换的时候会比较慢,大家尽量只勾选需要发布的那几个国家就行。

插件只会显示简称,因此注意对照上面的表执行。

通过读取Excel生成string

相比于上面的一键生成,这种方式要麻烦很多,但确实是很多大公司使用的方式,因为这种方式分工明确,准确度高,所以如果对翻译要求比较高的团队还是推荐使用这种方法。

这里分为三步骤:

  • 编写对应格式的Excel文档
  • 使用脚本解析
  • 使用脚本自动复制替换项目中的string

Excel格式定义

网上的普遍做法是将翻译好的数据卸载excel文件中,格式基本都是下面这样:
在这里插入图片描述

注意:excel文件的编写是由格式要求的,主要体现为:

  1. 前面是对应字符串的需要,用于生成string名字的
  2. 里面的内容如果有占位符,是通过&value的方式,具体对照下面的脚本文件可自行修改称自己的格式。
  3. 纵向是各语言对应的翻译。

执行转换脚本

然后通过编写脚本文件读取对应的行和列,写入到string文件中。使用的预研可能是Java也可能是python,用这两种语言的都不少。以python为例:

import xlrd
import re
import os#配置了多国语言的xls文件,必须是xls后缀名的文件 */
sourceFile = os.path.abspath('my.xlsx')
#输出文件夹 */
enterDir = os.path.abspath(os.path.dirname(sourceFile) + os.path.sep + ".")
#第几张表 */
sheetNum = ( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11, 12, 13, 14, 15, 16, 17, 19, 21, 22, 23, 25, 26, 27, 28, 29, 30,31, 32, 33, 34, 35, 36, 37, 38, 39, 40);localeMap = {'简体中文':'zh-rCN','English':'en-rUS','Deutsch':'de-rDE','法语':'fr-rFR','Spanish':'es-rES','捷克语':'cs-rCZ','保加利亚语':'bg-rBG','罗马尼亚语':'ro-rRO','葡萄牙':'pt-rPT','Italian':'it-rIT'}isSkip = True
skipSet = ("s14_38", "s22_22", "s23_19")def write():# 构建Workbook对象, 只读Workbook对象# 直接从本地文件创建Workbookreadwb = xlrd.open_workbook(sourceFile)# Sheet的下标是从0开始# 获取第一张Sheet表list = []for i in range(len(sheetNum)):readsheet = readwb.sheets()[sheetNum[i]]prefix = "s" + str(sheetNum[i]) + "_"# 获取Sheet表中所包含的总列数columns = readsheet.ncols# 获取Sheet表中所包含的总行数rows = readsheet.nrowsfor index in range(columns):list.append(XmlObj())for row in range(rows):for col in range(columns):cell = readsheet.cell(row, col)name = "s"cell0Row = str(readsheet.cell(row, 0).value)reg = "\\d+";p = re.compile(reg)num = ""nums = p.findall(cell0Row)if nums:# 只找到最后的数字num = nums[0]name = prefix + numif isSkip and name in skipSet:continue;if row != 1 and isEmpty(num):continuevalue = str(cell.value)#替换换行value = value.replace("\n", "\\n")if "&value&" in value or "& value &" in value:value = value.replace("%", "%%")value = re.sub("& *value *&", "%1$s", value)value = re.sub("& *value1 *&", "%1$s", value)value = re.sub("& *value2 *&", "%2$s", value)value = re.sub("& *value3 *&", "%3$s", value)value = re.sub("& *value4 *&", "%4$s", value)value = value.replace("&", "&amp;")value = value.replace("<br>", "\\n")value = value.replace("\"", "\\\"")value = value.replace("'", "\\'")value = value.replace("@", "\\@")hasHtmlTag = "<span " in valuer = re.compile(".*\\[.*].*")match = r.match(value)if match:value = value.replace("\\n", "<br>")value = value.replace("[", "<a href=\"{url}\">")value = value.replace("]", "</a>")hasHtmlTag = Trueif hasHtmlTag:value = "<![CDATA[" + value + "]]>"if row == 1:list[col].fileName = localeMap.get(value, value)else:if isEmpty(list[col].fileName) or isEmpty(value) and list[col].fileName != 'en-rUS':continueenter = Trueif row == rows - 1:enter = Falselist[col].content = list[col].content + getTag(name, value, enter)for item in list:if isEmpty(item.fileName):continuewriteXml(item.fileName, item.content)print("success")returndef writeXml(fileName,str):dir = enterDir + "/语言/" + fileNameif not os.path.exists(dir):os.makedirs(dir)f = open(dir + "/" + "strings.xml", "w+", encoding="utf-8")f.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n" + str + "</resources>\n")f.closedef getTag(name,str,enter):if isEmpty(name):return ""s = "<string name=" + "\"" + name + "\">" + str + "</string>"if enter:s += "\n"return sdef isEmpty(s):if not s.strip():return Truereturn Falseclass XmlObj:fileName = ""content = ""write()

执行复制脚本

这个时候,他会在对应的目录生成string文件,如果你希望自动把谢谢文件移动到你的项目中,你可以通过一个sh脚本实现:

dir=`dirname $0`
work='E://AndroidStudioProject/MyApplication'
cp $dir/语言/en-rUS/strings.xml $work/MyApplication/app/src/main/res/values
cp $dir/语言/en-rUS/strings.xml $work/MyApplication/app/src/main/res/values-en
cp $dir/语言/it-rIT/strings.xml $work/MyApplication/app/src/main/res/values-it
cp $dir/语言/pt-rPT/strings.xml $work/MyApplication/app/src/main/res/values-pt
cp $dir/语言/zh-rCN/strings.xml $work/MyApplication/app/src/main/res/values-zh
cp $dir/语言/es-rES/strings.xml $work/MyApplication/app/src/main/res/values-es
cp $dir/语言/de-rDE/strings.xml $work/MyApplication/app/src/main/res/values-de

这个我就不解释了,相信大家都看的懂。然后就大功告成了。


http://www.ppmy.cn/news/790770.html

相关文章

世界各国浏览器语言代码本地化对照表

阿尔巴尼亚语 [sq] 阿尔巴尼亚语(阿尔巴尼亚) [sq-AL] 阿尔萨斯语 [gsw] 阿尔萨斯语(法国) [gsw-FR] 阿拉伯语 [ar] 阿拉伯语(阿尔及利亚) [ar-DZ] 阿拉伯语(阿联酋) [ar-AE] 阿拉伯语(阿曼) [ar-OM] 阿拉伯语(埃及) [ar-EG] 阿拉伯语(巴林) [ar-BH] 阿拉伯语(卡塔尔) [ar-QA…

元宇宙新形态 NFT赋能万物

7月12日,第三界世界文化产业论坛上&#xff0c;代表韩国流行风尚前沿的SM公司董事长李秀满&#xff0c;就元宇宙与文化内容产业新远景发表演说。他说到&#xff1a;“作为未来娱乐世界的核心价值和蓝图所创造的SM元宇宙“SMCU”&#xff0c;是公司长久的企划&#xff0c;SMCU将…

基于sklearn随机森林算法探究肥胖的成因

目录 项目背景 数据介绍 数据来源 属性介绍 算法介绍 随机森林算法 决策树 随机森林定义 随机森林构建过程 随机森林算法评价 随机森林算法的发展现状及趋势 实验步骤 1.导入模块与数据 2.查看数据 3.数据预处理 4.可视化分析 5.特征工程 6.构建模型 实验总…

中国电竞20年:从小众娱乐到新兴体育产业

1958年&#xff0c;“电子游戏之父”威廉辛吉勃森开发出电子游戏——《双人网球》。 以当下的视角来看&#xff0c;这款游戏极为粗糙&#xff1a; 画面在示波器中显示&#xff0c;无非是一个网球场的俯视图&#xff0c;中间的竖线代表球网&#xff0c;两边的竖线代表球拍&…

js去空格、去重函数

js去除空格函数 var str" 薛 定 谔 的 猫 "; 去除所有空格: strstr.replace(/\s/g,""); alert(str);-->"薛定谔的猫" 去除两头空格: str str.replace(/^\s|\s$/g,""); alert(str);-->"薛 定 谔 的 猫&qu…

虎牙直播运维负责人张观石 | 解密SRE的六种能力及虎牙运维实践

本文是根据虎牙直播运维负责人张观石10月20日在msup携手魅族、Flyme、百度云主办的第十三期魅族开放日《虎牙直播平台SRE实践》演讲中的分享内容整理而成。 张观石&#xff0c;拥有10余年网站开发、架构、运维经验&#xff1b;目前关注互联网服务可靠性系统工程、运维平台的规划…

OSChina 周一乱弹 —— 等安好机械臂 再拒绝你的表白 人类

2019独角兽企业重金招聘Python工程师标准>>> Osc乱弹歌单&#xff08;2018&#xff09;请戳&#xff08;这里&#xff09; 【今日歌曲】 2amor &#xff1a;分享Imagine Dragons的单曲《Demons》 《Demons》- Imagine Dragons 手机党少年们想听歌&#xff0c;请使劲…

这家公司,打造电竞三冠王SKT,无视法律,韩国总统还得给他赔笑脸

最近最火热的电竞赛事没有悬念的当属英雄联盟季中邀请赛&#xff08;以下简称MSI&#xff09;&#xff0c;来自世界各大赛区的冠军齐聚一堂&#xff0c;争夺那座金光闪闪的奖杯。而参赛队伍中最受关注的无疑是S8世界冠军IG和打破低迷王者归来的SKT。 IG暂且不说&#xff0c;相信…