fix(hax-body): declare 2 undeclared i18n keys, drop 5,810 orphaned locale keys - #822
Conversation
Two keys in the shared "hax" namespace were read off `this.t` but never
declared in any component's this.t block. Both are fixed here, and the
locale files are re-aligned to the resulting canonical key set.
1. copiedToClipboard - elements/hax-body/lib/hax-view-source.js:231
`HAXStore.toast(this.t.copiedToClipboard)` has no inline fallback. The
key was absent from hax.en.json but present in all 102 translated
locale files, so behaviour was inverted: non-English users saw a
correctly translated toast after "Copy HTML", English users saw
`undefined`. Declaring it makes the existing translations reachable
from the canonical set - no new translation work is needed.
2. pages - elements/hax-body/lib/hax-tray.js:1024
hax-tray renders sibling <hax-stax-browser> labels: `this.t.templates`
(declared, translatable) and `this.t.pages || "Pages"` (undeclared).
The fallback meant it always rendered, so it was never noticed, but
the key reached no locale file and could not be translated in any
language. Declared next to templates and the now-redundant fallback
removed.
The other 59 keys carried by the locale files are dead. They are legacy
names from the text editor toolbar rename (bold -> boldButton,
bulledList -> unorderedListButton, crossOut -> strikethroughButton, and
so on); the locale files were never re-aligned afterwards.
i18n-manager copies every key it finds in a locale file straight onto the
element's `t` (elements/i18n-manager/i18n-manager.js:519), so those keys
were fetched, parsed, assigned across all 12 sub-components sharing the
namespace, and swept into the reactive spread - then never read.
All 103 locale files are now aligned to one canonical 124-key set. No
pre-existing translated value is altered.
key entries removed 5,810
key entries added 104 (pages x 103, copiedToClipboard in en.json)
locale payload 741.9 KB -> 497.7 KB (-244.2 KB, -32.9%)
Adds scripts/sync-shared-namespace-locales.js. Single-file extractors
cannot describe a namespace that many files contribute to: pointed at
hax-body.js they would see only the 1 key declared there and overwrite
hax.en.json with that fragment. This script scans every file that
registers the namespace. It also reports keys that are read but never
declared - run against master it names both bugs above directly:
WARNING: 2 key(s) read but never declared:
pages (lib/hax-tray.js:1024)
copiedToClipboard (lib/hax-view-source.js:231)
Adds elements/hax-body/test/hax-i18n-namespace.test.js as a regression
guard. Against master it fails, including `expected undefined to be a
string` for hax-view-source's this.t.copiedToClipboard - the bug
reproduced in a browser rather than inferred from a grep.
Verification:
- hax-body suite: 12/12 on master, 17/17 on this branch
- 12 files register namespace "hax", all under elements/hax-body
- aggregate this.t is 124 keys, matching hax.en.json exactly
- keys read but never declared: 2 on master, 0 here
- runtime merge simulated per locale: 9,682 resolutions, 0 empty
- 12,668 pre-existing values compared: 0 altered
- script is idempotent; a second run reports 0 changes
- generate-translation-manifest.js regenerates with no diff
Refs #3035
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
@SanikaA3 is attempting to deploy a commit to the HAXTheWeb Team on Vercel. A member of the Team first needs to authorize it. |
|
All contributors have signed the CLA. Thank you! |
|
I have read the CLA Document and I hereby sign the CLA. |
|
recheck |
There was a problem hiding this comment.
🟢 Approval recommended
The changes are narrowly scoped to i18n key declaration/synchronization and include a regression test to prevent reintroducing undeclared or drifting locale keys.
Pull request overview
This PR fixes two previously-undeclared i18n keys in the shared hax namespace (one causing an undefined toast for English users), and then normalizes the hax.*.json locale files to a single canonical key set. It also adds a script to keep shared-namespace locales in sync and a regression test to prevent future drift.
Changes:
- Declare
copiedToClipboard(used byhax-view-source) andpages(used byhax-tray) in componentthis.tdefaults and inhax.en.json. - Remove thousands of orphaned/legacy keys from translated locale files and align all
hax.<lang>.jsonfiles to the canonical key set/order. - Add a sync script for shared-namespace locales plus a regression test covering key presence and locale keyset parity.
File summaries
| File | Description |
|---|---|
| elements/hax-body/test/hax-i18n-namespace.test.js | Adds regression coverage for declared/read keys and locale keyset parity. |
| elements/hax-body/lib/hax-view-source.js | Declares copiedToClipboard in this.t defaults for the hax namespace. |
| elements/hax-body/lib/hax-tray.js | Declares pages in this.t defaults and removes inline fallback usage. |
| scripts/sync-shared-namespace-locales.js | Adds a utility to sync shared-namespace locale keysets across contributing files. |
| elements/hax-body/locales/hax.af.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.am.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.ar.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.az.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.be.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.bg.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.bn.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.bs.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.ca.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.co.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.cs.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.cy.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.da.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.de.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.el.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.en.json | Adds canonical English strings for copiedToClipboard and pages. |
| elements/hax-body/locales/hax.eo.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.es.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.et.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.eu.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.fa.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.fi.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.fo.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.fr.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.fy.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.ga.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.gl.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.gn.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.gu.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.ha.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.haw.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.he.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.hi.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.hr.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.hu.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.hy.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.id.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.ig.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.is.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.it.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.ja.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.jv.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.ka.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.kk.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.km.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.kn.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.ko.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.ku.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.ky.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.lb.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.lo.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.lt.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.lv.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.mi.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.mk.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.ml.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.mn.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.mr.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.ms.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.mt.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.my.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.nb.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.ne.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.nl.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.no.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.ny.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.om.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.pa.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.pl.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.pnb.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.ps.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.pt.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.qu.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.ro.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.ru.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.sd.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.si.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.sk.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.sl.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.sn.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.so.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.sq.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.sr.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.sv.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.sw.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.ta.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.te.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.tg.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.th.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.tk.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.tl.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.tr.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.tt.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.uk.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.ur.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.uz.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.vi.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.wuu.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.xh.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.yi.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.yo.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.zh.json | Locale alignment (canonical keyset/order + pages). |
| elements/hax-body/locales/hax.zu.json | Locale alignment (canonical keyset/order + pages). |
Review details
- Files reviewed: 107/107 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| const LOCALES = "/elements/hax-body/locales"; | ||
|
|
||
| async function loadLocale(lang) { | ||
| const res = await fetch(`${LOCALES}/hax.${lang}.json`); | ||
| expect(res.ok, `hax.${lang}.json should be fetchable`).to.be.true; |
Refs #3035.
While picking up #3035 I measured the drift against the source before starting the translation work, and the numbers came out differently than the issue describes. Along the way two keys turned up that are read off
this.tbut never declared anywhere — one of which is a live bug. This PR fixes both and aligns the locale files.Happy to be corrected if I've misread the intent of the 182-key set.
What the issue reported vs. what the code shows
#3035 reads the 182-key set as the aggregate
this.tacross ~35 sub-components, withhax.en.json(122) as the stale side, and proposes translating ~60 keys × 102 locales (~6,120 strings).Scanning it the other way around:
registerLocalization({ namespace: "hax" })elements/hax-bodythis.tacross those 12 fileshax.en.jsonhax.en.jsonhax.en.jsonbut missing from codehax.en.jsonand the code were already in sync. The 182-key set exists only in the translatedhax.<lang>.jsonfiles, and those keys were already translated — canonical coverage was 98.0% (12,198 / 12,444). So there was no cohort of strings rendering English-only for this reason.The extra keys are pre-rename names from the text editor toolbar. Current code declares
boldButton,italicButton,underlineButton,strikethroughButton,unorderedListButton,emojiButton,symbolButton,indentButton,outdentButton; the locale files still carriedbold,italic,underline,crossOut,bulledList,insertEmoji,insertSymbol,indent,outdent. ThebulledListtypo is a good tell — the rename happened and the locale files were never re-aligned.Two keys read but never declared
1.
copiedToClipboard— rendersundefinedfor English usersNo inline fallback. The key was absent from
hax.en.jsonbut present in all 102 translated locale files. Becausei18n-managercopies every key it finds in a locale file onto the element'st(i18n-manager.js:519), the behaviour was inverted from what the issue describes:undefinedDeclaring it makes the existing translations reachable from the canonical set. No new translation work is required — every locale already has this string.
2.
pages— silently untranslatablehax-trayrenders two sibling<hax-stax-browser>labels in the same template:The inline fallback meant it always rendered, so it was never noticed, but the key reached no locale file and could not be translated in any language. Declared next to
templates, and the now-redundant fallback removed.What changed
copiedToClipboardinhax-view-source.jspagesinhax-tray.js, drop the|| "Pages"fallbacken.jsonorderNo pre-existing translated value is altered — 12,668 values compared before and after, 0 changed.
New tooling
scripts/sync-shared-namespace-locales.jsaddresses the "why the skill tooling can't fix this automatically" note directly. Single-file extractors can't describe a namespace many files contribute to: pointed athax-body.jsthey see only the 1 key declared there and would overwritehax.en.jsonwith that fragment. This scans every file registering the namespace.It also reports keys read but never declared. Run against
masterit names both bugs above:Dry run by default;
--writeapplies. It is idempotent — a second run reports 0 changes.Verification
elements/hax-body/test/hax-i18n-namespace.test.jsis added as a regression guard. Againstmasterit fails, includingexpected undefined to be a stringforhax-view-source'sthis.t.copiedToClipboard— the bug reproduced in a browser rather than inferred from a grep.hax-bodysuitescripts/generate-translation-manifest.jsregenerates with no diff, so step 6 of the issue's plan is already satisfied.On the issue's step 5
Steps 1–4 and 6 still apply. Step 5 — "~60 keys × 102 locales" of net-new translation — would have translated 59 dead keys plus one that is already translated everywhere. Removing them instead is what produces the −32.9% payload reduction.
Notes
this.tbut not read withinhax-body. Left untouched: they're the declared contract and may be consumed in ways static analysis can't see. Removing them would be a separate, riskier change..github/workflows/build.ymldoes checkout → setup Node →yarn install→ rebuild the elements README, with noyarn testorlerna run teststep, so the guard test added here won't gate merges. Flagging it rather than expanding this PR's scope — happy to open a separate issue.🤖 Generated with Claude Code