Skip to content

fix(app-shell): draw a served object or list view label as served in the Console sidebar, recent list and object list header - #30388

Merged
objectstack-fleet[bot] merged 9 commits into
mainfrom
claude/project-thread-g2c1pk
Nov 5, 2026
Merged

objectstack-fleet[bot] merged 9 commits into
mainfrom
claude/project-thread-g2c1pk

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Requested by Bill · project thread

domain:ui#3 · os-bill · session_01Utp6CbPN5UYMnBaNJPJWfG

Refs #30311

Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么:Console 侧栏里未写标签的对象/列表视图入口、侧栏与首页的「最近访问」里的对象行和列表视图行、对象列表页标题、顶栏对象标题、对象 /data 页标题,改为直接显示服务端返回的名字;只有服务端没给名字(客户端自己派生的视图、还没读到的对象、待发布草稿)时才查客户端词典。
  • 为什么改:客户在 .custom 里给已安装包的对象或列表视图改了名,服务端返回新名字,但 Console 拿服务端的名字再去查词典,基础包的旧译名又把它盖回去;实测 zh-CN 下对象页标题和最近访问仍显示「任务」「进行中」。
  • 风险与回滚:未改名的条目显示不变(服务端本就用同一份词典翻译);记录页、表单、抽屉等其余约 43 处同类调用本 PR 未改,交席位立收口卡。回滚即还原本 PR。应用名一半等 Declared overrides: a mapping override publishes but is never served, doc and mapping overrides cannot be restored, and an override's label can be hidden by translation #30062 服务端,所以写 Refs 不关卡。
  • 先看:① ui/packages/app-shell/src/hooks/useNavTargetLabel.ts(object/view 分支与 servedObjectPluralLabel);② ui/packages/app-shell/src/views/ObjectView.tsx 的 listTitleOf(标题、收藏、无标签视图同一来源);③ ui/packages/app-shell/src/layout/AppHeader.tsx 对象分支。
  • 两分钟验证:pnpm --dir ui exec vitest run packages/app-shell/src/hooks/__tests__/useRecentItemLabel.test.tsx packages/app-shell/src/layout/__tests__/AppHeader.servedLabels-11295.test.tsx packages/app-shell/src/views/ObjectView.listTitlePlural-11696.test.tsx packages/app-shell/src/views/ObjectDataPage.listTitlePlural-11696.test.tsx,预期 4 个文件全部通过。
  • 需要你做的:无,席位落地。

What changes

  • The rule (the one PR fix(app-shell): draw a served report, page or dashboard label as served in the Console header, report index and recent list #30308 applied to report, page and dashboard). A label the /meta read or the app bundle served is already translated by the server, by its label order for an overridden item (i18n: an override's own label loses to the base's translation on page, dataset, app and book, and a translation in the .custom pair never wins on any type #30193), so it is drawn as given. The catalog key (useObjectLabel's objectLabel / objectPluralLabel / viewLabel) is asked only for text no server translated.
  • useNavTargetLabel.ts
    • object target (an unlabelled sidebar entry): the served object's label as given; a pending draft's label still goes through the catalog.
    • view target (an unlabelled sidebar entry, and a recent view row): a served view's label as given, decided by isServedView — the identity question the object page's view tabs already ask (objectui#11295, objectui#11336). A view the client derived (a container expansion) still goes through viewLabel. By name, the served reads are the names-only scope's own served and views, from the same readObjectScope call readObjectsByName makes, so no new request.
    • New private helper servedObjectPluralLabel(def, language, objectPluralLabel): what a served object's list is called — served pluralLabel, else served label, else the catalog under its name. Internal to app-shell (not in the package index).
  • useRecentItemLabel.ts: the recent object row uses servedObjectPluralLabel.
  • The object list header (Expected names the header; the seat widened the claim's surface, comment 6652505627, narrowed in 6652679548):
    • ObjectView.tsx: one listTitleOf feeds the page header's object crumb (ObjectViewPageHeader), the list favorite's label and an unlabelled view's tab text, so the three still agree (the header compares the tab text with the plural).
    • AppHeader.tsx: the object route's title, and the unlabelled-view fallback on a view route.
    • ObjectDataPage.tsx: the /data page title.
  • Not changed: ui/packages/i18n (useObjectLabel is published; changing its order is a Clause-② question). The rest of the family — record pages, record forms, drawers, preview cards, and call sites outside app-shell — is listed in Acceptance notes for the seat's closing card.

Tests

  • New, one top-level describe per existing harness:
    • useRecentItemLabel.test.tsx (objectstack#30311 describe, 9 cases): renamed object and view in the recent list and in useNavTargetLabel (whole-list and names-only-scope reads), served plural first, a view embedded in the served object document; controls: a client-derived view, an object the cache does not hold, a pending draft object, en.
    • AppHeader.servedLabels-11295.test.tsx (4 cases), ObjectView.listTitlePlural-11696.test.tsx (2), ObjectDataPage.listTitlePlural-11696.test.tsx (2).
  • Fixtures that served English in a zh-CN session (the world PR fix(app-shell): draw a served report, page or dashboard label as served in the Console header, report index and recent list #30308 named as not occurring: the Console's catalog is the server's own /api/v1/i18n/translations/:locale answer, and the server translates a served label with it): useRecentItemLabel.objectPlural-11733, ObjectView.listTitlePlural-11696, ObjectView.listLinksPlural-11733, ObjectView.labelLessViewTab-12774, ObjectDataPage.listTitlePlural-11696, AppHeader.objectCrumbPlural-11696, AppHeader.labelLessViewTitle-12805, StudioDesignSurface.standardNavEntries-11201 (8 files) now serve the zh-CN answer in zh-CN. Every existing assertion is unchanged.
  • Ablation (the five source files restored to ff3f83bb with git restore --source, marker count 0 on disk, restored with git checkout HEAD --, git status clean and blob hashes equal to HEAD after): Tests 9 failed | 63 passed (72). The 9 are exactly the renamed cells (object page title, app header en/zh, /data title, recent object, recent plural, recent/nav view, names-only scope, embedded view); every control stayed green.
Test runs
  • Pins, fix in place: Test Files 6 passed (6), Tests 72 passed (72), VERDICT command-exit 0.
  • Consumer sweep 1 (before the header half; 563 test files in app-shell and the Console that reference a module importing either hook): Test Files 1 failed | 562 passed (563), Tests 1 failed | 4324 passed (4325). The red was StudioDesignSurface.standardNavEntries-11201 (English served in zh-CN), fixed as above.
  • Consumer sweep 2 (after merging origin/main and rebuilding, head 23114841): the 6 pin files plus 136 more test files that reference ObjectView, ObjectDataPage or AppHeader: Test Files 1 failed | 140 passed (141), Tests 2 failed | 1395 passed (1397). The 2 reds were ObjectView.listLinksPlural-11733's zh-CN cells (English served in zh-CN), fixed as above; that file then Tests 7 passed (7) at ec3b0e69. This sweep ran 136 of the 298 test files its own reference search found, not all of them (see Acceptance notes).
  • Consumer sweep 3 (CI at ec3b0e69 red on 7 zh-CN cells in AppHeader.objectCrumbPlural-11696, AppHeader.labelLessViewTitle-12805 and ObjectView.labelLessViewTab-12774, reproduced locally, fixtures fixed at 1553cdd6): every AppHeader.*, ObjectView.* and ObjectDataPage.* test in app-shell, Test Files 114 passed (114), Tests 929 passed (929); then all 298 files of sweep 2's reference search at 6583026f (origin/main merged in, no ui/ file among the 37 it brought), in three locked runs: Test Files 97 passed (97) / 101 passed (101) / 100 passed (100), Tests 905 / 790 / 950 passed, each VERDICT command-exit 0.
  • eslint --no-inline-config on the changed TypeScript files (at 23114841): 0 errors (104 warnings, all on lines this PR does not touch).
  • pnpm exec turbo run type-check --filter=@object-ui/app-shell --concurrency=2 at ec3b0e69: Tasks 68 successful, VERDICT command-exit 0.

Live (showcase --fresh, zh-CN, Console from ui/ src through Vite)

Overrides written the way the platform takes them: POST /api/v1/packages/com.example.showcase/ensure-customization (pair com.example.showcase.custom); the object through an object_extension (PUT /api/v1/meta/object_extension/showcase_task?package=com.example.showcase.custom&mode=draft with extend, label: Work Item (renamed-30311), pluralLabel: Work Items (renamed-30311), then publish — an object overrides save is refused NOT_OVERRIDABLE, ADR-0146 D10); the view through a view override (showcase_task.in_progress, label: In flight (renamed-30311), overrides: { package: 'com.example.showcase', basedOn: '0.1.0' }, then publish).

Served under Accept-Language: zh-CN after the overrides: /meta/object/showcase_task → Work Item (renamed-30311) / Work Items (renamed-30311); /meta/view/showcase_task.in_progress → In flight (renamed-30311); the app bundle /meta/app/showcase_app/bundle carries the renamed object too. The zh-CN catalog keeps objects.showcase_task.label = 任务 and _views.in_progress.label = 进行中.

Console, zh-CN, same overrides origin/main ui (ff3f83bb sources) this branch
object list page title (crumb) 任务 / 全部任务 Work Items (renamed-30311) / 全部任务
view page title 任务 / In flight (renamed-30311) Work Items (renamed-30311) / In flight (renamed-30311)
sidebar 「最近使用」 客户 · 任务 · 进行中 客户 · Work Items (renamed-30311) · In flight (renamed-30311)
Home 「最近访问」 客户 · 任务 · 进行中 客户 · Work Items (renamed-30311) · In flight (renamed-30311)

Each leg restarted the Console's Vite (--force) after switching the five sources and checked that the served modules carried (or lacked) the change before the run: the first after-run read a stale transform from Vite's watcher. Screenshots (1440×900 at 2×, before/after of the object page, the view page, the expanded sidebar recent group and Home) are in the project's files at ui-seat3/30311-shots/; this channel cannot upload images to the PR body, so the table above is their text.

The live leg did not reach an unlabelled sidebar entry: every showcase navigation entry carries its own label, so the sidebar's object/view rows draw those (unchanged). That path is pinned by the useNavTargetLabel cases.

Acceptance notes

  • The card's premise "the object's own page shows the new name" did not hold. Measured above: on origin/main the object page title also showed 任务. The seat folded the header into this PR and named the rest of the family for a closing card.
  • The rest of the family, not touched here (objectLabel( / objectPluralLabel( over a served definition, at 23114841): in app-shell, AppContent 4, ActivityObjectLabel 1, ConsoleLayout 1, ObjectView 3 more (import wizard, delete confirmations, objectLabelOf), ObjectDataPage 1 (record drawer title), RecordDetailView 11, RecordFormPage 2, appReportIndex 2, RecordPreviewCard 1, recordDrawerStack 2, PackagedActionsSection 1, WidgetRefCellFaces 1; outside app-shell: fields RecordHoverCard 1, plugin-detail 3, plugin-form 2, plugin-gantt 1, plugin-grid 1. Some pass text no server translated ({ name, label: name } fallbacks, a widget ref's own label), so each needs a per-site reading. The other way to close the class is to change useObjectLabel's own order, a Clause-② card.
  • A rename of label alone keeps the served plural. The server translates label and pluralLabel separately: an extension that renames only label still serves the base's translated pluralLabel, so a list title (which reads the plural first) keeps it. That is the server's answer and Studio's; the live leg renamed both.
  • Deviation: an incomplete consumer sweep. Sweep 2 was described as covering every test file that references ObjectView, ObjectDataPage or AppHeader; it ran 136 of the 298 its search found. Three of the 162 it skipped carried the same English-in-zh-CN fixture and went red in CI at ec3b0e69. They are fixed at 1553cdd6 and the full 298 now pass (sweep 3).
  • App labels are unchanged (the app half waits for Declared overrides: a mapping override publishes but is never served, doc and mapping overrides cannot be restored, and an override's label can be hidden by translation #30062's server half), hence Refs.

Verification

  • Since ec3b0e69 the branch gained three test-fixture files (1553cdd6) and a merge of origin/main (6583026f, no ui/ file). dispatch-gates --commands at 1553cdd6 derives the same 35 commands; they were not re-run there. pnpm --filter @objectstack/spec check:liveness at 6583026f: exit 0 (main red: spec check:liveness — query/searchFields cites engine.ts, which no longer mentions searchFields after #30341 #30367 fixed on main by fix(spec): repoint the query.searchFields liveness row at engine-find.ts#expandSearchOnAst #30368).
  • Derived gates on ec3b0e69: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack lists 35 commands (the same list as at 23114841), each run with its exit code captured before any pipe, all 35 exit 0; --ran reconciliation: 35 derived, 35 run, 0 NOT-MEASURED, 0 UNRUN, exit 0. pnpm --dir ui exec vitest run scripts/ ran under os-verify-lock with --maxWorkers=2 (Test Files 170 passed | 2 skipped (172)): its first run at 23114841, with the showcase stack up, was SIGKILLed for memory.
  • ui/scripts/check-new-cross-file-line-citations.mjs at ec3b0e69: 0 new citations, exit 0.
  • Changeset: .changeset/30311-served-object-view-labels.md, @object-ui/app-shell patch, both declaration lines.

Human Minimum

  • 1. Schemas start as Zod; packages/spec holds no runtime logic.
  • 2. Every name I added uses the casing for its kind.
  • 3. No formatter ran; eslint on the changed files reports 0 errors (the repo-wide pnpm lint is CI's).
  • 4. One issue, one branch off an up-to-date main, one pull request.
  • 5. A change that publishes carries a changeset, and both declaration lines are filled in here and in the changeset.
  • 6. packages/spec touched: its generated artifacts are regenerated and committed. (not touched)
  • 7. No hand edits to content/docs/references/, packages/*/CHANGELOG.md or content/docs/releases/.
  • 8. Title, body and comments are in English.
  • The Before Submitting list in CONTRIBUTING.md is done.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Utp6CZywtebM5fE7KZuMEM

…l header fixtures

AppHeader.objectCrumbPlural-11696, AppHeader.labelLessViewTitle-12805 and
ObjectView.labelLessViewTab-12774 served the English object label and plural
to a zh-CN session. Under the served-first label rule the header and the view
tabs draw the served text, so those seven zh-CN cells read the English plural.
The fixtures now serve each language's own answer, as the server does; no
assertion changed.

Claude-Session: https://claude.ai/code/session_01Utp6CZywtebM5fE7KZuMEM
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:ui#3 · os-bill · session_01Utp6CbPN5UYMnBaNJPJWfG

维护者速读

席位核对 — ACCEPT · head 6583026

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review November 5, 2026 10:13
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Nov 5, 2026
Merged via the queue into main with commit efcc1a7 Nov 5, 2026
60 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-g2c1pk branch November 5, 2026 10:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/l tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant