实现一个多语言文案快速转换工具
Posted 唯鹿
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实现一个多语言文案快速转换工具相关的知识,希望对你有一定的参考价值。
在海外项目中,多语言的支持是很重要的一部分。例如我们的项目中需要支持简中繁中英法德西日韩俄意这十种类型。一个版本下来,需要添加就有二十多条新的文案,即使有时只有几条,当数量乘以10,都不是一个小数目。如果一条条的添加至项目中,也就是不下几十上百次的重复操作。
发现问题
- 耗时耗力
- 不能保证准确度(例如漏掉或岔行)
- 出错带来的二次检查修改
由于给到我们的多语言文案是表格形式,如下图:
可以看到产品同学整理的很方便,第一列有我们需要的key,其余每列是不同语言文案。
实现
因为以前用Python写过一些爬虫,中间就操作过一些表格的读写。所以优先想到用Python的openpyxl
模块来处理excle表格。
思路就是每次循环key所在列,同时读取对应的语言列获取value。之所以循环key是保证每次循环数量一致,因为表格中会有许多空内容。这里我的处理是当获取的key为空时,结束本次循环。
这里我也查了一个ios需要的输出格式,也简单支持了一下。代码如下:
"""
多语言文案表格转android string.xml 和 iOS Localizable.strings脚本
两个参数,第一个是文件路径(必传),第二个是操作工作表名称(不传为默认工作表)。
注意文件必须是xlsx格式,
"""
import sys
import openpyxl
import xml.dom.minidom as minidom
wb = openpyxl.load_workbook(sys.argv[1])
if len(sys.argv) == 3:
if sys.argv[2] is None:
# 获取当前工作表
sheet = wb.active
else:
# 获取某一特定的工作表
sheet = wb.get_sheet_by_name(sys.argv[2])
else:
sheet = wb.active
print('Start')
language = ["English", "traditional Chinese", "simplified Chinese", "French", "Spanish", "German", "Japanese", "Korean", "Russian", "Italian"]
area_code = ["", "-zh-rTW", "-zh-rCN", "-fr", "-es", "-de", "-ja", "-ko", "-ru", "-it"]
xml = minidom.getDOMImplementation()
# iOS内容
localizableContent = ''
for index, code in enumerate(area_code):
dom = xml.createDocument(None, 'resources', None)
root = dom.documentElement
# 对某一特定的列进行遍历 第三列为“key”
for i, cell in enumerate(list(sheet.columns)[3]):
if cell.value is None:
# 遇到key为空结束循环
break
value = sheet.cell(i + 1, index + 5).value
# 空单元格不添加
if not value is None:
element = dom.createElement('string')
if isinstance(value, str):
# 去除左右两边空格、换行
element.appendChild(dom.createTextNode(value.strip()))
localizableContent += "\\"\\" = \\"\\"\\n".format(cell.value, value.strip().replace('"','\\\\"'))
else:
# 非字符类型转化为str,例如数字。
element.appendChild(dom.createTextNode(str(value)))
localizableContent += "\\"\\" = \\"\\"\\n".format(cell.value, str(value))
element.setAttribute('name', cell.value)
root.appendChild(element)
# 保存安卓string.xml文件
with open('string' + code + '.xml', 'w', encoding='utf-8') as f:
dom.writexml(f, addindent='\\t', newl='\\n', encoding='utf-8')
localizableContent += "\\n\\n"
print(language[index] + ' Complete!')
# iOS文件统一写入部分
with open('Localizable.strings', 'w', encoding='utf-8') as file_object:
file_object.write(localizableContent)
print('End')
PS :注意这里的代码是根据表格内容格式实现的,并不具有通用性。
代码里还处理了几件事:
- 去除文案前后有时多出来的空格和换行。
- iOS部分会将引号转义。
- 如果value为空,则不添加。避免程序获取文字为空。
- 由于Android部分使用的
minidom
来处理xml,所以会自动转义,避免了使用"<“字符和”&"字符的影响。
使用起来很简单,执行命令python language_convert_strings.py xxx.xlsx
。
输出结果:
如果有些文案是不需要或者key的名称问题,可以一开始整理好表格内容再转换。然后直接将结果复制进项目就好了。
优化
这个脚本它也有一些限制,因为是用Python写的,所以它需要使用者的电脑有Python环境和对应的工具模块。为了便于组内的同学使用,那就需要将脚本打包成可执行文件。这里就用到了PyInstaller
,它的作用是将 Python 程序打包成一个独立可执行软件包,支持 Windows、Linux 和 Mac OS X。
所以我需要写一个简单的图形界面,刚好用python自带Tkinter
模块。最终代码如下:
import sys
import openpyxl
import xml.dom.minidom as minidom
from tkinter import *
from tkinter.filedialog import askopenfilename
from tkinter.messagebox import showinfo
def file_open():
filepath = askopenfilename(title="Select xlsx file", filetypes = (('xlsx files', '*.xlsx'),)) # 获得文件
if filepath:
v.set(filepath)
print(v.get())
def convert():
if v.get() == '':
showinfo(title = '错误', message = '请选择文件!')
return
try:
wb = openpyxl.load_workbook(v.get())
except Exception as e:
showinfo(title = '错误', message = str(e))
return
sheet = wb.active
area_code = ["", "-zh-rTW", "-zh-rCN", "-fr", "-es", "-de", "-ja", "-ko", "-ru", "-it"]
xml = minidom.getDOMImplementation()
# iOS内容
localizableContent = ''
for index, code in enumerate(area_code):
dom = xml.createDocument(None, 'resources', None)
root = dom.documentElement
# 对某一特定的列进行遍历 第三列为“key”
for i, cell in enumerate(list(sheet.columns)[3]):
if cell.value is None:
# 遇到key为空结束循环
break
value = sheet.cell(i + 1, index + 5).value
# 空单元格不添加
if not value is None:
element = dom.createElement('string')
if isinstance(value, str):
# 去除左右两边空格、换行
element.appendChild(dom.createTextNode(value.strip()))
localizableContent += "\\"\\" = \\"\\"\\n".format(cell.value, value.strip().replace('"','\\\\"'))
else:
# 非字符类型转化为str,例如数字。
element.appendChild(dom.createTextNode(str(value)))
localizableContent += "\\"\\" = \\"\\"\\n".format(cell.value, str(value))
element.setAttribute('name', cell.value)
root.appendChild(element)
# 保存安卓string.xml文件
with open('string' + code + '.xml', 'w', encoding='utf-8') as f:
dom.writexml(f, addindent='\\t', newl='\\n', encoding='utf-8')
localizableContent += "\\n\\n"
# iOS文件统一写入部分
with open('Localizable.strings', 'w', encoding='utf-8') as file_object:
file_object.write(localizableContent)
showinfo(title = '完成', message = '转换完成!')
if __name__ == '__main__':
root = Tk()
root.geometry('300x100')
root.wm_title('多语言文案表格转换工具')
frame = Frame(root)
frame.pack(padx = 10, pady = 10)
frame1 = Frame(root)
frame1.pack(padx = 10, pady = 10)
v = StringVar()
entry = Entry(frame, width = 20, textvariable = v).pack(fill = X, side = LEFT)
btn = Button(frame, text='选择文件', width = 20, command = file_open).pack(fill = X, padx = 10)
btn1 = Button(frame1, text='转换', width = 20, command = convert).pack(fill = X, padx = 10)
root.mainloop()
然后使用命令pyinstaller -F -w language_convert_strings.py
打包就行了。
下面简单演示一下(mac 版):
然后选择需要转换的文件,点击转换按钮。
如果文件路径错误,提示:
添加图形界面的好处:
- 便于使用操作。
- 选择文件时可以限制文件格式。
- 良好的提示信息。
当然这个小工具还可以进一步优化,比如可以指定输出目录,直接将结果添加到项目文件中。具体在后面使用中再不断去改进它。
本篇提供一个解决此类重复性高问题的思路,希望可以对你有启发作用。
以上是关于实现一个多语言文案快速转换工具的主要内容,如果未能解决你的问题,请参考以下文章
App Languages 批量导入管理flutter多语言文案
App Languages 批量导入管理flutter多语言文案
App Languages 批量导入管理flutter多语言文案