| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- import json
- import os
- import sys
- from pathlib import Path
- LOCALES_DIR = Path("src/locales")
- USER_MASTER = LOCALES_DIR / "translations.user.json"
- ADMIN_MASTER = LOCALES_DIR / "translations.admin.json"
- LANGUAGES = ["en", "me", "ru", "ua"]
- def get_nested_keys(data, prefix=""):
- keys = {}
- for k, v in data.items():
- new_prefix = f"{prefix}.{k}" if prefix else k
- if isinstance(v, dict):
- # Check if this is a leaf node with language keys
- if any(lang in v for lang in LANGUAGES):
- keys[new_prefix] = v
- else:
- keys.update(get_nested_keys(v, new_prefix))
- else:
- keys[new_prefix] = v
- return keys
- def set_nested_key(data, key_path, value):
- parts = key_path.split('.')
- for part in parts[:-1]:
- data = data.setdefault(part, {})
- data[parts[-1]] = value
- def _merge_files(master_file, suffix):
- """Generic merge from {lang}{suffix} into master_file"""
- master_data = {}
- all_keys = set()
- locale_data = {}
- for lang in LANGUAGES:
- path = LOCALES_DIR / f"{lang}{suffix}"
- if path.exists():
- with open(path, "r", encoding="utf-8") as f:
- data = json.load(f)
- flat = {}
- def flatten(d, prefix=""):
- for k, v in d.items():
- new_prefix = f"{prefix}.{k}" if prefix else k
- if isinstance(v, dict):
- flatten(v, new_prefix)
- else:
- flat[new_prefix] = v
- flatten(data)
- locale_data[lang] = flat
- all_keys.update(flat.keys())
- for key in sorted(all_keys):
- translations = {}
- for lang in LANGUAGES:
- translations[lang] = locale_data.get(lang, {}).get(key, "")
- set_nested_key(master_data, key, translations)
- with open(master_file, "w", encoding="utf-8") as f:
- json.dump(master_data, f, ensure_ascii=False, indent=2)
- print(f"Merged {suffix} files into {master_file}")
- def _split_master(master_file, suffix):
- """Generic split from master_file into {lang}{suffix}"""
- if not master_file.exists():
- print(f"Warning: {master_file} not found, skipping split for it.")
- return
- with open(master_file, "r", encoding="utf-8") as f:
- master_data = json.load(f)
- for lang in LANGUAGES:
- lang_data = {}
- def unflatten(d, target, current_lang):
- for k, v in d.items():
- if isinstance(v, dict):
- if any(l in v for l in LANGUAGES):
- target[k] = v.get(current_lang, "")
- else:
- target[k] = {}
- unflatten(v, target[k], current_lang)
- else:
- target[k] = v
-
- unflatten(master_data, lang_data, lang)
- output_path = LOCALES_DIR / f"{lang}{suffix}"
- with open(output_path, "w", encoding="utf-8") as f:
- json.dump(lang_data, f, ensure_ascii=False, indent=2)
- print(f"Generated {output_path}")
- def merge():
- """Merge individual JSON files into respective master files"""
- _merge_files(USER_MASTER, ".json")
- _merge_files(ADMIN_MASTER, ".admin.json")
- def split():
- """Split master files into individual JSON files"""
- _split_master(USER_MASTER, ".json")
- _split_master(ADMIN_MASTER, ".admin.json")
- def list_missing():
- """List all keys with missing translations in both master files"""
- for name, path in [("User", USER_MASTER), ("Admin", ADMIN_MASTER)]:
- if not path.exists():
- continue
- print(f"\n--- Missing in {name} ---")
- with open(path, "r", encoding="utf-8") as f:
- data = json.load(f)
- flat_keys = get_nested_keys(data)
- missing_found = False
- for key, trans in sorted(flat_keys.items()):
- if isinstance(trans, dict):
- missing = [l for l in LANGUAGES if not trans.get(l)]
- if missing:
- print(f"Key: {key} - Missing: {', '.join(missing)}")
- missing_found = True
- if not missing_found:
- print("Everything translated!")
- if __name__ == "__main__":
- if len(sys.argv) < 2:
- print("Usage: python manage_locales.py [merge|split|missing]")
- sys.exit(1)
-
- cmd = sys.argv[1].lower()
- if cmd == "merge":
- merge()
- elif cmd == "split":
- split()
- elif cmd == "missing":
- list_missing()
- else:
- print(f"Unknown command: {cmd}")
|