fix(ui): drive table card-mode labels from i18n instead of hardcoded zh strings - #163
Merged
Merged
Conversation
…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.
8 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Under
@media (max-width:560px)the table thead is hidden and each row is rendered as a card, wheretd::before { content: attr(data-label) }prints "label: value". Everydata-labelin the project was a hardcoded Chinese literal, andapplyStatic()only rewritesdata-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-body7/7,#api-keys5/6,#model-body8/8,#emp-body7/7) — e.g. 厂商 / 模型, 输入价 /1M, 输出价 /1M, 上下文, 能力, 可用性, 操作.Fix: all 53
data-labelsites 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())atapp.js:1743). The labels reuse the column-header keys that already existed asdata-i18non 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 theatp:langchangelistener callsrenderView(activeView), switching language updates the card labels live.Deliberately not done: handing the attributes over to
applyStatic(). That function assigns withinnerHTML, which would re-enter the raw-markup path — the same seam that had to be undone for the.nbspan in #161.i18n packs gain 7 missing keys (
admin.models.col.action, and*.col.emptymirror keys forshare/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 nodata-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。Tests
cargo test全部通过 — 148 passed; 0 failed.cargo fmt --check通过.cargo clippy --all-targets -- -D warnings通过(无新增 warning).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):
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-labelsites 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 atapp.js:532).Honest scope note: the runtime pass exercised the 4 tables whose rows the harness data produced;
sharing/admin-deptstayed empty with this stub andops-usersis 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)fix(ui): …)