Skip to content

Commit bd504f5

Browse files
fix(i18n): separate the verb from the app name in the zh build header (#26721)
<!-- claude-projects-attribution: {"github_login":"zhuangjianguo"} --> _Requested by **Steedos** · [project thread](https://claude.ai/code/project/chan_018ETKaNwMZCNRYD7D8Q9Ubb?thread=cmsg_018ETKaNwMZCNRYD7D8Q9UbbXvWtxSR1T4kCqZYPovXw9C)_ Fixes #26643 Clause-②: no Metadata-protocol: none ## 维护者速读 - **改了什么**:中文界面下聊天机器人构建面板的标题,动词和应用名之间加了分隔符:完成时显示「已构建 · CRM」,进行中显示「正在构建 · CRM…」。以前是「已构建CRM」「正在构建CRM…」,应用名直接粘在动词上。 - **为什么改**:应用名是英文时尤其难读(「已构建Library Lending Management」)。分隔符沿用同组已有的「已搭建并上线 · 应用名」。 - **风险与回滚**:极低。只改 zh 语言包里两个值,不增删任何键;日文、韩文本来就没有这个问题,保持不变,其它拉丁语系语言包不动。回滚即 revert 本 PR。 - **先看**:`ui/packages/i18n/src/locales/zh.ts` 的 `chatbot.build.building` / `built` 两行;`ui/packages/plugin-chatbot/src/__tests__/buildPanelI18n-7388.test.tsx` 改过的三个 zh 断言和新增的 ja/ko 用例。 - **两分钟验证**:`cd ui && pnpm exec vitest run packages/plugin-chatbot/src/__tests__/buildPanelI18n-7388.test.tsx`,预期 14 个用例全绿;或在中文控制台让聊天机器人构建一个应用,标题显示「已构建 · 应用名」。 - **需要你做的**:无,席位落地。 ## What changes In the zh pack, the chatbot build panel header composed the verb and the app name with nothing between them, so the name ran on into the verb (「已构建Library Lending Management」). Both header frames now use the ` · ` separator that the sibling `chatbot.build.builtAndLive` (「已搭建并上线 · APP」) already used: | key (zh) | before | after | |:--|:--|:--| | `chatbot.build.built` | `已构建APP` | `已构建 · APP` | | `chatbot.build.building` | `正在构建APP…` | `正在构建 · APP…` | (`APP` stands for the interpolated app name.) `building` is in this PR by the seat's ruling: the same defect, in the same pack and the same test. Values only: no key is added, removed or renamed. The other CJK packs did not run on and are unchanged: ja puts the name first and a particle after it (`APPを構築しました`), ko already leaves a space (`APP 빌드 완료`). The Latin-script packs are untouched. ## Why The chatbot build panel header is the first thing a zh user reads when a build finishes, and a Latin-script app name glued to the verb reads as one word. ## Tests - `buildPanelI18n-7388.test.tsx`: the three zh header pins move to the separated form (`正在构建 · CRM…`, `已构建 · CRM`, and the unnamed-build `正在构建 · 你的应用…`). A new describe pins the ja and ko headers as they are, for both the in-flight and the finished frame, so a later change to either pack has to say so. - Ablation (one-off, not kept): with the fix committed, `zh.ts` was restored to its `main` blob (old value count 1, new value count 0), `@object-ui/i18n` rebuilt, and the test file ran red: Tests 3 failed, 11 passed (the three zh header cases). Restored with `git checkout HEAD`, `git diff HEAD` empty, rebuilt, 14 passed. ## Acceptance notes - **The unnamed-build fallback.** `chatbot.build.appFallback` (`你的应用`) is not a separate frame: the component substitutes it into the same `building` / `built` template. So an unnamed build now reads 「正在构建 · 你的应用…」. Making it read without the separator would need a new key or a component change, both outside this card. The separated form matches what `builtAndLive` already renders for an unnamed build (「已搭建并上线 · 你的应用」), so the three frames now read alike. - Nothing else in the repository pins the old zh strings (`git grep` for `已构建` and `正在构建` finds only the pack and this test). ## Verification All readings at head `82120e07` (base `f6ffd723`). <details><summary>Touched packages: @object-ui/i18n and @object-ui/plugin-chatbot</summary> - `pnpm exec turbo run type-check --filter=@object-ui/plugin-chatbot --filter=@object-ui/i18n --concurrency=2` under the verify lock (each package runs `tsc --noEmit && tsc -p tsconfig.test.json`, so the test file is compiled): 45 tasks successful, VERDICT command-exit 0. - `cd ui && pnpm exec vitest run packages/plugin-chatbot/src/__tests__/buildPanelI18n-7388.test.tsx --maxWorkers=1` under the lock: Test Files 1 passed (1), Tests 14 passed (14), VERDICT command-exit 0. - The whole plugin-chatbot and i18n suites are left to CI's Test UI (the diff changes two pack values and one test file). </details> <details><summary>Derived gates: 34 of 34 run, all exit 0</summary> - `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derived 34 commands for the 3 changed paths; each ran with its exit code recorded, and `--ran` reconciled: "34 derived famil(ies) accounted for — 34 run, 0 NOT-MEASURED". - Notable: `pnpm --dir ui exec vitest run scripts/` (under the lock, after building formula, sdui-parser, lint and client): Test Files 178 passed, 2 skipped (180); Tests 5065 passed, 2 skipped. `pnpm check:type-check-debt` (under the lock): exit 0. `pnpm check:nul-bytes`, `check:cross-package-test-inputs`, `check:test-source-alias`, `check-empty-changeset`, `check-changeset-no-major`, `check-adr-0087-registration`: exit 0. - Families CI runs over the whole tree (type-check lanes, lint, artifact rosters) are CI's; the PR's check-runs are the reading. </details> ## Human Minimum - [x] 1. Schemas start as Zod; `packages/spec` holds no runtime logic. (not touched) - [x] 2. Every name I added uses the casing for its kind. (no names added) - [x] 3. No formatter ran; `pnpm lint` passes. (lint is CI's) - [x] 4. One issue, one branch off an up-to-date `main`, one pull request. - [x] 5. A change that publishes carries a changeset, and both declaration lines are filled in here and in the changeset. - [x] 6. `packages/spec` touched: its generated artifacts are regenerated and committed. (not touched) - [x] 7. No hand edits to `content/docs/references/`, `packages/*/CHANGELOG.md` or `content/docs/releases/`. - [x] 8. Title, body and comments are in English. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01QsR2jTN8uLtt5cTEu9c35K --- _Generated by [Claude Code](https://claude.ai/code/session_01QsR2jTN8uLtt5cTEu9c35K)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 8366f3e commit bd504f5

3 files changed

Lines changed: 45 additions & 5 deletions

File tree

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
'@object-ui/i18n': patch
3+
---
4+
5+
fix(i18n): the zh chatbot build header separates the verb from the app name
6+
7+
Clause-②: no
8+
Metadata-protocol: none
9+
10+
- **zh `chatbot.build.built`** reads `已构建 · APP` instead of `已构建APP`, and **zh `chatbot.build.building`** reads `正在构建 · APP…` instead of `正在构建APP…`. A name pasted straight onto the verb ran on into one word, most visibly with a Latin-script name (「已构建Library Lending Management」). The separator is the ` · ` the sibling `chatbot.build.builtAndLive` (`已搭建并上线 · APP`) already used.
11+
- The unnamed-build stand-in goes through the same frame, so it now reads `正在构建 · 你的应用…`, the same shape `builtAndLive` already had for an unnamed build.
12+
- Values only: no key is added, removed or renamed. `ja` (name first, then a particle) and `ko` (already spaced) did not run on and are unchanged; the Latin-script packs are untouched.

‎ui/packages/i18n/src/locales/zh.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3893,8 +3893,8 @@ const zh = {
38933893
nameField: '名称:{{field}}',
38943894
},
38953895
build: {
3896-
building: '正在构建{{app}}…',
3897-
built: '已构建{{app}}',
3896+
building: '正在构建 · {{app}}…',
3897+
built: '已构建 · {{app}}',
38983898
builtAndLive: '已搭建并上线 · {{app}}',
38993899
appFallback: '你的应用',
39003900
addingSampleData: '正在添加示例数据',

‎ui/packages/plugin-chatbot/src/__tests__/buildPanelI18n-7388.test.tsx‎

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,15 +104,18 @@ describe('control: a known phase renders exactly as it did before (en)', () => {
104104
// SUBJECT — the same panel under a zh console.
105105
// ---------------------------------------------------------------------------
106106
describe('the build panel under a zh console (objectui#7388)', () => {
107+
// The header composes the verb and the app name with the ` · ` separator
108+
// `builtAndLive` already used: a name pasted straight onto the verb ran on
109+
// into one word (「已构建Library Lending Management」).
107110
it('localizes the in-flight header instead of hard-coding "Building X…"', () => {
108111
renderIn('zh', panel('structure'));
109-
expect(screen.getByText('正在构建CRM…')).toBeInTheDocument();
112+
expect(screen.getByText('正在构建 · CRM…')).toBeInTheDocument();
110113
expect(screen.queryByText(/Building/)).not.toBeInTheDocument();
111114
});
112115

113116
it('localizes the finished header instead of hard-coding "Built X"', () => {
114117
renderIn('zh', panel('done'));
115-
expect(screen.getByText('已构建CRM')).toBeInTheDocument();
118+
expect(screen.getByText('已构建 · CRM')).toBeInTheDocument();
116119
expect(screen.queryByText(/^Built /)).not.toBeInTheDocument();
117120
});
118121

@@ -138,9 +141,11 @@ describe('the build panel under a zh console (objectui#7388)', () => {
138141
expect(screen.queryByText('App')).not.toBeInTheDocument();
139142
});
140143

144+
// The stand-in goes through the same frame, so it reads the way
145+
// `builtAndLive` already reads for an unnamed build (「已搭建并上线 · 你的应用」).
141146
it('localizes the unnamed-build stand-in, so the header is Chinese end to end', () => {
142147
renderIn('zh', panel('structure', { appLabel: undefined }));
143-
expect(screen.getByText('正在构建你的应用…')).toBeInTheDocument();
148+
expect(screen.getByText('正在构建 · 你的应用…')).toBeInTheDocument();
144149
expect(screen.queryByText(/your app/)).not.toBeInTheDocument();
145150
});
146151

@@ -160,3 +165,26 @@ describe('the build panel under a zh console (objectui#7388)', () => {
160165
expect(screen.queryByText(/chatbot\.build/)).not.toBeInTheDocument();
161166
});
162167
});
168+
169+
// ---------------------------------------------------------------------------
170+
// The other two CJK packs keep their headers as they are: neither runs the
171+
// verb into the name. ja puts the name first and a particle after it, ko
172+
// already leaves a space before the verb.
173+
// ---------------------------------------------------------------------------
174+
describe('the build panel header under ja and ko consoles', () => {
175+
it('ja — the name leads and the particle separates it from the verb', () => {
176+
renderIn('ja', panel('structure'));
177+
expect(screen.getByText('CRMを構築しています…')).toBeInTheDocument();
178+
cleanup();
179+
renderIn('ja', panel('done'));
180+
expect(screen.getByText('CRMを構築しました')).toBeInTheDocument();
181+
});
182+
183+
it('ko — a space already separates the name from the verb', () => {
184+
renderIn('ko', panel('structure'));
185+
expect(screen.getByText('CRM 빌드 중…')).toBeInTheDocument();
186+
cleanup();
187+
renderIn('ko', panel('done'));
188+
expect(screen.getByText('CRM 빌드 완료')).toBeInTheDocument();
189+
});
190+
});

0 commit comments

Comments
 (0)