Skip to content

Commit 0e88208

Browse files
i18n(service-settings): ship the built-in settings pages in zh-Hant, ar, fr and pt-BR (#30870)
<!-- 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 6 of 11, first half (`@objectstack/service-settings` in `zh-Hant`, `ar`, `fr`, `pt-BR`). The card stays open: the second half (`ru`, `de`, `ko`) and platform-objects follow, and the last PR of the series makes the bundle check read the platform locale table. Clause-②: no Metadata-protocol: none ## 维护者速读 - **改了什么:** 「设置」里内置的设置页(邮件、短信、品牌、公司、本地化、认证、文件存储、AI 与向量、知识库,以及 `@objectstack/objectql` 注册的数据生命周期页)的页标题和说明、分组、字段名和帮助、选项、提示条、操作按钮和来源标记,补上繁中、阿语、法语、巴葡 4 种。俄语、德语、韩语在下半包。 - **为什么改:** 平台语言表要求每个界面带齐 11 种语言;这是第 3 期按包补齐的第 6 个包的上半。用这 4 种语言的管理员打开「设置」不再看到英文。 - **风险与回滚:** 只加 4 个翻译文件和注册行,不动逻辑、schema、接口;原有 4 种语言一字未改。交接提交里改 `localization-currency-lock` / `localization-locale-options` 文案表的部分**按席位裁决整段去掉**:#30630(已作为 #30734 落地)拥有这两张表,且已带齐 11 种语言。测试改动只是覆盖测试把 4 种新语言加进列表(覆盖变宽,没有放宽断言)。回滚即撤 PR。 - **先看:** `src/translations/index.ts`(按表标签注册,zh-CN 在 zh-Hant 前),再看 `settings-translation-coverage.test.ts`,然后抽看任一新语言文件。 - **两分钟验证:** `pnpm --filter @objectstack/service-settings exec vitest run src/translations/settings-translation-coverage.test.ts` 全绿。 - **需要你做的:** 无,席位落地。 ## What changes - Four new hand-authored translation modules under the platform locale table's tags (`zh-Hant`, `ar`, `fr`, `pt-BR`), covering every built-in settings manifest: page titles and descriptions, group headings, field labels and help, option labels, banners, action buttons and the source badges. Country pickers name each country in the reader's language through `Intl.DisplayNames`, as the existing locales do. - `src/translations/index.ts` registers them in `settingsBuiltinTranslations` (`zh-CN` stays ahead of `zh-Hant`) and exports them beside the existing four. - Carried from the released handover commit `70f9870a` (session `session_01Utp6Cai5CRdAs4u9gTipWU`) **without** its `localization-currency-lock.ts` / `localization-locale-options.ts` hunks (and their test hunk), per the seat's ruling of 2026-11-05: #30630, landed as #30734, owns those copy tables and already carries all eleven languages there. This PR does not touch them. - The `zh-Hant` file writes the Chinese provider brands in Traditional script (`阿里通義`, `矽基流動`, `智譜`); the handover had kept the Simplified spelling. ## Tests - `settings-translation-coverage.test.ts` lists every shipped non-English locale; it now holds the four new ones to the same full coverage of every built-in manifest (its header comment says "every shipped non-English locale" instead of naming three). No assertion changed. ## Acceptance notes - **Quality bar (#17508 / PR #19345):** every leaf written for the reader; placeholders, code spans, URLs and identifiers byte-identical, checked mechanically per leaf against `en` and against `zh-CN` (which carries the inline-manifest keys `en.ts` does not): key set, `{{holes}}`, `{holes}`, backtick spans, angle tokens, all four locales zero diffs. Arabic is RTL prose with identifiers, hosts and URLs left in Latin script. `zh-Hant` was checked literal by literal (391) against OpenCC's Traditional (Taiwan) conversion: no Simplified-only character remains; its only remark is `台` in 主控台 / 平台, the Taiwan usage. - **Leaves equal to English, on purpose:** provider, product and protocol names (`SMTP`, `S3`, `OpenAI`, `Anthropic`, `Vercel AI Gateway`, `Turso / libSQL`, `RAGFlow`, …); the terms the existing `zh-CN` / `ja-JP` / `es-ES` also leave in English (`Base URL`, `Embedder`, `Bucket`, `Backend`, `Endpoint`); words spelled the same in the language (`fr` `Port`, `Contact`, `Finance`, `Sessions`, `Local`, `Global`; `pt-BR` `Host`, `Local`, `Global`); and country names whose local spelling is the English one. - No cross-locale coincidence: `check:i18n-stale-fill` passes with the baseline untouched. - 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 suite, typecheck, build (verify lock)</summary> ``` turbo run build --filter=!@objectstack/docs: 118/118 tasks successful, exit 0 (at head 9c22c66, on main a2f523a) pnpm --filter @objectstack/service-settings test && typecheck (at head 9c22c66) Test Files 71 passed (71) Tests 1313 passed (1313) os-verify-lock: VERDICT command-exit 0 same patch at f8d192f9 (on main ae82d05): 70 files, 1254 passed, VERDICT command-exit 0 (main's #30720 and #30835 added service-settings tests in between; neither touches translations/ or the manifests) ``` </details> <details><summary>i18n gates, the derived families and the docs &amp; code guards lane</summary> ``` node scripts/check-i18n-bundles.mjs (all packages; service-settings has no extract config) (at 9c22c66) check-i18n-bundles: OK (10 package(s) — all bundles in sync, no undeclared authoring keys). EXIT 0 node scripts/check-i18n-stale-fill.mjs (at 9c22c66) check-i18n-stale-fill: OK (11 bundle set(s) — no new stale fills, 1 baselined). EXIT 0 node scripts/check-cli-command-ids.mjs (at 9c22c66) EXIT 0 dispatch-gates --commands (at f8d192f9): 60 families, each run and recorded with its exit code: 60 x exit 0 dispatch-gates --ran: 60 derived, 60 run, 0 NOT-MEASURED (a derived zero) re-derived at 9c22c66: the identical 60-command list pnpm lint (repo-wide, at f8d192f9): exit 0 CI lane "Lint · docs & code guards", every command run locally (at f8d192f9) 56 commands (lane-verdict excepted), 56 x exit 0, check-cli-command-ids included changed lines 2697 (+2694 / -3), 7 files: under the 3000-line human-merge threshold ``` </details> The branch is one commit on `main` `a2f523aa` (after #30856 landed). Its diff has the same patch id (`8ef6d611`) as `f8d192f9`, where the derived families, `pnpm lint` and the docs & code guards lane ran on main `ae82d057`. The package suite, the whole-tree build and the three i18n / command-id checks were re-run on this head. (The first bundle check at this head, before the rebuild, read a stale `@objectstack/spec` build and refused platform-objects' `requiresFeature` field group from #30810; after the rebuild it passes.) 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> Co-authored-by: objectstack-fleet[bot] <332303061+objectstack-fleet[bot]@users.noreply.github.com>
1 parent 2a6a28d commit 0e88208

7 files changed

Lines changed: 2694 additions & 3 deletions

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'@objectstack/service-settings': patch
3+
---
4+
5+
i18n(service-settings): the built-in Setup settings pages ship in Traditional Chinese, Arabic, French and Brazilian Portuguese
6+
7+
Clause-②: no
8+
Metadata-protocol: none
9+
10+
The built-in settings pages (Mail, SMS, Branding, Company, Localization, Authentication, File Storage, AI & Embedder, Knowledge, and the Data Lifecycle page `@objectstack/objectql` registers) now carry `zh-Hant`, `ar`, `fr` and `pt-BR` beside the existing `en`, `zh-CN`, `ja-JP` and `es-ES`: page titles and descriptions, group headings, field labels and help, option labels, banners, action buttons and the source badges. An administrator reading Setup in one of those languages sees these pages in their own language instead of English. Country pickers name each country in the reader's language through `Intl.DisplayNames`, as the existing locales do. The settings coverage test now holds each new locale to the same full coverage. First half of package 6 of #30512; `ru`, `de` and `ko` follow in the second half.

‎packages/services/service-settings/src/translations/ar.ts‎

Lines changed: 698 additions & 0 deletions
Large diffs are not rendered by default.

‎packages/services/service-settings/src/translations/fr.ts‎

Lines changed: 752 additions & 0 deletions
Large diffs are not rendered by default.

‎packages/services/service-settings/src/translations/index.ts‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,20 @@ import { en } from './en.js';
2222
import { zhCN } from './zh-CN.js';
2323
import { jaJP } from './ja-JP.js';
2424
import { esES } from './es-ES.js';
25+
import { zhHant } from './zh-Hant.js';
26+
import { ar } from './ar.js';
27+
import { fr } from './fr.js';
28+
import { ptBR } from './pt-BR.js';
2529

26-
export { en, zhCN, jaJP, esES };
30+
export { en, zhCN, jaJP, esES, zhHant, ar, fr, ptBR };
2731

2832
export const settingsBuiltinTranslations: PlatformTranslationBundle = {
2933
en,
3034
'zh-CN': zhCN,
3135
'ja-JP': jaJP,
3236
'es-ES': esES,
37+
'zh-Hant': zhHant,
38+
'ar': ar,
39+
'fr': fr,
40+
'pt-BR': ptBR,
3341
};

‎packages/services/service-settings/src/translations/pt-BR.ts‎

Lines changed: 736 additions & 0 deletions
Large diffs are not rendered by default.

‎packages/services/service-settings/src/translations/settings-translation-coverage.test.ts‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
22

33
/**
4-
* Settings-translation coverage guard (zh-CN / ja-JP / es-ES).
4+
* Settings-translation coverage guard (every shipped non-English locale).
55
*
66
* Every built-in settings manifest ships English labels inline; the console
77
* localizes them by resolving `settings.<namespace>.…` against the shipped
@@ -24,7 +24,7 @@ import { describe, it, expect } from 'vitest';
2424
import type { SettingsManifest } from '@objectstack/spec/system';
2525
import { lifecycleSettingsManifest } from '@objectstack/objectql';
2626
import * as manifestsModule from '../manifests/index.js';
27-
import { en, zhCN, jaJP, esES } from './index.js';
27+
import { en, zhCN, jaJP, esES, zhHant, ar, fr, ptBR } from './index.js';
2828

2929
// The manifests barrel also exports action handlers and the aggregate array;
3030
// keep only the manifest objects.
@@ -53,6 +53,10 @@ const LOCALES: Array<[string, { settings?: Record<string, any> }]> = [
5353
['zh-CN', zhCN],
5454
['ja-JP', jaJP],
5555
['es-ES', esES],
56+
['zh-Hant', zhHant],
57+
['ar', ar],
58+
['fr', fr],
59+
['pt-BR', ptBR],
5660
];
5761

5862
function missingFor(data: { settings?: Record<string, any> }, m: SettingsManifest): string[] {

‎packages/services/service-settings/src/translations/zh-Hant.ts‎

Lines changed: 483 additions & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)