validate-translation-references derives an object's legal _sections names from three anchors (packages/lint/src/validate-translation-references.ts):
fieldGroups[].key (line 346-349),
- named sections on
listViews / formViews sub-views (line 234-255),
- named
record:details sections on pages (line 358-368),
- plus the view's OWN
sections (line 257-262).
collectViewRecord iterates for (const key of ['listViews', 'formViews']). The view CONTAINER's default form is not in that list, and it is not the view's own sections either — so view.form.sections[].name contributes nothing to the fact set, even though ObjectForm renders that form and translates its headings through the very same sectionLabel(object, section.name, ...) convention.
Repro against in-repo metadata
examples/app-showcase/src/ui/views/contact.view.ts declares the default form with four named sections (contact, work, status, notes) bound to showcase_contact. A bundle that correctly translates one of them:
translations: [{ 'zh-CN': { objects: { showcase_contact: { _sections: { contact: { label: '联系方式' } } } } } }]
validateTranslationReferences(stack) returns:
rule: translation-target-unknown
severity: warning
where: locale "zh-CN" · object "showcase_contact" · section "contact"
message: Translations are keyed to section "contact", which nothing on object
"showcase_contact" declares — no `fieldGroups[].key`, no named form-view
section, no named `record:details` section. The section heading stays in
the source locale.
hint: ... Object "showcase_contact" declares no named section at all.
Both the message and the hint are false: the object declares four named sections and the heading DOES resolve at render time. The advice the finding gives ("give the section a name and use it here, or drop the translation") points the author at deleting a translation that works.
Why it matters more now
PR for #5405 adds a section kind to the CLI i18n walker, and its second source is exactly this surface — the container default form, formViews.*, and page record:details. So after #5405, os i18n extract scaffolds objects.showcase_contact._sections.contact.label, and os lint immediately reports the key it just scaffolded as an unknown target. The two rules will contradict each other on real showcase metadata.
The #5405 walker deliberately covers view.form.sections because that is what the renderer reads; this issue is the reference validator catching up on the same anchor. The set relationship the two should hold is: every key the coverage walker DEMANDS must be a key the reference validator ACCEPTS.
Suggested fix
In collectViewRecord, feed the container's default form through the same section-name collection as formViews.* entries, binding it via bindingOf(view.form) ?? listBinding (mirroring how viewObjectName in the CLI walker resolves view.form.data.object). Worth a fixture pinning the showcase ContactViews shape so the anchor list cannot silently lose an entry again.
Found while implementing #5405 (out of scope there: packages/lint, and #5405 is CLI-walker scoped). Related: #5164 (the _views spelling disagreement — the same producer-drift family on the neighbouring key group).
Code references pinned to b4872a868.
validate-translation-referencesderives an object's legal_sectionsnames from three anchors (packages/lint/src/validate-translation-references.ts):fieldGroups[].key(line 346-349),listViews/formViewssub-views (line 234-255),record:detailssections on pages (line 358-368),sections(line 257-262).collectViewRecorditeratesfor (const key of ['listViews', 'formViews']). The view CONTAINER's defaultformis not in that list, and it is not the view's ownsectionseither — soview.form.sections[].namecontributes nothing to the fact set, even thoughObjectFormrenders that form and translates its headings through the very samesectionLabel(object, section.name, ...)convention.Repro against in-repo metadata
examples/app-showcase/src/ui/views/contact.view.tsdeclares the default form with four named sections (contact,work,status,notes) bound toshowcase_contact. A bundle that correctly translates one of them:validateTranslationReferences(stack)returns:Both the message and the hint are false: the object declares four named sections and the heading DOES resolve at render time. The advice the finding gives ("give the section a
nameand use it here, or drop the translation") points the author at deleting a translation that works.Why it matters more now
PR for #5405 adds a
sectionkind to the CLI i18n walker, and its second source is exactly this surface — the container defaultform,formViews.*, and pagerecord:details. So after #5405,os i18n extractscaffoldsobjects.showcase_contact._sections.contact.label, andos lintimmediately reports the key it just scaffolded as an unknown target. The two rules will contradict each other on real showcase metadata.The #5405 walker deliberately covers
view.form.sectionsbecause that is what the renderer reads; this issue is the reference validator catching up on the same anchor. The set relationship the two should hold is: every key the coverage walker DEMANDS must be a key the reference validator ACCEPTS.Suggested fix
In
collectViewRecord, feed the container's defaultformthrough the same section-name collection asformViews.*entries, binding it viabindingOf(view.form) ?? listBinding(mirroring howviewObjectNamein the CLI walker resolvesview.form.data.object). Worth a fixture pinning the showcaseContactViewsshape so the anchor list cannot silently lose an entry again.Found while implementing #5405 (out of scope there:
packages/lint, and #5405 is CLI-walker scoped). Related: #5164 (the_viewsspelling disagreement — the same producer-drift family on the neighbouring key group).Code references pinned to
b4872a868.