Skip to content

fix(ui): translate aria-label attributes and repair the search-clear tooltips - #167

Merged
argszero merged 1 commit into
mainfrom
fix/aria-label-i18n
Sep 11, 2026
Merged

argszero merged 1 commit into
mainfrom
fix/aria-label-i18n

Conversation

@argszero

Copy link
Copy Markdown
Owner

Summary

applyStatic() rewrites exactly three hooks — [data-i18n] (text), [data-i18n-ph] (placeholder) and [data-i18n-title] (title). There was no hook for aria-label, so the nine aria-label attributes written in the static markup stayed Chinese in English mode.

Because aria-label outranks title when the accessible name is computed, an English screen-reader user heard Chinese while the visible tooltip was English — the two attributes contradicted each other on the same element:

element title in EN (hook worked) aria-label in EN (no hook)
#theme-toggle Toggle light / dark theme 切换主题
each button.search-clear Clear search 清空搜索
#help-panel (role="dialog") — 快捷键帮助

Related Issue

(No issue — found by an i18n coverage audit; small, self-contained fix.)

Changes

  • Add a fourth pass to applyStatic() in ui/js/i18n.js: [data-i18n-label] → setAttribute("aria-label", t(key)), mirroring the existing title pass.
  • Tag the nine aria-label sites in ui/index.html. All three keys already exist in both packs, so no translations are added — this is missing wiring, not missing text:
    • #login-theme-toggle, #theme-toggle → theme.toggle.title
    • six button.search-clear → mk.clear
    • #help-panel (role="dialog") → help.title
  • Two adjacent defects on the same buttons, surfaced while wiring:
    • the clear button inside #ak-search carried data-i18n-title="common.search", so its tooltip read "Search"(搜索)on a clear button — wrong in both languages; its sibling on #mk-search correctly uses mk.clear.
    • four clear buttons (#emp-search, #od-search, #model-search, #ops-search) had a bare title="清空搜索" with no i18n hook at all, so they stayed Chinese in English mode.
  • Cache-bust bump ?v=20260911-11 → ?v=20260911-12 (5 references).
  • No config/data-structure changes.

Note on placeholder/value/alt, checked in the same audit: placeholder is already fully wired (18/18 CJK placeholders), and value (38 attrs) and alt (0 attrs) contain no CJK — no work needed there.

Tests

  • cargo test — 148 passed, 0 failed
  • cargo fmt --check — clean
  • cargo clippy --all-targets -- -D warnings — clean
  • node --check ui/js/i18n.js — clean
  • i18n key parity unchanged: 775 == 775 (verified by evaluating the real i18n.js module) with zero added keys
  • No unit tests added (static-markup attribute wiring; not reachable from the Rust suite)

Verified in a headless browser. Baseline and fixed trees were produced by the same generator (baseline = git archive HEAD ui), measured in EN and ZH on two surfaces (login and an authenticated view). The pre-existing [data-i18n-title] hook is kept as a built-in negative control: it is CJK-free in EN in the baseline too, which proves the probe can see translations, so the aria-label zeros are meaningful. 24/24 assertions pass:

  • EN aria-label sites still Chinese: 9 → 0; sites carrying the hook: 0 → 9
  • EN unhooked Chinese titles: 4 → 0; hooked title sites: 10 → 14
  • ZH aria-label sites still Chinese (9) — no regression
  • EN values: theme toggles Toggle light / dark theme, clear buttons Clear search, help panel Shortcuts; in ZH each now matches its own tooltip
  • the mislabel is gone: no search-clear aria-label says "Search"

A runtime I18n.setLang("en") switch with no reload confirms the baseline keeps a Chinese aria-label while its title goes English (the contradiction), and the fixed attributes follow the switch.

Checklist

  • Branch name follows the convention (fix/)
  • Commit message uses Conventional Commits (fix(ui): ...)
  • Single responsibility (one mechanism: the attribute hook family, plus the tooltips on the same buttons), minimal change (2 files, +23/−15)

…tooltips

`applyStatic()` rewrites exactly three hooks - `[data-i18n]` (text),
`[data-i18n-ph]` (placeholder) and `[data-i18n-title]` (title). There was no
hook for `aria-label`, so the nine `aria-label` attributes written in the static
markup stayed Chinese in English mode. Because `aria-label` outranks `title`
when the accessible name is computed, an English screen-reader user heard
Chinese while the visible tooltip was English - the two attributes contradicted
each other on the same element.

Add a fourth pass to `applyStatic()`: `[data-i18n-label]` -> `setAttribute(
"aria-label", t(key))`, mirroring the existing title pass, and tag the nine
sites. All three keys involved already exist in both packs, so no translations
are added - this was missing wiring, not missing text:

  - `#login-theme-toggle`, `#theme-toggle` -> `theme.toggle.title`
  - six `button.search-clear`             -> `mk.clear`
  - `#help-panel` (role="dialog")         -> `help.title`

While wiring those up, two adjacent defects on the same buttons surfaced and are
fixed here:

  - the clear button inside `#ak-search` carried `data-i18n-title=
    "common.search"`, so its tooltip read "Search" (搜索) on a *clear* button -
    wrong in both languages; its sibling on `#mk-search` correctly uses
    `mk.clear`.
  - four clear buttons (`#emp-search`, `#od-search`, `#model-search`,
    `#ops-search`) had a bare `title="清空搜索"` with no i18n hook at all and
    stayed Chinese in English mode.

Cache-bust bump `?v=20260911-11` -> `?v=20260911-12` (5 references).

Verified in a headless browser against a baseline built by the same generator
(`git archive HEAD ui`), EN and ZH, on two surfaces (login and an authenticated
view), with the pre-existing `[data-i18n-title]` hook kept as a built-in
negative control (CJK-free in EN in the *baseline* too, so the probe demonstrably
sees translations). 24/24 assertions pass:

  - EN aria-label sites still Chinese: 9 -> 0; sites carrying the hook: 0 -> 9
  - EN unhooked Chinese titles: 4 -> 0; hooked title sites: 10 -> 14
  - ZH aria-labels still Chinese (9) - no regression
  - EN values: theme toggles `Toggle light / dark theme`, clear buttons
    `Clear search`, help panel `Shortcuts`; ZH now matches each element's own
    tooltip
  - the mislabel is gone: no `search-clear` aria-label says "Search"

A runtime `I18n.setLang("en")` switch with no reload confirms the baseline keeps
Chinese while its `title` goes English (the contradiction), and the fixed
attributes follow the switch.
@argszero
argszero merged commit 8e40d79 into main Sep 11, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant