Skip to content

fix(ui): drive table card-mode labels from i18n instead of hardcoded zh strings - #163

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

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

Conversation

@argszero

Copy link
Copy Markdown
Owner

Summary

Under @media (max-width:560px) the table thead is hidden and each row is rendered as a card, where td::before { content: attr(data-label) } prints "label: value". Every data-label in the project was a hardcoded Chinese literal, and applyStatic() only rewrites data-i18n / data-i18n-ph / data-i18n-title — so those labels had no i18n path at all. With the language set to English the card headers still rendered in Chinese.

Measured on the real UI in English mode at card-mode width, before this change: 27 Chinese labels across the tables that had rows (#mk-body 7/7, #api-keys 5/6, #model-body 8/8, #emp-body 7/7) — e.g. 厂商 / 模型, 输入价 /1M, 输出价 /1M, 上下文, 能力, 可用性, 操作.

Fix: all 53 data-label sites now build the label from a translation key at render time, following the pattern the transaction table already used (title: () => T("tx.col.…") → esc(col.title()) at app.js:1743). The labels reuse the column-header keys that already existed as data-i18n on the matching <th> (e.g. mk.col.in, admin.emp.col.member), so no new vocabulary was invented. Because rows are re-rendered per request and the atp:langchange listener calls renderView(activeView), switching language updates the card labels live.

Deliberately not done: handing the attributes over to applyStatic(). That function assigns with innerHTML, which would re-enter the raw-markup path — the same seam that had to be undone for the .nb span in #161.

i18n packs gain 7 missing keys (admin.models.col.action, and *.col.empty mirror keys for share / admin.raise / settings.ak / admin.emp / admin.org / ops.users) — 769 keys in each pack, still exactly equal.

Not modified: the empty-state rows (emptyRow / loadErrorRow) keep their existing colspan-only cells with no data-label, matching the other renderers. Giving them a label would be a separate, visually-observable change.

Related Issue

Changes

  • 修复说明:ui/js/app.js — 53 个 data-label 字面量改为渲染期 T(key);ui/js/i18n.js — 补 7 个缺失键 + 7 个镜像键;ui/index.html — cache-bust -7 → -8。
  • 涉及配置/数据结构的改动已同步示例文件 — not applicable.

Tests

  • cargo test 全部通过 — 148 passed; 0 failed.
  • cargo fmt --check 通过.
  • cargo clippy --all-targets -- -D warnings 通过(无新增 warning).
  • 新增/更新了单元测试(如适用)— not applicable: static markup/i18n change with no Rust code path; verified with the browser harness + static audit below.
  • node --check ×4 OK;i18n 键集 769 == 769,0 unresolved.

Measured before/after (headless Chrome A/B; both trees from the same generator, baseline rebuilt from git objects, card-mode width ≤560px):

Phase Before After
EN mode Chinese labels 27 0
ZH mode (control) 27 27
Cell count 28 28 (no column added/removed)
Desktop 1400px no table in card mode no table in card mode

The ZH control (27 labels rendered via the app's real window.I18n.setLang) proves the EN zero is language-correctness and not labels simply failing to render.

Static audit: all 53 data-label sites are i18n-driven and 0 Chinese literals remain — this covers all 7 tables deterministically, including the ops table, which an admin session cannot reach (the ops view is role-gated at app.js:532).

Honest scope note: the runtime pass exercised the 4 tables whose rows the harness data produced; sharing / admin-dept stayed empty with this stub and ops-users is unreachable for an admin session, so those three are covered by the static audit rather than by the browser pass — they are untested at runtime, not confirmed clean.

Checklist

  • 分支命名符合约定(fix/data-label-i18n)
  • Commit message 使用 Conventional Commits 格式(fix(ui): …)
  • 单一职责,改动最小化

…zh strings

Under `@media (max-width:560px)` the table thead is hidden and each row is
rendered as a card, where `td::before { content: attr(data-label) }` prints
"label: value". Every `data-label` was a hardcoded Chinese literal, and
`applyStatic()` only rewrites `data-i18n` / `-ph` / `-title`, so those labels
had no i18n path at all: with the language set to English the card headers
still rendered in Chinese. Measured on the real UI in English mode at
card-mode width before this change: 27 Chinese labels across the tables that
had rows (`#mk-body` 7/7, `#api-keys` 5/6, `#model-body` 8/8, `#emp-body` 7/7).

All 53 `data-label` sites now build their label from a translation key at
render time, following the pattern the transaction table already used
(`title: () => T("tx.col.…")` then `esc(col.title())`). The labels reuse the
column-header keys that already existed as `data-i18n` on the matching `<th>`,
so no new vocabulary was invented; the 7 keys that were missing in both packs,
plus 7 mirror keys for the empty-state cell, are added (769 keys in each pack,
still exactly equal). Because rows are re-rendered per request and the
`atp:langchange` handler calls `renderView(activeView)`, switching language now
updates the card labels live.

Note this deliberately does not hand the attributes to `applyStatic()`: that
function assigns with `innerHTML`, which would re-enter the raw-markup path.

Verified with a headless-Chrome A/B harness in which both trees are produced by
the same generator and the baseline is rebuilt from git objects. At card-mode
width: 27 Chinese labels in English mode before, 0 after, with the same cell
counts and the same 27 labels still rendered in Chinese mode (control), so the
fix is language-correct rather than labels simply disappearing. A static audit
confirms all 53 sites are i18n-driven and no Chinese literal remains, which also
covers the ops table that an admin session cannot reach (the ops view is
role-gated). Desktop is unaffected: at 1400px no table enters card mode.

Bumped the asset cache-bust to 20260911-8.
@argszero
argszero merged commit 4bcddca 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