171 lines
5.8 KiB
Python
Executable File
171 lines
5.8 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
#-*- coding: utf-8 -*-
|
|
|
|
import sys, os, re, json, codecs
|
|
|
|
def myUnescape(s):
|
|
return s.replace("\\'", "'").replace('\\"', '"')
|
|
|
|
class color:
|
|
PURPLE = '\033[95m'
|
|
CYAN = '\033[96m'
|
|
DARKCYAN = '\033[36m'
|
|
BLUE = '\033[94m'
|
|
GREEN = '\033[92m'
|
|
YELLOW = '\033[93m'
|
|
RED = '\033[91m'
|
|
BOLD = '\033[1m'
|
|
UNDERLINE = '\033[4m'
|
|
END = '\033[0m'
|
|
|
|
def findRecursiveByExt(topdir, ext):
|
|
pathList = []
|
|
for dirpath, dirnames, files in os.walk(topdir):
|
|
for name in files:
|
|
if name.lower().endswith(ext):
|
|
pathList.append(os.path.join(dirpath, name))
|
|
return pathList
|
|
|
|
def phpWhereIs(s, p):
|
|
ln = 1
|
|
f = codecs.open(p, 'r', 'utf-8')
|
|
for line in f:
|
|
if re.search('>t\s*\(\s*[\'"](%s)[\'"]\s*\)' % re.escape(s), line):
|
|
f.close()
|
|
return ln
|
|
ln += 1
|
|
f.close()
|
|
|
|
def jsWhereIs(s, p, appname):
|
|
ln = 1
|
|
f = codecs.open(p, 'r', 'utf-8')
|
|
for line in f:
|
|
if re.search('t\s*\(\s*[\'"]%s[\'"]\s*,\s*[\'"](%s)[\'"]\s*[,)]' % (appname, re.escape(s)), line):
|
|
f.close()
|
|
return ln
|
|
ln += 1
|
|
f.close()
|
|
|
|
def jsonWhereIs(s, p):
|
|
ln = 1
|
|
f = codecs.open(p, 'r', 'utf-8')
|
|
for line in f:
|
|
if re.search('"%s"' % re.escape(s), line):
|
|
f.close()
|
|
return ln
|
|
ln += 1
|
|
f.close()
|
|
|
|
if __name__ == '__main__':
|
|
lang = sys.argv[1]
|
|
apppath = sys.argv[2]
|
|
appname = sys.argv[3]
|
|
|
|
########## parse PHP files #################
|
|
|
|
phpPathList = findRecursiveByExt(apppath, '.php')
|
|
phpContents = {}
|
|
phpCodeTranslations = []
|
|
phpCodeTranslationsByFile = {}
|
|
phpCodeTranslationsCorresp = {}
|
|
for path in phpPathList:
|
|
f = codecs.open(path, 'r', 'utf-8')
|
|
tlist = list(set(re.findall('>t\s*\(\s*[\'"](.*)[\'"]\s*\)', f.read())))
|
|
f.close()
|
|
tlistUnesc = list(map(myUnescape, tlist))
|
|
phpCodeTranslations.extend(tlistUnesc)
|
|
phpCodeTranslationsByFile[path] = tlistUnesc
|
|
# find line numbers after
|
|
for i in range(len(tlist)):
|
|
phpCodeTranslationsCorresp[tlistUnesc[i]] = tlist[i]
|
|
|
|
phpCodeTranslations.sort()
|
|
|
|
jsonf = codecs.open('%s/l10n/%s.json'%(apppath, lang), 'r', 'utf-8')
|
|
jsonc = json.load(jsonf)
|
|
|
|
keys = list(jsonc['translations'].keys())
|
|
keys.sort()
|
|
phpTranslations = list(map(myUnescape, keys))
|
|
phpTranslationsLineNumbers = {}
|
|
for i in range(len(phpTranslations)):
|
|
ln = jsonWhereIs(keys[i], '%s/l10n/%s.json'%(apppath, lang))
|
|
transText = phpTranslations[i]
|
|
phpTranslationsLineNumbers[transText] = ln
|
|
|
|
########## parse JS files #################
|
|
|
|
jsPathList = findRecursiveByExt(apppath, '.js')
|
|
jsContents = {}
|
|
jsCodeTranslations = []
|
|
jsCodeTranslationsByFile = {}
|
|
jsCodeTranslationsCorresp = {}
|
|
for path in jsPathList:
|
|
f = codecs.open(path, 'r', 'utf-8')
|
|
tlist = list(set(re.findall('t\s*\(\s*[\'"]%s[\'"]\s*,\s*[\'"](.*)[\'"]\s*[,)]'%appname, f.read())))
|
|
f.close()
|
|
tlistUnesc = list(map(myUnescape, tlist))
|
|
jsCodeTranslations.extend(tlistUnesc)
|
|
jsCodeTranslationsByFile[path] = tlistUnesc
|
|
# to find line numbers after
|
|
for i in range(len(tlist)):
|
|
jsCodeTranslationsCorresp[tlistUnesc[i]] = tlist[i]
|
|
|
|
jsCodeTranslations.sort()
|
|
|
|
jsjsonf = codecs.open('%s/l10n/%s.js'%(apppath, lang), 'r', 'utf-8')
|
|
jsjsons = jsjsonf.read()
|
|
jsjsons = jsjsons.replace('\n', '')
|
|
jsjsons = re.sub('[^{]*({.*})[^}]*', '\\1', jsjsons)
|
|
jsjsonc = json.loads(jsjsons)
|
|
|
|
keys = list(jsjsonc.keys())
|
|
keys.sort()
|
|
jsTranslations = list(map(myUnescape, keys))
|
|
jsTranslationsLineNumbers = {}
|
|
for i in range(len(jsTranslations)):
|
|
ln = jsonWhereIs(keys[i], '%s/l10n/%s.js'%(apppath, lang))
|
|
transText = jsTranslations[i]
|
|
jsTranslationsLineNumbers[transText] = ln
|
|
|
|
print('########### useless PHP translations ###############\n')
|
|
|
|
for s in phpTranslations:
|
|
if s not in phpCodeTranslations:
|
|
print('%s%s.json%s:%s%s%s: %s%s"%s"%s is useless, it was not found in any php file' %
|
|
(color.PURPLE, lang, color.END,
|
|
color.GREEN, phpTranslationsLineNumbers[s], color.END,
|
|
color.BOLD, color.RED, s, color.END))
|
|
|
|
print('\n########### useless js translations ###############\n')
|
|
|
|
for s in jsTranslations:
|
|
if s not in jsCodeTranslations:
|
|
print('%s%s.js%s:%s%s%s: %s%s"%s"%s is useless, it was not found in any js file' %
|
|
(color.PURPLE, lang, color.END,
|
|
color.GREEN, jsTranslationsLineNumbers[s], color.END,
|
|
color.BOLD, color.RED, s, color.END))
|
|
|
|
print('\n########### missing php translations ###############\n')
|
|
|
|
for fpath in phpCodeTranslationsByFile:
|
|
for s in phpCodeTranslationsByFile[fpath]:
|
|
if s not in phpTranslations:
|
|
print('%s%s%s:%s%s%s: %s%s"%s"%s is not translated in %s%s%s.json%s' %
|
|
(color.PURPLE, fpath, color.END,
|
|
color.GREEN, phpWhereIs(phpCodeTranslationsCorresp[s], fpath), color.END,
|
|
color.BOLD, color.RED, s, color.END,
|
|
color.GREEN, color.BOLD, lang, color.END))
|
|
|
|
print('\n########### missing js translations ###############\n')
|
|
|
|
for fpath in jsCodeTranslationsByFile:
|
|
for s in jsCodeTranslationsByFile[fpath]:
|
|
if s not in jsTranslations:
|
|
print('%s%s%s:%s%s%s: %s%s"%s"%s is not translated in %s%s%s.js%s' %
|
|
(color.PURPLE, fpath, color.END,
|
|
color.GREEN, jsWhereIs(jsCodeTranslationsCorresp[s], fpath, appname), color.END,
|
|
color.BOLD, color.RED, s, color.END,
|
|
color.GREEN, color.BOLD, lang, color.END))
|
|
|