在項(xiàng)目開(kāi)發(fā)中,偶爾需要新增國(guó)際化語(yǔ)言,但是提供的翻譯文檔一般是Excel文件,
若只是一個(gè),還可以簡(jiǎn)單一個(gè)一個(gè)辛苦的復(fù)雜,
若內(nèi)容很多,或新增好幾個(gè)國(guó)際化語(yǔ)言,就要吐....了,
之前用的是工具,現(xiàn)在自己簡(jiǎn)單實(shí)現(xiàn)學(xué)習(xí)一下,就不工具化了;
這個(gè)版本:批量處理讀取Excel到txt文件中
下一個(gè)版本,
將項(xiàng)目中的國(guó)際化語(yǔ)言批量導(dǎo)入到Excel中....
相關(guān)國(guó)際化處理:
iOS【語(yǔ)言國(guó)際化處理】python腳本讀取Excel內(nèi)容批量導(dǎo)入國(guó)際化語(yǔ)言文件中(一)
iOS【語(yǔ)言國(guó)際化處理】python腳本將國(guó)際化語(yǔ)言文件批量導(dǎo)入Excel文件中(二)
iOS【圖片國(guó)際化處理】python腳本Assets.xcassets圖片名稱及MD5批量處理(三)
文件示例目錄
|--------Language---ar.lproj-------------Localizable.strings----|
|---------------------en.lproj------------Localizable.strings----|
|---------------------es.lproj------------Localizable.strings----|
|---------------------Language.xlsx----------------------------|
Excel結(jié)構(gòu)示意圖
Excel第一行內(nèi)容:key | ar.lproj | en.lproj | es.lproj |
Excel后面行內(nèi)容:第一列為Key, 后面列為對(duì)應(yīng)語(yǔ)言的翻譯
[key]-----[ar.lporj]------[en.lproj]-----[es.lproj]
[key1]----[test_ar]------[test_en]-----[test_es]
[key2]----[test2_ar]----[test2_en]----[test2_es]
Localizable.strings結(jié)構(gòu)示意圖
"kTest_1" = "test_ar_1 \n 11";
"kTest_2" = "test_ar_2";
"kTest_3" = "test_ar_3 %@ 33";



Python3, 需要安裝xlrd讀Excel,xlwt寫Excel
python里面的xlrd模塊(python3.9)表示對(duì)應(yīng)版本
curl https://bootstrap.pypa.io/get-pip.py | python3.9
pip install xlrd
pip install xlwt
pip install pyexcel-xls
終端使用示例
python3.9 /Users/odd/Documents/Project/測(cè)試國(guó)際化/TestPython/CCExcelToLocalizationTool.py
配置使用:
print("可以配置調(diào)整路徑:")
# 國(guó)際化語(yǔ)言文件
languageFile = "/Users/odd/Documents/Project/測(cè)試國(guó)際化/Language"
# 需要國(guó)際化的語(yǔ)言文件名
languageLocalizableName = "Localizable.strings"
# 打開(kāi)excel文件讀取數(shù)據(jù)
languageExcefilePath = "/Users/odd/Documents/Project/測(cè)試國(guó)際化/Language/Language.xlsx"
# 添加版本分割注釋(可加可不加)
versionMark = "http:// ==================== V1.0.0 ==================== //"
#versionMark = ""
完整腳本:CCExcelToLocalizationTool.py
#-*-coding:utf-8-*-
import xlrd,sys,os
"""讀取Excel表格中的數(shù)據(jù),寫到txt、Localizable.strings中"""
def read_excel_to_txt():
'''
# 寫入文件路徑 示例
#/Users/odd/Documents/Project/測(cè)試國(guó)際化/Language/en.lproj/Localizable.txt
#/Users/odd/Documents/Project/測(cè)試國(guó)際化/Language/en.lproj/Localizable.strings
'''
print("可以配置調(diào)整路徑:")
# 國(guó)際化語(yǔ)言文件
languageFile = "/Users/odd/Documents/Project/測(cè)試國(guó)際化/Language"
# 需要國(guó)際化的語(yǔ)言文件名
languageLocalizableName = "Localizable.strings"
# 打開(kāi)excel文件讀取數(shù)據(jù)
languageExcefilePath = "/Users/odd/Documents/Project/測(cè)試國(guó)際化/Language/Language.xlsx"
# 添加版本分割注釋(可加可不加)
versionMark = "http:// ==================== V1.0.0 ==================== //"
#versionMark = ""
# 打開(kāi)Excel
languageExceData = xlrd.open_workbook(languageExcefilePath)
table = languageExceData.sheets()[0] # 表頭
nrows = table.nrows # 行數(shù)
ncols = table.ncols # 列數(shù)
firstRowDatas = table.row_values(0);
print(firstRowDatas);
# 對(duì)應(yīng)語(yǔ)言文件夾
languageLprojName = ""
index = 1
for firtName in firstRowDatas:
if firtName.upper() == "KEY":
print("跳過(guò):"+firtName)
continue
print("\n===========開(kāi)始寫文件=========")
print("\n===========" + firtName + "===========\n")
print("開(kāi)發(fā)處理語(yǔ)言文件:" + firtName + " : 第 "+ str(index) + " 個(gè)\n")
# 寫入文件路徑
languageLprojName = languageFileName(firtName)
languagePathDir = languageFile+"/"+languageLprojName
languagePathFile = languageFile+"/"+languageLprojName+"/"+languageLocalizableName
# 判斷文件目錄是否存在
isPathExitsDir(languagePathDir)
# 判斷文件是否存在,不存在,則創(chuàng)建
isPathExitsFile(languagePathFile)
#
# 盡量不要清空處理
# 若想調(diào)整文檔順序一致,可以先清空一次(要確保文檔里的,已經(jīng)存在excel里)
# clearLocalization(languagePathFile)
'''
#1、可以先用CCExcelToLocalizationTool.py:把要導(dǎo)入更新的excel里的文案加入翻譯里
#2、在用CCLocalizationToExcelTool.py:把已經(jīng)處理的文案導(dǎo)入到excel里
#3、在調(diào)用CCExcelToLocalizationTool.py時(shí),打開(kāi)清理clearLocalization(languagePathFile)
'''
# 讀取文件內(nèi)容,格式化處理
sourceTxtDic = readTxtToDic(languagePathFile)
needWriteMark = isNeedVersionMark(languagePathFile,versionMark)
#先追加在替換
sqlfile = open(languagePathFile,"a")
replateArray = []
for ronum in range(1, nrows):
#這行有多少列
row = table.row_values(ronum)
#過(guò)濾空方式:s.strip()=='',len(s) ==0,s.isspace() == True
rowFirstKey = str(row[0]).strip()
if rowFirstKey == '':
print("跳過(guò):空數(shù)據(jù),第"+str(ronum)+"行")
continue
# 將行數(shù)據(jù)拼接成字符串
rowValue = handleRowIndexContent(row,index)
rowKey = str(row[0]).strip()
# print("======== 行key: "+rowKey)
if rowKey in sourceTxtDic.keys():
print("包含:"+rowKey + " 修改value: " + rowValue)
sourceVlaue = sourceTxtDic[rowKey]
sourceVlaue["value"] = rowValue
replateArray.append(sourceVlaue)
else:
print("追加:"+rowKey + " value: " + rowValue)
if versionMark != "" and needWriteMark:
print("=========添加分割標(biāo)識(shí)=======")
sqlfile.writelines(versionMark + "\r") #將字符串寫入新文件
needWriteMark = False
sqlfile.writelines(rowValue + "\r") #將字符串寫入新文件
sqlfile.close() # 關(guān)閉寫入的文件
# #替換
sqlReplacefile = open(languagePathFile,"r+")
relpaceLines = sqlReplacefile.readlines()
#print("讀取原始txt內(nèi)容:")
#print(relpaceLines)
#print("\n")
# 序號(hào)+內(nèi)容
for txtIndex, txtItem in enumerate(relpaceLines):
#移除 原始內(nèi)容中行最后默認(rèn)的\\n,
txtItem = txtItem.strip('\n')
relpaceLines[txtIndex] = txtItem
#print("讀取去掉\\n換行txt內(nèi)容:")
#print(relpaceLines)
#print("\n")
# 如果向文件寫入數(shù)據(jù)后,不想馬上關(guān)閉文件,也可以調(diào)用文件對(duì)象提供的 flush() 函數(shù),它可以實(shí)現(xiàn)將緩沖區(qū)的數(shù)據(jù)寫入文件中
for replaceDic in replateArray:
replaceRow = replaceDic["row"]
replaceValue = replaceDic["value"]
print("替換:" + " 行 " + replaceRow + " key: " + replaceDic["key"] + " value: " + replaceValue)
# 替換需要改變的內(nèi)容
relpaceLines[int(replaceRow)] = replaceValue
sqlWriteFile = open(languagePathFile,"w+")
#寫入對(duì)應(yīng)行+換行
sqlWriteFile.writelines([tempLine+"\r" for tempLine in relpaceLines])
sqlWriteFile.close()
sqlReplacefile.close()
index = index + 1
print("\n===========結(jié)束寫文件=========\n")
# 將excel首行的key與其他行分別拼接處理
def handleRowIndexContent(row,index):
#strip方法用于去除字符串首尾空格
#效果:"key" = "value";
values = "\"" +str(row[0]).strip() + "\"" + " = " + "\"" +str(row[index]).strip() + "\"" + ";"
#print("將excel首行的key與其他行分別拼接處理:\n"+values)
return values
# en.lproj 文件名處理
def langFieleName(nameString):
result = ""
#小寫處理
nameString = nameString.lower()
#方式一:截取 nameString[-5:] 輸出右5位:lproj
# if len(nameString) > 1 :
# #獲取:en
# result = nameString[0:2]
#方式二:分割
#nameList = nameString.split(".")
#result = nameList[0]
#方式三:查找截取 變量.find("要查找的內(nèi)容"[,開(kāi)始位置,結(jié)束位置])
#lprojIndex = nameString.find('lproj') #3
#result = nameString[0:lprojIndex]
#方法四:替換
result = nameString.replace('.lproj','')
print(result)
return result
def languageFileName(nameString):
#小寫處理
result = nameString.lower()
return result
# 判斷目錄是否存在,及創(chuàng)建
def isPathExitsDir(dirs):
if dirs == '':
print("不是文件目錄路徑")
return
if not os.path.exists(dirs):
print("不存在目錄,創(chuàng)建目錄")
os.makedirs(dirs)
# 判斷文件是否存在,及創(chuàng)建
def isPathExitsFile(filePath):
if filePath == '':
print("不是文件路徑")
return
if not os.path.exists(filePath):
#調(diào)用系統(tǒng)命令行來(lái)創(chuàng)建文件
os.system(r"touch {}".format(filePath))
# 讀取iOS國(guó)際化語(yǔ)言文件
"""
行樣式:"name" = "occc";
rowKey = "name"
rowValue = ""occc";"
row = "0" #第幾行
itemDic = {"key":rowKey, "value":rowValue, "row":row}
dic={rowKey=ItemDic}
"""
def readTxtToDic(txtPath):
#item.endswith('.mp4')
# line.startswith('#')
#b = True a = bool(1-b)
#bool()函數(shù)中的1-bool值 就是取bool值的反值了。
if not os.path.exists(txtPath):
print("讀取國(guó)際化語(yǔ)言文件不存在")
return {}
txtDic = {}
with open(txtPath,"r") as f:
txtData = f.readlines()
# print("\ntxt內(nèi)容:讀取所以內(nèi)容,并以數(shù)組格式返回,會(huì)讀取到'\\n'")
#print(txtData)
#print("\n")
#['"cancel"="CANCEL11"\n', '"done"="Done222"\n']
lineIndex = 0
for line in txtData:
#移除 \\n
line = line.strip('\n')
#print(line)
#判斷以"開(kāi)頭,
if line.startswith("\""):
rowDataList = line.split('=')
# key先移除首尾空,在移除"符號(hào)
key = clearTextBeginEnd(rowDataList[0],"\"")
value = rowDataList[1].strip()
print("read 行: " + str(lineIndex) + " key: " + key + " value: " + value)
txtDic[key] = {"key":key,"value":value,"row":str(lineIndex)}
lineIndex = lineIndex + 1
f.close()
#print("字典集合:")
#print("key==============\n")
#print(list(txtDic.keys()))
#print(txtDic)
return txtDic
# 是否需要添加版本分割標(biāo)識(shí)
def isNeedVersionMark(filePath,versionMark):
if versionMark == "":
return False
ishas = True
with open(filePath,"r") as f:
txtData = f.readlines()
for line in txtData:
# 或 versionMark in line
if line.find(versionMark) != -1:
ishas = False
f.close
return ishas
# 讀取txt內(nèi)容方式
def readeTxtFile(filePath):
# 一次性讀取txt內(nèi)容
with open(filePath,"r") as f:
txtData = f.read()
print("txt內(nèi)容:一次性讀取")
print(txtData)
f.close()
with open(filePath,"r") as f:
txtData = f.readline()
print("txt內(nèi)容:讀取一行")
print(txtData)
f.close()
# with open(filePath,"r") as f:
# txtData = f.readlines()
# print("txt內(nèi)容:讀取所以內(nèi)容,并以數(shù)組格式返回,會(huì)讀取到'\\n'")
# #print(txtData)
# #['"cancel"="CANCEL11"\n', '"done"="Done222"\n']
# for line in txtData:
# #移除
# line = line.strip('\n')
# print(line)
# f.close()
# 寫txt文件追加
def writetxt_a(txt,path):
#f.seek(0):把文件定位到數(shù)據(jù)起始位置(index=0),
#若沒(méi)有這句,文件默認(rèn)定位到數(shù)據(jù)結(jié)束位置,w.truncate()不起作用
with codecs.open(path,'a','utf-8') as f:
f.seek(0) # 定位
f.truncate() # 清空文件
f.write(txt)
f.close()
# 清空內(nèi)容,可以保持順序一致
def clearLocalization(path):
# 清空文件內(nèi)容
clearTextContent(path)
#讀取txt內(nèi)容
#readeTxtFile(path)
# 清空txt文件內(nèi)容
def clearTextContent(path):
# 清空txt文件內(nèi)容(方式一)
clearfile = open(path, 'w').close()
#清空txt文件內(nèi)容(方式二)
#with open(path, 'r+') as file:
# file.truncate(0)
# file.close()
print("清空文件內(nèi)容:"+path)
# 清除首尾空和"符號(hào)
def clearTextBeginEnd(sourceText,clearChart):
# isinstance(sourceText,str) 是否字符串,然后取反
if bool(1 - isinstance(sourceText,str)):
print("清除數(shù)據(jù)不是字符串")
return ""
sourceText = sourceText.strip()
sourceText = sourceText.strip(clearChart);
return sourceText
# 將excel某行的數(shù)據(jù),拼接處理
def strs(row):
values = "";
for i in range(len(row)):
if i == len(row) - 1:
values = values + str(row[I])
else:
values = values + str(row[i]) + ","
return values
read_excel_to_txt()