fix(i18n): retire four hand-rolled zh/en branches (#2871, part 1) - #2887
Merged
Conversation
Four surfaces picked their language with a hand-written `startsWith('zh')`
check instead of the locale packs. Only Chinese was ever handled, so the other
eight shipped languages silently fell back to English — and because the strings
were baked into the components, no translator could fix that.
- RecordTitleChip carried a private zh-CN/zh-TW dictionary behind a comment
claiming "components is i18n-free". It isn't: the package declares
@object-ui/i18n and its sibling containers.tsx already uses it. All four keys
already existed in ALL TEN packs, so this deletes ~35 lines and fixes ten
locales with zero new translations — on a component that renders on every
record detail page.
- EnvironmentListToolbar's three state-aware CTA labels move to a new
`environment.*` namespace. This surface already regressed once for the same
reason (#844), and was fixed then with inline {en,zh} pairs.
- StudioAiCopilot's dock title moves to the Studio catalog.
- StudioHomePage.relativeTime uses Intl.RelativeTimeFormat instead of five
ternaries. Better than adding ten keys: every locale, correct plural rules,
and "yesterday"/「昨天」 instead of "1d ago". Arabic gets its dual form
(«أسبوعين»), which a ternary cannot express.
New `environment.*` keys go into all ten packs, so this doesn't widen the gap
tracked by #2872 part (a).
EnvironmentListToolbar's tests now render inside a real I18nProvider pinned to
`en`. Without one `t()` returns the raw key, so the previous assertions on
literal English would have been asserting nothing — the tests failed the moment
the component started resolving properly, which is how I caught it.
Suites: components 311, app-shell environment+views 1539, i18n 121 — all green.
ESLint 0 errors; the one exhaustive-deps warning on StudioAiCopilot is
pre-existing (verified against a stashed baseline).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TubWYdWquVkS9dj733sDmC
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
os-zhuang
marked this pull request as ready for review
July 28, 2026 02:28
This was referenced Jul 28, 2026
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.
Part 1 of #2871. Takes the four highest cost/benefit items from the classification; the four
pick({en,zh})clones follow in part 2.Why these four
Each picked its language with a hand-written
startsWith('zh')instead of the locale packs. Two consequences, and the second is the worse one: only Chinese was ever handled, so ja/ko/de/fr/es/pt/ru/ar silently rendered English; and because the strings were baked into the component, no translator could ever fix that without a code change.components/custom/RecordTitleChip.tsxenvironment/EnvironmentListToolbar.tsxenvironment.*namespaceviews/studio-design/StudioAiCopilot.tsxviews/metadata-admin/StudioHomePage.tsxIntl.RelativeTimeFormatRecordTitleChip is free
Its private dictionary sat behind this comment:
That premise is false.
packages/components/package.jsondeclares@object-ui/i18n, and the very file it cites —containers.tsx— already importsuseObjectTranslationfrom it.And all four keys already exist in all ten packs. I checked each one rather than assuming:
So: delete ~35 lines, fix ten locales, write zero translations — on a component that renders on every record detail page.
StudioHomePage:
Intlbeats ten catalog keysrelativeTimewas fivezh ? … : …ternaries. Adding ten keys would have "fixed" it for two languages.Intl.RelativeTimeFormat(locale, { numeric: 'auto' })covers every locale with correct plural rules — verified:Note
numeric: 'auto'giving "yesterday"/「昨天」 rather than "1 day ago", and Arabic's dual form «أسبوعين» for two weeks — grammar a ternary structurally cannot produce.A test that was asserting nothing
EnvironmentListToolbar's tests asserted literal English labels while rendering without anI18nProvider. Once the component started resolving from the packs,t()returned the raw key and three tests failed — which is how I noticed. They now render inside a real provider pinned toen(detectBrowserLanguage: falsefor determinism), following the existingstudio-locale.i18n.test.tsxpattern. Previously they'd have passed against any English string, including a wrong one.Scope notes
environment.*keys go into all ten packs, consistent withcloudConnection.*(fix(cloud-connection): localize the Cloud Connection panel (objectstack#3589 follow-up) #2865) andauth.remediation.*(fix(auth): localize the ADR-0069 remediation gate and the auth split-panel (#2870) #2875), so this does not widen the gap tracked by 语言包 key 缺口:8 个语言各缺 357–359 键,74 键只存在于 zh.ts,且没有任何 parity 测试 #2872 part (a).StudioAiCopilot's key goes to the Studio catalog, not the main packs — per the 14 个文件手搓 startsWith('zh') 判断绕开语言包,其余 8 种语言硬回退英文且无法翻译 #2871 classification, that catalog is a deliberate Studio-admin-scoped system (1375 keys, ~1255 call sites), not drift.Verification
components311,app-shellenvironment+views 1539,i18n121 — all green. ESLint 0 errors; the singleexhaustive-depswarning onStudioAiCopilot:157is pre-existing, verified against a stashed baseline. en↔zh key parity still holds.🤖 Generated with Claude Code
https://claude.ai/code/session_01TubWYdWquVkS9dj733sDmC
Generated by Claude Code