Skip to content

Commit ffcf136

Browse files
Patch76claude
andauthored
refactor(internal): drop two orphaned locale keys and pin the direction that let them in (#2082)
* refactor(internal): drop two locale keys English no longer has #2043 removed advanced.entity_search_limit.label and .help from en.json, de, fr, ru, zh-Hans and the baseline. es and it kept them, by two different routes: es was not one of the catalogs that PR knew about, and it was written against the older English source and rebased past the removal. Neither key renders. build_payload ships them and t() never asks for them, since every lookup goes through a key en.json declares. Nothing in src/ or tests/ references either one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * test(i18n): fail when a catalog keeps a message key English dropped The two orphans this removes got in because every key check here runs the other way. The ceilings count English keys a locale is missing, and the baseline hashes English sources only, so a key with no English counterpart sits outside both. The sibling sections were never exposed: tool_groups and tools are pinned in both directions against the parsed tool set, the component catalogs have their own key check, and the add-on flavors reject a configuration.<key> the schema no longer declares. Only the orphan direction is asserted. messages may omit keys — English is the per-key fallback, and AGENTS.md states the allowance — so asserting the missing direction here would forbid something the contract permits. AGENTS.md gains the other half of that sentence. Also corrects the ceiling comment's denominator, which #2043 left at 421 when it took en.json down to 419. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent e857c32 commit ffcf136

4 files changed

Lines changed: 35 additions & 8 deletions

File tree

AGENTS.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -722,9 +722,10 @@ That list of codes is itself pinned by
722722
code here, in the same PR, or the suite goes red.
723723

724724
Settings UI catalogs are auto-discovered (no registration). Their `messages` may
725-
omit keys — English is the per-key fallback — but `tool_groups` and `tools` may
726-
not: each locale must carry exactly the renderable group headings and every tool
727-
name, no key more and none fewer. **Adding a tool therefore means translating it
725+
omit keys — English is the per-key fallback — but may not carry one `en.json`
726+
lacks: nothing renders it. `tool_groups` and `tools` may do neither: each locale
727+
must carry exactly the renderable group headings and every tool name, no key
728+
more and none fewer. **Adding a tool therefore means translating it
728729
in every locale, in the PR that adds it**: the check derives the tool set from
729730
the sources (`scripts/extract_tools.py`), not from the committed
730731
`site/src/data/tools.json` that `sync-tool-docs.yml` regenerates only after

src/ha_mcp/settings_ui/locales/es.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -373,8 +373,6 @@
373373
"advanced.verify_ssl.help": "Desactiva la verificación TLS solo en redes de confianza. Hay que reiniciar.",
374374
"advanced.fuzzy_threshold.label": "Umbral de la búsqueda difusa",
375375
"advanced.fuzzy_threshold.help": "Los valores más bajos permiten una coincidencia de entidades más laxa. Rango 0–100.",
376-
"advanced.entity_search_limit.label": "Límite de resultados de la búsqueda de entidades",
377-
"advanced.entity_search_limit.help": "Número máximo de entidades que devuelve ha_search_entities. Rango 1–1000.",
378376
"advanced.automation_config_time_budget.label": "Presupuesto de tiempo para la configuración de automatizaciones (s)",
379377
"advanced.automation_config_time_budget.help": "Tiempo máximo que la búsqueda profunda dedica a obtener configuraciones de automatizaciones. Rango 1–600. Hay que reiniciar.",
380378
"advanced.script_config_time_budget.label": "Presupuesto de tiempo para la configuración de scripts (s)",

src/ha_mcp/settings_ui/locales/it.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -373,8 +373,6 @@
373373
"advanced.verify_ssl.help": "Disattiva la verifica TLS solo su reti fidate. È necessario il riavvio.",
374374
"advanced.fuzzy_threshold.label": "Soglia della ricerca approssimata",
375375
"advanced.fuzzy_threshold.help": "Valori più bassi rendono più permissiva la corrispondenza delle entità. Intervallo 0–100.",
376-
"advanced.entity_search_limit.label": "Limite dei risultati nella ricerca delle entità",
377-
"advanced.entity_search_limit.help": "Numero massimo di entità restituite da ha_search_entities. Intervallo 1–1000.",
378376
"advanced.automation_config_time_budget.label": "Tempo massimo per le configurazioni delle automazioni (s)",
379377
"advanced.automation_config_time_budget.help": "Tempo massimo che la ricerca approfondita dedica al recupero delle configurazioni delle automazioni. Intervallo 1–600. È necessario il riavvio.",
380378
"advanced.script_config_time_budget.label": "Tempo massimo per le configurazioni degli script (s)",

tests/src/unit/test_locale_parity.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1077,14 +1077,44 @@ def test_settings_catalog_keys_name_real_groups_and_tools(locale: str) -> None:
10771077
)
10781078

10791079

1080+
@pytest.mark.parametrize("locale", _non_english_settings_locales())
1081+
def test_settings_messages_carry_no_key_english_dropped(locale: str) -> None:
1082+
"""The one direction nothing else here looks in.
1083+
1084+
``messages`` may omit keys — English is the per-key fallback, and AGENTS.md
1085+
states the allowance — so this asserts the other direction only. A key with
1086+
no English counterpart is not a fallback, it is text that reaches nobody:
1087+
``build_payload`` ships it and ``t()`` never asks for it.
1088+
1089+
#2043 removed ``advanced.entity_search_limit.label`` and ``.help`` from
1090+
``en`` and from the five catalogs it knew about, and two got past it by
1091+
different routes — ``es`` was not one of the five, and ``it`` was written
1092+
against the older English source and rebased past the removal. Neither
1093+
failed anything: the ceilings count English keys a locale is missing, and
1094+
the baseline hashes English sources only, so a key English does not have is
1095+
outside both. The sibling sections have had this covered all along, by
1096+
``test_settings_catalog_keys_name_real_groups_and_tools``; the component
1097+
and add-on surfaces by their own key checks.
1098+
"""
1099+
english = set(_settings_catalog("en")["messages"])
1100+
orphaned = sorted(set(_settings_catalog(locale)["messages"]) - english)
1101+
1102+
assert not orphaned, (
1103+
f"src/ha_mcp/settings_ui/locales/{locale}.json translates message "
1104+
f"key(s) en.json does not have: {orphaned}. Nothing renders them — "
1105+
"delete them, or restore the English key if it went missing by "
1106+
"mistake."
1107+
)
1108+
1109+
10801110
# A catalog wholesale-copied from English passes key parity, placeholder
10811111
# parity and the markup allowlist — every existing check. All four surfaces
10821112
# get a ceiling: leaving one of them out accepts a wholesale-English catalog
10831113
# there.
10841114
#
10851115
# The ceilings differ because what legitimately repeats differs. The settings
10861116
# UI messages sit far under theirs: the highest among the shipped locales is 9
1087-
# of 421 (2.1%), all words that genuinely read the same in that language. The
1117+
# of 419 (2.1%), all words that genuinely read the same in that language. The
10881118
# component catalogs are short and carry the product names as keys of their
10891119
# own, so ``de``'s 7 of 93 (7.5%) — six product names plus ``Update`` — is
10901120
# correct and the ceiling has to clear it. Both add-on flavors translate

0 commit comments

Comments
 (0)