AutoGenStrings.py 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. #!/usr/bin/env python
  2. # encoding: utf-8
  3. """
  4. AutoGenStrings.py
  5. Created by linyu on 2015-02-13.
  6. Modify by wz on 2017-06-02.
  7. Copyright (c) 2017 __MyCompanyName__. All rights reserved.
  8. """
  9. import imp
  10. import sys
  11. import os
  12. import glob
  13. import string
  14. import re
  15. import time
  16. imp.reload(sys)
  17. sys.setdefaultencoding('utf-8') #设置默认编码,只能是utf-8,下面\u4e00-\u9fa5要求的
  18. KTargetFile = '*.lproj/*.strings'
  19. KGenerateStringsFile = 'TempfileOfStoryboardNew.strings'
  20. ColonRegex = ur'["](.*?)["]'
  21. KeyParamRegex = ur'["](.*?)["](\s*)=(\s*)["](.*?)["];'
  22. AnotationRegexPrefix = ur'/(.*?)/'
  23. def getCharaset(string_txt):
  24. filedata = bytearray(string_txt[:4])
  25. if len(filedata) < 4 :
  26. return 0
  27. if (filedata[0] == 0xEF) and (filedata[1] == 0xBB) and (filedata[2] == 0xBF):
  28. print 'utf-8'
  29. return 1
  30. elif (filedata[0] == 0xFF) and (filedata[1] == 0xFE) and (filedata[2] == 0x00) and (filedata[3] == 0x00):
  31. print 'utf-32/UCS-4,little endian'
  32. return 3
  33. elif (filedata[0] == 0x00) and (filedata[1] == 0x00) and (filedata[2] == 0xFE) and (filedata[3] == 0xFF):
  34. print 'utf-32/UCS-4,big endian'
  35. return 3
  36. elif (filedata[0] == 0xFE) and (filedata[1] == 0xFF):
  37. print 'utf-16/UCS-2,little endian'
  38. return 2
  39. elif (filedata[0] == 0xFF) and (filedata[1] == 0xFE):
  40. print 'utf-16/UCS-2,big endian'
  41. return 2
  42. else:
  43. print 'can not recognize!'
  44. return 0
  45. def decoder(string_txt):
  46. var = getCharaset(string_txt)
  47. if var == 1:
  48. return string_txt.decode("utf-8")
  49. elif var == 2:
  50. return string_txt.decode("utf-16")
  51. elif var == 3:
  52. return string_txt.decode("utf-32")
  53. else:
  54. return string_txt
  55. def constructAnotationRegex(str):
  56. return AnotationRegexPrefix + '\n' + str
  57. def getAnotationOfString(string_txt,suffix):
  58. anotationRegex = constructAnotationRegex(suffix)
  59. anotationMatch = re.search(anotationRegex,string_txt)
  60. anotationString = ''
  61. if anotationMatch:
  62. match = re.search(AnotationRegexPrefix,anotationMatch.group(0))
  63. if match:
  64. anotationString = match.group(0)
  65. return anotationString
  66. def compareWithFilePath(newStringPath,originalStringPath):
  67. print(newStringPath)
  68. print(originalStringPath)
  69. #read newStringfile
  70. nspf=open(newStringPath,"r")
  71. #newString_txt = str(nspf.read(5000000)).decode("utf-16")
  72. newString_txt = decoder(str(nspf.read(5000000)))
  73. nspf.close()
  74. newString_dic = {}
  75. anotation_dic = {}
  76. for stfmatch in re.finditer(KeyParamRegex , newString_txt):
  77. linestr = stfmatch.group(0)
  78. anotationString = getAnotationOfString(newString_txt,linestr)
  79. linematchs = re.findall(ColonRegex, linestr)
  80. if len(linematchs) == 2:
  81. leftvalue = linematchs[0]
  82. rightvalue = linematchs[1]
  83. newString_dic[leftvalue] = rightvalue
  84. anotation_dic[leftvalue] = anotationString
  85. #read originalStringfile
  86. ospf=open(originalStringPath,"r")
  87. originalString_txt = decoder(str(ospf.read(5000000)))
  88. ospf.close()
  89. originalString_dic = {}
  90. for stfmatch in re.finditer(KeyParamRegex , originalString_txt):
  91. linestr = stfmatch.group(0)
  92. linematchs = re.findall(ColonRegex, linestr)
  93. if len(linematchs) == 2:
  94. leftvalue = linematchs[0]
  95. rightvalue = linematchs[1]
  96. originalString_dic[leftvalue] = rightvalue
  97. #compare and remove the useless param in original string
  98. for key in originalString_dic:
  99. if(key not in newString_dic):
  100. keystr = '"%s"'%key
  101. replacestr = '//'+keystr
  102. match = re.search(replacestr , originalString_txt)
  103. if match is None:
  104. originalString_txt = originalString_txt.replace(keystr,replacestr)
  105. #compare and add new param to original string
  106. executeOnce = 1
  107. for key in newString_dic:
  108. values = (key, newString_dic[key])
  109. if(key not in originalString_dic):
  110. newline = ''
  111. if executeOnce == 1:
  112. timestamp = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))
  113. newline = '\n//##################################################################################\n'
  114. newline +='//# AutoGenStrings '+timestamp+'\n'
  115. newline +='//##################################################################################\n'
  116. executeOnce = 0
  117. newline += '\n'+anotation_dic[key]
  118. newline += '\n"%s" = "%s";\n'%values
  119. originalString_txt += newline
  120. #write into origial file
  121. sbfw=open(originalStringPath,"w")
  122. sbfw.write(originalString_txt)
  123. sbfw.close()
  124. def extractFileName(file_path):
  125. seg = file_path.split('/')
  126. lastindex = len(seg) - 1
  127. return seg[lastindex]
  128. def extractFilePrefix(file_path):
  129. seg = file_path.split('/')
  130. lastindex = len(seg) - 1
  131. prefix = seg[lastindex].split('.')[0]
  132. return prefix
  133. def generateStoryboardStringsfile(storyboard_path,tempstrings_path):
  134. cmdstring = 'ibtool '+storyboard_path+' --generate-strings-file '+tempstrings_path
  135. if os.system(cmdstring) == 0:
  136. return 1
  137. def generateLocalizableFiles(filePath ,sourceFilePath):
  138. print ('-------> sourceFilePath: ' + sourceFilePath + ' filePath: ' + filePath)
  139. sourceFile_list = glob.glob(sourceFilePath)
  140. if len(sourceFile_list) == 0:
  141. print 'error dictionary,you should choose the dic upper the Base.lproj'
  142. return
  143. targetFilePath = filePath + '/' + KTargetFile
  144. targetFile_list = glob.glob(targetFilePath)
  145. tempFile_Path = filePath + '/' + KGenerateStringsFile
  146. if len(targetFile_list) == 0:
  147. print 'error framework , no .lproj dic was found'
  148. return
  149. for sourcePath in sourceFile_list:
  150. sourceprefix = extractFilePrefix(sourcePath)
  151. sourcename = extractFileName(sourcePath)
  152. print 'init with %s'%sourcename
  153. if generateStoryboardStringsfile(sourcePath,tempFile_Path) == 1:
  154. print '- - genstrings %s successfully'%sourcename
  155. for targetPath in targetFile_list:
  156. targetprefix = extractFilePrefix(targetPath)
  157. targetname = extractFileName(targetPath)
  158. if cmp(sourceprefix,targetprefix) == 0:
  159. print '- - dealing with %s'%targetPath
  160. compareWithFilePath(tempFile_Path,targetPath)
  161. print 'finish with %s'%sourcename
  162. os.remove(tempFile_Path)
  163. else:
  164. print '- - genstrings %s error'%sourcename
  165. #根据项目根目录遍历所有的xib和storyboard的文件路径
  166. def getAllNibSrcPathFor(dir):
  167. sourceFilePaths = []
  168. #三个参数:1.父目录 2.所有文件夹名字(不含路径) 3.所有文件名字
  169. for parent,dirnames,filenames in os.walk(dir):
  170. for filename in filenames: #输出文件信息
  171. print filename
  172. if (('.xib' in filename) | ('.storyboard' in filename)):
  173. filePath = os.path.join(parent)
  174. if filePath not in sourceFilePaths:
  175. sourceFilePaths.append(filePath)
  176. #print sourceFilePaths
  177. return sourceFilePaths
  178. def main():
  179. print(sys.argv)
  180. if len(sys.argv) == 1 :
  181. #如果在终端运行,注意要修改自己需要国际化的项目文件夹的路径!
  182. filePath = '/Users/wz/Documents/git/AutoLocalization/AutoLocalization/'
  183. else:
  184. filePath = sys.argv[1]
  185. # if filePath == None or filePath == '':
  186. # print('[Error] filePath can not None!')
  187. # exit(1)
  188. sourceFilePaths = getAllNibSrcPathFor(filePath)
  189. # *.storyboard 国际化
  190. for sourceFilePath in sourceFilePaths:
  191. baseStrIdx = 0
  192. try:
  193. baseStrIdx = sourceFilePath.index('Base.lproj')
  194. except Exception as e:
  195. pass
  196. else:
  197. sourceFilePathName = sourceFilePath + '/*.storyboard'
  198. upperFilePath = sourceFilePath[0:(baseStrIdx-1)]
  199. #print upperFilePath
  200. generateLocalizableFiles(upperFilePath, sourceFilePathName)
  201. # *.xib 国际化
  202. for sourceFilePath in sourceFilePaths:
  203. baseStrIdx = 0
  204. try:
  205. baseStrIdx = sourceFilePath.index('Base.lproj')
  206. except Exception as e:
  207. pass
  208. else:
  209. sourceFilePathName = sourceFilePath + '/*.xib'
  210. upperFilePath = sourceFilePath[0:(baseStrIdx-1)]
  211. #print upperFilePath
  212. generateLocalizableFiles(upperFilePath, sourceFilePathName)
  213. if __name__ == '__main__':
  214. main()