antalotec commented on code in PR #45974: URL: https://github.com/apache/superset/pull/45974#discussion_r4455335909
########## scripts/translations/check_do_not_translate.py: ########## @@ -0,0 +1,145 @@ +#!/usr/bin/env python3 +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +""" +Fail when a catalog translates a msgid listed in the do-not-translate registry. + +What this checks, and what it does not +-------------------------------------- +``superset/translations/do-not-translate.txt`` lists msgids that must stay +identical to the source: icon names, enum and option values, SQL keywords, API +field names, code constants, example placeholders and product names. + +Two existing pieces already consume that registry, but neither of them keeps a +catalog honest: + +* ``apply_do_not_translate.py`` stamps a ``#. do-not-translate`` extracted + comment on each entry. The comment is advisory — nothing rejects a + translation that ignores it. +* ``backfill_po.py`` honours the registry when it *generates* a translation, so + it never introduces a violation. Entries translated before a term was + registered, or by hand, are untouched. + +The result is that the registry silently drifts out of effect. This script +closes that gap: it reads the registry, walks every catalog and reports any +entry whose ``msgstr`` is both non-empty and different from its ``msgid``. + +An empty ``msgstr`` is the correct state for these entries — gettext then falls +back to the source token — so emptying a translation is how a violation is +fixed, not by copying the English into ``msgstr``. + +Usage +----- +Check the catalogs in the repo:: + + python scripts/translations/check_do_not_translate.py + +Check a different tree (used by CI against a worktree):: + + python scripts/translations/check_do_not_translate.py \\ + --translations-dir /tmp/base-worktree/superset/translations +""" + +from __future__ import annotations + +import argparse +import sys +from pathlib import Path + +try: + import polib # type: ignore[import-untyped] +except ImportError: + print("polib is required. Install with: pip install polib", file=sys.stderr) + sys.exit(1) + +DEFAULT_TRANSLATIONS_DIR = ( + Path(__file__).resolve().parent.parent.parent / "superset" / "translations" +) + +# The English catalog uses empty msgstrs by convention (source language == +# target), so it can hold no violation. +SKIP_LANGS = {"en"} + + +def load_registry(path: Path) -> set[str]: + """Return the registered msgids, skipping comments and blank lines.""" + entries: set[str] = set() + for raw_line in path.read_text(encoding="utf-8").splitlines(): + line = raw_line.strip() + if line and not line.startswith("#"): + entries.add(line) + return entries + + +def violations(po_file: Path, registry: set[str]) -> list[tuple[str, str]]: + """Return ``(msgid, msgstr)`` for every registered entry that is translated.""" + found: list[tuple[str, str]] = [] + for entry in polib.pofile(str(po_file)): + if entry.obsolete or entry.msgid not in registry: + continue + # Only an exactly empty msgstr makes gettext fall back to the source + # token, which is what the registry asks for. A padded or + # whitespace-only value is a translation like any other — " DELETE " + # and " " are both returned verbatim — so compare the raw msgstr. + translated = entry.msgstr + if translated and translated != entry.msgid: Review Comment: Added `tests/unit_tests/scripts/translations/check_do_not_translate_test.py`, covering the cases you listed: `" DELETE "`, `" "` and a real translation are reported; `""`, an identical `msgstr`, an obsolete entry and an unregistered `msgid` are not; `main()` exits 1 naming the offender, or returns cleanly. I also pinned that the `en` catalog is skipped. Checked it fails for the right reason: putting `.strip()` back breaks 3 of the tests, and loosening the comparison to `translated.strip() != entry.msgid.strip()` breaks 2. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
