Skip to content

fix(app-shell): draw a served app label as served on every Console surface that names an app - #30443

Queued
objectstack-fleet[bot] wants to merge 4 commits into
mainfrom
claude/project-thread-pqop9u
Queued

objectstack-fleet[bot] wants to merge 4 commits into
mainfrom
claude/project-thread-pqop9u

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Sales · project thread

domain:ui#5 · os-sales · session_01L6bhgVwQZbHRRM9CaXeKif

Fixes #30311

Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么:控制台所有显示应用名的地方(应用切换器、侧栏标题、首页应用卡片/应用条/最近访问、无权限页、AI 对话、应用市场「打开应用」按钮、报表索引)改为直接显示服务端已翻译好的应用名;应用卡片的描述同理。
  • 为什么改:客户在 .custom 配对包里给已安装应用改名后,服务端(fix(metadata-protocol,rest): a .custom pair's declared override is labelled in the ruled order on every /meta read #30353)已按裁定顺序返回新名字,但前端又用基础包的 apps.NAME.label 译文盖回去,中文下仍显示旧名。
  • 风险与回滚:只改 ui/packages/app-shell 的读取顺序;草稿预览(?preview=draft)、键式标签、无标签应用仍走前端词条,未改名的应用显示不变。回滚即撤本 PR,无数据迁移。
  • 先看:ui/packages/app-shell/src/hooks/useServedAppLabel.ts(新 helper 的取值顺序),再看 layout/AppSwitcher.tsx 一处调用点。
  • 两分钟验证:pnpm --dir ui exec vitest run packages/app-shell/src/hooks/__tests__/useServedAppLabel-30311.test.tsx,预期 18 条全绿;修复前的取值顺序下其中 5 条是红的。
  • 需要你做的:无,席位落地。

What changes

  • New private hook useServedAppLabel (ui/packages/app-shell/src/hooks/useServedAppLabel.ts). appLabel(app) draws a served label (a string, or an inline locale map resolved by metadataText) as given; appDescription(app) does the same for description. The bundle (useObjectLabel().appLabel / appDescription, the apps.NAME.label lookup) is asked only for text no server translated: an item stamped _draft: true by ?preview=draft, a keyed { key, defaultValue } label (still resolved through t, as before), or an app with no label / description.
  • Every app-shell surface that named an app through useObjectLabel().appLabel({ name, label: resolveKeyedI18nLabel(app.label, t) }) now calls useServedAppLabel().appLabel(app): 17 call sites in 11 files, taken from the tree at fdd06415 (AppSwitcher x3, AiChatPage x4, HomePage x2, UnifiedSidebar, AppHeader hidden-app menu, AppNoAccessEmptyState, AppCard label and description, HomeAppsStrip, MarketplacePage, MarketplacePackagePage, AppReportIndexView).
  • useNavTargetLabel.ts and ui/packages/i18n/** are untouched (claim fences); the hook only imports the exported metadataText.
  • Root changeset .changeset/30311-served-app-labels.md (@object-ui/app-shell patch).

Why

Since #30353 the server serves an overridden app's label in the ruled order (the .custom pair's own text over the base package's translation). The Console handed that served label to the bundle lookup as its fallback, so the base package's apps.NAME.label translation won it back and a renamed app kept its old name on zh-CN. The object / view half of #30311 landed in #30388 with the same served-first rule; this is the app half.

Tests

  • ui/packages/app-shell/src/hooks/__tests__/useServedAppLabel-30311.test.tsx (new, 18 cases): the real hook over the real useObjectLabel inside a real I18nProvider with a packaged catalogue, en and zh-CN: a renamed served label and description draw as served; an unedited one shows the server's translation; an inline locale map resolves in the active language; controls for a _draft item, a keyed label, an absent / empty label and a translation-only description keep the bundle. Plus a census: no non-test source under app-shell/src other than the hook destructures appLabel / appDescription from useObjectLabel() (with a positive control that the walk reaches the hook and AppSwitcher.tsx, and that the pattern matches the banned shape).

Acceptance notes

  • Evidence branch deviation. The dispatch asked for screenshots on a never-merged evidence branch; this card thread can push only its designated branch, so the PNGs were committed at 71a58ff3 and removed again in the next commit. The PR squash-merges, so they never reach main; the links below point at that commit.
  • CommandPalette already drew resolveKeyedI18nLabel(app.label, t) without the bundle, so it showed the served name before this PR and is unchanged.
  • The live leg exercised the app switcher pill, the sidebar title and Home (app card, recent row app name). The marketplace "Open app" button, the AI chat, the no-access state and the report index's other-app links are pinned by the census and the hook cases, not browser-measured.

Verification

Live, showcase --fresh, zh-CN, Console from ui/ src through Vite, 1440 wide

Override written the way the platform takes it: POST /api/v1/packages/com.example.showcase/ensure-customization (pair com.example.showcase.custom, created), then PUT /api/v1/meta/app/showcase_app?package=com.example.showcase.custom&mode=draft with the served app body, label: Showcase Hub (renamed-30311) and overrides: { package: 'com.example.showcase', basedOn: '0.1.0' }, then POST /api/v1/meta/app/showcase_app/publish?package=com.example.showcase.custom (seq 2). GET /meta/app/showcase_app then serves Showcase Hub (renamed-30311) under both Accept-Language: zh-CN and en; the zh-CN catalogue keeps apps.showcase_app.label = 功能展示.

Console, zh-CN, same override origin/main app-shell sources (fdd06415, restored into the tree, Vite --force) this branch
app switcher pill 功能展示 Showcase Hub (renamed-30311)
/apps/showcase_app page text matches renamed 0, 功能展示 1 renamed 1, 功能展示 0
Home matches (app card + recent row) renamed 0, 功能展示 1 renamed 2, 功能展示 0

Screenshots (commit 71a58ff3):
before app ·
after app ·
before Home ·
after Home

Tests, ablation, typecheck, lint (sources at 6f7c06c)
  • New pin: Test Files 1 passed (1), Tests 18 passed (18), lock VERDICT command-exit 0.
  • Ablation 1 (via scripts/ablation-replace.mjs, anchor 1 to 0, restored blob == HEAD, git diff HEAD empty): the hook's served-text rung replaced by return undefined (the old bundle-first order) turns exactly the 5 predicted cells red: renamed label en / zh-CN, inline locale map, renamed description en / zh-CN; Tests 5 failed | 13 passed (18).
  • Ablation 2: AppSwitcher.tsx back on useObjectLabel() turns the census red naming layout/AppSwitcher.tsx; Tests 1 failed | 17 passed (18); restored, blob == HEAD.
  • Consumer sweep: every test file under ui/ that names one of the 11 changed modules or appLabel (310 files): Test Files 310 passed (310), Tests 2598 passed (2598), lock VERDICT command-exit 0.
  • turbo run type-check --filter=@object-ui/app-shell: Tasks: 68 successful, 68 total, VERDICT command-exit 0.
  • eslint on the changed files: 0 new errors; the 2 errors it reports (react-hooks "Cannot create components during render" in AppCard.tsx and HomeAppsStrip.tsx) are on origin/main unchanged.
  • ui/scripts/check-new-cross-file-line-citations.mjs: 0 new, exit 0.
Derived gates (dispatch-gates --commands, head 6f7c06c)

node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derives 36 commands from 14 paths; each was run with its exit code captured before any pipe: all 35 node / pnpm check commands exit 0, and pnpm --dir ui exec vitest run scripts/ ran under os-verify-lock with --maxWorkers=2 (result in the os-dev-report on #30311). The two evidence commits add and remove the same files, so the derived set is unchanged at the final head.

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; pnpm lint passes.
  • 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_01L6bhgX1ZNco5W3wXZFLVbh


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:ui#5 · os-sales · session_01L6bhgVwQZbHRRM9CaXeKif

维护者速读

席位核对 — ACCEPT · domain:ui#5 · head b5a93b87160dd1930a5cc21d3564bde1031636c6

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review November 5, 2026 12:04
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Nov 5, 2026
Any commits made after this event will not be merged.

This branch has not been deployed

No deployments
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/m tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Console sidebar and recent list re-translate an overridden object, list view or app label with the base package's translation, over the server's answer

1 participant