Skip to content

fix(i18n): 回填 console 命名空间 41 个缺失语言 key + console.ai.group. 前缀家族,十包补齐 (#3546 切片四) - #3839

Merged
yinlianghui merged 1 commit into
mainfrom
claude/issue-3546-slice4-console
Aug 8, 2026
Merged

fix(i18n): 回填 console 命名空间 41 个缺失语言 key + console.ai.group. 前缀家族,十包补齐 (#3546 切片四)#3839
yinlianghui merged 1 commit into
mainfrom
claude/issue-3546-slice4-console

Conversation

@yinlianghui

@yinlianghuiyinlianghui commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

Fixes-part-of #3546 — 切片四。本单不关闭#3546:回填后仍余 68 个缺失 key + 3 个整族缺失前缀。

基线 origin/main@c85268256

正文修订一次:GitHub 正文消毒器吃掉了两处字符(尖括号占位符、非空断言 !),已改写为等义写法。这正是 AGENTS.md 提醒过的 at-rest 消毒行为。

分母:脚本实测,不手数

node scripts/check-i18n-call-site-keys.mjs(#3530 的守卫)的 analyze() 实测本切片命名空间:

实测
不重复缺失 key41(全部 console.*)
对应调用点47(五个 key 多站点)
属本切片的 missing-prefix1(console.ai.group.,棘轮四个前缀家族里唯一属 console 的)
棘轮内本切片条目42(41 key + 1 前缀,与实测清单双向精确相等,无差集)
en 新增 key46(41 实测 + 前缀家族枚举出的 5)

五个多站点 key(切片二"预测 90 实为 93"的教训,这次先量):

console.ai.dock.maximize -> ChatDock.tsx:391, :392, :519 (3)
console.ai.collapseToDock -> AiChatPage.tsx:1176, :1177 (2)
console.ai.newApp -> AiChatPage.tsx:1899, :1931 (2)
console.ai.dock.title -> ChatDock.tsx:379, :504 (2)
console.ai.dock.open -> ChatDock.tsx:562, :563 (2)

守卫读数,前后对照(同一命令):

前: 2372 pack-backed (2199/2320 literal keys resolve) … en pack (2790 keys)
后: 2372 pack-backed (2246/2320 literal keys resolve) … en pack (2836 keys)
Every in-scope call-site key resolves against the en pack (2836 keys).

解析数 +47(= 47 个调用点)、en key 数 +46,与清单精确相等。

棘轮 ASSERT 输出:

before: 109 after: 68 removed: 41
ASSERT removed===41 -> true
ASSERT lines deleted===41 -> true
ASSERT no console.* key left -> true
ASSERT missingPrefixes 4->3 -> true (removed 1)
remaining prefixes: ["gantt.linkEnd.","marketplace.disclosure.runtime.","organization.invitations.status."]
ASSERT file still valid JSON -> true (parsed)

棘轮按行删除而非重序列化(先试了重序列化,git diff 变成 213 insert / 115 delete 的全文件重排;切片三的 diff 是干净的 54 行删除)。最终 diff:42 deletions(-),零插入。

严重度:全部是"英文可见、十语不可译"

按切片一验收修正后的框架叙述。47 处全部带内联 defaultValue,无一渲染裸 key。zh 会话下实际看到的:/ai 连接横幅三句(Waiting for server… / Still working… / Connection lost — reconnecting…)全英文;propose_blueprint 那段长等待的 lead-in 加十条轮播提示全英文;方案卡上 Built / Not yet built / Published / Publish failed;ChatDock 整套 chrome(标题、拖宽把手、折叠、Open full page)全英文,其中两个是 aria-label;会话侧栏日期分组读作 Today / Yesterday / Previous 7 days;敲错 URL 得到英文 Page not found;? 快捷键面板里 AI 组是英文表格里的一块英文。其中 Not yet builtTODAY 正是 #2458 第 4 条点名的字串(已回填进度记在该单)。

死兜底:先量再动,本切片 key 为 0(并顺带量出 5 处别人的)

全仓 308 个 console.* 调用点(不只本切片的 47 个)做 AST 扫描,找 t(key) || '…' / ?? '…' 形态:

checked 308 console.* call sites in 20 files; dead-fallback constructs found: 5

5 处全在 ObjectView.tsx,且 key 都在 en 有值(所以 || 右侧恒不求值),不属本切片的 41 个 key,一处未动。切片一(PR #3583)删的是同一文件里 key 缺失的 5 处(那时 || 因 i18next miss 返回 key 恒真而失效);这 5 处从来没进过棘轮,谁也扫不到。已回填进 #3810(它正文自陈"规模未量"),并指出该单选项 B 的门禁若只判 defaultValue 会整支漏掉 ||所以本 PR 零组件改动。

en ↔ 内联 defaultValue:46/47 逐字节相同,1 处结构上不可能

slice call sites: 47 (literal defaultValue: 47, none: 0)
en value === inline defaultValue: 46/47
MISMATCH packages/app-shell/src/layout/ChatDock.tsx:563 console.ai.dock.open
en = "Open assistant"
site = "Open assistant (⌘⇧I)"

ChatDock.tsx:562/563同一个 key同一个按钮上写了两句不同的英文:

aria-label={t('console.ai.dock.open', { defaultValue: 'Open assistant' })}
title={t('console.ai.dock.open', { defaultValue: 'Open assistant (⌘⇧I)' })}

key 缺失时两句今天都是活的(各渲染自己的 defaultValue);补进 en 后包值恒胜,其中一句必然改变。这不是切片一 cannotEditMetaView 那种"四句从未渲染过的死英文"(那里合并不损失任何用户见过的东西),所以那条先例不覆盖它,必须裁一次。

aria-label 那句,两条理由:(1) 无障碍名不能带 (⌘⇧I) 这种被读屏念成符号的字形 —— #3546 切片一整条线就是无障碍名被 i18n miss 毁掉;(2) 是 mac 专有字形,en语言包,无法按平台分叉(Windows/Linux 上真实绑定是 Ctrl+Shift+I,该串对非 mac 用户本来就是错的)。

诚实记下后果:该 title 的悬浮提示由 Open assistant (⌘⇧I) 变为 Open assistant,不再提示快捷键。该快捷键是真的(chatDockState.ts:168matchChatDockShortcut 匹配 ⌘/Ctrl+Shift+I),但它没有出现在 KeyboardShortcutsDialog 的 aiChat 组(那里只有 ⌘⇧O 与 ⌘⇧S),所以补键之后它在 UI 上没有发现面了。是否把它加进快捷键面板属产品裁量,已连同这处分歧一并回填 #3810,不在本 PR 改组件。另注:ChatDockLauncher 的注释写明 console 在 P3b 已退役该 launcher(只有 Studio dock 用它),所以这个提示的实际暴露面是 Studio 侧。

前缀家族 console.ai.group.:按封闭联合枚举,不通配

调用点是 t(`console.ai.group.${group.key}`, { defaultValue: CONVERSATION_GROUP_LABELS[group.key] })(ConversationsSidebar.tsx:277)。取值面不是开放字符串,而是同文件的封闭联合:

export type ConversationGroupKey = 'today' | 'yesterday' | 'previous7Days' | 'previous30Days' | 'older';

所以修法是枚举五个成员,不是补一个通配前缀。测试读组件自己的联合与 CONVERSATION_GROUP_LABELS,钉两件事:

  • key 面:enconsole.ai.group 子对象的键集合 === 联合成员集合(第六个分组一旦加入,这条红 —— 正是棘轮里那条 prefix 条目原本的职责,从棘轮搬进测试);
  • 值面:五个 en 值与 CONVERSATION_GROUP_LABELS 的英文逐字节相同(包在时 i18next 答、包不在时 label 表答,用户不能分辨跑的是哪条)。

这是"key 可达性 vs 值判定"两件不同的事,分别断言。棘轮 missingPrefixes 4 → 3,切片三写的"恰 4 条"钉子同步改为 3 条并加一条 not.toContain('console.ai.group.')

九包实译:逐包邻键取证

每包都在同一个包console 邻域取证(不跨包套用):

邻键证据本切片落值举例
zhconsole.ai.offlineDemoMode = 离线演示模式 — 无法获取助手列表(短状态行用破折号加空格,长散文才用 ——);近 7 天 的数字空格连接已断开 — 正在重新连接…;过去 7 天;全角 ,。
jaconsole.ai.usage.title = AI 使用状況(AI 后带空格);包内 88 处AI アシスタントを利用できません;プランをまとめています…
kopublicForm.unavailableTitle = 양식을 사용할 수 없습니다;包内无全角句号AI 어시스턴트를 사용할 수 없습니다;양식과 목록을 배치하는 중…
deconsole.ai.emptyDescription / planApproveHint 用敬语 Sie;home.pendingDrafts.publishing = Wird veröffentlicht…Ihre App wird entworfen…Wird erstellt…;KI-Assistent(承 KI-Nutzung 的连字符复合)
frcalendar.today = Aujourd'hui(直角撇号,非 U+2019)Ouvrir l'assistant7 jours précédents
esconsole.ai.emptyDescription = …su aplicación actualplanApproveHint = Responda para… —— console.ai 邻域一致 ustedDiseñando su aplicación…La URL que siguió…reinténtelo
ptconsole.ai.offlineDemoMode = Modo de demonstração off-line(该包的 off-line 拼法)…temporariamente off-line — tente novamente…
ruconsole.ai.emptyDescriptionо чёмshortcuts.toggleDarkModeтёмный —— 该包写 ёЕщё не собраноВсё ещё выполняется…не включён(有断言钉 ё)
ar既有 console.ai.* 进行式用 جارٍ …;包内把 AI 拼写为 الذكاء الاصطناعي 而非嵌 Latin 缩写جارٍ إعادة الاتصال…;三条 AI 相关句均动词/名词居首,并有断言"首字符非 Latin 字母"

en 相同的字符串,一律复用邻键既有译文而不另造:console.notFound.back = en Go backdetail.goBack 同字符串,九包取同一译文;console.ai.publishFailedhome.pendingDrafts.publishFailed;unavailableRetry(Try again)← cloudConnection.retry(不是console.errors.tryAgain,后者 en 是 Try Again,不同字符串);unavailableHomemarketplace.action.backHome;dock.title(Assistant)← console.ai.assistant;group.todaycalendar.today;group.yesterdaydashboard.filters.range.yesterdayconsole.ai.published 取各包 console.ai.publishOk(Published — objects are now live.)的首句既有译法(已发布 / 公開しました / تم النشر …)。

反抄袭断言:精确集合 1 对,单一理由

实测"与 en 逐字节相同"的 lang :: key 对:1 / 414,只有一个:

fr :: console.ai.dock.title ("Assistant")

Assistant 在法语里拼写完全相同,是真同形词,不是漏译 —— 与切片二的 12 对、切片三的 18 对同类。断言是集合相等而非子集:第 2 对同形会红,把这一对改成别的写法也会红、迫使出列。

配 presence 断言防空转(切片二 B1 暴露的问题:集合相等在包为空时同样"绿"),并给出反面对照——同一个词嵌进句子里的两个法语邻键都与 en 不同形,证明豁免划在这一个词上,不是划在"法语包偷懒"上:

expect(UNTRANSLATED_COGNATES).toHaveLength(1);expect(at(builtInLocales.fr,'console.ai.dock.title')).toBe('Assistant');expect(at(builtInLocales.fr,'console.ai.dock.description')).not.toBe(at(builtInLocales.en,'console.ai.dock.description'));expect(at(builtInLocales.fr,'console.shortcuts.groups.aiChat')).not.toBe(at(builtInLocales.en,'console.shortcuts.groups.aiChat'));

另加两条本切片特有的形状断言:零插值(这 46 个字串没有一个带 option,任何包加 {{x}} 都会把花括号渲染给用户 —— 与切片三 {seconds} 那类正相反,所以钉的是"不许有")、省略号字符随 en(15 个以 结尾的 key,十包必须同样用 U+2026 而非三个半角点;实测十包在 console.* 里对 en 的 /... 是逐 key 镜像的)。

provider-mounted 抽样钉扎(discrimination check)

五个组件(AiChatPage / ChatDock / ConversationsSidebar / AppContentRouteNotFound / KeyboardShortcutsDialog)都是裸 useObjectTranslation(),没有 createSafeTranslation defaults map 挡在前面 —— 所以挂 provider 不是仪式:不挂,回答问题的就不是 i18next,测的就不是 console 用的那条路。抽样(不是 46 key 全测):

  • en / zh 各解析 6 个代表 key(每组件/每子区一个),断言 not.toBe(key) 且等于包内值;
  • 前缀家族按真实模板调用形态(t(`console.ai.group.${key}`))在 en/zh 两路把五个分组全渲染一遍;
  • 另八包各钉一条用户可见面(横跨四种书写系统):fr unavailableRetry、de planDeferred、es notFound.description、pt dock.collapse、ru connectionStalled、ja designingPlanHint.finalize、ko shortcuts.groups.aiChat、ar published;
  • ru 的 ё 与 ar 的"RTL 句首不落 Latin token"各一条专项断言。

反向验证:三处全部预测为红/绿,三处全中

方向在跑之前就定了 —— 本切片是"包里没有 → 补上",没有被删的死枝、没有计数类下游门禁、没有 canonical-first 的 ?? 链,所以不存在切片先例里的"诊断变多"或"反转"情形:第 1、2 条应为常规的红,第 3 条应为守卫绿而 parity/本测试红(那是 #3530 记录的门禁分工,不是漏检):

  1. 只把棘轮 42 行放回(包保留)→ 守卫报 42 条 stale,退出码 1:
    GUARD EXIT=1
    42 baseline entries are stale — the defect is gone, so the entry must go too (this file is a ratchet; it only shrinks):
    missingKeys: console.ai.collapseToDock … (41 条)
    missingPrefixes: console.ai.group. (前缀那条同样被判 stale,因为 en 现在有 console.ai.group.* 了)
    
  2. 只回退 en.ts(棘轮保持已删)→ 守卫报 48 条 unexpected / 42 distinct,退出码 1:
    GUARD EXIT=1
    2372 pack-backed (2199/2320 literal keys resolve) ← 解析数同步回落 2246 → 2199
    48 call sites reference a key the en pack does not define (42 distinct):
    packages/app-shell/src/chrome/KeyboardShortcutsDialog.tsx:62:14 [missing-key] console.shortcuts.groups.aiChat
    packages/app-shell/src/console/ai/ConversationsSidebar.tsx:277:20 [missing-prefix] console.ai.group.
    
    48 = 47 个 missing-key 站点 + 1 个 missing-prefix 站点;42 distinct 正是棘轮那 42 行。
  3. 只回退 zh.ts(en 保留)→ 守卫仍然绿(它只看 en),而 parity 与本切片测试红,失败文本就是前提本身:
    守卫: Every in-scope call-site key resolves against the en pack (2836 keys). GUARD EXIT=0
    AssertionError: zh is missing 46 key(s)
    AssertionError: expected 'Today' to be '今天'
    AssertionError: expected 'AI assistant unavailable' to be 'AI 助手不可用'
    AssertionError: expected undefined to be '正在搭建…' ← convZh 字节钉子(见下)
    Test Files 2 failed (2) | Tests 8 failed | 46 passed (54)
    
    第 3 条同时证明三道门禁的边界没被本 PR 弄混:只补 en 不补九包这种半成品,守卫看不见,parity 看得见。

顺手量出、未在本 PR 修的事

  1. AiChatPage 的 planBuildingLabel 按「对话语言」而非 UI 语言取值 —— 英文界面 + 中文会话时,方案卡上唯一一个中文标签,且 zh 包该 key 永远读不到 #3837(新立,concrete)AiChatPage.tsx:2195planBuildingLabelconvZh 门控住(convZh ? '正在搭建…' : t('console.ai.planBuilding', …))。同文件 1580-1586 行的注释自己写明规则是"发送内容随会话语言、标签随 UI 语言",而这是标签。后果:英文 UI + 中文会话时方案卡上其他标签全英文、中间夹一个中文;且中文会话恒走硬编码字面量,zh 包这个 key 对真实中文用户无效。本 PR 的防护(不是修复):zh 值写成与该字面量逐字节相同的 正在搭建…,并加断言读源码把两者钉住,三元被删时该断言会红提示回来清理:
    constliteral=src.match(/convZh\?'([^']+)':t\('console\.ai\.planBuilding'/);expect(literal,'the convZh planBuilding branch moved — recheck the finding').not.toBeNull();expect(at(builtInLocales.zh,'console.ai.planBuilding')).toBe(literal[1]);// ↑ 实际代码在 literal 后带非空断言;GitHub 正文消毒器会吃掉那个字符,故此处省略
  2. [finding] 8 处 auth 调用点的内联 defaultValue 与 en 包值不一致 —— key 存在故兜底是死代码,三道 i18n 门禁按设计都看不见这一类 #3810(已存在,回填评论) — 上面第 1/2 项:console.ai.dock.open 的两句英文(该单类别的新实例,并说明它证明该单选项 A 对"一 key 多站点两句英文"无效、选项 B 的判据需加"同 key 各站点彼此也要相同");以及 ObjectView.tsx 5 处 t(key) || '英文' 死兜底(该单门禁设计若只判 defaultValue 会整支漏掉)。附本次 console 面的规模数据,回应该单正文自陈的"规模未量"。
  3. console-ai UX:三轮真实浏览器魔法流程测试的体验问题清单(登录无声失败/agent 蓝图感知/转介等待/i18n 混杂等) #2458(已存在,进度评论) — 该单第 4 条点名的 Not yet built / TODAY 由本 PR 补齐,Your apps / Needs your attention 仍在棘轮(home 欠 5 个),Open in Builder → 等属 cloud 侧产出、本仓守卫扫不到。未改该单状态(仍 pm:on-hold)。

验证

node scripts/check-i18n-call-site-keys.mjs
→ Every in-scope call-site key resolves against the en pack (2836 keys).
node scripts/check-i18n-en-drift.mjs
→ 0 en value(s) changed (46 key(s) added, 0 removed) — No en value changed in this range.
node scripts/check-control-bytes.mjs
→ OK (scanned 3746 tracked text file(s); skipped 85 binary)
node scripts/check-changeset-presence.mjs
→ 12 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)
grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f]' 15 个改动文件 → 无匹配
git log -1 --format=%B | grep -ci fable → 0
flock /tmp/os-heavy-verify.lock -c 'NODE_OPTIONS=--max-old-space-size=4096 \
pnpm exec vitest run packages/i18n \
scripts/__tests__/check-i18n-call-site-keys.test.ts \
scripts/__tests__/check-i18n-en-drift.test.ts --maxWorkers=2'
→ Test Files 30 passed (30) | Tests 490 passed (490)
pnpm --workspace-concurrency=2 --filter @object-ui/i18n type-check → tsc --noEmit 通过
pnpm --workspace-concurrency=2 --filter '@object-ui/react^...' build → 先建依赖(新 worktree)
pnpm --workspace-concurrency=2 --filter @object-ui/react type-check → tsc --noEmit + tsconfig.typetests.json 通过
npx eslint 本 PR 改动的 13 个 i18n 文件 → 0 problems

all-locales-key-parity.test.ts 含在上面 30 个文件内,已绿(它是补完 en 后立刻要求九包补齐的那道门禁)。@object-ui/react 只是 type TranslationKeys 的转出口(TranslationKeys = typeof en),全仓无任何消费方把它当必需形状声明,所以加 key 不会窄化谁 —— 已 grep 确认并实跑该包 type-check。

测试命令按 AGENTS.md §9 的唯一正确写法(仓根 pnpm exec vitest run 加相对仓根的路径),不用 pnpm --filter 包名 test(陷阱一)、不把路径挂在 -- 后(陷阱二)。

围栏

packages/i18n/src/locales/*.ts(十包,仅新增本切片 key)、scripts/i18n-call-site-key-baseline.json(仅删本切片 42 条)、packages/i18n/src/__tests__/console-namespace-3546.test.tsx(新增)、auth-namespace-3546.test.tsx + organization-namespace-3546.test.tsx(仅棘轮总数 109 → 68,前者另同步 missingPrefixes 4 → 3 —— 那个计数器每切片动一次且只降)、changeset。零组件改动(本切片 key 的死兜底量出为 0)。与在飞 #3755/#3759(create-plugin)、#3812(components/action)、#3813(data-objectstack)、#3762(plugin-grid)零相交。未动 content/docs/releases/**

…#3546 切片四)
`scripts/check-i18n-call-site-keys.mjs`(#3530)实测:`console` 命名空间有 41
个 key 被 `t()` 引用而**任何语言包都没有**,对应 **47 个调用点**(五个 key 多站点,
`console.ai.dock.maximize` 有三个;分母一律脚本实测,不手数)。47 处全部写了内联
`t(key, { defaultValue: '英文' })`,即 #3517 那一类:英文照常渲染,十种语言统统
翻不了。裸 key 站点在切片一(PR #3583)已清完;对全仓 308 个 `console.*` 调用点
做 AST 扫描,本切片 key 的死兜底为 0 —— 所以不动任何组件文件。
- `en.ts` 补 46 key = 实测的 41 + 前缀家族 5。`console.notFound` 是新子命名空间,
其余扩充 `console.shortcuts` 与 `console.ai`(新增 `dock` /
`designingPlanHint` / `group` 三个子对象)。41 个 key 的 en 值取调用点内联
defaultValue **逐字节相同**(脚本比对 46/47 站点)。
- 唯一不能相同的一处:`ChatDock.tsx:562/563` 用**同一个 key**
(`console.ai.dock.open`)写了两句英文 —— `aria-label` 是 `Open assistant`,
`title` 是 `Open assistant (⌘⇧I)`。一个 key 只能有一个值,en 取 aria-label
那句:无障碍名不能带被读屏念成符号的字形,且 `⌘` 是 mac 专有字形,语言包无法
按平台分叉。后果(title 不再提示该快捷键)记在 PR 正文并回填进 #3810。
- `console.ai.group.` 从棘轮 `missingPrefixes` 摘除(4 → 3)。它是模板 key
(`ConversationsSidebar.tsx:277`),取值面是**封闭**的 `ConversationGroupKey`
联合,所以按枚举补齐五个成员而不是通配;测试读组件自己的联合与 fallback label
表,第六个分组一旦加入就红。
- 九包实译按同包 `console` 邻键取证(zh 全角标点与单破折号状态行、ja/ko 的
`AI ` 空格、de 敬语 Sie 与 `Wird …` 进行式、fr 直角撇号、es usted、pt `off-line`
拼法、ru ё、ar 动词居首不让 RTL 句首落 Latin token)。en 相同的字符串一律复用
邻键既有译文(`Go back` / `Publish failed` / `Try again` / `Back to home` /
`Assistant` / `Today` / `Yesterday`)。
- 棘轮 `scripts/i18n-call-site-key-baseline.json` 精确减 42(41 key + 1 前缀):
109 → 68 key,4 → 3 前缀。切片二/三把总数硬钉在 109,两处同步改为 68。
- `zh` 的 `console.ai.planBuilding` 与 `AiChatPage.tsx:2195` 硬编码的
`convZh ? '正在搭建…'` 逐字节相同,并有断言读源码钉住两者 —— 那个三元本身是
独立缺陷(标签跟了会话语言而非 UI 语言),已立 #3837,不在本 PR 修。
Co-authored-by: Claude <noreply@anthropic.com>
@vercel

vercelBot commented Aug 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectuiIgnoredIgnoredAug 8, 2026 6:53pm

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Main entry (gzip)28.1 KB350 KB
Entry fileindex-Bc01Pece.js
StatusPASS

📦 Bundle Size Report

PackageSizeGzipped
app-shell (index.js)8.66KB3.13KB
app-shell (runtime-config.js)7.42KB2.32KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)7.57KB2.97KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)1.17KB0.53KB
auth (AuthProvider.js)22.10KB4.37KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.13KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.64KB2.21KB
auth (SocialSignInButtons.js)9.60KB3.89KB
auth (UserMenu.js)3.40KB1.22KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)35.76KB9.11KB
auth (createAuthenticatedFetch.js)4.37KB1.69KB
auth (index.js)2.35KB1.07KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)4.91KB0.87KB
auth (useIsWorkspaceAdmin.js)1.61KB0.85KB
collaboration (CommentThread.js)26.07KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.65KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)481.85KB106.09KB
core (index.js)2.96KB1.13KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)139.61KB35.99KB
fields (index.js)230.82KB56.70KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (i18n.js)4.32KB1.77KB
i18n (index.js)2.65KB1.06KB
i18n (pickLocalized.js)1.70KB0.83KB
i18n (provider.js)9.48KB3.27KB
i18n (useObjectLabel.js)27.59KB6.63KB
i18n (useSafeTranslation.js)4.52KB1.96KB
layout (index.js)38.53KB10.71KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.74KB
mobile (index.js)1.50KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.71KB0.42KB
mobile (useResponsiveConfig.js)1.36KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)8.75KB3.06KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)3.67KB1.12KB
permissions (evaluator.js)4.41KB1.44KB
permissions (index.js)0.91KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.52KB
permissions (usePermissions.js)1.55KB0.71KB
plugin-ai (index.js)15.71KB3.79KB
plugin-calendar (index.js)44.98KB12.37KB
plugin-charts (index.js)61.04KB17.31KB
plugin-chatbot (index.js)180.33KB42.79KB
plugin-dashboard (index.js)117.21KB30.27KB
plugin-designer (index.js)210.51KB42.51KB
plugin-detail (index.js)233.78KB57.92KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)112.10KB27.10KB
plugin-gantt (index.js)162.55KB39.57KB
plugin-grid (index.js)187.63KB49.66KB
plugin-kanban (index.js)48.30KB13.28KB
plugin-list (index.js)105.12KB25.48KB
plugin-map (index.js)16.81KB5.24KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)40.58KB10.58KB
plugin-timeline (index.js)25.76KB7.33KB
plugin-tree (index.js)8.50KB2.88KB
plugin-view (index.js)84.03KB20.55KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.71KB3.53KB
providers (index.js)0.44KB0.22KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.67KB2.37KB
react (LazyPluginLoader.js)3.77KB1.33KB
react (SchemaRenderer.js)19.28KB6.38KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)1.02KB0.55KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)4.09KB1.74KB
sdui-parser (index.js)4.47KB2.03KB
sdui-parser (parse.js)10.04KB2.82KB
sdui-parser (types.js)0.29KB0.24KB
sdui-parser (validate.js)4.69KB1.48KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)0.20KB0.18KB
types (crud.js)0.20KB0.18KB
types (data-display.js)0.20KB0.18KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.87KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-retry.js)4.32KB2.02KB
types (index.js)2.71KB1.34KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)0.20KB0.18KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@yinlianghuiClaude

Copy link
Copy Markdown
CollaboratorAuthor

✅ 切片四验收:ACCEPT — PR #3839(Fixes-part-of,#3546 继续 open,余 68 key + 3 前缀家族)。(objectui 分片 PM,session_01GTRjn8xBqp75dk7kFupVRt)

裁定要点:(1) 分母纪律四轮如一 —— 41+1 前缀实测、五个多站点 key 主动点名、棘轮 42 双向差集为空、ASSERT 全真;(2) 前缀家族的处理优于要求:按封闭联合 ConversationGroupKey 枚举而非通配,key 面(联合成员集合相等,第六分组即红)与值面(与 fallback 表逐字节)分别断言 —— 把棘轮 prefix 条目的职责搬进测试;(3) dock.open 裁量采纳 A(aria-label 句):无障碍名不带读屏念成符号的字形 + mac 专有字形不进语言包,论证成立;其推荐的真正收口(⌘⇧I 补进 KeyboardShortcutsDialog aiChat 组)已在 #3810 立此存照,属小型后续不阻塞;(4) 反抄袭集合 1/414 唯一真同形词带双反面对照;(5) 三方向反向验证全中,失败文本即前提。19/19 CI 零失败;trailer 自查零命中;衍生 #3837(planBuilding 语言门控)已内建 zh 逐字节防护待判级。切片五(候选 marketplace 19 / preview 18)在本 PR 落 main 后开。


Generated by Claude Code

@yinlianghui
yinlianghui marked this pull request as ready for review August 8, 2026 19:02
@yinlianghui
yinlianghui added this pull request to the merge queueAug 8, 2026
Merged via the queue into main with commit f5f8744Aug 8, 2026
20 checks passed
@yinlianghui
yinlianghui deleted the claude/issue-3546-slice4-console branch August 8, 2026 19:02
akarma-synetal pushed a commit to akarma-synetal/objectui that referenced this pull request Aug 10, 2026
…3837) (objectstack-ai#3897)
* fix(app-shell): 方案卡的 Building… 徽标随 UI 语言取值,不再被会话语言门控 (objectstack-ai#3837)
`AiChatPage` 用 `convZh`(会话语言)门控四个字符串,因为 cloud 确认门
(`service-ai-studio` `confirm-gate.ts` `APPROVAL_RE`)只认中英,发进线程的
文本必须与线程本身同语言(objectstack-ai#772/objectstack-ai#2884)。该门上方注释的后半句写明了另一半规
则:button LABELS stay on the UI locale。
`planBuildingLabel`(objectstack-ai#2632 引入)落在了这句的错误一侧,中文会话恒取硬编码的
`正在搭建…`,两个后果都已实测:
- **混合语言的卡片**:英文控制台里,中文会话的方案卡 `Proposed plan` /
`Build it` / `Built` / `Not yet built` 全英文,中间夹一个中文徽标。objectstack-ai#2458
第 4 条记录的是同一个病的反方向。
- **翻译永远读不到**:中文会话恒走字面量,`console.ai.planBuilding` 的 zh
值对中文读者无效。objectstack-ai#3546 切片四(PR objectstack-ai#3839)刚把该 key 补进十包,只能做围
堵 —— 把 zh 值写成与字面量逐字节相同并把两者钉在一起。
徽标现在与相邻十二个标签一样读 `t('console.ai.planBuilding', …)`:十个包全
部可达(德文控制台 + 中文会话渲染 `Wird erstellt…`),zh 包成为该中文措辞的
唯一来源(值不变,中文读者看到的字符串与改动前完全一致)。
三条出站文本(`planApproveMessage` / `planApproveDefaultsMessage` /
`changesConfirmMessage`)一行未动,仍随会话语言 —— 复核确认三者都交给
`onSendMessage`(`ChatbotEnhanced.tsx:1598`、`:2395`)、由门读取,正是
`convZh` 分支存在的那一类;全文件再无其它 `*Label`/`*Title` 被该门控住
(`convZh` 全部读点:定义 1 处 + 这三条)。
钉子:
- `packages/app-shell/.../AiChatPage.planCardLocale.test.tsx`(新增)真渲染
`ChatPane` + 真 `I18nProvider` + 真 `isConversationZh`,把
`ChatbotEnhanced` 换成 props 记录器:en 控制台 + 中文会话 → `Building…`
且卡上 `*Label` 无一含中日韩字符;de 控制台 + 中文会话 → `Wird erstellt…`
(三方语言证明是包在应答,而非两路三元);zh 控制台 → `正在搭建…`;三条
出站文本仍随会话。
- `packages/i18n/.../console-namespace-3546.test.tsx`:切片四埋的围堵钉按其
自述翻转 —— 从「字面量与 zh 包逐字节相同」改为钉住门已移除,并把不变量放
宽一步:`convZh` 只许门控出站 `*Message`,任何新读点都会红。
反向验证(方向先判后跑,与预判一致):还原三元 → 3 红 —— i18n 钉子按自定义
消息点名、en 控制台用例、de 控制台用例;zh 控制台用例与三条出站文本保持绿
(前者按设计逐字节相同,不具区分力,已在测试头注明)。
顺带:`conversationLanguage.ts` 模块头把 progress labels 也列进「随会话」,
该句在本改动后不再为真,收窄为「只治离开控制台发给 agent 的文本」。
写钉子时量到发送半边另有一个缺陷(zh 控制台 + 英文会话会把中文确认句发进英
文线程;`planAnswerMessage` 完全没有门控),不在本单范围,已立 objectstack-ai#3896。
测试:`packages/app-shell/src/console/ai` + `packages/i18n` 47 文件 654 通过;
两包 type-check 通过,全仓 `turbo run type-check` 78/78 通过;改动文件
eslint 零告警;`check-control-bytes` / `check-i18n-call-site-keys` /
`check-i18n-en-drift` 均通过(零 en 值变更)。
Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt
Co-authored-by: Claude <noreply@anthropic.com>
* test(app-shell): 钉子里的 agent 桩改用具名类型断言,不用 as never
评审可读性,零行为改动:`ChatPane` 的 agents 桩从 `as never` 改成
`as unknown as AgentDescriptor`(类型导入,运行期擦除;该模块在本文件里被
vi.mock,类型不受影响)。
Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt
Co-authored-by: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@yinlianghui@claude