fix(i18n): complete Simplified Chinese on every authored surface (#645) - #662
Merged
Conversation
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
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
yinlianghui
marked this pull request as ready for review
August 3, 2026 10:09
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.
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:create_campaign.zh-CN lint warnings 98 → 0 (repo total 803 → 705). Scoped to zh-CN deliberately —
en/ja-JP/es-ESstill carry the debt enumerated in #645 and #494.Type of Change
Related Issues
Related to #645, #494
Does not address #661 (see Additional Notes)
Changes Made
src/translations/zh-CN.ts— added thepagesgroup (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, thecreate_campaignparam label, and 55 fieldlabel/helpstrings 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:
pages.<name>.title/.subtitle) — apage:headercarries no stable id, so the page name is the only identifier that reaches it.titlelegitimately falls back tolabel, so it is authored only where the two differ.{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
npm test) — 1177 passed, 1 skipped, 48 filesnpm run lint)npm run build)Why no existing check caught this, and why the guard is a test.
objectstack linthas rules that find every one of these gaps, and CI never runs them:pnpm lintisobjectstack lint --skip-i18n, andobjectstack lintexits 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
helpand 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 labelspent its life looking up the wrong bundle shape and asserting nothing), which is why they were verified rather than trusted.Checklist
.changeset/zh-cn-complete-on-every-surface.md)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.labelis anI18nLabelSchema, documented as "i18n keys are auto-generated by the framework"ObjectTranslationDataSchemahas_views,_actionsand_sections— no tab keyi18n-resolver.tshas no tab-label resolver;resolveViewLabelonly reads_views.<name>.labelSo
tabs[].labelis 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 whentabs[].labelis 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