由于需要将之前使用Java开发的代码进行俄文本地化,原来没有考虑本地化工作,费劲地将代码中所有的中文字符转成res.getString("xxx")模式,但是由于代码比较多,难免会出现字符串输入错误,而Java编译器不能在编译时发现找不到对应的字符串,运行时可能会出现空指针异常。为了解决这个问题就想写个程序能够自动匹配一下本地化字符串,发现可能存在的问题。而正在学习Python,听说这个东西写程序很简单,就拿这事练手吧。因此就有了下面的这些代码。由于是边看英文手册变写程序,因此代码可能不够简洁,算法也不会很好。但是确实正确地解决了我的问题。如果您也有这样的需求,不妨测试一下这个代码。如果您甚至还想改进这个代码,那就更好了,别忘了将代码也发给大家看看。
# -*- coding: gbk -*-
#Author: Ultrared
#Date: 2009-10-13
#Java本地化字符串检查
#资源文件中是否有重复的字符串
#Java源文件调用的字符串是否在资源文件中有对应的字符串
#
#使用限制:
#目前只支持ListResourceBunble
#定义资源文件中包含:extends ListResourceBundle
#使用资源文件中包含:
#资源变量定义,ResourceBundle xxx = ResourceBundle.getBundle("yyy")
#资源字符串使用,xxx.getString("zzz")
#资源字符串的定义:[A-Za-z0-9,_,.]+
#
#命令行参数:
#一个参数,指定Java工程源文件目录
#
import string, os, sys, re
#检查源文件
def checkSource(root, verbose):
global deep,fileCount,mismatchNum
files = os.listdir(root)
deep = deep + 1
filePrefix = ""
dirPrefix = ""
for i in range(0,deep):
filePrefix = filePrefix + "--"
for i in range(0,deep):
dirPrefix = dirPrefix + "=="
for f in files:
pathfile=os.path.join(root, f) #要处理的文件绝对路径
if os.path.isfile(pathfile):
if re.search("java",f):
if verbose:
print(filePrefix+f)
fileCount = fileCount + 1
#读入全部文件内容
fo = open(pathfile)
content = ""
try:
content = fo.read( )
finally:
fo.close( )
#搜索ResourceBundle变量定义,可能定义了多个变量对应不同的资源文件
resFileURL=re.findall(r'ResourceBundle/s*[A-Za-z0-9,_]+/s*=/s*ResourceBundle.getBundle/(/s*".*"/s*/)',content)
if resFileURL:
for k in range(0,len(resFileURL)): #循环多个ResourceBundle变量
resFileURL[k]=resFileURL[k].replace("/r","")
resFileURL[k]=resFileURL[k].replace("/n","")
#获得资源变量名称
resvar=re.search(r'/s+[A-Za-z0-9,_]+/s+/=', resFileURL[k]).group(0)
resvar=resvar.replace("=","")
resvar=resvar.strip()
#获得资源文件类路径,例如:com.xyz.MyResource
url=re.search(r'"[A-Za-z0-9,_,/.]+"',resFileURL[k]).group(0)
url=url.replace("/"","")
#搜索文件中所有的resvar.getString("...")
pattern = resvar + '/.getString/(/s*"[A-Za-z0-9,.,_]+"/s*/)'
result = re.findall(pattern, content)
for j in range(0,resFileNum):
fileURL=resFilePath[j].replace(os.sep,".") #将文件绝对路径转成近似的类路径,用于查找对应的资源文件
if re.search(url,fileURL): #找此Java文件对应的资源文件
keyword = resFileKeyword[j] #对应的资源文件的(key,value)哈希表
for i in range(0,len(result)):
#获得资源字符串
key=result[i].replace("/r","")
key=key.replace("/n","")
key=key.replace(" ","")
key=key.replace(resvar+".getString(/"","")
key=key.replace("/")","")
if not keyword.has_key(key): #查找资源字符串在对应资源文件中是否存在
mismatchNum+=1
print(filePrefix+f +", mismatch: " + key + ", " + result[i])
else:
usedKeywords[key]="1" #记录使用的key
break
else:
if verbose:
print(dirPrefix+f)
checkSource(pathfile, verbose)
deep = deep -1
#搜索资源文件,找出本地化字符串
def findResource(root):
global resFileNum,resFileKeyword,resFilePath
files = os.listdir(root)
for f in files:
pathfile=os.path.join(root, f)
if os.path.isfile(pathfile):
#读入文件内容
fo = open(pathfile)
content = ""
try:
content = fo.read( )
finally:
fo.close( )
if re.search("extends ListResourceBundle", content): #判断是否是资源文件
keyword={}
print(f)
result=re.findall(r'/{/s*".*"/s*,/s*".*"/s*/}', content)
for i in range(0,len(result)):
result[i]=result[i].replace("/r","")
result[i]=result[i].replace("/n","")
item=result[i].split("/"") #使用引号分割字符串
if keyword.has_key(item[1]):
print(f+" duplicated key "+item[1])
else:
keyword[item[1]]=item[3]
resFileKeyword.append(keyword) #添加到资源文件(key,value)哈希表列表
resFilePath.append(pathfile) #添加到资源文件名称列表
resFileName.append(f)
resFileNum += 1
else:
findResource(pathfile)
###################################
# Main
###################################
DEBUG = False
root=sys.argv[1] #Java源文件目录
resFileKeyword=[]
resFilePath=[]
resFileName=[]
usedKeywords={}
resFileNum = 0
deep = 0
fileCount = 0
mismatchNum = 0
print("Check java files in " + root + "/n")
print("Resource files list:")
findResource(root)
print("/nResource keywords list:")
for i in range(0,resFileNum):
keyword = resFileKeyword[i]
print(resFileName[i])
for k,v in keyword.iteritems():
print(k+"/t"+ v)
#搜索多个资源文件中重复定义的key
print("/nDuplicated keywords list:")
for i in range(0,resFileNum):
keyword1=resFileKeyword[i]
for j in range(0,resFileNum):
if j==i :
continue
keyword2=resFileKeyword[j]
for k,v in keyword1.iteritems():
if keyword2.has_key(k):
print(resFileName[i]+"/t"+resFileName[j]+"/t duplicated key "+ k +"/t"+v+"/t"+keyword2[k])
#搜索java源文件使用了而资源文件中没有定义的key
print("/nCheck java files...")
checkSource(root, DEBUG)
print("/n"+str(fileCount) + " java files checked, mismatch "+str(mismatchNum))
#搜索资源文件中已经定义而java源文件没有使用的key
print("/nNot used keywords list:")
for i in range(0,resFileNum):
keyword=resFileKeyword[i]
for k,v in keyword.iteritems():
if not usedKeywords.has_key(k):
print(resFileName[i]+"/t"+k)
print("/nGame Over")