R-516: the formal forms the gate did not count are in the te-form; the gate's stems widened

49 Hungarian values on the debug (RESET prompt), storage, network-storage, security, system,
deploy, restore and remote-backup copy moved from the formal („ön") to the product's te-form
(„írd be", „add meg", „hozz létre", „biztosan eltávolítod", „engedélyezd", „próbáld", ...).
i18n_missing_gate.py's stem list widened by 33 stems (+ one listed third-person exception,
„sora adja meg"); it counted 61 on the previous bundle and counts 0 now, ceiling stays 0.
Decoys: a widened-stem form convicts, its te-form twin and the third-person phrase pass.
38 parity fixtures changed by exactly those bytes. Seven Go-side keys listed as REWORDED in the
go-parity map. Pinned by TestR516_WidenedFormalFormsAreGone; two tests that quoted the old
words follow them.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-10-06 02:36:55 +02:00
parent 2fc314d491
commit 4c3c2037fd
45 changed files with 253 additions and 175 deletions
+7 -7
View File
@@ -162,6 +162,13 @@
"err.backup.restore_drive_gone": "BORN AS A KEY (R-362) -- names the drive a restore could not reach instead of a raw permission error; a NEW sentence, never a Go literal. Pinned in both languages by TestR362_DetachedDriveIsNamed.",
"restore.refuse.files.second_drive_whole": "BORN AS A KEY (R-675) -- the unit-restore refusal names the second drive's WHOLE restore (decision 26); a NEW sentence, never a Go literal. Pinned in both languages by TestR675_RefusalNamesTheWholeCopy.",
"flash.login.password_changed": "R-516 item 12 -- REWORDED on purpose: the formal „Kérjük, jelentkezzen be\" became the product's te-form „Jelentkezz be\"; the row is about exactly these bytes, so byte parity with the base literal cannot hold. Pinned by TestR516_FormalFormsAreGone.",
"flash.backup.window_invalid_time": "R-516 (2026-10-06) -- REWORDED on purpose: the formal („ön\") verb forms in this sentence became the product's te-form; the row is about exactly these bytes, so byte parity with the base literal cannot hold. Pinned by TestR516_WidenedFormalFormsAreGone.",
"api.deploy.netstorage_unreachable": "R-516 (2026-10-06) -- REWORDED on purpose: the formal („ön\") verb forms in this sentence became the product's te-form; the row is about exactly these bytes, so byte parity with the base literal cannot hold. Pinned by TestR516_WidenedFormalFormsAreGone.",
"api.deploy.no_space": "R-516 (2026-10-06) -- REWORDED on purpose: the formal („ön\") verb forms in this sentence became the product's te-form; the row is about exactly these bytes, so byte parity with the base literal cannot hold. Pinned by TestR516_WidenedFormalFormsAreGone.",
"debug.api.reset_confirm_invalid": "R-516 (2026-10-06) -- REWORDED on purpose: the formal („ön\") verb forms in this sentence became the product's te-form; the row is about exactly these bytes, so byte parity with the base literal cannot hold. Pinned by TestR516_WidenedFormalFormsAreGone.",
"err.web.formazas_kesz_de_az_uj_fajlrendszer": "R-516 (2026-10-06) -- REWORDED on purpose: the formal („ön\") verb forms in this sentence became the product's te-form; the row is about exactly these bytes, so byte parity with the base literal cannot hold. Pinned by TestR516_WidenedFormalFormsAreGone.",
"err.selfupdate.mentes_fut_probalja_kesobb": "R-516 (2026-10-06) -- REWORDED on purpose: the formal („ön\") verb forms in this sentence became the product's te-form; the row is about exactly these bytes, so byte parity with the base literal cannot hold. Pinned by TestR516_WidenedFormalFormsAreGone.",
"err.stacks.field_required_password": "R-516 (2026-10-06) -- REWORDED on purpose: the formal („ön\") verb forms in this sentence became the product's te-form; the row is about exactly these bytes, so byte parity with the base literal cannot hold. Pinned by TestR516_WidenedFormalFormsAreGone.",
"health.system_disk_high": "BORN AS A KEY (R-516 item 10) -- the dashboard banner's own sentence for a health-check warning/issue whose wire text (report health.*) is English and stays so; a NEW sentence, never a Go literal. Pinned in both languages by TestR516_HealthBannersFollowTheHousehold.",
"health.system_disk_critical": "BORN AS A KEY (R-516 item 10) -- the dashboard banner's own sentence for a health-check warning/issue whose wire text (report health.*) is English and stays so; a NEW sentence, never a Go literal. Pinned in both languages by TestR516_HealthBannersFollowTheHousehold.",
"health.data_disk_high": "BORN AS A KEY (R-516 item 10) -- the dashboard banner's own sentence for a health-check warning/issue whose wire text (report health.*) is English and stays so; a NEW sentence, never a Go literal. Pinned in both languages by TestR516_HealthBannersFollowTheHousehold.",
@@ -198,7 +205,6 @@
"flash.restore.started": "Visszaállítás elindult — az állapot itt frissül.",
"flash.restore.file_started": "Fájl-visszaállítás elindult — az állapot itt frissül.",
"flash.restore.full_started": "Teljes visszaállítás elindult — az állapot itt frissül.",
"flash.backup.window_invalid_time": "Érvénytelen időpont. Használja a ÓÓ:PP formátumot (például 02:30).",
"flash.backup.window_save_failed": "A mentési időablak mentése nem sikerült.",
"flash.backup.window_updated": "Mentési időablak frissítve.",
"flash.sharing.save_failed": "A mentés nem sikerült.",
@@ -594,9 +600,7 @@
"country.YE": "Jemen",
"country.ZM": "Zambia",
"country.ZW": "Zimbabwe",
"api.deploy.netstorage_unreachable": "A kiválasztott hálózati tárhely jelenleg nem érhető el az alkalmazások környezetéből — a telepítés nem indítható. Próbálja újra pár perc múlva, vagy jelezze az üzemeltetőnek.",
"api.deploy.not_installable": "Ez az alkalmazás jelenleg nem telepíthető.",
"api.deploy.no_space": "Nincs elég szabad tárhely a telepítéshez: csak %.0f GB szabad, és a rendszer %.0f GB tartalékot tart fenn az alapszolgáltatások (vezérlő, proxy) védelmében. Szabadítson fel helyet, vagy bővítse a tárhelyet.",
"api.deploy.started": "Telepítés elindítva – az állapot a kártyán követhető",
"api.start.drive_missing": "A(z) %s tárhely jelenleg nem elérhető — az alkalmazás nem indítható, amíg a meghajtó vissza nem csatlakozik.",
"api.start.not_enough_memory": "Nincs elég memória az indításhoz. Szükséges: %d MB, elérhető: %d MB (használt: %d MB / használható: %d MB)",
@@ -638,7 +642,6 @@
"debug.api.gitea_reachable": "Gitea elérhető (HTTP %d, %dms)",
"debug.api.telemetry_collected": "Telemetria összegyűjtve: %d app, %d hiba, %d figyelmeztetés (%dms)",
"debug.api.selfupdate_unconfigured": "Self-update nincs konfigurálva",
"debug.api.reset_confirm_invalid": "Érvénytelen megerősítés — írja be: RESET",
"debug.api.marker_write_failed": "Marker fájl írási hiba: %v",
"debug.api.restarting_to_setup": "Controller újraindítása setup módba...",
"debug.api.agent_unconfigured": "Az ügynök nincs konfigurálva ezen a rendszeren.",
@@ -857,7 +860,6 @@
"err.web.formazas_sikertelen": [
"formázás sikertelen: %w"
],
"err.web.formazas_kesz_de_az_uj_fajlrendszer": "formázás kész, de az új fájlrendszer-azonosító nem feloldható — frissítsen és használja a Csatolás funkciót",
"err.web.csatlakoztatas_sikertelen": [
"csatlakoztatás sikertelen: %w"
],
@@ -924,7 +926,6 @@
"err.selfupdate.hianyos_registry_hitelesito_adatok_felhasznalonev_es": "hiányos registry hitelesítő adatok (felhasználónév és token együtt szükséges)",
"err.selfupdate.frissites_mar_folyamatban": "Frissítés már folyamatban",
"err.selfupdate.dev_verzio_nem_frissitheto": "Dev verzió nem frissíthető",
"err.selfupdate.mentes_fut_probalja_kesobb": "Mentés fut, próbálja később",
"err.selfupdate.a_frissites_nem_erheto_el_nincs": "A frissítés nem érhető el (nincs gazda-ügynök)",
"err.selfupdate.nincs_elerheto_frissites": "Nincs elérhető frissítés",
"err.selfupdate.docker_pull_hianyos_registry_hitelesito_adatok": "docker pull: hiányos registry hitelesítő adatok (felhasználónév és token együtt szükséges)",
@@ -943,7 +944,6 @@
"err.notify.hub_elerhetetlen": [
"hub elérhetetlen: %w"
],
"err.stacks.field_required_password": "a(z) %q mező kitöltése kötelező — használja a Generálás gombot vagy írjon be egy jelszót",
"err.stacks.field_required": "a(z) %q (%s) mező kitöltése kötelező",
"err.backup.offsite_over_quota": "A távoli mentés túllépte a tárhelykeretet (%d/%d GB) — törölj régi mentéseket vagy kérj nagyobb keretet.",
"err.stacks.not_enough_memory": [
+29 -3
View File
@@ -55,6 +55,20 @@ EN_FORBIDDEN = re.compile(r"\b(please|kindly)\b", re.I)
HU_FORMAL = [
"olvassa be", "kerjuk", "vegye fel", "ujratelepiti az", "importalnia", "biztosan kikapcsolja",
"ellenorizze", "csatlakoztassa", "adjon hozza", "nezze meg", "kattintson", "valassza ki",
# Widened 2026-10-06 (R-516, the forms the list above did not see on the debug, storage,
# network-storage, security and system pages). Each was in hu.json and is now te-form.
"irja be", "adja meg", "adja hozza", "adjon neki", "hozzon letre", "biztosan eltavolitja",
"engedelyezze", "probalja", "valasszon", "jelezze", "jegyezze fel", "mentse el", "kapcsolja be",
"hasznalja a", "akkor hasznalja", "szabaditson", "bovitse", "irjon be", "toltse", "folytatja?",
"biztosan ujrainditja", "ujraindithatja", "alkalmazasai ", "tavolitsa el", "jeloljon ki",
"allitsa a", "nem csatolja", "levalasztja a", "visszacsatlakoztatja", "visszaallitja a hianyzo",
"erositenie", "frissitsen", "letrehozza a",
]
# Third-person statements that contain a formal stem but address nobody (ASCII-folded). Removed from
# a value before the stems are matched; a phrase is listed here only with the key that needs it.
HU_FORMAL_NOT = [
"sora adja meg", # storage_network.ip_cim_vagy_dns_nev: "the Sharing page's line gives the address"
]
@@ -63,6 +77,13 @@ def fold(s):
return "".join(c for c in s if not unicodedata.combining(c)).lower()
def formal_text(s):
f = fold(s)
for phrase in HU_FORMAL_NOT:
f = f.replace(phrase, " ")
return f
def load(lang):
p = os.path.join(LOCALES, lang + ".json")
if not os.path.exists(p):
@@ -91,8 +112,13 @@ def main():
if "kerjuk" not in fold("Kérjük, vegye fel"):
print("i18n gate INCONCLUSIVE: positive control failed (folding does not strip accents)")
return 2
if any(stem in fold("Csatlakoztasd újra a meghajtót") for stem in HU_FORMAL):
print("i18n gate INCONCLUSIVE: negative control failed (an informal te-form sentence matched a formal stem)")
for informal in ("Csatlakoztasd újra a meghajtót",
"Írd be, add meg, hozz létre, engedélyezd, próbáld újra. Biztosan eltávolítod?"):
if any(stem in fold(informal) for stem in HU_FORMAL):
print("i18n gate INCONCLUSIVE: negative control failed (an informal te-form sentence matched a formal stem)")
return 2
if not any(stem in formal_text("Írja be a meghajtó nevét") for stem in HU_FORMAL):
print("i18n gate INCONCLUSIVE: positive control failed (a widened stem does not match its formal form)")
return 2
problems = []
@@ -113,7 +139,7 @@ def main():
problems.append("en.json %r says %r -- plain second person, no pleading" % (k, EN_FORBIDDEN.search(en[k]).group(0)))
missing = [k for k in hu if k not in en and (k + ".other") not in en]
formal = [(k, stem) for k in hu for stem in HU_FORMAL if stem in fold(hu[k])]
formal = [(k, stem) for k in hu for stem in HU_FORMAL if stem in formal_text(hu[k])]
print("i18n: %d markers in %d templates; hu %d keys, en %d keys" % (used, len(tpls), len(hu), len(en)))
print("i18n: English missing %d (ceiling %d); Hungarian formal forms %d (ceiling %d, R-516)"
+10
View File
@@ -171,6 +171,16 @@ swapped("i18n/gap-grew", "i18n_missing_gate.py", EN_JSON,
_one(' "launcher.link_masolasa": "Copy link",\n', ''))
swapped("i18n/new-formal-form", "i18n_missing_gate.py", HU_JSON,
_one('"launcher.link_masolasa": "Link másolása"', '"launcher.link_masolasa": "Kattintson a link másolásához"'))
# R-516 (2026-10-06): the widened stems -- a form the original list did not see convicts, its te-form
# twin and the one listed third-person statement pass.
swapped("i18n/new-formal-wide", "i18n_missing_gate.py", HU_JSON,
_one('"launcher.link_masolasa": "Link másolása"', '"launcher.link_masolasa": "Írja be a link nevét"'))
swapped("i18n/te-form-wide", "i18n_missing_gate.py", HU_JSON,
_one('"launcher.link_masolasa": "Link másolása"', '"launcher.link_masolasa": "Írd be a link nevét"'),
expect="accept")
swapped("i18n/third-person-ok", "i18n_missing_gate.py", HU_JSON,
_one('"launcher.link_masolasa": "Link másolása"', '"launcher.link_masolasa": "A Megosztás oldal sora adja meg"'),
expect="accept")
# Scope: the copy gates read the page AS RENDERED, so copy that lives in a bundle is still judged.
swapped("emoji/bundle", "emoji_gate.py", EN_JSON,
_one('"launcher.link_masolasa": "Copy link"', '"launcher.link_masolasa": "Copy link \U0001F600"'))