Skip to content

Commit 5db77f7

Browse files
fix(app-shell): zh-CN view properties panel reads the empty filter prompt and the description hint in Chinese (#30265)
<!-- claude-projects-attribution: {"github_login":"os-support-ai"} --> _Requested by **Yibo Wang** · [project thread](https://claude.ai/code/project/chan_01BVUyyPie8gHwoPM18iABwB?thread=cmsg_01BVUyyPie8gHwoPM18iABwBTf9u99MNcXxBFXXba1TPyn)_ Refs #30039 Clause-②: no Metadata-protocol: none ## 维护者速读 - 改了什么:中文控制台下,视图属性面板里筛选框的空白提示从英文「+ Add filter…」改为「+ 添加筛选…」,「描述」一栏的说明文字改为中文。 - 为什么改:#30039 第 5 项浏览器验证时,卡片点名的六个位置里只有视图属性面板还剩这两处英文,其余五处(发布清单、流程问题页、节点面板、通知节点、仪表盘用词)实测已是中文。 - 风险与回滚:只改两处界面文字,英文控制台不变,不动数据和接口。回滚即还原本 PR。 - 先看:`ui/packages/app-shell/src/views/metadata-admin/widgets.tsx`(筛选按钮取词)、`metadata-form-zh-cn.ts`(视图 `description` 的中文说明)。 - 两分钟验证:`pnpm --dir ui exec vitest run packages/app-shell/src/views/metadata-admin/widgets.filterBuilderHeldRow-26738.test.tsx`,预期全部通过,其中 objectstack#30039 一组断言中文为「+ 添加筛选…」、英文仍为「+ Add filter…」。 - 需要你做的:无,席位落地。 ## What changes Browser verification of #30039 (Acceptance 5) on a dev boot of the example CRM with the console in zh-CN found two English strings left at position 1, the view properties panel (`/studio/com.example.crm/interfaces?surface=view:crm_lead.all`). Both are in the card's evidence list for that position: - **`+ Add filter…`**: the `filter-builder` widget's empty trigger in `widgets.tsx` was an English literal. It now reads `engine.inspector.dataset.addFilter`, the Studio string the dataset scope filter (`FilterConditionField`) already uses for the same button, which has a zh row (`+ 添加筛选…`). The widget already held `locale` from `useMetadataLocale()`. - **`View description for documentation/tooltips`**: the `description` row's hint was the spec schema's own `.describe()` text, because neither the form nor the platform's zh-CN metadata-forms bundle carries help for it. The zh-CN view overlay (`metadata-form-zh-cn.ts`) now gives that row `helpText: '视图说明,用于文档与悬停提示'`. The file's header said every leaf is copied from the platform bundle; it now names this kind of hand-worded leaf as the one exception and the row is marked. Changeset: `@object-ui/app-shell` patch. ## Verification Boot: full `turbo run build --filter='!@objectstack/docs'` at `6f095b9c` under the verify lock (VERDICT command-exit 0), `examples/app-crm` `objectstack dev --seed-admin --fresh`, console Vite pointed at it, Playwright Chromium with `locale: 'zh-CN'`, signed in as the dev admin. For positions 2 to 5 a writable package `com.qa.zhterms` was seeded over the REST door: an object and a record-after-update flow saved active, then five drafts (object label change, flow `status` change, new dataset, dashboard and permission set) with `?mode=draft`. `GET /api/v1/automation/_status` answered the flow `bound: false`, `unboundCause: missing_trigger`. | # | Position | Result | Shot | |:--|:--|:--|:--| | 1 | View properties panel, below 条件格式化 | Before this PR: two English strings (`+ Add filter…`, the description hint). After: 基础信息 / 标识与主显示形态 / 描述 / 视图说明,用于文档与悬停提示 / 列与筛选 / + 添加筛选… / 可搜索字段 / 表格选项 / 终端用户控制 / 导航与共享 | `30039-p1-view-panel.png` | | 2 | Publish sheet, a flow's detail | 其他变更: ~ 状态 (object row: ~ 显示名称) | `30039-p2-p3-publish-sheet.png` | | 3 | Publish sheet, summary line | 5 项 · 对象 1 · 流程 1 · 数据集 1 · 仪表盘 1 · 权限集 1 | `30039-p2-p3-publish-sheet.png` | | 4 | Flow 问题 tab, trigger not armed | 未在此运行 · 此部署不运行由这类触发器启动的流程。开发人员可以在应用中加入相应的触发器包,之后该流程就会运行。 Below it: 结构检查没有发现需要修改的地方。该流程不在此运行的原因见上方说明。 (no 没有问题 line) | `30039-p4-flow-problems.png` | | 5 | Palette "Save notice", notify "Template" | Palette: 保存提示 · 告诉保存记录的人,这次保存触发了什么;提示随保存结果一起显示. Notify node: 邮件模板 and its hint in zh. The save-notice node's 提示内容 row is zh too. All zh already through the ui tables; nothing waits on #30164 here | `30039-p5a-palette-save-notice.png`, `30039-p5b-notify-template.png` | | 6 | Dashboard word: rail, menu, create dialog, publish sheet | 仪表盘 in all four (rail chip and group, create menu item, 新建仪表盘 / 仪表盘名称 dialog, sheet group). 仪表板 appears in none of the 15 page text dumps taken | `30039-p6a-rail-and-create-menu.png`, `30039-p6b-create-dialog.png`, `30039-p2-p3-publish-sheet.png` | The shots are in the project's `ui-orders/30039-shots/` folder (2x, 1440 wide); this repository has no place to commit them, per `ui/AGENTS.md` Housekeeping. <details><summary>Tests at 808dbf8</summary> - `pnpm --dir ui exec vitest run` on `metadata-form-i18n.test.ts`, `widgets.filterBuilderHeldRow-26738.test.tsx`, `inspectorStrings.i18n-10586.test.tsx` and `SchemaForm.controlWidgetGridNaming-9889.test.tsx` (every test file that reads either changed string or the filter trigger): `Test Files 4 passed (4)`, `Tests 75 passed (75)`, lock VERDICT command-exit 0. - New pins: `widgets.filterBuilderHeldRow-26738.test.tsx` gains a top-level `describe` (zh reads `+ 添加筛选…` and not `Add filter`; en control reads `+ Add filter…`); `metadata-form-i18n.test.ts`'s #30039 group asserts the zh `description` help and that en has none. - `pnpm --filter @object-ui/app-shell run type-check` (both tsconfigs): exit 0, VERDICT 0. - eslint on the four touched files from the package dir: 0 errors (38 pre-existing warnings). - No ablation: the change is copy, and the zh pin is beside its en control. </details> <details><summary>Gates at 808dbf8</summary> `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` (5 paths vs merge base 6f095b9): 35 commands, all run under one lock (VERDICT command-exit 0), every one exit 0. `--ran` with the exit codes recorded: 35 derived, 35 run, 0 NOT-MEASURED (a derived zero). `pnpm --dir ui exec vitest run scripts/`: `Test Files 170 passed | 2 skipped (172)`, `Tests 4985 passed | 2 skipped`. </details> Not run locally: the full ui suite. `origin/main` moved to `31260ca8` after the branch point, touching none of this PR's files (one unrelated test under `metadata-admin`); CI's Test UI shards run the suite. ## Acceptance notes - **Out of this card's surface, reported to the seat:** with the view panel's collapsed sections opened (表格选项, 分页, 终端用户控制, 导航与共享), about sixty rows still read English: field hints the form declares no help for (`Enable column resizing`, `Row height / density setting`, …) and every sub-field of the `selection`, `pagination`, `userFilters`, `appearance`, `userActions`, `navigation` and `sharing` composites (labels such as `Page Size`, `Element`, `Allowed Visualizations` and its options, and their hints). None of them is in any catalogue: the platform zh-CN metadata-forms bundle carries only keys the form declares, and the overlay's composite rule forbids naming children the form does not declare (naming one would hide the rest). The lasting fix is upstream: the spec view form declares those sub-fields and hints so the extractor emits keys, the platform bundle translates them, and the overlay copies them. Shot: `30039-p1b-view-panel-expanded-finding.png`. - The design canvas and the panel header show the view's authored label `All Leads`, while the rail shows the translated 全部线索. Noted, not filed here. - #30164 (the platform bundle's 仪表板) did not show at any position: the dashboard inspector read 仪表盘 on this boot. --- _Generated by [Claude Code](https://claude.ai/code/session_01WGufzgWrZ7dEo8uwMCqevS)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 713beba commit 5db77f7

5 files changed

Lines changed: 48 additions & 3 deletions

File tree

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
'@object-ui/app-shell': patch
3+
---
4+
5+
fix(app-shell): on a zh-CN console the view properties panel's empty filter button reads 「+ 添加筛选…」 and the description row's hint reads in Chinese
6+
7+
Clause-②: no
8+
Metadata-protocol: none
9+
10+
- The `filter-builder` widget's empty trigger was an English literal (`+ Add filter…`); it now reads the Studio string the dataset scope filter already uses, so it follows the designer locale.
11+
- The zh-CN view form overlay gains the `description` row's help text, which showed the schema's English description.

‎ui/packages/app-shell/src/views/metadata-admin/metadata-form-i18n.test.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,13 +202,17 @@ describe('every form type Studio renders reads in zh-CN (objectstack#30039)', ()
202202
expect(sections(zh).find((s) => s.label === '基础信息')?.description).toBe('标识与主显示形态');
203203
expect(fieldByName(zh, 'searchableFields')?.label).toBe('可搜索字段');
204204
expect(fieldByName(zh, 'description')?.label).toBe('描述');
205+
// The description row's hint: without the overlay leaf it showed the
206+
// schema's English `.describe()` text.
207+
expect(fieldByName(zh, 'description')?.helpText).toBe('视图说明,用于文档与悬停提示');
205208
});
206209

207210
it('an English console reads the spec English, the same object every time — the control', () => {
208211
const en = getViewForm('en');
209212
expect(en).toBe(getViewForm('en'));
210213
expect(sections(en).map((s) => s.label)).toContain('Basics');
211214
expect(fieldByName(en, 'searchableFields')?.label).toBeUndefined();
215+
expect(fieldByName(en, 'description')?.helpText).toBeUndefined();
212216
});
213217

214218
it('the page and report panels read in Chinese too', () => {

‎ui/packages/app-shell/src/views/metadata-admin/metadata-form-zh-cn.ts‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
* these forms with), so a form reads the same words whether the server
1515
* localized it or this console did. A leaf the platform has not translated
1616
* (still the English source) is left out: the overlay then returns the spec's
17-
* own English for it, as it does for every type it does not name.
17+
* own English for it, as it does for every type it does not name. The one
18+
* exception is a leaf a curated inspector SHOWS that the platform has no zh
19+
* for; it is hand-worded here and marked so at its row.
1820
*
1921
* ## Two depths, by who renders the form
2022
*
@@ -375,7 +377,9 @@ export const ZH_CN_SPEC_FORMS: NonNullable<TranslationData['metadataForms']> = {
375377
fields: {
376378
name: { label: '名称', helpText: 'snake_case,环境内唯一' },
377379
label: { label: '显示名称' },
378-
description: { label: '描述' },
380+
// Hand-worded: the platform bundle has no zh leaf for this help, and the
381+
// view inspector shows it (the schema's own `.describe()` text).
382+
description: { label: '描述', helpText: '视图说明,用于文档与悬停提示' },
379383
type: { label: '类型', helpText: '主要的视图形态' },
380384
data: { label: '数据', helpText: '数据源——如:{"provider":"object","object":"task"}' },
381385
columns: { label: '列', helpText: '要展示的列(来自所选对象的字段名)' },

‎ui/packages/app-shell/src/views/metadata-admin/widgets.filterBuilderHeldRow-26738.test.tsx‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,14 @@ import '@testing-library/jest-dom/vitest';
2525
import * as React from 'react';
2626
import { afterEach, describe, expect, it, vi } from 'vitest';
2727
import { cleanup, fireEvent, render, screen } from '@testing-library/react';
28+
import { I18nProvider } from '@object-ui/i18n';
29+
import { loadStudioCatalogue } from '@object-ui/i18n/namespaces/studio';
2830
import { WIDGETS } from './widgets';
2931
import { loaded } from './loadState';
3032

33+
// The studio namespace fetches zh on demand; load it before any zh render.
34+
await loadStudioCatalogue('zh');
35+
3136
// The builder lives inside a Radix popover, which does not open in jsdom.
3237
// Rendering the popover parts inline is this directory's existing way of
3338
// reaching it (`WidgetContext.catalogUnion.test.tsx`); the rest of the barrel
@@ -147,3 +152,24 @@ describe('the filter-builder widget holds a row until it is complete (objectstac
147152
expect(writes).toEqual([]);
148153
});
149154
});
155+
156+
describe('the empty filter trigger reads in the designer locale (objectstack#30039)', () => {
157+
const renderIn = (lang: 'en' | 'zh') =>
158+
render(
159+
<I18nProvider config={{ defaultLanguage: lang, detectBrowserLanguage: false }}>
160+
<Host initial={{ type: 'grid' }} writes={[]} />
161+
</I18nProvider>,
162+
);
163+
164+
it('a zh-CN console reads the Chinese prompt, not the English literal', () => {
165+
renderIn('zh');
166+
const trigger = screen.getByTestId('filter-builder-trigger');
167+
expect(trigger).toHaveTextContent('+ 添加筛选…');
168+
expect(trigger).not.toHaveTextContent('Add filter');
169+
});
170+
171+
it('CONTROL: an English console keeps the English prompt', () => {
172+
renderIn('en');
173+
expect(screen.getByTestId('filter-builder-trigger')).toHaveTextContent('+ Add filter…');
174+
});
175+
});

‎ui/packages/app-shell/src/views/metadata-admin/widgets.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2875,7 +2875,7 @@ export function FilterBuilderField({ value, onChange, fields, readOnly, id, aria
28752875
<Button {...controlNaming({ id, ariaLabelledBy })} variant="outline" size="sm" disabled={readOnly || notEditable}
28762876
title={notEditable ? tr('console.objectView.filterOrGroupNotEditable') : undefined}
28772877
className="h-8 w-full justify-between text-xs font-normal" data-testid="filter-builder-trigger">
2878-
<span className="truncate text-left">{summary || <span className="text-muted-foreground">+ Add filter…</span>}</span>
2878+
<span className="truncate text-left">{summary || <span className="text-muted-foreground">{t('engine.inspector.dataset.addFilter', locale)}</span>}</span>
28792879
<ChevronDown className="h-3.5 w-3.5 opacity-60 shrink-0" />
28802880
</Button>
28812881
</PopoverTrigger>

0 commit comments

Comments
 (0)