# # 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 + "", 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) # 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) 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()