发现于 #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)
test/i18n-references.test.ts 的 every 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_page 是 isDefault: true、发给 sales_rep / sales_manager 的落地页。
一个 zh-CN 用户登录后看到的首页,页头是「销售看板 / 欢迎回来,…」(有翻译位),而右侧
和左侧四张卡片、四个 KPI 块全是英文 —— 同一屏两种语言。
这与 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_briefing、kpi_revenue_won …),却没有对应的 components 面。两个形状几乎
一样的 UI 组件树,一个能翻一个不能,更像是 spec 侧少了一个面,而不是本应用的用法问题。
处置建议(不预判,交分诊)
三条路成本差别很大:
上游补面 :给 pages 加 components: Record( id, { title?, description?, label?, help? } ),
与 dashboards.widgets 对齐 —— 一致性最好,但要动 @objectstack/spec;
应用侧规避 :把这类文案挪到有翻译位的表面(例如能承载它的组件类型),或接受
首页卡片只有英文并在守卫里把这一点写成明示豁免 ,免得下一个人再查一遍;
先量再定 :先确认控制台是否真的直接渲染这些字面量(与 closing_this_quarter 的切换器页签标题写作 "Closing Soon" —— 与 label / 四个语言包的第四个拼法,且 tabs[].label 没有翻译位 #760 同样的不确定性,
只是那一条是 tabs[].label)。本条的静态证据比 closing_this_quarter 的切换器页签标题写作 "Closing Soon" —— 与 label / 四个语言包的第四个拼法,且 tabs[].label 没有翻译位 #760 强(strict schema 直接排除了
键的存在),但「渲染出来是什么」仍值得在浏览器里看一眼再定路线。
关联
发现于 #1002 实施过程(改首页
ai_briefing卡片文案时,按裁定 grep 四个语言包找对应键,发现根本没有这个键面)。#1002 的文件面是那一张卡片,故单独立单。
现状(基线 origin/main = 86010ff)
翻译契约里
pages只有四个键,而且是.strict():(
node_modules/@objectstack/spec/dist/translation.zod-*.d.ts)test/i18n-references.test.ts的every 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是isDefault: true、发给sales_rep/sales_manager的落地页。一个 zh-CN 用户登录后看到的首页,页头是「销售看板 / 欢迎回来,…」(有翻译位),而右侧
和左侧四张卡片、四个 KPI 块全是英文 —— 同一屏两种语言。
这与 AGENTS.md 的 i18n 约束(「No new feature ships without all 4 locales」)以及
仓里 9 个 locale 相关守卫的一贯口径是冲突的:那些守卫覆盖对象/字段/视图/动作/选项,
唯独页面组件文案覆盖不到,因为契约里没有那个键可查。
为什么这像是契约的不对称,而不是本应用漏写
同一个翻译契约里,仪表盘的组件是有翻译位的:
widget 用
id定位就能翻译 title/description;page 的组件同样有稳定id(
ai_briefing、kpi_revenue_won…),却没有对应的components面。两个形状几乎一样的 UI 组件树,一个能翻一个不能,更像是 spec 侧少了一个面,而不是本应用的用法问题。
处置建议(不预判,交分诊)
三条路成本差别很大:
pages加components: Record( id, { title?, description?, label?, help? } ),与
dashboards.widgets对齐 —— 一致性最好,但要动@objectstack/spec;首页卡片只有英文并在守卫里把这一点写成明示豁免,免得下一个人再查一遍;
只是那一条是
tabs[].label)。本条的静态证据比 closing_this_quarter 的切换器页签标题写作 "Closing Soon" —— 与 label / 四个语言包的第四个拼法,且 tabs[].label 没有翻译位 #760 强(strict schema 直接排除了键的存在),但「渲染出来是什么」仍值得在浏览器里看一眼再定路线。
关联
tabs[].label也没有翻译位 —— 那条是视图切换器,本条是页面组件;两条合起来说明「没有翻译位」不是个别键的遗漏)
test/i18n-references.test.ts(语言包内部的键漂移 —— 与本条不同,那是有键但漂了,这里是根本没有键)