Skip to content

自定义系统页 page:header 未国际化 (Installed Apps / Cloud Connection / Connect an Agent) #3589

Closed

Description

@baozhoutao

问题

若干「自定义系统页」的标题/副标题直接写死在 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 做定点翻译映射。快、风险低;不通用。

关联

Activity

  1. self-assigned this
    on Jul 27, 2026
  2. os-zhuang commented on Jul 27, 2026

    @os-zhuang
    Contributor

    评估结论:选 方案 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 早已在 probe pages.<name>.label——面包屑顺带一起修好了。

    4. 方案 B 在客户端做通用解析有真实障碍。

    page:header 渲染器(objectui containers.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;注册进 translateMetadataDocument
    • TRANSLATABLE_META_TYPES 加 'page'(单 token 改动,下游全部复用)
    • objectstack i18n extract 支持 pages,避免新命名空间对工具链隐形
    • zh-CN / ja-JP / es-ES 三页译文

    两个设计取舍请 review:

    • 页头文案按 page name 寻址,而非组件 id——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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions