您的位置:首页 > 编程语言 > Python开发

用 Python 管理 Android 中 strings.xml 的字符翻译

2015-07-15 17:26 741 查看
对于一个带有多种语言的 Android 应用。如果要修改某个字符某种语言的翻译,就要去修改该语言对应的
strings.xml
文件字符的内容。这样操作比较麻烦,也容易出错。于是,就想着利用 Excel 表格的可读性和易于管理性,通过 Python 脚本将 Excel 表格转化成
strings.xml
对应的字符。该脚本的源码见:https://github.com/heray1990/txt2xml

构建 Excel 表格

假设在我们的 Android 应用里,
values-zh/
目录下的
strings.xml
文件内容如下:

<?xml version="1.0" ?>
<resources>
<string name="Main.MenuShowHistory">历史</string>
<string name="Main.MenuShowDownloads">下载</string>
<string name="Main.MenuPreferences">配置</string>
<string name="PreferencesActivity.EnableJavascriptPreferenceSummary">如果不支持JavaScript,很多网站效果不能打开,建议打开.</string>
</resources>


根据上述
strings.xml
文件的内容,我们在 Excel 中创建类似如下表格(翻译不一定准确,仅供参考):

zhfresde
Main.MenuShowHistory历史HistoriqueHistorialVerlauf
Main.MenuShowDownloads下载TéléchargementsDescargasDownloads
Main.MenuPreferences配置PréférencesPreferenciasEinstellungen
PreferencesActivity.EnableJavascriptPreferenceSummary如果不支持JavaScript,很多网站效果不能打开,建议打开.Active ou désactive le JavaScript.Activar o desactivar JavaScript.JavaScript ein-/ausschalten.
其中,第一行表示了 Android 应用中不同语言的语言简码。例如,我们的应用中有中文、法语、西班牙语和德语,那么对应的表格第一行就有 zh、fr、es和de。

表格中的第一列则对应
strings.xml
文件中
<string>
节点
name
属性的值。

表格中剩下的部分对应
strings.xml
文件中
<string>
节点的值。例如:“历史”就是
Main.MenuShowHistory
对应的中文翻译。

生成 Unicode txt 文件

构建完 Excel 表格之后,将内容保存到 Unicode txt 文件中。即在 Excel 软件里面:另存为 -> Unicode 文本(*.txt)。这样就生成了 Python 可以解析的 txt 文件(假设我们这里的文件名字为:
strings.txt
)。内容如下:

zh  fr  es  de
Main.MenuShowHistory    历史  Historique  Historial   Verlauf
Main.MenuShowDownloads  下载  Téléchargements Descargas   Downloads
Main.MenuPreferences    配置  Préférences Preferencias    Einstellungen
PreferencesActivity.EnableJavascriptPreferenceSummary   如果不支持JavaScript,很多网站效果不能打开,建议打开.    Active ou désactive le JavaScript.  Activar o desactivar JavaScript.     JavaScript ein-/ausschalten.


解析 Unicode txt 文件

注意到,从 Excel 表格生成的
strings.txt
Unicode txt 文件里,每个单元格之间使用制表符
'\t'
隔开。在解析的时候可以通过检测制表符来获取每个单元格的内容。

由于
strings.txt
的内容是以 Unicode 进行编码,因此需要先将 Unicode 转成 utf-8,便于后面的字符处理。这要用到
codecs
模块,此部分的代码如下:

cwd = os.path.dirname(sys.argv[0])
self.txt_fd = codecs.open(os.path.join(cwd,txt_fname),'r','utf-16')

ls = [line.strip().encode('utf-8') for line in self.txt_fd]
self.txt_fd.close()


其中,我们将
strings.txt
文件中的每一行作为列表的一个元素保存到列表
ls
中。此时,我们已经初步将
strings.txt
的内容提取出来。

接下来,我们对提取出来的内容做进一步的分解。将第一行的语言简码保存到
self.langls
列表中,用于后面根据不同的语言生成不同的
values-*
目录。

Note: Android 中,不同语言的
strings.xml
文件被放到不同的
values-*
目录。例如,中文的
strings.xml
文件会放到
values-zh
目录。而
zh
就是对应于 Excel 表格第一行(
ls[0]
)的语言简码。

获取语言简码的代码如下:

self.langls = ls[0].split('\t')


最后,将字符的变量名和对应的字符翻译放到一个字典
self.stringdict
中。其中变量名为 key,字符的翻译为 value。以字典的形式保存字符翻译,便于后面的操作。这部分的代码如下:

lskey = []
lsval = []
for i in ls[1:]:
subls = i.split('\t')
lskey.append(subls[0])
lsval.append(subls[1:])

self.stringdict = collections.OrderedDict(zip(lskey,lsval))


其中,
lskey
列表保存了表格中第一列的字符变量名。该列表的内容应该如下:

['Main.MenuShowHistory', 'Main.MenuShowDownloads', 'Main.MenuPreferences', 'PreferencesActivity.EnableJavascriptPreferenceSummary']


lsval
列表则保存了字符翻译的值,该列表的内容如下:

[['\xe5\x8e\x86\xe5\x8f\xb2', 'Historique', 'Historial', 'Verlauf'], ['\xe4\xb8\x8b\xe8\xbd\xbd', 'T\xc3\xa9l\xc3\xa9chargements', 'Descargas', 'Downloads'], ['\xe9\x85\x8d\xe7\xbd\xae', 'Pr\xc3\xa9f\xc3\xa9rences', 'Preferencias', 'Einstellungen'], ['\xe5\xa6\x82\xe6\x9e\x9c\xe4\xb8\x8d\xe6\x94\xaf\xe6\x8c\x81JavaScript\xef\xbc\x8c\xe5\xbe\x88\xe5\xa4\x9a\xe7\xbd\x91\xe7\xab\x99\xe6\x95\x88\xe6\x9e\x9c\xe4\xb8\x8d\xe8\x83\xbd\xe6\x89\x93\xe5\xbc\x80\xef\xbc\x8c\xe5\xbb\xba\xe8\xae\xae\xe6\x89\x93\xe5\xbc\x80.', 'Active ou d\xc3\xa9sactive le JavaScript.', 'Activar o desactivar JavaScript.', ' JavaScript ein-/ausschalten.']]


collections.OrderedDict(zip())
函数可以将两个列表转换成一个字典。下面是一个关于该函数的例子:

>>> a = ['a','b','c']
>>> b = [[1,2,3],[4,5,6],[7,8,9]]
>>> zip(a,b)
[('a', [1, 2, 3]), ('b', [4, 5, 6]), ('c', [7, 8, 9])]
>>> import collections
>>> collections.OrderedDict(zip(a,b))
OrderedDict([('a', [1, 2, 3]), ('b', [4, 5, 6]), ('c', [7, 8, 9])])


在这个地方,本来是用
dict()
函数的,即

self.stringdict = dict(zip(lskey,lsval))


但是由于在 Python 中,字典是无序的。这样会导致产生字典的字符顺序与最初 Excel 表格的字符顺序不一致。下面是用
dict()
函数的例子:

>>> a = ['a','b','c']
>>> b = [[1,2,3],[4,5,6],[7,8,9]]
>>> zip(a,b)
[('a', [1, 2, 3]), ('b', [4, 5, 6]), ('c', [7, 8, 9])]
>>> dict(zip(a,b))
{'a': [1, 2, 3], 'c': [7, 8, 9], 'b': [4, 5, 6]}


可以看到用
dict()
函数输出的字典键值对的顺序与输入的时候不一致。而
collections.OrderedDict()
则可以保证输入输出前后字典键值对的顺序一致。

补充:

下面提供一种更加简单的方法来生成
self.stringdict
(上面的方法有点啰嗦,其实字典是可以直接地构建的):

for i in ls[1:]:
subls = i.split('\t')
self.stringdict[subls[0]] = subls[1:]


生成 strings.xml 文件

首先,我们要根据前面提到的
self.langls
列表来生成不同语言的目录
values-*
。下面是这部分的代码:

for j in self.langls:
# Create the directories according to the language.
os.mkdir(XML_FILE_DIR_PREFIX + j)


然后,就是调用 Python 的
xml.dom.minidom
模块构建 XML 的节点和相关的内容。其中,字符对应语言的翻译是从
self.stringdict
字典提取出来。相关代码如下:

doc = Document()
resources = doc.createElement("resources")
doc.appendChild(resources)

for k,v in self.stringdict.items():
stringele = doc.createElement("string")
stringele.setAttribute("name",k)
text = doc.createTextNode(v[self.langls.index(j)])
stringele.appendChild(text)
resources.appendChild(stringele)


最后,生成
strings.xml
文件:

uglyXml = doc.toprettyxml(indent='  ')
text_re = re.compile('>\n\s+([^<>\s].*?)\n\s+</', re.DOTALL)
prettyXml = text_re.sub('>\g<1></', uglyXml)

self.xmlfd = open(os.path.join(XML_FILE_DIR_PREFIX + j,XML_FILE_NAME),'w')
#doc.writexml(self.xmlfd)
self.xmlfd.write(prettyXml)
self.xmlfd.close()
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: