Skip to content

lint: a form section with a label but no name can never be translated and nothing warns — 70/70 HotCRM form sections are in that state #5417

Description

@yinlianghui

A form section authored with a label but no name is structurally
untranslatable — _sections is keyed by section name, so there is no key for a
bundle to carry. Nothing in the toolchain says so: not the schema (name is
optional), not os lint, and — after #5405 — not the coverage report either,
because a walker that emits sections[].name emits nothing for a section that
has no name. The heading silently stays in the source locale in every locale,
and coverage reads 100%.

The renderer keys off name, and correctly so

objectui resolves form section headings through the same resolver the detail
page uses, useObjectLabel().sectionLabel(objectName, section.name, authored):

  • packages/plugin-form/src/ObjectForm.tsx:165-167 (tSec, feeding all five
    form-type branches) and :966-968 (stacked section divider)
  • packages/plugin-form/src/ModalForm.tsx:588, :684
  • detail half: packages/plugin-detail/src/renderers/record-details.tsx:199

All of them guard on section.name and fall back to the authored label when it
is absent. That guard is right — the alternative (slugify the label and go
fishing for a second key) would fossilize a second de-facto contract. The defect
is that authoring a nameless section is silently accepted while being
permanently unreachable by translation.

Why #5405 and #5415 do not cover this

Both operate on sections that HAVE names:

The set relationship #5415 states ("every key the coverage walker DEMANDS must
be a key the reference validator ACCEPTS") is about keys that exist. This issue
is the third leg: a rendered heading that no key can ever address.

Measured impact (HotCRM @ 0899b4f)

Every form-view section in the app — 70 of 70, across all 14 view files
is authored with label (+ columns/fields) and no name:

account 5/5   campaign 3/3   case 4/4      contact 3/3   contract 4/4
event 4/4     event_attendee 2/2           forecast 3/3  knowledge_article 3/3
lead 25/25    opportunity 4/4              product 3/3   quote 4/4   task 3/3
TOTAL: 70 sections, 0 named, 70 nameless

So after objectstack-ai/hotcrm#697 brought all four locales to full declared
coverage, and after #5405 lands, HotCRM's form section headings will still be
English in all four locales with zero warnings — the gap is invisible to
every gate we are currently building.

This is also the actual cause of #5408, which was filed as a renderer bug: the
crm_case detail page sections carry names (info/status/description
in src/pages/case_detail.page.ts) and translate, while its form view
sections ({ label: 'Case' }, { label: 'SLA' }, { label: 'Resolution' } in
src/views/case.view.ts) carry none — producing exactly the reported
Case / SLA / Resolution strip. The renderer half was verified correct against
objectui origin/main and is now pinned by objectstack-ai/objectui#3373.

Suggested fix shape

A diagnostic at the producer, not tolerance at the consumer. Two candidates,
not mutually exclusive:

  1. Lint rule (packages/lint, alongside validate-translation-references):
    a section that declares a label but no name, on an object that has any
    translations at all, warns — "this heading can never be translated; give the
    section a stable name". Cheap, non-breaking, and it is the rule that would
    have caught all 70.
  2. Schema (packages/spec): consider requiring name on FormSection
    outright. Stronger (declared = enforced, and it makes AI-authored metadata
    hard to get wrong), but it is a breaking authoring change and needs the
    usual migration — worth a maintainer decision rather than a drive-by.

Whichever route, the co-derivation point from #5405 holds: the set of headings
the renderer displays should equal the set of headings the toolchain can
address.

Blocked-by: #5405 (the walker's section-awareness is the natural place for the
name-set to come from; this rule reads the same anchors).

Found while verifying #5408 (whose stated renderer premise was disproven — see
objectstack-ai/objectui#3373). Related: #5415, #5164.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions