Ariver
2026-06-28 755ca63e4d37c1a54db7fc6475152319a4e46ceb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#!/usr/bin/env bash
set -euo pipefail
 
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
 
python3 - "$ROOT_DIR" <<'PY'
import json
import pathlib
import re
import sys
 
root = pathlib.Path(sys.argv[1])
l10n_swift = root / "Apptag" / "L10n.swift"
localization_dir = root / "Apptag" / "Localization"
english_path = localization_dir / "en.json"
 
EXPECTED_LANGUAGE_COUNT = 29
ALLOWED_ENGLISH_COPY_KEYS = {
    "pro.card.badge",
}
REQUIRED_PLACEHOLDERS = {
    "pro.notes.remaining": {"%limit%", "%remaining%"},
    "pro.theme.status.previewCountdown": {"%time%"},
}
 
 
def fail(message: str) -> None:
    print(f"FAIL: {message}", file=sys.stderr)
    sys.exit(1)
 
 
def load_json(path: pathlib.Path) -> dict[str, str]:
    try:
        data = json.loads(path.read_text(encoding="utf-8"))
    except Exception as error:
        fail(f"{path} is not valid JSON: {error}")
    if not isinstance(data, dict):
        fail(f"{path} must contain a JSON object")
    return data
 
 
def extract_language_codes() -> list[str]:
    text = l10n_swift.read_text(encoding="utf-8")
    match = re.search(
        r"static\s+let\s+supported\s*:\s*\[\(code:\s*String,\s*name:\s*String\)\]\s*=\s*\[(.*?)\n\s*\]",
        text,
        re.S,
    )
    if not match:
        fail("could not find L10n.supported language list")
    codes = re.findall(r'\("([^"]+)",\s*"[^"]+"\)', match.group(1))
    if len(codes) != EXPECTED_LANGUAGE_COUNT:
        fail(f"L10n.supported has {len(codes)} languages, expected {EXPECTED_LANGUAGE_COUNT}")
    if len(set(codes)) != len(codes):
        fail("L10n.supported contains duplicate language codes")
    return codes
 
 
language_codes = extract_language_codes()
english = load_json(english_path)
pro_keys = [key for key in english if key.startswith("pro.")]
if not pro_keys:
    fail("en.json has no pro.* keys")
 
for code in language_codes:
    path = localization_dir / f"{code}.json"
    if not path.is_file():
        fail(f"missing localization file: {path}")
    data = load_json(path)
    missing = [
        key for key in pro_keys
        if not isinstance(data.get(key), str) or not data.get(key, "").strip()
    ]
    if missing:
        fail(f"{code}.json is missing pro translations: {', '.join(missing)}")
 
    badge = data["pro.card.badge"]
    if data.get("pro.card.title.free") == badge:
        fail(f"{code}.json uses the badge text as the upgrade title for pro.card.title.free")
 
    dirty_keys = [key for key in pro_keys if "__" in data[key] or "###FILE" in data[key]]
    if dirty_keys:
        fail(f"{code}.json still contains placeholder artifacts: {', '.join(dirty_keys)}")
 
    placeholder_errors = []
    for key, placeholders in REQUIRED_PLACEHOLDERS.items():
        value = data.get(key, "")
        missing_placeholders = sorted(placeholder for placeholder in placeholders if placeholder not in value)
        if missing_placeholders:
            placeholder_errors.append(f"{key} missing {', '.join(missing_placeholders)}")
    if placeholder_errors:
        fail(f"{code}.json has broken Pro placeholders: {'; '.join(placeholder_errors)}")
 
    if code != "en":
        copied_english = [
            key for key in pro_keys
            if key not in ALLOWED_ENGLISH_COPY_KEYS and data.get(key) == english.get(key)
        ]
        if copied_english:
            fail(f"{code}.json copies English Pro copy: {', '.join(copied_english)}")
 
print(
    "PASS Pro localization QA: "
    f"{len(language_codes)} languages, {len(pro_keys)} keys, "
    "no placeholder artifacts or English fallback copies"
)
PY