fix(showcase): 注册 ContactViews —— 文档引用的「create form ≠ edit form」参考实现终于真的进栈 (#5420) - #5438
Merged
baozhoutao merged 1 commit intoAug 5, 2026
Merged
Conversation
`src/ui/views/contact.view.ts` declares the whole "create form != edit form"
reference implementation — a default grouped `form` with four named sections,
a sparse `formViews.create`, and the list's
`addRecord: { mode: 'form', formView: 'create' }` binding — and
`src/ui/views/index.ts` exports it. `objectstack.config.ts` named the other
four containers on line 23 and line 196 and never named this one.
There is no directory scan behind `views:`; the CLI reads exactly that array.
So the metadata compiled, type-checked and linted clean while reaching
nothing: `nav_contacts` rendered a derived default form instead of the
authored one, `addRecord.formView` never bound, and no static pass
(`os validate` / `os lint` / `os i18n extract` / the coverage ratchet) could
see it either — which is also why #5405's new `i18n/missing-section` gate
found 10 headings in the showcase and zero of them under `showcase_contact`.
`content/docs/ui/create-vs-edit-form.mdx` cites this file as the live
reference implementation the whole time.
Registration makes exactly five zh-CN coverage keys newly reachable, measured
on the real config rather than predicted:
os lint examples/app-showcase/objectstack.config.ts
483 warnings (before) -> 488 (registered, untranslated) -> 484 (translated)
+ i18n/missing-view objects.showcase_contact._views.list.label
+ i18n/missing-section objects.showcase_contact._sections.{contact,work,status,notes}.label
All five are translated in this commit, following PR #5416's rework: zh-CN
takes its words from the vocabulary this bundle already uses, and `en` gains
nothing (the default locale is satisfied by the inline labels; echoing the
source string only fakes coverage). The ratchet baseline
`scripts/i18n-coverage-baseline.json` and `i18n.supportedLocales` are
untouched — `check-i18n-coverage: OK (12 config(s), 660 baselined
untranslated string(s), none new)`, showcase back to exactly 451.
Two guards in `test/seed.test.ts`:
* every container the barrel exports reaches `stack.views`, matched by
target object (`defineStack` parses the config, so a registered container
is a structural copy and never `===` the export). Reverting the config
hunk fails it naming `ContactViews`.
* the four section names and their zh-CN `_sections` keys are asserted as
set EQUALITY, because the two i18n gates read that set in opposite
directions — `i18n/missing-section` fails on a declared section with no
entry, `translation-target-unknown` on an entry no section declares.
With #5422 on main this is the first time the relationship is testable on
the real config: the four correctly-translated sections are NOT reported
as orphans.
The remaining `translation-target-unknown` on `_views.list` is #5164's
open contradiction between the three `_views` producers, not new here — the
showcase already carried four identical instances (project / task / inquiry /
business_unit) before this change.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016FNvXhtSdnEGEfLEsMmvxh
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
This was referenced Aug 5, 2026
baozhoutao
marked this pull request as ready for review
August 5, 2026 11:57
baozhoutao
deleted the
claude/issue-5420-showcase-register-contact-views
branch
August 5, 2026 12:05
This was referenced Aug 5, 2026
This was referenced Aug 5, 2026
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.
Fixes #5420
前提复核(先证伪,再实现)
在
origin/main123067ce7(即 #5416 / #5422 合并之后)上实证,issue 的前提仍然成立 —— #5416 与 #5422 都没有做注册:barrel
src/ui/views/index.ts导出 5 个容器,config 的具名 import 只取了 4 个。views:背后没有目录扫描,CLI 读的就是这个数组,所以这份元数据编译通过、类型通过、lint 干净,却既进不了运行栈,也进不了任何静态门:nav_contacts渲染的是派生默认表单而不是作者写的那份,addRecord.formView: 'create'从未绑定,而content/docs/ui/create-vs-edit-form.mdx一直把这个文件当作活的参考实现引用。这也解释了 #5405 的i18n/missing-section为什么在 showcase 上采到 10 条却没有一条属于showcase_contact。改了什么
examples/app-showcase/objectstack.config.ts—— 第 23 行 import + 第 196 行views:各补一个ContactViews。examples/app-showcase/src/system/translations/index.ts—— 为注册后新可见的 5 个 zh-CN 覆盖键补译文。examples/app-showcase/test/seed.test.ts—— 两条 pin(见下)。⛔ 未动
packages/**,未动棘轮基线scripts/i18n-coverage-baseline.json,未缩supportedLocales。新增键是实测的,不是预测的
注册引入的 5 条,逐条 diff 出来的:
formViews.create的那个段落没有name,按渲染器的约定天生不可翻译,所以不在集合内 —— 这不是遗漏。译文体例对齐 PR #5416 的返工 commit
e3d1e855c:zh-CN 从本 bundle 既有词汇表取词(状态/备注就是它自己stage族与notes的用词),en不加条目(默认语言由内联 label 满足,复述源串只会伪造覆盖率)。两处需要解释的取词写在代码注释里:contact取「联系方式」而不是在联系人记录里再套一个循环的「联系人」;_views.list的源串是光秃秃的 "Contacts",所以用对象自己的pluralLabel,而 task/project 列表的「全部…」属于那些真的写了 "All …" 的 label。两条 pin
test/seed.test.ts:registers every view container the barrel exports—— 按目标对象比对,不是按对象标识:defineStack会 parse config,stack.views[i]是结构副本,永远不===导出的容器(第一版按标识写的,五个全红,已改)。容器本身按 spec 无顶层name,隐式以list/form绑定的对象为键,与 objectql 的resolveMetadataItemName和 i18n walker 同一套推导。keys the contact form sections to exactly what the container declares—— 断言集合相等,因为两个 i18n 门是反向读同一个集合的:i18n/missing-section(cli: the i18n coverage walker never collectsobjects.<o>._sections— a bundle can ship every section heading in English and lint zero warnings #5405)红在「声明了没译文」,translation-target-unknown(lint:translation-target-unknownmisses a view container's DEFAULTform.sections— correctly translating a rendered heading is reported as a stale key #5415/fix(lint):translation-target-unknown读取视图容器的默认form.sections(#5415) #5422)红在「有译文没声明」。只查一个方向的测试会在另一个方向坏掉时保持绿。fix(lint):translation-target-unknown读取视图容器的默认form.sections(#5415) #5422 落地后这个集合关系第一次在真实 config 上可测,实测结论:四个正确翻译的段落没有被translation-target-unknown误报。反向验证(方向是事先预判的:红)
把 config 那一处 hunk stash 掉重跑,两条 pin 按预期变红,且第一条精确点名:
只点名
ContactViews、不误伤其余四个,说明按目标对象比对的那版 helper 是对的。验证
仓库级
check:i18n-coverage是先turbo run build再跑的(门 shell 到构建产物)—— #5416 用一次 CI 红换来的教训,这次没有重付。已知遗留:
_views.list上那条translation-target-unknown补
_views.list译文之后,translation-target-unknown多出一条 —— 但这不是本 PR 引入的新类:showcase_project/showcase_task/showcase_inquiry/showcase_business_unit在 main 上已经各有一条一模一样的。根因是 #5164 记录的那件事:i18n 覆盖 walker 把容器默认列表按primary.name || 'list'推导出_views.list.label并要求它,而引用校验器认为没有任何视图叫list—— 同一次os lint里两条规则互相打架。validate-translation-references.ts的注释也明写了这归 #5164。本 PR 只能二选一,选了不让覆盖率棘轮变红的那一边,并把第 5 个实例作为数据点评论回 #5164。Generated by Claude Code