Skip to content

页面组件文案没有翻译位:12 处用户可见字符串(首页占 10)在 zh/ja/es 下只能是英文,而 dashboards.widgets 有同形的翻译面 #1004

Description

@yinlianghui

Blocked-by: objectstack-ai/objectstack#12231 — ⛔ VOID, and it was never load-bearing. Removed from the reverse index at round 15. That upstream card was filed on 2026-08-25 asking for a face that had already shipped in @objectstack/spec 17.0.0-rc.6 (measured on this card 2026-08-11, verified upstream 2026-08-14); it was closed completed on 2026-08-28. This repo is pinned at 17.1.0, so the slot exists in the package actually installed. See the round-15 claim comment.

发现于 #1002 实施过程(改首页 ai_briefing 卡片文案时,按裁定 grep 四个语言包找对应键,
发现根本没有这个键面)。#1002 的文件面是那一张卡片,故单独立单。

现状(基线 origin/main = 86010ff)

翻译契约里 pages 只有四个键,而且是 .strict():

pages: Record( name, { label?, description?, title?, subtitle? } )   // strict

(node_modules/@objectstack/spec/dist/translation.zod-*.d.ts)

⚠️ 上面这段是立单时(2026-08-06)的现状,今天已不成立 —— pages 现已带 components 面,见 2026-08-11 / 08-14 两条评论。保留原文是为了让这张卡的论证链可读,⛔ 不要把它当作今天的契约形状。

test/i18n-references.test.tsevery page has translated nav copy and header copy 也照着这四个键写,并且在注释里点明了 title / subtitle 的语义:它们对应
page:header
,因为 header 实例没有稳定 id,页面名是唯一能够到它的键。

于是 page:header 以外的组件文案 —— 卡片标题、卡片描述、指标块 label —— 没有任何
翻译位
。语言包写不进去(strict 会拒),运行时也无处可读,值链就是 *.page.ts 里的
字面量直通 dist/objectstack.json

实测面(从 dist 产物统计,非源码 grep)

8 个页面,12 处这样的用户可见字符串:

sales_home_page (10)
  quick_create.title        "Quick Create"
  my_recent_items.title     "Recent Items"
  key_metrics.title         "Key Performance Indicators"
  kpi_revenue_won.label     "Revenue (Won)"
  kpi_deals_won.label       "Deals Won"
  kpi_pipeline_value.label  "Pipeline Value"
  kpi_open_leads.label      "Open Leads"
  ai_briefing.title         "Ask the AI Assistant"
  ai_briefing.description   "Open the assistant panel from the right edge …"
  upcoming_events.title     "Today's Schedule"
lead_detail_page (1)
  related_tasks.title       "Open Tasks"
utility_bar_page (1)
  quick_notes.title         "Quick Notes"

sales_home_pageisDefault: true、发给 sales_rep / sales_manager 的落地页。
一个 zh-CN 用户登录后看到的首页,页头是「销售看板 / 欢迎回来,…」(有翻译位),而右侧
和左侧四张卡片、四个 KPI 块全是英文 —— 同一屏两种语言。

⚠️ 这一段「同一屏两种语言」是推断,不是实测(见 2026-08-25 评论)。同族 #760 用同样强度的
静态证据立单,实测后判 premise-false。⛔ 不要把 12 这个数字当作已验证的影响面向前引用。

这与 AGENTS.md 的 i18n 约束(「No new feature ships without all 4 locales」)以及
仓里 9 个 locale 相关守卫的一贯口径是冲突的:那些守卫覆盖对象/字段/视图/动作/选项,
唯独页面组件文案覆盖不到,因为契约里没有那个键可查

为什么这像是契约的不对称,而不是本应用漏写

同一个翻译契约里,仪表盘的组件是有翻译位的:

dashboards: Record( name, { label?, description?, actions?, widgets? } )
widgets:    Record( id,   { title?, description? } )                  // 按 id 定位

widget 用 id 定位就能翻译 title/description;page 的组件同样有稳定 id
(ai_briefingkpi_revenue_won …),却没有对应的 components 面。两个形状几乎
一样的 UI 组件树,一个能翻一个不能,更像是 spec 侧少了一个面,而不是本应用的用法问题。

处置建议(不预判,交分诊)

三条路成本差别很大:

  1. 上游补面:给 pagescomponents: Record( id, { title?, description?, label?, help? } ),
    dashboards.widgets 对齐 —— 一致性最好,但要动 @objectstack/spec;
  2. 应用侧规避:把这类文案挪到有翻译位的表面(例如能承载它的组件类型),或接受
    首页卡片只有英文并在守卫里把这一点写成明示豁免,免得下一个人再查一遍;
  3. 先量再定:先确认控制台是否真的直接渲染这些字面量(与 closing_this_quarter 的切换器页签标题写作 "Closing Soon" —— 与 label / 四个语言包的第四个拼法,且 tabs[].label 没有翻译位 #760 同样的不确定性,
    只是那一条是 tabs[].label)。本条的静态证据比 closing_this_quarter 的切换器页签标题写作 "Closing Soon" —— 与 label / 四个语言包的第四个拼法,且 tabs[].label 没有翻译位 #760 强(strict schema 直接排除了
    键的存在),但「渲染出来是什么」仍值得在浏览器里看一眼再定路线。

路线 1 已由上游交付(@objectstack/spec 17.0.0-rc.6,面比本卡所求更宽:
title / description / label / placeholder / emptyText / submitLabel)。
⛔ 路线 2 本车道宪章明令不可用(绕行把平台缺口藏进样板)。
⚠️ 路线 3 仍未做,且它是实施的第一步,不是可选项 —— 见 R15 派发令。

关联

Metadata

Metadata

Assignees

Labels

metadataDeclarative metadata — schema, security posture, UI surfacespm:dispatchedDispatched to a dev agent by /pm-dispatchprio:p2Triaged backlog — no near-term schedule

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions