## 问题 若干「自定义系统页」的标题/副标题直接写死在 metadata 的 `page:header` 组件 `properties.title` / `properties.subtitle` 里,在非英文 locale 下始终显示英文。当前 **i18n-resolver 没有 page / 组件级解析链路**:`packages/spec/src/system/translation.zod.ts` 已有 `pages` 命名空间(`{ title, description }` keyed by page name),但没有任何 resolver 把它应用到 page metadata,console 也原样渲染 `page:header` 的 properties。 对应设置导航里的这几个页(截图均为中英混排): | 页面 | 来源 | 写死文案 | |---|---|---| | Installed Apps | `packages/cloud-connection/src/marketplace-ui.ts` | title `Installed Apps` / subtitle `Marketplace packages currently installed into this runtime's kernel.` | | Cloud Connection | `packages/cloud-connection/src/cloud-connection-ui.ts` | title `Cloud Connection` + 一大段 subtitle | | Connect an Agent | `packages/mcp/src/connect-ui.ts` | title `Connect an Agent` + 一大段 subtitle | > 注:这些页的**左侧导航项** label 已走 app 翻译包(`apps.setup.navigation.*`)正常中文化;缺的是**页内 `page:header` 的 title/subtitle**。页正文 widget(InstalledListWidget / CloudConnectionPanel / ConnectAgentWidget)大多已 i18n。 ## 方案(待设计) 给 `page:header`(或 `pages` 命名空间)补一条翻译解析链路,二选一或结合: - **A. framework 通用解析**:在 `i18n-resolver` 落地 pages / page:header 的 title/subtitle 解析(按 page name 或组件),补三页对应译文。通用,插件页也能受益;需动 spec/resolver + console 渲染,测试面较大。 - **B. console 本地化已知页**:console 对这几个已知系统 page name 做定点翻译映射。快、风险低;不通用。 ## 关联 - 母 issue(系统设置 i18n 总),另含 P1(service-settings 译文补全)、P2(console 硬编码接 i18n):objectstack-ai/objectui#2851
Activity
os-zhuang commentedon Jul 27, 2026
评估结论:选 方案 A(framework 通用解析)。实现已提交:#3648(draft)
调研两个仓库后,方案 A 比 issue 里预估的小得多——服务端翻译链路的所有接缝都已存在,这是补一块缺失的拼图,而不是新建一条链路。objectstack 侧 4 处代码改动 + 译文,objectui/console 零改动。
关键发现
1.
pages命名空间挂在了错误的 schema 上,而且完全没有读端。pages定义在AppTranslationBundleSchema(translation.zod.ts:579),但II18nService上它的存取方法getAppBundle/loadAppBundle是 optional 且零实现——运行时真正流转的是TranslationData(经i18n.getTranslations(locale)),而它没有pages键。所以第一步是把pages加到TranslationDataSchema上,而不是复用原来那个。2. 服务端翻译管线已就绪,
page只是被一个 Set 挡在门外。rest-server.ts:51的TRANSLATABLE_META_TYPES = new Set(['view','action','object','app','dashboard'])是唯一闸门;GET /api/v1/meta/:type[/:name]的 list/single 两条路由都已调用translateMetaItem(s)→translateMetadataDocument,page直接 fall through 原样返回。Accept-Language提取、locale 入 ETag 缓存键(#1319)、Vary: Accept-Language全都已对所有 metadata 类型生效——左侧 nav label 正是走这条路被翻译的,这也解释了为什么 nav 中文了而页头没有。3. console 对方案 A 是"免费"的,还白捡一个修复。
createAuthenticatedFetch在所有 API 调用上带Accept-Language,页面 metadata 到达 console 时已是译文。额外收益:transformSpecTranslations会原样转发未知顶层键,pages.*自动到达客户端 catalog,而useObjectLabel().pageLabel早已在 probepages.<name>.label——面包屑顺带一起修好了。4. 方案 B 在客户端做通用解析有真实障碍。
page:header渲染器(objectuicontainers.tsx:795)拿不到自己所属的 page name(没有 PageContext),要么穿 context(工作量不比 A 小且放错层),要么按英文字面量做字典映射(同文件KNOWN_LABEL_DICT的先例)——后者英文文案一改就断。B 还要新建cloudConnection.*语言包,却只覆盖已知三页,framework 缺口原样保留。实现要点(#3648)
TranslationDataSchema新增pages.<name>.{label,description,title,subtitle}translatePage,翻页面自身 label/description,并把 title/subtitle 覆盖到 regions 里每个page:header;注册进translateMetadataDocumentTRANSLATABLE_META_TYPES加'page'(单 token 改动,下游全部复用)objectstack i18n extract支持 pages,避免新命名空间对工具链隐形两个设计取舍请 review:
page:header实例没有稳定id,page name 是文档上唯一可寻址标识。title缺省回退到label——三页的页头标题与 nav label 都是同一串字符串,要求写两遍只会制造 drift;两者确实不同时显式title仍然优先。英文字面量保留在 metadata 里作为 fallback,没有
pages条目的页面渲染行为完全不变。顺带修复
nav_cloud_connection/nav_connect_agent此前只存在于zh-CN.ts,已补en/ja-JP/es-ES。需要另开 issue 的发现
CloudConnectionPanel.tsx正文完全未 i18n。 本 issue 假设三页正文 widget "大多已 i18n",实测:InstalledListWidget、ConnectAgentWidget 确实翻好了,但 CloudConnectionPanel 没有任何@object-ui/i18n引用,10 个语言包里也都没有cloudConnection.*命名空间(硬编码英文:"Checking connection…"/"Try again"/"Connected to ObjectStack Cloud"/"Disconnect" 等)。所以云连接这一页在本 PR 合入后,页头会中文、正文仍是英文。 属 objectui 侧,建议接在 #2851 的"复核其余 SDUI widget 正文 i18n 覆盖"那条下。一点教训
本仓库已有两处"schema 加了、读端没接"的死代码:
AppTranslationBundle.pages本身,以及整个resolveSettings*家族(零调用点)。#3648 把 schema 与读端放在同一个 PR 里落地,建议后续同类改动沿用这个约束。Generated by Claude Code
feat(spec): resolve page metadata i18n — page:header title/subtitle (#…
test(cli): pin the plugin-carried Setup pages against their translati…