1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-02-01 02:10:56 +00:00

feat(core): allow splitting/merging translations for Crowdin

This way, each layout could be translated independently.

[no changelog]
This commit is contained in:
Roman Zeyde 2025-01-14 18:09:12 +02:00
parent 3f61f735d5
commit 00375decf7
2 changed files with 72 additions and 43 deletions

View File

@ -1,55 +1,83 @@
import subprocess from __future__ import annotations
import tempfile
from pathlib import Path from pathlib import Path
import collections
import json import json
import sys
import os import click
from cli import TranslationsDir
from trezorlib._internal import translations
from trezorlib.debuglink import LayoutType
HERE = Path(__file__).parent HERE = Path(__file__).parent
# staging directory for layout-specific translation JSON files
CROWDIN_DIR = HERE / "crowdin"
def download() -> None: # layouts with translation support
with tempfile.TemporaryDirectory() as temp_dir: ALL_LAYOUTS = frozenset(LayoutType) - {LayoutType.T1}
command = f"crowdin download --all --verbose --token $CROWDIN_TOKEN --base-path={temp_dir}"
print("command", command)
subprocess.run(command, shell=True, check=True)
for directory in Path(temp_dir).iterdir():
print("directory", directory)
lang_name = directory.name
en_file = directory / "en.json"
if not en_file.exists():
print("Skipping - no en.json inside", lang_name)
continue
print("Processing", lang_name)
data = json.loads(en_file.read_text())
lang_file = HERE / f"{lang_name}.json"
if not lang_file.exists():
print("Skipping - no lang_file on our side", lang_name)
continue
lang_file_data = json.loads(lang_file.read_text())
lang_file_data["translations"] = data["translations"]
lang_file.write_text(json.dumps(lang_file_data, indent=2, sort_keys=True, ensure_ascii=False) + "\n")
print("Translations updated", lang_name)
def upload() -> None: @click.group()
command = "crowdin upload sources --token $CROWDIN_TOKEN" def cli() -> None:
print("command", command) pass
subprocess.run(command, shell=True, check=True)
@cli.command()
def split() -> None:
"""Split translation files for Crowdin upload.
Create a separate JSON file for each language and layout.
"""
tdir = TranslationsDir()
for lang in tdir.all_languages():
blob_json = tdir.load_lang(lang)
for layout_type in ALL_LAYOUTS:
# extract translations specific to this layout
layout_specific_translations = {
key: translations.get_translation(blob_json, key, layout_type)
for key in blob_json["translations"].keys()
}
# create a JSON file with only the "translations" item
result = {"translations": layout_specific_translations}
with open(CROWDIN_DIR / f"{lang}_{layout_type.name}.json", "w") as f:
json.dump(result, f, indent=2, ensure_ascii=False)
click.echo(f"Successfully generated layout-specific translation files in '{CROWDIN_DIR}'")
@cli.command()
def merge() -> None:
"""Merge back translation files downloaded from Crowdin."""
tdir = TranslationsDir()
for lang in sorted(tdir.all_languages()):
merged_translations: dict[str, str | dict[str, str]] = collections.defaultdict(dict)
for layout_type in ALL_LAYOUTS:
with open(CROWDIN_DIR / f"{lang}_{layout_type.name}.json", "r") as f:
blob_json = json.load(f)
# mapping string name to its translation (for the current layout)
layout_specific_translations: dict[str, str] = blob_json["translations"]
for key, value in layout_specific_translations.items():
merged_translations[key][layout_type.name] = value
for key in merged_translations.keys():
# deduplicate entries if all translations are the same
unique_translations = set(merged_translations[key].values())
if len(unique_translations) == 1:
merged_translations[key] = unique_translations.pop()
blob_json = tdir.load_lang(lang)
blob_json["translations"] = merged_translations
tdir.save_lang(lang, blob_json)
click.echo(f"Updated {lang}")
click.echo(f"Successfully merged back layout-specific translation files from '{CROWDIN_DIR}'")
if __name__ == "__main__": if __name__ == "__main__":
if not os.environ.get("CROWDIN_TOKEN"): cli()
print("CROWDIN_TOKEN env variable not set")
sys.exit(1)
if "download" in sys.argv:
download()
elif "upload" in sys.argv:
upload()
else:
print("Usage: python crowdin.py [download|upload]")
sys.exit(1)

1
core/translations/crowdin/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.json