Skip to content

fix(i18n): complete Simplified Chinese on every authored surface (#645) - #662

Merged
yinlianghui merged 1 commit into
mainfrom
claude/chinese-i18n-issues-lq7hlp
Aug 3, 2026
Merged

fix(i18n): complete Simplified Chinese on every authored surface (#645)#662
yinlianghui merged 1 commit into
mainfrom
claude/chinese-i18n-issues-lq7hlp

Conversation

@yinlianghui

Copy link
Copy Markdown
Collaborator

Description

#660 finished select-option coverage in Chinese, which left zh-CN complete on the one surface anyone had a ledger for (PENDING_SELECT_LABELS). The other four an authored bundle owns were still English — 98 gaps, and not cosmetic ones:

  • Every page in the app rendered its nav label, breadcrumb and header in English. A Chinese-language trial saw "Opportunity Detail" above a fully translated opportunity record.
  • The six win/loss widgets Require win/loss reasons on close and surface win/loss analytics #593 added to the Sales dashboard shipped untranslated.
  • 55 field labels and help strings, both Lead empty states, and the campaign picker inside create_campaign.

zh-CN lint warnings 98 → 0 (repo total 803 → 705). Scoped to zh-CN deliberately — en / ja-JP / es-ES still carry the debt enumerated in #645 and #494.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)

Related Issues

Related to #645, #494
Does not address #661 (see Additional Notes)

Changes Made

  • src/translations/zh-CN.ts — added the pages group (absent entirely, which is why that whole surface was missing rather than partly filled), the six Sales-dashboard win/loss widgets, both Lead empty states, the create_campaign param label, and 55 field label/help strings across 14 objects.
  • test/metadata-references.test.ts — five assertions requiring a zh-CN entry on each surface, walking 357 field strings, 8 pages, 90 widget strings, 4 empty states and 11 action-param labels.

Two details worth flagging for review:

  • Header copy is keyed by page name (pages.<name>.title / .subtitle) — a page:header carries no stable id, so the page name is the only identifier that reaches it. title legitimately falls back to label, so it is authored only where the two differ.
  • Strings holding {field} tokens ({case_number} · {subject}, {crm_account}) keep the token spelling verbatim. The console substitutes on the raw key, so a translated token resolves to nothing and the header renders blank.

Testing

  • Unit tests pass (npm test) — 1177 passed, 1 skipped, 48 files
  • Linting passes (npm run lint)
  • Build succeeds (npm run build)
  • New tests added

Why no existing check caught this, and why the guard is a test. objectstack lint has rules that find every one of these gaps, and CI never runs them: pnpm lint is objectstack lint --skip-i18n, and objectstack lint exits 0 on warnings regardless. The i18n rules are switched off in the one place that would fail a PR, so this suite is the only available gate.

All five assertions were mutation-checked — a page label, a widget title, an empty state, a field help and a param label were each deleted in turn, and each produced a distinct failure. This suite already carries one green-but-vacuous test in its history (every navigation node has a zh-CN label spent its life looking up the wrong bundle shape and asserting nothing), which is why they were verified rather than trusted.

Checklist

  • I have added a changeset (.changeset/zh-cn-complete-on-every-surface.md)
  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective
  • New and existing unit tests pass locally with my changes

Additional Notes

View tab labels (#661) are not fixable in this repo. The list-page tab bar — 59 labels across 15 objects — stays English, and I confirmed against the upstream source why:

  • ViewTabSchema.label is an I18nLabelSchema, documented as "i18n keys are auto-generated by the framework"
  • ObjectTranslationDataSchema has _views, _actions and _sections — no tab key
  • i18n-resolver.ts has no tab-label resolver; resolveViewLabel only reads _views.<name>.label

So tabs[].label is structurally unreachable by translation. Each tab does point at a listViews entry whose label is translatable, so the gap could close if the console fell back to the referenced view's label when tabs[].label is omitted — but the console isn't in the public objectstack tree, so that fallback can't be confirmed from source and isn't something to guess at here.


Generated by Claude Code

zh-CN was complete only on picklist options — the surface #645 finished and
the only one with a ledger. The other four an authored bundle owns were still
English: every page's nav label, breadcrumb and header copy; the six win/loss
widgets #593 added to the Sales dashboard; 55 field labels and help strings;
both Lead empty states; and the campaign picker in `create_campaign`.

The `pages` group was absent from zh-CN.ts entirely, which is why that surface
was wholly missing rather than partly filled. Header copy is keyed by PAGE name
(`pages.<name>.title` / `.subtitle`) since a `page:header` carries no stable id.
Strings holding `{field}` tokens keep the token spelling verbatim — the console
substitutes on the raw key, so a translated token resolves to nothing.

Nothing in CI could have caught this: `pnpm lint` runs `--skip-i18n`, and
`objectstack lint` exits 0 on warnings anyway, so the rules that do find these
gaps are off in the one place that would fail a PR. Five assertions in
metadata-references.test.ts are therefore the gate — they walk 357 field
strings, 8 pages, 90 widget strings, 4 empty states and 11 action-param labels
and require a zh-CN entry for each. Each was confirmed to fail when a
translation is removed; this suite has a green-but-vacuous test in its history,
so they were mutation-checked rather than trusted.

zh-CN lint warnings 98 -> 0 (total 803 -> 705). en / ja-JP / es-ES keep the debt
in #645 and #494. View tab labels are untouched: `tabs[].label` has no key in
ObjectTranslationDataSchema and no resolver in i18n-resolver.ts, so that gap is
upstream (#661).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J8UZqd6mJMPHAXKb6XcHmi
@vercel

vercel Bot commented Aug 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
hotcrm Ignored Ignored Aug 3, 2026 6:30am

Request Review

@github-actions github-actions Bot added ci/cd CI plumbing and the verification pipeline metadata Declarative metadata — schema, security posture, UI surfaces labels Aug 3, 2026
@yinlianghui
yinlianghui marked this pull request as ready for review August 3, 2026 10:09
@yinlianghui
yinlianghui added this pull request to the merge queue Aug 3, 2026
Merged via the queue into main with commit 910acfc Aug 3, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cd CI plumbing and the verification pipeline metadata Declarative metadata — schema, security posture, UI surfaces

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants