fix(cli): _views 翻译键改用运行时视图身份命名(#5164 第 1 棒 / cli 段) - #6124
Merged
Conversation
The i18n extractor derived a container's default-list translation key as `view.list.name ?? 'list'`, while the composer that assigns the runtime view identity (`expandViewContainer`) names the same view `<object>.default`. An app declaring only a default `list` therefore got a bundle skeleton keyed `list`, a registry entry keyed `default`, and an English label on screen forever — no authoring side could ever make it resolve. Maintainer ruling 2026-08-06: canonical = the runtime identity's bare key. This is leg 1 of 3 (cli); `packages/lint` narrowing is #6038, objectui `viewSuffixes` is objectui#3502. The extractor now ASKS the composer for the key instead of re-deriving it, so no third dialect can drift back in. That also inherits the composer's signature dedupe: a default list that merely restates a `listViews` entry is collapsed into it and gets no key of its own — the `examples/app-crm` shape, whose `_views.list` entry was dead weight that looked correct. Migrated in lockstep: app-showcase (5 blocks) and app-todo (2 bundles) renamed to `default`; app-crm (3 collapsed blocks) removed. `check:i18n-coverage` measured green with the baseline unchanged — both ends moved together, so no count did. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wbxm29qPKnLf44AbSxizqW
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 21 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
qq9340100
marked this pull request as ready for review
August 7, 2026 02:54
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #5164
本 PR 只交付维护者 2026-08-06 裁决(方案 A)的第 1 棒 / cli 段。第 2 棒
packages/lint收窄见 #6038,第 3 棒 objectuiviewSuffixes见 objectstack-ai/objectui#3502 —— 所以首行刻意写Part of而不是Fixes,合并后 issue 由 PM 保持打开,等三棒跑完再关。前提复核(实测,先于实现)
在 origin/main
f7f54a960上重跑了 issue 正文那段「组装器 vs 提取器」的测量,分歧确认复现:一个只声明了默认
list、没有listViews的应用,因此拿到一份键为list的骨架、一个键为default的运行时视图 —— 无论作者按哪一侧编写都命中不了,界面上永远是英文原文。顺带按派发单要求审了同文件的 FORM 面:该文件根本不为 form 视图产
_views键(注释写明 form 视图在viewLabel解析约定里没有对应物),formViews只喂_sections;文件里也不存在?? 'form'一类的同族兜底站点。所以 form 面无需镜像,这是设计,不是遗漏。实现:提取器改为「向组装器查询」,而不是字面改成
?? 'default'派发单预设的字面改法(
view.list.name ?? 'list'→?? 'default')实测在 app-crm 形状上仍然错,这是本 PR 唯一偏离派发词的地方,记录如下:examples/app-crm三个容器的默认list与各自的listViews.all结构签名完全相同,组装器按签名把两者折叠,list 家族的真实注册键只有all;而它们的formViews.default已经占住了对象名.default。字面改法会把全部商机写进一个表单视图的键上 —— 把今天可见的孤儿键换成一个看不见的错标,而且它会通过 lint(因为formViews.default确实注册了default),比现状更糟。所以提取器现在调用组装器本身取这个键:
expandViewContainer是运行时视图身份的唯一生产者,而本 issue 的病根正是「第二次自行推导会漂移」。问身份本身,而不是再推导一遍,同时白拿组装器仅有的规则:name的默认列表键为default(不再是list),带name的沿用作者的name;listViews条目结构相同的默认列表被折叠进该条目,没有自己的键 —— 提取器不再为它多写一个谁也读不到的骨架条目;listViews已占default时组装器给default_2)骨架跟着改名,因为改名后的才是注册表键。packages/spec零字节改动(裁决否决 B 案,组装器命名不变),只是复用它已导出的函数。键相等实测(改后)
showcase 五个对象,组装器 list 家族键集合与提取器
_views键集合完全相等(两侧独有项均为空):_views)defaultdefault, …by_status,budget_chart,defaultdefault,by_status,budget_charttriage,defaultdefault,triageorg_chart,defaultdefault,org_chartdefaultdefault改前每个对象都是「只在组装器:
default/ 只在提取器:list」。app-crm(折叠形状)改后提取器输出
["all","pipeline"]/["all","calendar"],与组装器 list 家族一致;对象名.default在那里是表单视图,提取器按约定不覆盖。译文随迁
examples/app-showcase:5 个_views.list块改名为default(showcase_project / showcase_task / showcase_contact / showcase_inquiry / showcase_business_unit)。examples/app-crm:3 个_views.list块删除而不是改名 —— 它们是折叠形状,改名后指向的是表单视图(见上),而同块里的all已经带着一模一样的译文串。issue 正文说它「是看着正确的死重量」,实测确认,并且删除后 lint 少 3 条。examples/app-todo:zh-CN / ja-JP 两个包各 1 块改名为default。派发单没点名 app-todo,但它与 showcase 同属「无名默认list」形状(实测组装器给todo_task.default),不随迁会让覆盖棘轮变红 —— 属同一次迁移的必然范围。覆盖棘轮基线:实测不需要调整
派发单预期「基线 adjust DOWN」。实测下来这条预设不成立,照实记录而不硬凑:
原因:裁 A 下需求侧仍然要求一个键(只是改名),译文侧同批改名,覆盖数不变;app-crm 删掉的那三条本来就是「已译且被要求」,改后变成「不再被要求」,缺失数同样不变。08-05 那条评论预期的下调,对应的是「walker 侧彻底不再产该键」的那一支,不是裁 A 这一支。基线文件因此不在本 PR 的 diff 里。
验收锚点:
os lint全量对照showcase(
node packages/cli/bin/run.js lint examples/app-showcase/objectstack.config.ts --json),改前 / 改后总量完全一致(total=523 errors=0 warnings=501),那 5 条「一条规则要求该键、另一条判它孤儿」的矛盾对是原样迁移,没有新增:这 5 条正是第 2 棒 #6038 要让
collectViewRecord注册的键 —— 派发单已言明「lint 侧收窄归第 2 棒,现有双拼写容忍预期保留」。app-crm 则是净减少:
total 104 → 101(warnings 102 → 99),三条_views.list的translation-target-unknown消失,无新增。反向验证(方向事前预测:红;实测:红)
把
?? 'list'放回同一位置后跑新增的 pin 测试:8 例中 6 例红,断言文本正是本 PR 要钉的等式:另外 2 例保持绿是正确的:它们是「默认
list带显式name」和「根本没有默认list」两种形状,新旧代码在这两种形状上本来就同解。测试
新增
packages/cli/test/i18n-extract-view-key-identity.test.ts(8 例)。它用组装器本身当 oracle,而不是硬编码'default'这个拼写 —— 钉的是不变式(两侧同键),不是某一侧当下的意见;将来若身份规则再变,测试跟着变,不会变成一条只会重复自己的死断言。不在本次范围
packages/lint的collectViewRecord收窄 = 第 2 棒 packages/lint:collectViewRecord收窄_views键到运行时裸键单拼写 —— #5164 裁 A 的 lint 段 #6038(Blocked-by本单);viewSuffixes去掉带前缀第二候选 = 第 3 棒 useObjectLabelviewSuffixes:去掉带前缀全名第二候选 —— objectstack#5164 裁 A 的 objectui 段 objectui#3502;packages/spec组装器命名(裁决否决 B 案,零字节改动);content/docs/releases/—— 从不在代码 PR 里动;已发布 bundle 的键变更走 changeset(.changeset/views-translation-key-runtime-identity.md,带 FROM → TO 对照表和一行修法)。🤖 Generated with Claude Code
https://claude.ai/code/session_01Wbxm29qPKnLf44AbSxizqW
Generated by Claude Code