#!/usr/bin/env python3 """ i18n-verify-keys.py — Detect missing/extra translation keys between zh-CN and en-US. Usage: python3 scripts/i18n-verify-keys.py # Report only python3 scripts/i18n-verify-keys.py --fix # Copy zh-CN values as placeholder Exit code: 0 if keys are in sync, 1 if there are missing keys. """ import json import sys import os import argparse def flatten(d, prefix=''): items = {} for k, v in d.items(): full = f'{prefix}.{k}' if prefix else k if isinstance(v, dict): items.update(flatten(v, full)) else: items[full] = v return items def set_nested(d, key_path, value): parts = key_path.split('.') current = d for part in parts[:-1]: if part not in current or not isinstance(current[part], dict): current[part] = {} current = current[part] current[parts[-1]] = value def main(): parser = argparse.ArgumentParser(description='Verify i18n key parity between zh-CN and en-US') parser.add_argument('--fix', action='store_true', help='Copy zh-CN values as placeholder for missing en-US keys') args = parser.parse_args() base = os.path.join(os.path.dirname(__file__), '..', 'frontend', 'src', 'locales') zh_path = os.path.join(base, 'zh-CN.json') en_path = os.path.join(base, 'en-US.json') zh = json.load(open(zh_path)) en = json.load(open(en_path)) zh_flat = flatten(zh) en_flat = flatten(en) missing_en = sorted(set(zh_flat) - set(en_flat)) extra_en = sorted(set(en_flat) - set(zh_flat)) print(f'zh-CN keys: {len(zh_flat)}') print(f'en-US keys: {len(en_flat)}') print(f'Missing in en-US: {len(missing_en)}') print(f'Extra in en-US: {len(extra_en)}') if missing_en: # Group by namespace ns = {} for k in missing_en: prefix = k.split('.')[0] + '.' + k.split('.')[1] if '.' in k else k ns[prefix] = ns.get(prefix, 0) + 1 print('\nMissing by sub-namespace:') for k, v in sorted(ns.items()): print(f' {k}.* : {v} keys') print('\nFirst 20 missing keys:') for k in missing_en[:20]: print(f' - {k} = {zh_flat[k]}') if extra_en: print('\nExtra en-US keys (not in zh-CN):') for k in extra_en[:10]: print(f' + {k}') if args.fix and missing_en: for key in missing_en: set_nested(en, key, zh_flat[key]) with open(en_path, 'w', encoding='utf-8') as f: json.dump(en, f, ensure_ascii=False, indent=2) f.write('\n') print(f'\n[fix] Copied {len(missing_en)} zh-CN values as en-US placeholders.') print('[fix] NOTE: Replace with proper English translations!') if missing_en or extra_en: sys.exit(1) else: print('\nāœ… zh-CN and en-US keys are in sync.') sys.exit(0) if __name__ == '__main__': main()