在海外專案中,多語言的支持是很重要的一部分,例如我們的專案中需要支持簡中繁中英法德西日韓俄意這十種型別,一個版本下來,需要添加就有二十多條新的文案,即使有時只有幾條,當數量乘以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 版):

然后選擇需要轉換的檔案,點擊轉換按鈕,

如果檔案路徑錯誤,提示:

添加圖形界面的好處:
- 便于使用操作,
- 選擇檔案時可以限制檔案格式,
- 良好的提示資訊,
當然這個小工具還可以進一步優化,比如可以指定輸出目錄,直接將結果添加到專案檔案中,具體在后面使用中再不斷去改進它,
本篇提供一個解決此類重復性高問題的思路,希望可以對你有啟發作用,
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/289624.html
標籤:其他
上一篇:【Flutter 常見問題三十七】Cannot Save Settings:The Flutter SDK installation is incomplete
