Skip to content

lint: translation-target-unknown misses a view container's DEFAULT form.sections — correctly translating a rendered heading is reported as a stale key #5415

Description

@baozhoutao

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.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions