From f2276d828d798268d85375bcdd506d7003497727 Mon Sep 17 00:00:00 2001 From: ruscher Date: Thu, 8 Oct 2026 21:20:06 -0300 Subject: [PATCH] fix(build): check() passes on the BigLinux builder - "Read or stop the selected text" was inside f-strings: the translation bot's xgettext does not look there, dropped it from the .pot and test_pot_lists_every_string failed. _() now sits outside the f-strings, the string is back in the .pot, and a test rejects _() in f-strings. - The builder runs with LC_ALL=C, which wins over the LANG the language tests set: they now clear LC_ALL/LC_MESSAGES. --- locale/tts-biglinux.pot | 5 +++++ tests/test_i18n.py | 5 +++++ tests/test_preview_lang.py | 7 +++++++ tests/test_text_rules.py | 2 ++ .../tts-biglinux/services/desktop_integration_service.py | 7 +++++-- 5 files changed, 24 insertions(+), 2 deletions(-) diff --git a/locale/tts-biglinux.pot b/locale/tts-biglinux.pot index 68052f8..bff95ae 100644 --- a/locale/tts-biglinux.pot +++ b/locale/tts-biglinux.pot @@ -2106,3 +2106,8 @@ msgstr "" # File: tts-biglinux/usr/share/biglinux/tts-biglinux/window.py, line: 465 msgid "Restore" msgstr "" + +# +# File: tts-biglinux/usr/share/biglinux/tts-biglinux/services/desktop_integration_service.py, line: 297 +msgid "Read or stop the selected text" +msgstr "" diff --git a/tests/test_i18n.py b/tests/test_i18n.py index 0986728..4f83c85 100644 --- a/tests/test_i18n.py +++ b/tests/test_i18n.py @@ -151,6 +151,11 @@ def test_every_translated_string_is_a_literal_xgettext_can_extract(): arg = node.args[0] if node.args else None if not (isinstance(arg, ast.Constant) and isinstance(arg.value, str)): bad.append(f"{path.relative_to(APP)}:{node.lineno} _(non-literal)") + # Nor does it look inside f-strings: f"{_('x')}" is lost too. + if isinstance(node, ast.JoinedStr): + for inner in ast.walk(node): + if isinstance(inner, ast.Call) and isinstance(inner.func, ast.Name) and inner.func.id == "_": + bad.append(f"{path.relative_to(APP)}:{inner.lineno} _() inside an f-string") assert not bad, bad diff --git a/tests/test_preview_lang.py b/tests/test_preview_lang.py index 46fdf62..c842729 100644 --- a/tests/test_preview_lang.py +++ b/tests/test_preview_lang.py @@ -16,6 +16,13 @@ pytest.skip(f"GTK unavailable headless: {e}", allow_module_level=True) +@pytest.fixture(autouse=True) +def _only_lang(monkeypatch): + # LC_ALL/LC_MESSAGES win over LANG: builders run with LC_ALL=C. + monkeypatch.delenv("LC_ALL", raising=False) + monkeypatch.delenv("LC_MESSAGES", raising=False) + + def test_espeak_voice_for_pt(monkeypatch): monkeypatch.setenv("LANG", "pt_BR.UTF-8") assert VoiceManagerDialog._espeak_voice_for_lang("pt_BR") == "pt-br" diff --git a/tests/test_text_rules.py b/tests/test_text_rules.py index e935994..351d759 100644 --- a/tests/test_text_rules.py +++ b/tests/test_text_rules.py @@ -17,6 +17,8 @@ def en(text: str, **kw) -> str: # ── The voice's language decides, not the system's ──────────────────── def test_english_voice_on_a_portuguese_system(monkeypatch): + monkeypatch.delenv("LC_ALL", raising=False) # builders: LC_ALL=C + monkeypatch.delenv("LC_MESSAGES", raising=False) monkeypatch.setenv("LANG", "pt_BR.UTF-8") out = en("Mail john@example.com, 50% off at 5 p.m. with Dr. Jones") assert "arroba" not in out and "cinquenta" not in out and "doutor" not in out diff --git a/usr/share/biglinux/tts-biglinux/services/desktop_integration_service.py b/usr/share/biglinux/tts-biglinux/services/desktop_integration_service.py index cbe6b32..57cb60d 100644 --- a/usr/share/biglinux/tts-biglinux/services/desktop_integration_service.py +++ b/usr/share/biglinux/tts-biglinux/services/desktop_integration_service.py @@ -293,6 +293,8 @@ def ensure_desktop_file(kde_key: str) -> Path: exec_path = DesktopIntegrationService._exec_path_for_speak() # Name/GenericName are what the desktop's shortcut settings list. + # (_() outside the f-string: xgettext does not look inside f-strings.) + generic_name = _("Read or stop the selected text") content = f"""[Desktop Entry] Type=Application Exec={exec_path} @@ -302,7 +304,7 @@ def ensure_desktop_file(kde_key: str) -> Path: NoDisplay=true X-KDE-Shortcuts={kde_key} Name=BigLinux TTS -GenericName={_("Read or stop the selected text")} +GenericName={generic_name} """ desktop_dst.parent.mkdir(parents=True, exist_ok=True) desktop_dst.write_text(content, encoding="utf-8") @@ -356,7 +358,8 @@ def write_kde_shortcut_config(cls, accel: str) -> None: if group_prefix == "services": val = kde_shortcut else: - val = f"{kde_shortcut},{kde_shortcut},{_('Read or stop the selected text')}" + name = _("Read or stop the selected text") + val = f"{kde_shortcut},{kde_shortcut},{name}" subprocess.run(cmd + [val], timeout=2, check=False) else: subprocess.run(cmd + ["--delete"], timeout=2, check=False)