Repository navigation
Commit 226c988
docs(skills): objectui i18n guide keys the built-in packs by platform locale tag (zh-Hans, zh-Hant, pt-BR) (#31043)
<!-- claude-projects-attribution: {"github_login":"huangyiirene"} -->
_Requested by **Irene** · [project
thread](https://claude.ai/code/project/chan_01TJXtQ1tVD26ecLDZxFS67x?thread=cmsg_01TJXtQ1tVD26ecLDZxFS67xE9wgHWTh9Jrvm1WVhqbLKh)_
Fixes #30911
Clause-②: no
Metadata-protocol: none
## 维护者速读
- **改了什么**:`skills/objectui/guides/i18n.md` 不再教已退役的 `zh` / `pt`
语言包键:内置语言改为平台语言表 `PLATFORM_LOCALES` 的 11
个标签(`en`、`zh-Hans`、`zh-Hant`、`es`、`ar`、`fr`、`pt-BR`、`ru`、`de`、`ja`、`ko`)及模块路径
`@object-ui/i18n/locales/<tag>`;setup 示例改用 `'zh-Hans'` 键;语言切换器改为遍历
`PLATFORM_LOCALES`,不再手写列表,且以 `resolveBuiltInLanguage(language) ??
language` 选中当前语言(实例以已存别名如 `zh` 运行时也能选中);说明已存的 `zh` / `zh-CN` / `zh-TW` /
`pt` 经语言表的读别名(`resolveBuiltInLanguage`)继续解析。
- **为什么改**:PR #30902 已把内置包从 `zh` / `pt` 改名为 `zh-Hans` / `pt-BR` 并新增
`zh-Hant`,照旧指南写的键和 import 在 `main` 上不再解析,也提供不了繁体中文。
- **风险与回滚**:只改 skill 文本和一个 changeset;token 天花板不动(1411/1413);回滚即
revert,无运行时影响。
- **先看**:指南的「Built-in locales」段与切换器示例,对照
`ui/packages/i18n/src/locales/registry.ts` 和
`packages/spec/src/system/platform-locales.ts`。
- **两分钟验证**:`node scripts/check-skills-token-ratchet.mjs`,预期 exit
0,`skills/objectui/guides/i18n.md` 读数 1411/1413。
- **需要你做的**:`skills/**` 属 Tier H,需要 `os-zhuang` 或 `hotlong` 批准。
## What changes
Every tag, path and alias the guide now states was read on `main`
(`3fe5f2a02`, after PR #30902 at `5bca14fc`):
| Taught | Source on `main` |
|:--|:--|
| The eleven pack keys, in table order |
`packages/spec/src/system/platform-locales.ts` `ROWS`;
`ui/packages/i18n/src/locales/registry.ts` `LAZY_LOCALE_LOADERS` (typed
on `PlatformLocaleTag`) and `BUILT_IN_LANGUAGE_CODES`;
`locales/index.ts` `builtInLocales` ("there is no `zh` or `pt` key") |
| Module `@object-ui/i18n/locales/<tag>` |
`ui/packages/i18n/package.json` export `./locales/*`; after `pnpm
build`, `dist/locales/zh-Hans.js`, `zh-Hant.js`, `pt-BR.js` (+ `.d.ts`)
exist |
| Stored `zh` / `zh-CN` → `zh-Hans`, `zh-TW` → `zh-Hant`, `pt` → `pt-BR`
| `PLATFORM_LOCALE_READ_ALIASES`, read by `resolveBuiltInLanguage`
(`registry.ts`) through `platformLocaleTagOf` |
| "Write the tag" | `platform-locales.ts`: read aliases are "Reads only:
a new write uses the table tag itself" |
| Switcher fed by `PLATFORM_LOCALES` (`tag`, `label`) | `PlatformLocale`
interface, exported from `@objectstack/spec/system` |
| Switcher `value={resolveBuiltInLanguage(language) ?? language}` | An
instance can run in a stored alias (`zh` from a stored choice via
`resolveBootstrapConfig`, a seeded `zh-CN` via `resolveSeedLanguage`);
`resolveBuiltInLanguage` is exported from the package entry
(`ui/packages/i18n/src/index.ts`) |
The switcher fence is `os:check`-marked and compiles against the built
types: `pnpm --dir ui run check:skill-examples` exit 0, `--list` shows
`i18n.md:38 marked pass` (the `@objectstack/spec/system` import
resolves). The unmarked setup fence's only `--measure` error is the
pre-existing `AppContent` fragment name; the `'zh-Hans'` key
type-checks.
The inline-map section (L133 on) is untouched: its `zh-CN` keys are
still valid inline-map keys and it needs no `zh-Hant` example to stay
correct.
**Evals swept:** `skills/objectui/evals/i18n.json` has no case grading a
`zh` / `pt` pack key or path. Its one `zh` string, `must_not_contain:
"import zh from './zh.json'"`, grades an app's own JSON import, not the
retired built-in key, so it is left as is.
## Token budget
`node scripts/check-skills-token-ratchet.mjs`:
`skills/objectui/guides/i18n.md` **1413 → 1411** (5652 → 5643 bytes;
ceiling 1413, unchanged, headroom 2). Bundle total 228257 → 228255. No
ratchet raise; `scripts/check-skills-token-ratchet.mjs` is not touched.
Growth paid by deleting restatement in the same file, each with its
surviving home:
1. L3 intro "Multi-language support via `@object-ui/i18n`." Home: the H1
and every fence's `import … from '@object-ui/i18n'` (first at Setup).
2. The Setup comment `// Auto-detect from navigator` on
`detectBrowserLanguage: true`. Home: the option's own name (and its doc
on `I18nConfig.detectBrowserLanguage` in
`ui/packages/i18n/src/i18n.ts`).
3. The RTL section's fence `const { direction } =
useObjectTranslation(); // direction: 'ltr' | 'rtl'`. Home: the
useObjectTranslation hook example, which destructures `direction` and
applies it (`<header dir={direction}>`); the RTL prose ("The provider
updates `document.dir`…") stays.
4. Common mistakes bullet "Bundling all locale files upfront — use lazy
loading for apps with many languages." Home: § Lazy language loading
("For large apps, load translations on demand instead of bundling all
locales").
5. (review S1 payment) The § Language-aware + responsive page intro
"When combining with `@object-ui/mobile` for responsive layouts:". Home:
the section heading ("responsive page") and the fence's `import {
useBreakpoint } from '@object-ui/mobile'`.
Review round 1 (contract review PASS at `291ef83d8`, comment
6694588461): S1 fixed in delta commit `450d72405`. The switcher's
controlled `value` now resolves a stored alias to its table tag, so an
instance running in `zh` or `zh-CN` selects 简体中文 instead of falling to
the first option. Its +60 bytes are paid by deletion 5. The out-of-scope
LocaleSwitcher finding is removed from this body: the seat files it as
its own card.
## Review tier
`dispatch-gates` mandates the contract-review tier for `skills/**`
(clause ①); waived by the maintainer's standing order in this project
(2026-11-03). The seat runs the contract review.
## Gates
`node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` on head `450d72405` (2 paths vs merge base
`9d939c582`): **45 commands** (the same list as round 1), each run under
`timeout 900` with `NODE_OPTIONS=--max-old-space-size=8192` (raised from
the cloud container default heap), exit code captured before any pipe →
**45 × exit 0**. `pnpm --filter @objectstack/spec run
check:skill-examples` first exited 3 (NOT MEASURED: the spec build
predated the rebase onto `9d939c582`); after `pnpm --filter
@objectstack/spec build` it exited 0, and that is the recorded code.
`--ran` reconciliation: `45 derived famil(ies) accounted for — 45 run, 0
NOT-MEASURED`. Extra, not derived but run by CI (`ci.yml`): `pnpm --dir
ui run check:skill-examples` → exit 0 after the spec rebuild; `--list`
shows `i18n.md:38 marked pass` with the new import. Round 1 at
`291ef83d8` was also 45 × exit 0 after a full `pnpm build` (119/119).
`origin/main` has since gained `e396095b6` (`ui/packages/types` only,
disjoint), so no merge was needed. `node
scripts/check-commit-card-trailers.mjs --range origin/main..HEAD` → exit
0 before each push.
<details><summary>Ran list</summary>
```
node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0
node scripts/check-adr-0087-registration.mjs --self-test :: exit 0
node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0
node scripts/check-closing-keyword-parity.mjs :: exit 0
node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0
node scripts/check-comment-mask-corpus.mjs :: exit 0
node scripts/check-doc-route-spelling.mjs --advisory :: exit 0
node scripts/check-doc-route-spelling.mjs --self-test :: exit 0
node scripts/check-dts-emitted.mjs --self-test :: exit 0
node scripts/check-empty-changeset.mjs --base origin/main :: exit 0
node scripts/check-empty-changeset.mjs --self-test :: exit 0
node scripts/check-skills-token-ratchet.mjs :: exit 0
node scripts/check-skills-token-ratchet.mjs --self-test :: exit 0
node scripts/ci/assert-turbo-remote-cache.mjs --self-test :: exit 0
node scripts/ci/plan-test-core-shards.mjs --self-test :: exit 0
node scripts/ci/prune-turbo-cache.mjs --self-test :: exit 0
node scripts/ci/snapshot-next.mjs --self-test :: exit 0
node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0
node scripts/release-pending-publish.mjs --self-test :: exit 0
pnpm --dir ui exec vitest run scripts/ :: exit 0
pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 0
pnpm --filter @objectstack/spec run check:skill-examples :: exit 0
pnpm check:agent-test-spelling :: exit 0
pnpm check:changeset-gate-self-tests :: exit 0
pnpm check:ci-filter-parity :: exit 0
pnpm check:closed-ceremony-text :: exit 0
pnpm check:corpus-claim-drift :: exit 0
pnpm check:cross-package-test-inputs :: exit 0
pnpm check:doc-authoring :: exit 0
pnpm check:driver-memory-census :: exit 0
pnpm check:dts-closure :: exit 0
pnpm check:dual-build-cjs-loads :: exit 0
pnpm check:gitlink-declared :: exit 0
pnpm check:lean-entry-closure :: exit 0
pnpm check:nul-bytes :: exit 0
pnpm check:pm-governed-merges :: exit 0
pnpm check:pm-skill-id-lint :: exit 0
pnpm check:published-files :: exit 0
pnpm check:refd-timer-probe :: exit 0
pnpm check:role-word :: exit 0
pnpm check:skill-compatibility :: exit 0
pnpm check:skill-frame-sync :: exit 0
pnpm check:skill-identifier-liveness :: exit 0
pnpm check:sourcemap-no-sources-content :: exit 0
pnpm check:watch-hint-literal :: exit 0
```
</details>
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01J8VVAjteesTptAwhHn3GuE
<!-- signed: domain:skills#3 · huangyiirene ·
session_01J8VVAj7CvjkGXvgXzd6RZ7 -->
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent cef3b8f commit 226c988
2 files changed
Lines changed: 21 additions & 21 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
4 | | - | |
5 | 3 | | |
6 | 4 | | |
7 | 5 | | |
| |||
10 | 8 | | |
11 | 9 | | |
12 | 10 | | |
13 | | - | |
| 11 | + | |
14 | 12 | | |
15 | 13 | | |
16 | | - | |
| 14 | + | |
17 | 15 | | |
18 | 16 | | |
19 | 17 | | |
| |||
28 | 26 | | |
29 | 27 | | |
30 | 28 | | |
31 | | - | |
32 | | - | |
33 | | - | |
34 | | - | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
35 | 34 | | |
36 | 35 | | |
37 | 36 | | |
38 | 37 | | |
39 | 38 | | |
40 | | - | |
| 39 | + | |
| 40 | + | |
41 | 41 | | |
42 | 42 | | |
43 | 43 | | |
44 | 44 | | |
45 | 45 | | |
46 | 46 | | |
47 | 47 | | |
48 | | - | |
49 | | - | |
50 | | - | |
51 | | - | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
52 | 52 | | |
53 | 53 | | |
54 | 54 | | |
| |||
75 | 75 | | |
76 | 76 | | |
77 | 77 | | |
78 | | - | |
79 | | - | |
80 | | - | |
81 | | - | |
82 | | - | |
83 | 78 | | |
84 | 79 | | |
85 | 80 | | |
| |||
153 | 148 | | |
154 | 149 | | |
155 | 150 | | |
156 | | - | |
157 | | - | |
158 | 151 | | |
159 | 152 | | |
160 | 153 | | |
| |||
176 | 169 | | |
177 | 170 | | |
178 | 171 | | |
179 | | - | |
180 | 172 | | |
181 | 173 | | |
182 | 174 | | |
| |||
0 commit comments