#!/usr/bin/env python3 """Translation check (run by build.sh): 1. every L.t("...") / L.f("...") key in the code has a Galician entry in L.java, 2. English and Galician use the same placeholders in the same order, 3. no English text reaches the screen without going through L (setText/setTitle/... literals), 4. no unused entries. usage: check_i18n.py """ import os import re import sys root = sys.argv[1] if len(sys.argv) > 1 else "." LIT = r'"((?:[^"\\]|\\.)*)"' def unescape(s): out, i = [], 0 while i < len(s): c = s[i] if c == "\\" and i + 1 < len(s): n = s[i + 1] if n == "u": out.append(chr(int(s[i + 2:i + 6], 16))) i += 6 continue out.append({"n": "\n", "t": "\t", "r": "\r", '"': '"', "'": "'", "\\": "\\"}.get(n, n)) i += 2 continue out.append(c) i += 1 return "".join(out) def placeholders(s): return re.findall(r"%[sdn%]", s) lsrc = open(os.path.join(root, "src/org/gingercal/L.java"), encoding="utf-8").read() table = {} for m in re.finditer(r"put\(\s*" + LIT + r"\s*,\s*" + LIT + r"\s*\);", lsrc, re.S): en, gal = unescape(m.group(1)), unescape(m.group(2)) if en in table: print("DUPLICATE key:", en[:60]) table[en] = gal problems, used = [], set() UI_CALL = re.compile(r"\b(setText|setTitle|setMessage|setHint|setPositiveButton|setNegativeButton|setNeutralButton|" r"toast\([^,]+,|ProgressDialog\.show\([^,]+,[^,]+,|Rows\.add|rows\.add|Rows\.add|" r"new DavException\([^,]+,|new IOException\(|label\(|field\([^,]+,)\s*\(?\s*" + LIT) for d in ("src", "android"): for dirpath, _, files in os.walk(os.path.join(root, d)): for f in files: if not f.endswith(".java") or f == "L.java": continue path = os.path.join(dirpath, f) text = open(path, encoding="utf-8").read() for m in re.finditer(r"\bL\.[tf]\(\s*" + LIT, text): key = unescape(m.group(1)) used.add(key) if key not in table: problems.append("%s: no Galician for %r" % (f, key[:70])) elif placeholders(key) != placeholders(table[key]): problems.append("%s: placeholders differ for %r" % (f, key[:70])) for line_no, line in enumerate(text.splitlines(), 1): for m in UI_CALL.finditer(line): s = unescape(m.group(2)) if re.search(r"[A-Za-z]{2,}", s) and s not in ("Galego", "English", "Lingua / Language"): problems.append("%s:%d: untranslated UI text %r" % (f, line_no, s[:60])) for m in re.finditer(r"\.add\(\s*" + LIT, line): s = unescape(m.group(1)) if " " in s and re.search(r"[A-Za-z]{3,} [A-Za-z]{3,}", s): problems.append("%s:%d: untranslated list text %r" % (f, line_no, s[:60])) for key in sorted(set(table) - used): problems.append("unused entry in L.java: %r" % key[:70]) for p in problems: print("I18N:", p) print("translations: %d entries, %d keys used, %s" % (len(table), len(used), "OK" if not problems else "PROBLEMS")) sys.exit(1 if problems else 0)