From c0eea3b8ed25f32b032a8e74811b5f7d2e18ca2d Mon Sep 17 00:00:00 2001 From: Alexander01998 Date: Tue, 7 Jan 2025 23:39:16 +0100 Subject: [PATCH] Add check_translations workflow --- .github/workflows/check_translations.yml | 32 +++++++ .gitignore | 3 + scripts/check_translations.py | 96 +++++++++++++++++++ scripts/util.py | 17 ++++ .../resources/intentionally_untranslated.json | 8 ++ 5 files changed, 156 insertions(+) create mode 100644 .github/workflows/check_translations.yml create mode 100644 scripts/check_translations.py create mode 100644 scripts/util.py create mode 100644 src/main/resources/intentionally_untranslated.json diff --git a/.github/workflows/check_translations.yml b/.github/workflows/check_translations.yml new file mode 100644 index 0000000..986295d --- /dev/null +++ b/.github/workflows/check_translations.yml @@ -0,0 +1,32 @@ +name: Check Translations + +on: + push: + branches-ignore: + - "dependabot/**" + tags-ignore: + - "**" + paths: + - "src/main/resources/assets/wi_zoom/lang/**.json" + - "src/main/resources/intentionally_untranslated.json" + pull_request: + paths: + - "src/main/resources/assets/wi_zoom/lang/**.json" + - "src/main/resources/intentionally_untranslated.json" + workflow_dispatch: + +jobs: + check_translations: + runs-on: ubuntu-latest + steps: + + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Python 3.12 + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Run check_translations.py + run: python scripts/check_translations.py diff --git a/.gitignore b/.gitignore index 2a4d72b..b38657f 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,9 @@ run/ # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* +# python +*.pyc + desktop.ini # (neo)forge diff --git a/scripts/check_translations.py b/scripts/check_translations.py new file mode 100644 index 0000000..c9c2ed1 --- /dev/null +++ b/scripts/check_translations.py @@ -0,0 +1,96 @@ +import util +from pathlib import Path + +translations_dir = Path("src") / "main" / "resources" / "assets" / "wi_zoom" / "lang" + + +def show_translation_stats(en_us: dict, translations: dict): + """Render a table of the current translation progress for each language.""" + util.add_github_summary("| Language | Translated | % |") + util.add_github_summary("| --- | --- | --- |") + util.add_github_summary(f"| en_us | {len(en_us)} | 100.00% |") + for lang, data in translations.items(): + util.add_github_summary(f"| {lang} | {len(data)} | {len(data) / len(en_us) * 100:.2f}% |") + util.add_github_summary("") + + +def check_extra_keys(en_us: dict, translations: dict): + """Check if any translation files contain keys that don't exist in the original.""" + extra_keys_found = False + for lang, data in translations.items(): + extra_keys = set(data.keys()) - set(en_us.keys()) + if extra_keys: + extra_keys_found = True + util.add_github_summary( + f"⚠ {lang}.json contains translations that don't exist in en_us.json ({len(extra_keys)} found):" + ) + for key in extra_keys: + util.add_github_summary(f"- {key}") + if extra_keys_found: + raise Exception("Found extra keys in one or more translation files, see summary") + util.add_github_summary("✅ No extra keys found") + + +def check_untranslated_strings(en_us: dict, translations: dict): + """Check if any translation files contain untranslated strings.""" + untranslated_strings_found = False + intentionally_untranslated = util.read_json_file( + Path("src") / "main" / "resources" / "intentionally_untranslated.json" + ) + + for lang, data in translations.items(): + untranslated_strings = set() + for key, value in data.items(): + if value == en_us[key]: + if lang in intentionally_untranslated and key in intentionally_untranslated[lang]: + continue + untranslated_strings.add(key) + if untranslated_strings: + untranslated_strings_found = True + util.add_github_summary( + f"⚠ {lang}.json contains strings that are identical to en_us.json ({len(untranslated_strings)} found):" + ) + for key in untranslated_strings: + util.add_github_summary(f"- {key}: {en_us[key]}") + util.add_github_summary( + "\nIf this is intentional, add the affected key(s) to intentionally_untranslated.json:" + ) + util.add_github_summary("```json") + util.add_github_summary(f' "{lang}": [') + for key in untranslated_strings: + util.add_github_summary(f' "{key}"') + util.add_github_summary(" ]") + util.add_github_summary("```") + + if untranslated_strings_found: + raise Exception("Found untranslated strings in one or more translation files, see summary") + util.add_github_summary("✅ No accidentally untranslated strings found") + + +def check_order_of_strings(en_us: dict, translations: dict): + """Check if the strings in each translation file are in the same order as in en_us.json.""" + for lang, data in translations.items(): + en_us_keys_present_in_translation = [key for key in en_us.keys() if key in data.keys()] + translation_keys_present_in_en_us = [key for key in data.keys() if key in en_us.keys()] + if en_us_keys_present_in_translation != translation_keys_present_in_en_us: + raise Exception(f"⚠ The order of strings in {lang}.json is different from en_us.json") + util.add_github_summary("✅ The order of strings in each translation file matches en_us.json") + + +def main(): + en_us = util.read_json_file(translations_dir / "en_us.json") + translations = {} + for path in sorted(translations_dir.rglob("*.json"), key=lambda x: x.name): + if path.is_file() and path.name != "en_us.json": + lang = path.name.removesuffix(".json") + data = util.read_json_file(path) + translations[lang] = data + + show_translation_stats(en_us, translations) + check_extra_keys(en_us, translations) + check_untranslated_strings(en_us, translations) + check_order_of_strings(en_us, translations) + + +if __name__ == "__main__": + main() diff --git a/scripts/util.py b/scripts/util.py new file mode 100644 index 0000000..807fce1 --- /dev/null +++ b/scripts/util.py @@ -0,0 +1,17 @@ +import json +import os +from pathlib import Path + + +def read_json_file(path: Path) -> dict: + """Read a JSON data file.""" + return json.loads(path.read_text(encoding="utf-8")) + + +def add_github_summary(summary: str): + """Add a line to the GitHub Actions summary for the current step.""" + if "GITHUB_STEP_SUMMARY" not in os.environ: + print(summary) + return + with open(os.environ["GITHUB_STEP_SUMMARY"], "a") as summary_file: + print(summary, file=summary_file) diff --git a/src/main/resources/intentionally_untranslated.json b/src/main/resources/intentionally_untranslated.json new file mode 100644 index 0000000..c5544a7 --- /dev/null +++ b/src/main/resources/intentionally_untranslated.json @@ -0,0 +1,8 @@ +{ + "de_de": [ + "key.wi_zoom.zoom" + ], + "fr_fr": [ + "key.wi_zoom.zoom" + ] +}