Skip to content

cli: the i18n coverage walker never collects objects.<o>._sections — a bundle can ship every section heading in English and lint zero warnings #5405

Closed

Description

@yinlianghui

objectstack lint's i18n coverage is driven by a shared walker whose kind union
simply has no entry for an app object's _sections:

  • packages/cli/src/utils/i18n-extract.ts:93-108 — ExpectedEntry['source'] is
    object | field | option | view | action | globalAction | app | navigation | dashboard | widget | page | metadataType | metadataFormSection | metadataFormField. The two metadataForm* kinds cover Studio metadata
    forms
    (metadataForms.<type>.sections.*, hidden behind
    --include-platform), not app objects.
  • The walker never emits an objects.<o>._sections.* path: the string
    '_sections' does not occur in i18n-extract.ts, and nothing walks
    fieldGroups or a field's group.
  • packages/cli/src/utils/i18n-coverage.ts:190-204 (COVERAGE_SOURCE) mirrors
    the same union, so computeI18nCoverage structurally cannot report a missing
    section heading.

Yet the surface is real and supported end-to-end everywhere else:
ObjectTranslationDataSchema declares _sections
(packages/spec/src/system/translation.zod.ts), the resolver applies them
(record detail pages render translated headings), and os i18n extract will
never scaffold them either — same walker.

Code references pinned to main @ 98369a8.

Measured impact (HotCRM, four locales)

HotCRM's metadata declares 85 sections across 15 objects (union of field
groups and page/view sections[].name). Before objectstack-ai/hotcrm#697,
ja-JP and es-ES each carried 2 of 85 — English headings on essentially
every record page and form — while objectstack lint reported 0 i18n
warnings
for both. The gap also kept growing invisibly: objects added later
(crm_event, crm_event_attendee) shipped with headings untranslated in every
locale, and nothing flagged it. Downstream had to build its own guard
(hotcrm#697) deriving the expected set from metadata.

Suggested fix shape

Add a section kind to the walker: emit
objects.<o>._sections.<key>.label for (a) every distinct group across an
object's fields — the fields are the authority for which sections exist;
fieldGroups[].label supplies the default-locale text — and (b) every
sections[].name under the object's pages/form views. Both sources are needed;
detail pages nest sections inside page:tabs → components → properties.sections, which a shallow walk misses. COVERAGE_SOURCE then maps
it, giving lint an i18n/missing-section category and the extractor the
scaffold for free (they share the walker — that co-derivation is the point of
collectExpectedEntries).

Related: #5164 (the _views key-spelling disagreement between composer,
extractor and lint — adjacent producer-drift problem on the neighbouring group).
Downstream: objectstack-ai/hotcrm#683 (part 2).

Activity

  1. self-assigned this
    on Aug 5, 2026
  2. baozhoutao commented on Aug 5, 2026

    @baozhoutao
    Contributor

    分诊(cli 车道 PM,session_016FNvXhtSdnEGEfLEsMmvxh,2026-08-05):入队 pm:queue 并即时派发。判级:auto-queue 类 —— 具名位置(walker kind union 缺 section)+ 实测影响(HotCRM 85 section 仅 2 有译文而 lint 零告警)+ 修法草图齐备,属「声明即强制」恢复不变量类(spec 声明 _sections、resolver 消费,唯独覆盖面结构性缺位)。查重仅相邻 #5377(spec 车道,tab label)与 #5164(_views 拼写,已留串行备忘),无重复。walker 两文件自 674ac99 后无 churn,前提引用(98369a8)仍有效。维护者可否决。

    认领:PM 循环第 2 轮(cli 车道)
    会话:session_016FNvXhtSdnEGEfLEsMmvxh
    分支:claude/issue-5405-i18n-walker-sections
    Worktree:objectstack-issue-5405
    域:domain:cli
    文件面:packages/cli/src/utils/i18n-extract.ts、packages/cli/src/utils/i18n-coverage.ts + packages/cli 对应测试(与在飞 #5412 commands/doctor.ts 不相交)

    执行口径:按 issue 修法草图 —— walker 增 section kind,双源取齐(字段 group 的去重集为准 + pages/form views 的 sections[].name,注意 detail page 的深嵌套 page:tabs → components → properties.sections);COVERAGE_SOURCE 映射之,lint 得 i18n/missing-section 类别,extractor 骨架随共享 walker 免费获得。⛔ 不动 _views 族(#5164 领地,截断待修复)。


    Generated by Claude Code

  3. baozhoutao commented on Aug 5, 2026

    @baozhoutao
    Contributor

    验收(cli 车道 PM,session_016FNvXhtSdnEGEfLEsMmvxh):ACCEPT → PR #5416。

    下一步:CI 全绿后转 ready 入合并队列,跟到 MERGED。


    Generated by Claude Code

  4. baozhoutao commented on Aug 5, 2026

    @baozhoutao
    Contributor

    REWORK 第 1 轮(cli 车道 PM,session_016FNvXhtSdnEGEfLEsMmvxh,2026-08-05 10:5xZ):PR #5416 CI 一处红 —— check:i18n-coverage 棘轮(showcase 未翻译声明串 451 → 461)。非缺陷,是本功能的正确后果:walker 新采出的 showcase _sections key 在其声明支持的 locale 语言包里没有译文,repo 级门当场逮住(dev 本地只跑了包级 typecheck,覆盖不到该门)。已按同一认领返工原 dev:脚手架 + 按 showcase 既有体例翻译新 key,⛔ 不动棘轮基线、不缩 supportedLocales;pnpm check:i18n-coverage 回到 ≤451 后追加 commit(auto-merge 已挂,绿即自动入队)。文件面追加 examples/app-showcase/** 翻译 bundle,PM 批准记录在案。


    Generated by Claude Code

  5. baozhoutao commented on Aug 5, 2026

    @baozhoutao
    Contributor

    REWORK 第 1 轮闭环(cli 车道 PM,session_016FNvXhtSdnEGEfLEsMmvxh):修复 commit e3d1e855c 已推同分支,验收通过。

    CI 绿后 auto-merge 自动入队,跟到 MERGED。


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions