Repository navigation
Commit a11ef71
i18n(platform-objects): ship the platform objects, Setup, Studio and Account in zh-Hant (#30951)
<!-- claude-projects-attribution: {"github_login":"os-elon-musk"} -->
_Requested by **Elon** · [project
thread](https://claude.ai/code/project/chan_01WedDzV26nniwxv7jC88B9D?thread=cmsg_01WedDzV26nniwxv7jC88B9D7v5H7BaFmL7sUCoN7tSxhm)_
domain:server#1 · os-elon-musk · session_016WV4cya5ej5GQV86RPbRPK
Part of #30512 — package 11 of 11 (`@objectstack/platform-objects`),
first of its seven locales: `zh-Hant`. Per the seat's ruling B, `ar`,
`fr`, `pt-BR`, `ru`, `de` and `ko` follow one PR each, and the last PR
of the series makes the bundle check read the platform locale table.
Clause-②: no
Metadata-protocol: none
## 维护者速读
- **改了什么:** 平台内置对象(用户、组织、会话、API
密钥、OAuth、SSO、SCIM、通知、邮件、任务、导入、元数据、设置、汇率等全部 `sys_*`)、Studio
里各元数据类型的配置表单、「设置」「Studio」「账户」三个应用的导航、系统概览仪表盘与数据集、平台页面标题,以及用户 /
组织记录页上的内联文案,补上繁体中文(zh-Hant)。
- **为什么改:** 平台语言表要求每个界面带齐 11 种语言;这是第 3 期按包补齐的最后一个包(platform-objects)的第 1
种语言。用繁中的管理员和开发者打开平台不再大面积看到英文。
- **风险与回滚:** 只加翻译数据和注册行,不动逻辑、schema、接口;原有 4
种语言一字未改。新语言同样走「源文本哈希回退」,手写部分每条都记了源哈希。测试改动都是把 zh-Hant
加进各测试的语言列表(覆盖变宽,没有放宽断言),外加 cli 一个形状测试的语言码正则放宽到接受 `zh-Hant`
这种书写体子标签(否则它一个内联文案都认不出)。回滚即撤 PR。
- **先看:** `src/apps/translations/setup.translation.ts` 与
`src/metadata-translations/index.ts`(注册),`scripts/i18n-extract.config.ts`(`--locales`
加 zh-Hant),然后抽看 `zh-Hant.ts`(导航,约 140 条)和任一生成文件。
- **两分钟验证:** `node scripts/check-i18n-bundles.mjs
--filter=platform-objects` 输出 in sync;`pnpm --filter
@objectstack/platform-objects test` 全绿。
- **需要你做的:** 本 PR 改动超过 3000 行(含生成物),按规程需人工合并;契约复核尚未做(contract review
owed),复核通过后由席位请 os-zhuang / hotlong 审批。
## What changes
- **Generated bundles** `zh-Hant.objects.generated.ts` (1,674 leaves)
and `zh-Hant.metadata-forms.generated.ts` (1,263 leaves), written by the
repo's own `os i18n extract --fill=default --source-hashes` from the
merge baseline, plus its provenance companion
`zh-Hant.source-hashes.generated.ts`.
- **Hand bundle** `zh-Hant.ts` (138 leaves: the Setup, Studio and
Account navigation, the System Overview dashboard, the datasets and the
platform pages), with `zh-Hant.source-hashes.ts` recording the digest of
the `en` source each leaf was translated from: all 138, so the first
source edit under any of them falls back instead of serving a superseded
translation.
- **Registration:** `SetupAppTranslations` and
`MetadataFormsTranslations` serve `zh-Hant` through
`withSourceFallback`, exactly as the existing three; the `apps` barrel
exports `zhHant`.
- **Extract config:** its docstring's `--locales` (what `check:i18n`
executes) and its merge baseline carry `zh-Hant`, so the gate covers the
new bundles from this PR on. The root `pnpm i18n:extract` script still
lists three locales; the final PR of the series moves both it and
`scripts/check-i18n-bundles.mjs` to the platform locale table.
- **Inline page copy:** the 42 inline locale maps on the user and
organization record pages and the System Overview dataset's null label
gain a `zh-Hant` entry.
## Tests
- Locale lists widened to `zh-Hant`, no assertion changed: in this
package `plugin.translations.test.ts`,
`setup-nav-per-user-stores.test.ts`, `sys-user-details-tab.test.ts`,
`system-overview-null-label.test.ts` (these four pin the shipped set and
go red without it), and the vocabulary, parity, tombstone, source-hash,
BU-rename, metadata-forms, repeater, dashboard-header, confirm-question
and identity copy tests (these iterate a fixed list, so `zh-Hant` is now
held to the same bars).
- Cross-package pins held for `zh-Hant`: `plugin-security`'s People &
Organization nav test (its control pins the Setup locale set and goes
red without the new tag); `service-settings`'
`setup-nav-hub-parity.test.ts` (each Setup sidebar entry reads as its
hub card's title); `plugin-approvals`'
`approval-status-vocabulary.test.ts` (the `my_pending` view label equals
the account nav's `nav_account_approvals`: 待我核准).
- `packages/cli/test/platform-page-i18n-parity.test.ts`: its inline-map
shape test recognised a locale key as `xx` or `xx-YY` only, so with a
`zh-Hant` key present it recognised no map at all (`expected 0 to be
greater than or equal to 38`). The pattern now also accepts a script
subtag; the 42 maps are found again and every one is complete in all
five shipped locales.
## Acceptance notes
- **Quality bar (#17508 / PR #19345):** written for a Taiwan reader.
Each leaf starts from the reviewed `zh-CN` text, converted with OpenCC's
Traditional (Taiwan, phrases) table and then a house glossary of about
170 term rules that matches the `zh-Hant` bundles nine packages already
ship (權限, 類型, 中繼資料, 工作階段, 權杖, 金鑰, 檢視, 欄 / 列 for column / row, 套件, 範本,
稽核, 共用, 指派, 核准, 電子郵件, 唯讀, 逾時, 背景工作, …). 446 leaves whose English and
`zh-CN` pair already has a `zh-Hant` rendering elsewhere in the repo
reuse it verbatim. Every one of the 1,541 distinct short leaves was
read, and the long help texts were reviewed by sample and by a targeted
audit of each rule that rewrites words in context (row / column, 應用 /
應用程式, 按 / 依, 通過 / 透過).
- **Mechanical checks, per leaf against `zh-CN`:** backtick spans,
`{{holes}}`, `{holes}`, angle tokens and snake_case identifiers
byte-identical (three intended differences, all Chinese prose inside a
hole default or a JSON example: `default:'該成員'`, `"已封存"`); no
Simplified-only character remains (the only s2t remarks are the Taiwan
forms 台, 准, 群, 游, 里).
- **Cross-package wording pins carried:** `nav_account_approvals` =
plugin-approvals' `my_pending` (待我核准); `nav_assignment_rules` = #30856's
object name (指派規則); the queue, sharing, approval-delegation and
HTTP-delivery entries read as their objects' `zh-Hant` labels; each
`nav_settings_*` entry reads as its settings hub title from #30870 (so
郵件投遞 / 簡訊投遞 there, while the HTTP delivery log says 傳送).
- **Leaves equal to English, on purpose:** the 40 `objects` leaves
`zh-CN` already decided as echoes (`ID`, `JWKS`, `Client ID`, the SSO
placeholders, …), each recorded by the extractor in
`zh-Hant.source-hashes.generated.ts`, and three hand leaves (`Webhooks`,
`Studio`, `AI`).
- **One cross-locale coincidence fixed:** `zh-CN`'s
`action.fields.method.helpText` is the Latin `GET / POST / PUT /
DELETE`, not the source; a converted copy made two locales agree on it
and `check:i18n-stale-fill` reported it. `zh-Hant` now translates it
(`HTTP 方法(GET、POST、PUT、DELETE)`); the stale-fill check passes with the
baseline untouched. The `zh-CN` leaf itself is left as it is (existing
fills are out of this card's scope).
- No string opens with `os ` followed by a lowercase word
(`check-cli-command-ids` passes), and the whole "Lint · docs & code
guards" lane was run locally before opening.
## Verification
<details><summary>Package suites, typecheck, build (verify
lock)</summary>
```
pnpm install --frozen-lockfile && turbo run build --filter=!@objectstack/docs (at head e8d9055, on main 33043bd)
Tasks: 118 successful, 118 total
pnpm --filter @objectstack/platform-objects test
Test Files 117 passed (117)
Tests 1636 passed (1636) (1593 before this PR; the 43 new are the zh-Hant cases)
pnpm --filter @objectstack/platform-objects typecheck (tsc, scripts tsconfig, check:test-typecheck OK)
pnpm --filter @objectstack/plugin-security test 246 files, 5686 passed | 45 skipped
pnpm --filter @objectstack/plugin-approvals test 115 files, 1502 passed
pnpm --filter @objectstack/service-settings test 71 files, 1351 passed
packages/cli: vitest run test/platform-page-i18n-parity.test.ts 27 passed
os-verify-lock: VERDICT command-exit 0 (one '&&' chain)
typecheck of plugin-security, plugin-approvals, service-settings and cli: 4 x exit 0
```
</details>
<details><summary>i18n gates, the derived families and the docs &
code guards lane</summary>
```
node scripts/check-i18n-bundles.mjs (all packages) (at e8d9055)
check-i18n-bundles: OK (10 package(s) — all bundles in sync, no undeclared authoring keys). EXIT 0
node scripts/check-i18n-stale-fill.mjs
check-i18n-stale-fill: OK (11 bundle set(s) — no new stale fills, 1 baselined). EXIT 0
pnpm check:app-nav-i18n
check-app-nav-i18n: OK (13 contributor(s), 5 locale(s), 2 app(s) — setup: 56 merged nav id(s),
account: 12 merged nav id(s) — every id labelled in every locale). EXIT 0
pnpm check:i18n-coverage OK (14 config(s), 426 baselined untranslated string(s), none new). EXIT 0
pnpm check:i18n-walk-parity EXIT 0
node scripts/check-cli-command-ids.mjs EXIT 0
dispatch-gates --commands (at e8d9055): 64 families, each run and recorded with its exit code: 64 x exit 0
dispatch-gates --ran: 64 derived, 64 run, 0 NOT-MEASURED (a derived zero)
pnpm lint (repo-wide, at e8d9055): exit 0
CI lane "Lint · docs & code guards", every command run locally (at e8d9055)
56 commands (lane-verdict excepted), 56 x exit 0, check-cli-command-ids included
changed lines 7271 (+7216 / -55), 36 files: over the 3000-line human-merge threshold
```
</details>
The branch is one commit on `main` `33043bd8` (after #30931 landed);
every number above was measured at that head. Main's commits since the
earlier draft (#30846, #30919, #30929, #30931) touch no file this PR
changes.
Dogfood: not run — content-only package PR, no `!` in the title and no
`(narrowing)` arm.
---
_Generated by [Claude
Code](https://claude.ai/code/session_016WV4cya5ej5GQV86RPbRPK)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 8ae0ab9 commit a11ef71
36 files changed
Lines changed: 7218 additions & 55 deletions
File tree
- .changeset
- packages
- cli/test
- platform-objects
- scripts
- src
- apps
- dashboards
- translations
- identity
- metadata-translations
- pages
- plugins
- plugin-approvals/src/translations
- plugin-security/src
- services/service-settings/src
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
738 | 738 | | |
739 | 739 | | |
740 | 740 | | |
741 | | - | |
742 | | - | |
743 | | - | |
| 741 | + | |
| 742 | + | |
| 743 | + | |
| 744 | + | |
744 | 745 | | |
745 | | - | |
| 746 | + | |
746 | 747 | | |
747 | 748 | | |
748 | 749 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
11 | | - | |
| 11 | + | |
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
| |||
221 | 221 | | |
222 | 222 | | |
223 | 223 | | |
| 224 | + | |
224 | 225 | | |
225 | 226 | | |
226 | 227 | | |
227 | 228 | | |
| 229 | + | |
228 | 230 | | |
229 | 231 | | |
230 | 232 | | |
| |||
247 | 249 | | |
248 | 250 | | |
249 | 251 | | |
| 252 | + | |
250 | 253 | | |
251 | 254 | | |
252 | 255 | | |
| |||
347 | 350 | | |
348 | 351 | | |
349 | 352 | | |
| 353 | + | |
350 | 354 | | |
351 | 355 | | |
352 | 356 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
| 33 | + | |
33 | 34 | | |
34 | 35 | | |
35 | 36 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
57 | 57 | | |
58 | 58 | | |
59 | 59 | | |
60 | | - | |
| 60 | + | |
61 | 61 | | |
62 | 62 | | |
63 | 63 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
45 | 45 | | |
46 | 46 | | |
47 | 47 | | |
| 48 | + | |
48 | 49 | | |
49 | 50 | | |
50 | 51 | | |
51 | 52 | | |
| 53 | + | |
52 | 54 | | |
53 | 55 | | |
54 | 56 | | |
55 | 57 | | |
| 58 | + | |
56 | 59 | | |
57 | 60 | | |
58 | 61 | | |
| |||
127 | 130 | | |
128 | 131 | | |
129 | 132 | | |
130 | | - | |
131 | | - | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
132 | 137 | | |
133 | 138 | | |
| 139 | + | |
134 | 140 | | |
135 | 141 | | |
136 | 142 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
| 18 | + | |
18 | 19 | | |
19 | | - | |
| 20 | + | |
20 | 21 | | |
21 | 22 | | |
22 | 23 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
110 | 110 | | |
111 | 111 | | |
112 | 112 | | |
| 113 | + | |
113 | 114 | | |
114 | 115 | | |
115 | | - | |
| 116 | + | |
116 | 117 | | |
117 | 118 | | |
118 | 119 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
58 | 58 | | |
59 | 59 | | |
60 | 60 | | |
| 61 | + | |
61 | 62 | | |
62 | | - | |
| 63 | + | |
63 | 64 | | |
64 | 65 | | |
65 | 66 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
| 17 | + | |
17 | 18 | | |
18 | 19 | | |
19 | 20 | | |
20 | 21 | | |
21 | 22 | | |
22 | 23 | | |
| 24 | + | |
23 | 25 | | |
24 | 26 | | |
25 | 27 | | |
| |||
0 commit comments