在项目开发中,偶尔需要新增国际化语言,但是提供的翻译文档一般是Excel文件,
若只是一个,还可以简单一个一个辛苦的复杂,
若内容很多,或新增好几个国际化语言,就要吐....了,
之前用的是工具,现在自己简单实现学习一下,就不工具化了;
这个版本:批量处理读取Excel到txt文件中
下一个版本,
将项目中的国际化语言批量导入到Excel中....
相关国际化处理:
iOS【语言国际化处理】python脚本读取Excel内容批量导入国际化语言文件中(一)
iOS【语言国际化处理】python脚本将国际化语言文件批量导入Excel文件中(二)
iOS【图片国际化处理】python脚本Assets.xcassets图片名称及MD5批量处理(三)
文件示例目录
|--------Language---ar.lproj-------------Localizable.strings----|
|---------------------en.lproj------------Localizable.strings----|
|---------------------es.lproj------------Localizable.strings----|
|---------------------Language.xlsx----------------------------|
Excel结构示意图
Excel第一行内容:key
| ar.lproj
| en.lproj
| es.lproj
|
Excel后面行内容:第一列为Key
, 后面列为对应语言的翻译
[key]-----[ar.lporj]------[en.lproj]-----[es.lproj]
[key1]----[test_ar]------[test_en]-----[test_es]
[key2]----[test2_ar]----[test2_en]----[test2_es]
Localizable.strings结构示意图
"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)表示对应版本
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/测试国际化/TestPython/CCExcelToLocalizationTool.py
配置使用:
print("可以配置调整路径:")
# 国际化语言文件
languageFile = "/Users/odd/Documents/Project/测试国际化/Language"
# 需要国际化的语言文件名
languageLocalizableName = "Localizable.strings"
# 打开excel文件读取数据
languageExcefilePath = "/Users/odd/Documents/Project/测试国际化/Language/Language.xlsx"
# 添加版本分割注释(可加可不加)
versionMark = "// ==================== V1.0.0 ==================== //"
#versionMark = ""
完整脚本:CCExcelToLocalizationTool.py
#-*-coding:utf-8-*-
import xlrd,sys,os
"""读取Excel表格中的数据,写到txt、Localizable.strings中"""
def read_excel_to_txt():
'''
# 写入文件路径 示例
#/Users/odd/Documents/Project/测试国际化/Language/en.lproj/Localizable.txt
#/Users/odd/Documents/Project/测试国际化/Language/en.lproj/Localizable.strings
'''
print("可以配置调整路径:")
# 国际化语言文件
languageFile = "/Users/odd/Documents/Project/测试国际化/Language"
# 需要国际化的语言文件名
languageLocalizableName = "Localizable.strings"
# 打开excel文件读取数据
languageExcefilePath = "/Users/odd/Documents/Project/测试国际化/Language/Language.xlsx"
# 添加版本分割注释(可加可不加)
versionMark = "// ==================== V1.0.0 ==================== //"
#versionMark = ""
# 打开Excel
languageExceData = xlrd.open_workbook(languageExcefilePath)
table = languageExceData.sheets()[0] # 表头
nrows = table.nrows # 行数
ncols = table.ncols # 列数
firstRowDatas = table.row_values(0);
print(firstRowDatas);
# 对应语言文件夹
languageLprojName = ""
index = 1
for firtName in firstRowDatas:
if firtName.upper() == "KEY":
print("跳过:"+firtName)
continue
print("\n===========开始写文件=========")
print("\n===========" + firtName + "===========\n")
print("开发处理语言文件:" + firtName + " : 第 "+ str(index) + " 个\n")
# 写入文件路径
languageLprojName = languageFileName(firtName)
languagePathDir = languageFile+"/"+languageLprojName
languagePathFile = languageFile+"/"+languageLprojName+"/"+languageLocalizableName
# 判断文件目录是否存在
isPathExitsDir(languagePathDir)
# 判断文件是否存在,不存在,则创建
isPathExitsFile(languagePathFile)
#
# 尽量不要清空处理
# 若想调整文档顺序一致,可以先清空一次(要确保文档里的,已经存在excel里)
# clearLocalization(languagePathFile)
'''
#1、可以先用CCExcelToLocalizationTool.py:把要导入更新的excel里的文案加入翻译里
#2、在用CCLocalizationToExcelTool.py:把已经处理的文案导入到excel里
#3、在调用CCExcelToLocalizationTool.py时,打开清理clearLocalization(languagePathFile)
'''
# 读取文件内容,格式化处理
sourceTxtDic = readTxtToDic(languagePathFile)
needWriteMark = isNeedVersionMark(languagePathFile,versionMark)
#先追加在替换
sqlfile = open(languagePathFile,"a")
replateArray = []
for ronum in range(1, nrows):
#这行有多少列
row = table.row_values(ronum)
#过滤空方式:s.strip()=='',len(s) ==0,s.isspace() == True
rowFirstKey = str(row[0]).strip()
if rowFirstKey == '':
print("跳过:空数据,第"+str(ronum)+"行")
continue
# 将行数据拼接成字符串
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("=========添加分割标识=======")
sqlfile.writelines(versionMark + "\r") #将字符串写入新文件
needWriteMark = False
sqlfile.writelines(rowValue + "\r") #将字符串写入新文件
sqlfile.close() # 关闭写入的文件
# #替换
sqlReplacefile = open(languagePathFile,"r+")
relpaceLines = sqlReplacefile.readlines()
#print("读取原始txt内容:")
#print(relpaceLines)
#print("\n")
# 序号+内容
for txtIndex, txtItem in enumerate(relpaceLines):
#移除 原始内容中行最后默认的\\n,
txtItem = txtItem.strip('\n')
relpaceLines[txtIndex] = txtItem
#print("读取去掉\\n换行txt内容:")
#print(relpaceLines)
#print("\n")
# 如果向文件写入数据后,不想马上关闭文件,也可以调用文件对象提供的 flush() 函数,它可以实现将缓冲区的数据写入文件中
for replaceDic in replateArray:
replaceRow = replaceDic["row"]
replaceValue = replaceDic["value"]
print("替换:" + " 行 " + replaceRow + " key: " + replaceDic["key"] + " value: " + replaceValue)
# 替换需要改变的内容
relpaceLines[int(replaceRow)] = replaceValue
sqlWriteFile = open(languagePathFile,"w+")
#写入对应行+换行
sqlWriteFile.writelines([tempLine+"\r" for tempLine in relpaceLines])
sqlWriteFile.close()
sqlReplacefile.close()
index = index + 1
print("\n===========结束写文件=========\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("要查找的内容"[,开始位置,结束位置])
#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
# 判断目录是否存在,及创建
def isPathExitsDir(dirs):
if dirs == '':
print("不是文件目录路径")
return
if not os.path.exists(dirs):
print("不存在目录,创建目录")
os.makedirs(dirs)
# 判断文件是否存在,及创建
def isPathExitsFile(filePath):
if filePath == '':
print("不是文件路径")
return
if not os.path.exists(filePath):
#调用系统命令行来创建文件
os.system(r"touch {}".format(filePath))
# 读取iOS国际化语言文件
"""
行样式:"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()函数中的1-bool值 就是取bool值的反值了。
if not os.path.exists(txtPath):
print("读取国际化语言文件不存在")
return {}
txtDic = {}
with open(txtPath,"r") as f:
txtData = f.readlines()
# print("\ntxt内容:读取所以内容,并以数组格式返回,会读取到'\\n'")
#print(txtData)
#print("\n")
#['"cancel"="CANCEL11"\n', '"done"="Done222"\n']
lineIndex = 0
for line in txtData:
#移除 \\n
line = line.strip('\n')
#print(line)
#判断以"开头,
if line.startswith("\""):
rowDataList = line.split('=')
# key先移除首尾空,在移除"符号
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
# 是否需要添加版本分割标识
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内容方式
def readeTxtFile(filePath):
# 一次性读取txt内容
with open(filePath,"r") as f:
txtData = f.read()
print("txt内容:一次性读取")
print(txtData)
f.close()
with open(filePath,"r") as f:
txtData = f.readline()
print("txt内容:读取一行")
print(txtData)
f.close()
# with open(filePath,"r") as f:
# txtData = f.readlines()
# print("txt内容:读取所以内容,并以数组格式返回,会读取到'\\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):把文件定位到数据起始位置(index=0),
#若没有这句,文件默认定位到数据结束位置,w.truncate()不起作用
with codecs.open(path,'a','utf-8') as f:
f.seek(0) # 定位
f.truncate() # 清空文件
f.write(txt)
f.close()
# 清空内容,可以保持顺序一致
def clearLocalization(path):
# 清空文件内容
clearTextContent(path)
#读取txt内容
#readeTxtFile(path)
# 清空txt文件内容
def clearTextContent(path):
# 清空txt文件内容(方式一)
clearfile = open(path, 'w').close()
#清空txt文件内容(方式二)
#with open(path, 'r+') as file:
# file.truncate(0)
# file.close()
print("清空文件内容:"+path)
# 清除首尾空和"符号
def clearTextBeginEnd(sourceText,clearChart):
# isinstance(sourceText,str) 是否字符串,然后取反
if bool(1 - isinstance(sourceText,str)):
print("清除数据不是字符串")
return ""
sourceText = sourceText.strip()
sourceText = sourceText.strip(clearChart);
return sourceText
# 将excel某行的数据,拼接处理
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()