All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 54s
- Changed file permissions from 644 to 755 for various files in the mobile-app and mobile-app_legacy_rn_expo directories, ensuring executable permissions where necessary. - Added a new SQL migration script to the backend to introduce missing columns for club billing and invoice settings in the clubs table, maintaining synchronization with the current Sequelize model.
121 lines
3.6 KiB
Python
Executable File
121 lines
3.6 KiB
Python
Executable File
#!/usr/bin/env python3
|
||
"""Schreibt Locale-Overrides aus Cache + EN-Fallback – ohne API-Aufrufe."""
|
||
|
||
from __future__ import annotations
|
||
|
||
import json
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
ROOT = Path(__file__).resolve().parents[1]
|
||
LOCALES_DIR = ROOT / "frontend" / "src" / "i18n" / "locales"
|
||
CACHE_FILE = Path(__file__).resolve().parent / ".i18n-translate-cache.json"
|
||
|
||
TARGETS = {
|
||
"fr": "fr",
|
||
"es": "es",
|
||
"it": "it",
|
||
"pl": "pl",
|
||
"ja": "ja",
|
||
"zh": "zh-CN",
|
||
"th": "th",
|
||
"tl": "tl",
|
||
"fil": "tl",
|
||
}
|
||
|
||
|
||
def deep_merge(base, override):
|
||
if not isinstance(base, dict) or isinstance(base, list):
|
||
return override if override is not None else base
|
||
result = dict(base)
|
||
for key, value in (override or {}).items():
|
||
if (
|
||
isinstance(value, dict)
|
||
and not isinstance(value, list)
|
||
and isinstance(result.get(key), dict)
|
||
and not isinstance(result.get(key), list)
|
||
):
|
||
result[key] = deep_merge(result[key], value)
|
||
else:
|
||
result[key] = value
|
||
return result
|
||
|
||
|
||
def flatten(obj, prefix=""):
|
||
out = {}
|
||
for key, value in (obj or {}).items():
|
||
next_key = f"{prefix}.{key}" if prefix else key
|
||
if isinstance(value, dict) and not isinstance(value, list):
|
||
out.update(flatten(value, next_key))
|
||
elif isinstance(value, str):
|
||
out[next_key] = value
|
||
return out
|
||
|
||
|
||
def set_by_path(obj, dot_path, value):
|
||
parts = dot_path.split(".")
|
||
cur = obj
|
||
for part in parts[:-1]:
|
||
if part not in cur or not isinstance(cur[part], dict):
|
||
cur[part] = {}
|
||
cur = cur[part]
|
||
cur[parts[-1]] = value
|
||
|
||
|
||
def build_overrides(de_flat, target_flat):
|
||
out = {}
|
||
for key, value in target_flat.items():
|
||
if value != de_flat.get(key):
|
||
set_by_path(out, key, value)
|
||
return out
|
||
|
||
|
||
def apply_locale(code: str, cache: dict, en_flat: dict, de_flat: dict) -> None:
|
||
target = TARGETS[code]
|
||
locale_path = LOCALES_DIR / f"{code}.json"
|
||
locale_json = json.loads(locale_path.read_text(encoding="utf-8"))
|
||
de = json.loads((LOCALES_DIR / "de.json").read_text(encoding="utf-8"))
|
||
merged = flatten(deep_merge(json.loads(json.dumps(de)), locale_json))
|
||
|
||
from_cache = from_en = still = 0
|
||
for key, de_val in de_flat.items():
|
||
if merged.get(key) != de_val:
|
||
continue
|
||
from_lang = "en" if en_flat.get(key) and en_flat[key] != de_val else "de"
|
||
text = en_flat[key] if from_lang == "en" else de_val
|
||
cache_key = f"{from_lang}|{target}|{text}"
|
||
if cache_key in cache:
|
||
merged[key] = cache[cache_key]
|
||
from_cache += 1
|
||
elif from_lang == "en":
|
||
merged[key] = text
|
||
from_en += 1
|
||
else:
|
||
still += 1
|
||
|
||
overrides = build_overrides(de_flat, merged)
|
||
locale_path.write_text(json.dumps(overrides, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
|
||
print(
|
||
f"[{code}] cache={from_cache} enFallback={from_en} stillDe={still} overrides={len(flatten(overrides))}",
|
||
flush=True,
|
||
)
|
||
|
||
|
||
def main():
|
||
codes = sys.argv[1:] or list(TARGETS.keys())
|
||
cache = json.loads(CACHE_FILE.read_text(encoding="utf-8"))
|
||
de = json.loads((LOCALES_DIR / "de.json").read_text(encoding="utf-8"))
|
||
en_us = json.loads((LOCALES_DIR / "en-US.json").read_text(encoding="utf-8"))
|
||
de_flat = flatten(de)
|
||
en_flat = flatten(deep_merge(de, en_us))
|
||
|
||
for code in codes:
|
||
if code not in TARGETS:
|
||
print(f"skip unknown: {code}", file=sys.stderr)
|
||
continue
|
||
apply_locale(code, cache, en_flat, de_flat)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|