Skip to content

fix(ui): render the raise-request table header in the active language - #166

Merged
argszero merged 1 commit into
mainfrom
fix/raise-thead-i18n
Sep 11, 2026
Merged

argszero merged 1 commit into
mainfrom
fix/raise-thead-i18n

Conversation

@argszero

Copy link
Copy Markdown
Owner

Summary

The admin "raise requests" table (US-20) rendered its <thead> from Chinese string literals inside renderRaiseRequests() (ui/js/app.js). That markup is injected via innerHTML after boot and carries no data-i18n, so applyStatic() had no hook to reach it — the header stayed Chinese in English mode.

The same table's body cells had already been i18n-ised (data-label + T("admin.raise.col.*")), so the translation was only half applied. On narrow screens this inverted the result:

Viewport English mode, before
1400px (thead visible) 成员 / 申请点数 / 原因 / 状态 — Chinese
390px (thead display:none, td::before) Member / Requested pts / Reason / Status — English

i.e. the table was correctly translated exactly where it is invisible, and untranslated exactly where it is visible.

Related Issue

(No issue — reported and fixed directly; small, self-contained bug.)

Changes

  • Build the four <th> cells with T("admin.raise.col.member"/"amount"/"reason"/"status") at render time instead of embedding Chinese literals. The deliberately empty 5th column header is unchanged.
  • Bump the cache-busting query string ?v=20260911-10 → ?v=20260911-11 (5 references in ui/index.html).
  • No config/data-structure changes.

Why render-time T() rather than a data-i18n attribute: the table is re-injected by the existing atp:langchange → renderView path, so the header must be produced already translated and must re-read the language on every rebuild. An attribute-only fix would still show Chinese until the next language switch. This follows the established precedent in the same file — the transaction table resolves its headers through col.title() in tableTheadHtml().

No new i18n keys. The four admin.raise.col.* keys already exist in both packs (they were used by the data-label attributes in the very same function), so this is missing wiring, not a missing translation.

Tests

  • cargo test — 148 passed, 0 failed
  • cargo fmt --check — clean
  • cargo clippy --all-targets -- -D warnings — clean
  • node --check ui/js/app.js — clean
  • i18n key parity unchanged: 775 == 775 (verified by evaluating the real i18n.js module, not by regex) with zero added keys
  • No unit tests added (this is UI-rendering markup; not reachable from the Rust test 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 at 1400px and 390px:

  • baseline EN thead: 10 CJK chars (defect reproduced) at both widths
  • fixed EN thead: 0 CJK, exactly Member / Requested pts / Reason / Status
  • negative control: #emp-body (index.html-authored header carrying data-i18n) renders in English in the baseline too — so the probe demonstrably sees translations, and the baseline differential is real rather than a blind probe
  • ZH: fixed output byte-identical to baseline header text (no Chinese regression)
  • body data-labels (5) and row count (3) unchanged vs baseline — no regression
  • after the fix, desktop thead texts == mobile td data-labels (inversion gone)
  • a runtime I18n.setLang("en") switch with no reload: baseline keeps a Chinese header while its data-labels become English (the inversion), fixed header follows the switch

Checklist

  • Branch name follows the convention (fix/)
  • Commit message uses Conventional Commits (fix(ui): ...)
  • Single responsibility, minimal change (2 files, +13/−6)

The admin "raise requests" table built its `<thead>` from Chinese string
literals inside `renderRaiseRequests()` (app.js). Because that markup is
injected after boot and carries no `data-i18n`, `applyStatic()` had no path to
it, so the header stayed Chinese in English mode. The same table's body cells
were already translated by C1991 (`data-label` via `T(admin.raise.col.*)`), so
the language fix was only half applied - which inverted the result on narrow
screens:

  1400px, English: th = 成员 / 申请点数 / 原因 / 状态   (Chinese, visible)
   390px, English: th hidden, td::before = Member / Requested pts / ... (English)

Resolve the four header cells with `T()` at render time instead of embedding
literals. Render-time lookup (rather than a `data-i18n` attribute) is required
because the table is re-injected by the existing `atp:langchange` ->
`renderView` path, so the header must be produced already translated and must
re-read the language on every rebuild. This mirrors the existing precedent in
this file: the transaction table resolves headers via `col.title()` in
`tableTheadHtml()`.

No new i18n keys: `admin.raise.col.member/amount/reason/status` already exist
in both packs (they were used by the `data-label` attributes right below).

Verified in a headless browser against a baseline built from the same
generator, EN and ZH, at 1400px and 390px: baseline header = 10 CJK chars in
EN (negative control `#emp-body` = 0, proving the probe sees translations),
fixed header = 0 CJK with exactly `Member / Requested pts / Reason / Status`;
ZH output byte-identical to baseline; body `data-label`s and row count
unchanged. A runtime `I18n.setLang("en")` switch with no reload confirms the
baseline keeps a Chinese header while its `data-label`s go English (the
inversion), and the fixed header follows the switch.
@argszero
argszero merged commit c14a590 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