Files
coco 7846a45f2c a
2026-07-03 15:47:27 +08:00

485 lines
19 KiB
Python

#
# Copyright 2020 Dash Core Group
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# author: Eric Britten
# Sync Translations
import codecs
import xml.dom.minidom
import re
from datetime import date
from fuzzywuzzy import fuzz
from fuzzywuzzy import process
androidFiles = [
"../wallet/res/values/strings.xml",
"../wallet/res/values/strings-extra.xml",
"../common/src/main/res/values/strings.xml",
"../integrations/uphold/src/main/res/values/strings-uphold.xml",
"../integrations/crowdnode/src/main/res/values/strings-crowdnode.xml",
"../integrations/coinbase/src/main/res/values/strings.xml",
"../features/exploredash/src/main/res/values/strings-explore-dash.xml"
]
androidFileDesc = ["wallet", "wallet", "common", "uphold", "crowdnode", "coinbase", "explore-dash"]
iOSFiles = {"iOS/app-localizable-strings.strings", "iOS/dashsync-localizable-strings.strings"}
# primary lists
androidStrings = {}
iOSStrings = []
def loadAndroidFiles():
"""
Load all of the android strings into a dictionary
The key is the string
The value is the android string id
"""
for i in range(len(androidFiles)):
fileName = androidFiles[i]
module = androidFileDesc[i]
doc = xml.dom.minidom.parse(fileName)
resourceNode = doc.getElementsByTagName("resources")[0]
for string in resourceNode.childNodes:
try:
if string.nodeName == "string":
stringData = {}
stringData["name"] = string.getAttribute("name")
stringData["module"] = module
androidStrings[string.firstChild.data] = stringData #string.getAttribute("name")
except AttributeError:
pass
def loadiOSFiles():
"""
load all of the iOS strings into a list
"""
for fileName in iOSFiles:
file = open(fileName+"-utf8", "r")
for line in file:
if line.startswith("\""):
end = line.find('\"', 1)
if end != -1:
iOSStrings.append(line[1:end])
def formatiOSFiles():
"""Convert the iOS string format of UTF-16LE to UTF8"""
for fileName in iOSFiles:
with open(fileName, 'rb') as source_file:
with open(fileName + "-utf8", 'w+b') as dest_file:
contents = source_file.read()
dest_file.write(contents.decode('utf-16').encode('utf-8'))
def mykey(val):
return val.upper()
def printHeader(header, text, output):
print("<" + header + ">" + text + "</" + header + ">", file=output)
def countWords(text):
words = 1
lastChar = ''
for char in text:
if char.isspace() and char != lastChar:
words += 1
lastChar = char
return words
def getFirstThreeWords(text):
words = 1
threeWords = ''
lastChar = ''
for char in text:
if char.isspace() and char != lastChar:
words += 1
if words > 3:
return threeWords.rstrip(",.!?;:")
lastChar = char
threeWords += char
return threeWords.rstrip(",.!?;:")
def fuzzycompare(iOSStrings, androidStrings):
matches = {}
for i in iOSStrings:
if countWords(i) > 2:
for a in androidStrings:
if countWords(a) > 2:
ratio = fuzz.WRatio(i, a)
if ratio > 87:
matches[i] = a
return matches
def main():
loadAndroidFiles()
#print(androidStrings)
formatiOSFiles()
loadiOSFiles()
#print(iOSStrings)
found = {}
notFound = {}
listNotFound = []
withWildcards = 0
withWildcardsAndroid = 0
iOSStringsWithWildcards = []
androidStringsWithWildcards = []
stringsWithWildcards = {}
stringsWithWildcardsList = []
iOSStringsWithEscapeSequences = {}
androidStringsWithEscapeSequences = {}
androidStringsWithBadWords = {}
# currently these are case sensitive
badWords = [ "passphrase", "Passphrase", "secret key", "Crowdnode", "crowdnode" "CoinBase"]
outputFile = codecs.open("translation-comparison-report.html", "w", "utf-8")
outputFile.write(u'\ufeff')
title = "Translation Source Comparison Report: " + str(date.today())
print("<!DOCTYPE html><html><head>", file=outputFile)
print(" <title>", end="", file=outputFile)
print(title, end="", file=outputFile)
print(" </title>", end="", file=outputFile)
print('<STYLE type="text/css"">' +
'H1, H2, H3 { color: blue; font-family: Arial}\n' +
'.ios { color: red; }\n' +
'.android { color: green; }\n' +
'.string { border-width: 1px; border-style: solid }' +
'</STYLE>', file=outputFile)
print("</head><body>", file=outputFile)
print("<h1>", title, "</h1>", sep="", file=outputFile)
printHorizontalLine(outputFile)
printHeader("h2", "Source File Summary", outputFile)
print("<ul>", file=outputFile)
print("<li>iOS total number of strings:", len(iOSStrings), "in", len(iOSFiles), "files.</li>", file=outputFile)
print("<li>android total number of strings:", len(androidStrings), "in", len(androidFiles), "files.</li>", file=outputFile)
for f in iOSFiles:
print("<li>iOS File: ", f, "</li>", file=outputFile)
for f in androidFiles:
print("<li>Android File:", f, "</li>", file=outputFile)
print("</ul>", file=outputFile)
# find exact matches
for i in iOSStrings:
if i.find("%@") != -1:
withWildcards += 1
iOSStringsWithWildcards.append(i)
stringsWithWildcards[i] = "iOS"
stringsWithWildcardsList.append(i)
if i.find('\\') != -1:
iOSStringsWithEscapeSequences[i] = "iOS"
if i in androidStrings:
found[i] = androidStrings[i]["name"]
else:
notFound[i] = "iOS"
listNotFound.append(i)
for a in androidStrings:
if a.find('\\') != -1:
androidStringsWithEscapeSequences[a] = "android - " + getAndroidStringLocation(a)
for a in androidStrings:
for badWord in badWords:
if a.find(badWord) != -1:
androidStringsWithBadWords[a] = "android - " + getAndroidStringLocation(a) + " word: " + badWord
for f in found:
if f in androidStrings:
del androidStrings[f]
if f in iOSStrings:
iOSStrings.remove(f)
fuzzy = fuzzycompare(iOSStrings, androidStrings)
# compare case
iOSStringsUpper = {}
androidStringsUpper = {}
foundUpper = {}
foundStartsWith = {}
for i in iOSStrings:
iOSStringsUpper[i.upper()] = i
for a in androidStrings:
androidStringsUpper[a.upper()] = a
if a.find("%") != -1:
withWildcardsAndroid += 1
androidStringsWithWildcards.append(a)
stringsWithWildcards[a] = "android - " + getAndroidStringLocation(a)
stringsWithWildcardsList.append(a)
for i in iOSStringsUpper:
if i in androidStringsUpper:
foundUpper[iOSStringsUpper[i]] = androidStringsUpper[i]
del androidStringsUpper[i]
try:
del notFound[iOSStringsUpper[i]]
listNotFound.remove(iOSStringsUpper[i])
except KeyError:
pass
try:
del notFound[androidStringsUpper[i]]
listNotFound.remove(androidStringsUpper[i])
except KeyError:
pass
else:
# look for strings that start with the same words
words = countWords(i)
threeWords = getFirstThreeWords(i)
for a in androidStringsUpper:
if words >= 2:
if a.startswith(i):
foundStartsWith[iOSStringsUpper[i]] = androidStringsUpper[a]
elif words > 2:
if a.startswith(threeWords):
foundStartsWith[iOSStringsUpper[i]] = androidStringsUpper[a]
for a in androidStringsUpper:
if a not in iOSStringsUpper:
words = countWords(a)
threeWords = getFirstThreeWords(a)
for i in iOSStringsUpper:
if words >= 2:
if i.startswith(a):
foundStartsWith[iOSStringsUpper[i]] = androidStringsUpper[a]
elif words > 2:
if i.startswith(threeWords):
foundStartsWith[iOSStringsUpper[i]] = androidStringsUpper[a]
# find differences in punctuation:
iOSStringsUpperNoPunctuation = {}
androidStringsUpperNoPunctuation = {}
for i in iOSStringsUpper:
iOSStringsUpperNoPunctuation[re.sub("[,.!?;:]", "", i)] = iOSStringsUpper[i]
for a in androidStringsUpper:
androidStringsUpperNoPunctuation[re.sub("[,.!?;:]", "", a)] = androidStringsUpper[a]
foundPunctuation = {}
for i in iOSStringsUpperNoPunctuation:
if i in androidStringsUpperNoPunctuation:
foundPunctuation[iOSStringsUpperNoPunctuation[i]] = androidStringsUpperNoPunctuation[i]
for a in androidStringsUpperNoPunctuation:
if a in iOSStringsUpperNoPunctuation:
foundPunctuation[iOSStringsUpperNoPunctuation[a]] = androidStringsUpperNoPunctuation[a]
# find differences in strings with wildcards:
foundWildCards = {}
iOSStringsUpperNoWildCards = {}
androidStringsUpperNoWildCards = {}
for i in iOSStringsUpper:
if i.find('%') != -1:
iOSStringsUpperNoWildCards[re.sub("%[@D]", "", i)] = iOSStringsUpper[i]
for a in androidStringsUpper:
if a.find('%') != -1:
androidStringsUpperNoWildCards[re.sub("%[SD]", "", a)] = androidStringsUpper[a]
for i in iOSStringsUpperNoWildCards:
if i in androidStringsUpperNoWildCards:
foundWildCards[iOSStringsUpperNoWildCards[i]] = androidStringsUpperNoWildCards[i]
for a in androidStringsUpperNoWildCards:
if a in iOSStringsUpperNoWildCards:
foundWildCards[androidStringsUpperNoWildCards[a]] = androidStringsUpperNoWildCards[a]
# add the remaining non matching android strings to the not found lists
for a in androidStrings:
notFound[a] = "android -- " + getAndroidStringLocation(a)
listNotFound.append(a)
# print report
print(file=outputFile)
printHeader("h2", "<a name='top'>Summary Report iOS vs Android</a>", outputFile)
printHorizontalLine(outputFile)
print("<ul>", file=outputFile)
print("<li><a href='#exact'>", len(found), "strings match exactly between iOS and android</a></li>", file=outputFile)
print("<li><a href='#fuzzy'>", len(fuzzy), "iOS strings are similar to Android</li>", file=outputFile)
print("<li><a href='#nomatch'>", len(iOSStrings), "iOS strings do not match Android</li>", file=outputFile)
print("<li><a href='#nomatch'>", len(androidStrings), "Android Strings do not match iOS</li>", file=outputFile)
print("<li><a href='#wildcard'>", withWildcards, "strings have wildcards for iOS</li>", file=outputFile)
print("<li><a href='#wildcard'>", withWildcardsAndroid, "strings have wildcards for Android</li>", file=outputFile)
print("<li><a href='#case'>", len(foundUpper), "iOS strings differ by case with Android</a></li>", file=outputFile)
print("<li><a href='#start'>", len(foundStartsWith), "iOS strings start with words similar to Android</a></li>", file=outputFile)
print("<li><a href='#punctuation'>", len(foundPunctuation), "iOS strings differ by punctuation with Android</a></li>", file=outputFile)
print("<li><a href='#iosescape'>", len(iOSStringsWithEscapeSequences), "iOS strings have Escape Sequences</a></li>", file=outputFile)
print("<li><a href='#androidescape'>", len(androidStringsWithEscapeSequences), "Android strings have Escape Sequences</a></li>", file=outputFile)
print("<li><a href='#bad'>", len(androidStringsWithBadWords), "Android Strings with Invalid Words</a></li>", file=outputFile)
print("</ul>", file=outputFile)
printHeader("h2", "<a name='case'>iOS Strings that differ by case with Android</a>", outputFile)
printHorizontalLine(outputFile)
printPreformatedComparisonList(foundUpper, outputFile)
printHeader("h2", "<a name='start'>iOS Strings start with words similar Android</a>", outputFile)
printHorizontalLine(outputFile)
printPreformatedComparisonList(foundStartsWith, outputFile)
printHeader("h2", "<a name='fuzzy'>iOS Strings are similar to Android</a>", outputFile)
printHorizontalLine(outputFile)
printPreformatedComparisonList(fuzzy, outputFile)
printHeader("h2", "<a name='punctuation'>iOS Strings that differ by punctuation with Android</a>", outputFile)
printHorizontalLine(outputFile)
printPreformatedComparisonList(foundPunctuation, outputFile)
printHeader("h2", "<a name='iosescape'>iOS Strings with escape sequences</a>", outputFile)
printHorizontalLine(outputFile)
for w in iOSStringsWithEscapeSequences:
print("<div class=string>", file=outputFile)
try:
if iOSStringsWithEscapeSequences[w][0] == 'i':
print("<pre class=ios>", file=outputFile)
print("iOS: ", end="", file=outputFile)
else:
print("<pre class=android>", file=outputFile)
print("android: ", end="", file=outputFile)
print("'", w, "' - ", iOSStringsWithEscapeSequences[w], sep="", file=outputFile)
print("</pre>", file=outputFile)
except UnicodeEncodeError:
print("UnicodeDecodeError exception")
print("</div>", file=outputFile)
printHeader("h2", "<a name='androidescape'>Android Strings with escape sequences [problematic: \\n = line breaks]</a>", outputFile)
printHorizontalLine(outputFile)
for w in androidStringsWithEscapeSequences:
print("<div class=string>", file=outputFile)
try:
if androidStringsWithEscapeSequences[w][0] == 'i':
print("<pre class=ios>", file=outputFile)
print("iOS: ", end="", file=outputFile)
else:
print("<pre class=android>", file=outputFile)
print("android: ", end="", file=outputFile)
print("'", w, "' - ", androidStringsWithEscapeSequences[w], sep="", file=outputFile)
print("</pre>", file=outputFile)
except UnicodeEncodeError:
print("UnicodeDecodeError exception")
print("</div>", file=outputFile)
printHeader("h2", "<a name='bad'>Android Strings with Invalid Words</a>", outputFile)
printHorizontalLine(outputFile)
for w in androidStringsWithBadWords:
print("<div class=string>", file=outputFile)
try:
if androidStringsWithBadWords[w][0] == 'i':
print("<pre class=ios>", file=outputFile)
print("iOS: ", end="", file=outputFile)
else:
print("<pre class=android>", file=outputFile)
print("android: ", end="", file=outputFile)
print("'", w, "' - ", androidStringsWithBadWords[w], sep="", file=outputFile)
print("</pre>", file=outputFile)
except UnicodeEncodeError:
print("UnicodeDecodeError exception")
print("</div>", file=outputFile)
printHeader("h2", "<a name='wildcard'>iOS Strings that differ by wildcard with Android (These appear the same to the user)</a>", outputFile)
printHorizontalLine(outputFile)
printPreformatedComparisonList(foundWildCards, outputFile)
printHeader("h2", "<a name='exact'>iOS Strings found in Android</a>", outputFile)
printHorizontalLine(outputFile)
for f in found:
print("<div class=string>", file=outputFile)
print("<pre>", file=outputFile)
print("'", f, "': in iOS matches ", found[f], " in Android", sep="", file=outputFile)
print("</pre>", file=outputFile)
print("</div>", file=outputFile)
printHeader("h2", "<a name='wildcard'>Wildcard strings containing %</a>", outputFile)
printHorizontalLine(outputFile)
stringsWithWildcardsList.sort(key=mykey)
for w in stringsWithWildcardsList:
print("<div class=string>", file=outputFile)
try:
if stringsWithWildcards[w][0] == 'i':
print("<pre class=ios>", file=outputFile)
print("iOS: ", end="", file=outputFile)
else:
print("<pre class=android>", file=outputFile)
print("android: ", end="", file=outputFile)
print("'", w, "' - ", stringsWithWildcards[w], sep="", file=outputFile)
print("</pre>", file=outputFile)
except UnicodeEncodeError:
print("UnicodeDecodeError exception")
print("</div>", file=outputFile)
print(file=outputFile)
printHeader("h2", "<a name='notfound'>List of Strings not found in the other platform</a>", outputFile)
printHorizontalLine(outputFile)
listNotFound.sort(key=mykey)
for l in listNotFound:
print("<div class=string>", file=outputFile)
try:
if notFound[l][0] == 'i':
print("<pre class=ios>", file=outputFile)
print("iOS: ", end="", file=outputFile)
else:
print("<pre class=android>", file=outputFile)
print("android: ", end="", file=outputFile)
print("'", l, "' - ", notFound[l], sep="", file=outputFile)
print("</pre>", file=outputFile)
except UnicodeEncodeError:
print("UnicodeDecodeError exception")
except KeyError:
print("KeyError")
print("</div>", file=outputFile)
print("</body>", file=outputFile)
print("</html>", file=outputFile)
outputFile.close()
def printPreformatedComparisonList(found, outputFile):
if len(found) > 0:
for f in found:
print("<div class=string>", file=outputFile)
print("<pre class=ios>", file=outputFile)
print("iOS: '", f, "'", sep="", file=outputFile)
print("</pre>", file=outputFile)
print("<pre class=android>", file=outputFile)
print("android: '", found[f], "' ", getAndroidStringLocation(found[f]), sep="", file=outputFile)
print("</pre>", file=outputFile)
print("</div>", file=outputFile)
else:
printParagraph("no results found that match this criteria", outputFile)
def printParagraph(text, outputFile):
print("<p>" + text + "</p>", file=outputFile)
def printHorizontalLine(outputFile):
print("<hr />", file=outputFile)
def getAndroidStringLocation(a):
return "[{}/{}]".format(androidStrings[a]["module"], androidStrings[a]["name"])
# perform the comparisons
main()