#
# 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("
", file=outputFile)
print(" ", end="", file=outputFile)
print(title, end="", file=outputFile)
print(" ", end="", file=outputFile)
print('', file=outputFile)
print("", file=outputFile)
print("", title, "
", sep="", file=outputFile)
printHorizontalLine(outputFile)
printHeader("h2", "Source File Summary", outputFile)
print("", file=outputFile)
print("- iOS total number of strings:", len(iOSStrings), "in", len(iOSFiles), "files.
", file=outputFile)
print("- android total number of strings:", len(androidStrings), "in", len(androidFiles), "files.
", file=outputFile)
for f in iOSFiles:
print("- iOS File: ", f, "
", file=outputFile)
for f in androidFiles:
print("- Android File:", f, "
", file=outputFile)
print("
", 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", "Summary Report iOS vs Android", outputFile)
printHorizontalLine(outputFile)
print("", file=outputFile)
print("- ", len(found), "strings match exactly between iOS and android
", file=outputFile)
print("- ", len(fuzzy), "iOS strings are similar to Android
", file=outputFile)
print("- ", len(iOSStrings), "iOS strings do not match Android
", file=outputFile)
print("- ", len(androidStrings), "Android Strings do not match iOS
", file=outputFile)
print("- ", withWildcards, "strings have wildcards for iOS
", file=outputFile)
print("- ", withWildcardsAndroid, "strings have wildcards for Android
", file=outputFile)
print("- ", len(foundUpper), "iOS strings differ by case with Android
", file=outputFile)
print("- ", len(foundStartsWith), "iOS strings start with words similar to Android
", file=outputFile)
print("- ", len(foundPunctuation), "iOS strings differ by punctuation with Android
", file=outputFile)
print("- ", len(iOSStringsWithEscapeSequences), "iOS strings have Escape Sequences
", file=outputFile)
print("- ", len(androidStringsWithEscapeSequences), "Android strings have Escape Sequences
", file=outputFile)
print("- ", len(androidStringsWithBadWords), "Android Strings with Invalid Words
", file=outputFile)
print("
", file=outputFile)
printHeader("h2", "iOS Strings that differ by case with Android", outputFile)
printHorizontalLine(outputFile)
printPreformatedComparisonList(foundUpper, outputFile)
printHeader("h2", "iOS Strings start with words similar Android", outputFile)
printHorizontalLine(outputFile)
printPreformatedComparisonList(foundStartsWith, outputFile)
printHeader("h2", "iOS Strings are similar to Android", outputFile)
printHorizontalLine(outputFile)
printPreformatedComparisonList(fuzzy, outputFile)
printHeader("h2", "iOS Strings that differ by punctuation with Android", outputFile)
printHorizontalLine(outputFile)
printPreformatedComparisonList(foundPunctuation, outputFile)
printHeader("h2", "iOS Strings with escape sequences", outputFile)
printHorizontalLine(outputFile)
for w in iOSStringsWithEscapeSequences:
print("", file=outputFile)
try:
if iOSStringsWithEscapeSequences[w][0] == 'i':
print("
", file=outputFile)
print("iOS: ", end="", file=outputFile)
else:
print("", file=outputFile)
print("android: ", end="", file=outputFile)
print("'", w, "' - ", iOSStringsWithEscapeSequences[w], sep="", file=outputFile)
print("", file=outputFile)
except UnicodeEncodeError:
print("UnicodeDecodeError exception")
print(" ", file=outputFile)
printHeader("h2", "Android Strings with escape sequences [problematic: \\n = line breaks]", outputFile)
printHorizontalLine(outputFile)
for w in androidStringsWithEscapeSequences:
print("", file=outputFile)
try:
if androidStringsWithEscapeSequences[w][0] == 'i':
print("
", file=outputFile)
print("iOS: ", end="", file=outputFile)
else:
print("", file=outputFile)
print("android: ", end="", file=outputFile)
print("'", w, "' - ", androidStringsWithEscapeSequences[w], sep="", file=outputFile)
print("", file=outputFile)
except UnicodeEncodeError:
print("UnicodeDecodeError exception")
print(" ", file=outputFile)
printHeader("h2", "Android Strings with Invalid Words", outputFile)
printHorizontalLine(outputFile)
for w in androidStringsWithBadWords:
print("", file=outputFile)
try:
if androidStringsWithBadWords[w][0] == 'i':
print("
", file=outputFile)
print("iOS: ", end="", file=outputFile)
else:
print("", file=outputFile)
print("android: ", end="", file=outputFile)
print("'", w, "' - ", androidStringsWithBadWords[w], sep="", file=outputFile)
print("", file=outputFile)
except UnicodeEncodeError:
print("UnicodeDecodeError exception")
print(" ", file=outputFile)
printHeader("h2", "iOS Strings that differ by wildcard with Android (These appear the same to the user)", outputFile)
printHorizontalLine(outputFile)
printPreformatedComparisonList(foundWildCards, outputFile)
printHeader("h2", "iOS Strings found in Android", outputFile)
printHorizontalLine(outputFile)
for f in found:
print("", file=outputFile)
print("
", file=outputFile)
print("'", f, "': in iOS matches ", found[f], " in Android", sep="", file=outputFile)
print("", file=outputFile)
print("
", file=outputFile)
printHeader("h2", "Wildcard strings containing %", outputFile)
printHorizontalLine(outputFile)
stringsWithWildcardsList.sort(key=mykey)
for w in stringsWithWildcardsList:
print("", file=outputFile)
try:
if stringsWithWildcards[w][0] == 'i':
print("
", file=outputFile)
print("iOS: ", end="", file=outputFile)
else:
print("", file=outputFile)
print("android: ", end="", file=outputFile)
print("'", w, "' - ", stringsWithWildcards[w], sep="", file=outputFile)
print("", file=outputFile)
except UnicodeEncodeError:
print("UnicodeDecodeError exception")
print(" ", file=outputFile)
print(file=outputFile)
printHeader("h2", "List of Strings not found in the other platform", outputFile)
printHorizontalLine(outputFile)
listNotFound.sort(key=mykey)
for l in listNotFound:
print("", file=outputFile)
try:
if notFound[l][0] == 'i':
print("
", file=outputFile)
print("iOS: ", end="", file=outputFile)
else:
print("", file=outputFile)
print("android: ", end="", file=outputFile)
print("'", l, "' - ", notFound[l], sep="", file=outputFile)
print("", file=outputFile)
except UnicodeEncodeError:
print("UnicodeDecodeError exception")
except KeyError:
print("KeyError")
print(" ", file=outputFile)
print("", file=outputFile)
print("", file=outputFile)
outputFile.close()
def printPreformatedComparisonList(found, outputFile):
if len(found) > 0:
for f in found:
print("", file=outputFile)
print("
", file=outputFile)
print("iOS: '", f, "'", sep="", file=outputFile)
print("", file=outputFile)
print("
", file=outputFile)
print("android: '", found[f], "' ", getAndroidStringLocation(found[f]), sep="", file=outputFile)
print("", file=outputFile)
print("
", file=outputFile)
else:
printParagraph("no results found that match this criteria", outputFile)
def printParagraph(text, outputFile):
print("" + text + "
", file=outputFile)
def printHorizontalLine(outputFile):
print("
", file=outputFile)
def getAndroidStringLocation(a):
return "[{}/{}]".format(androidStrings[a]["module"], androidStrings[a]["name"])
# perform the comparisons
main()