Skip to content

finding(spec/objectql): injected system-column labels are hard-coded English, so every non-English tenant sees "Organization" / "Created By" on every business object #14972

Description

@baozhoutao

Seam card filed from cloud#1904 (repo:cloud lane). That card fixed the consumer half — the AI-Studio build linter no longer reports these labels to the user, because the user cannot act on them. This card is the producer half: the labels really are unlocalised, measured on the tree, and only this repo can fix it.

Measured

packages/spec/src/data/injected-system-column-provenance.ts hard-codes an English label on every injected column, with no locale plumbing of any kind:

  • AUDIT_FIELD_DEFSCreated At, Created By, Last Modified At, Last Modified By
  • TENANT_SCOPE_FIELD_DEFOrganization
  • OWNER_FIELD_DEFOwner
  • OWNING_BUSINESS_UNIT_FIELD_DEF — same shape (currently hidden: true, so not user-visible yet)

applySystemFields (packages/objectql/src/registry.ts) spreads those definitions verbatim onto every eligible object, and the /meta read exits merge them in via applyInjectedSystemColumns. So a tenant whose app is authored entirely in zh-CN gets a field list that reads 名称 / 阶段 / 金额 / Organization / Created By / Owner on every business object — in list views, detail layouts, filter pickers and lookup chips.

Observed downstream (cloud#1904)

On the 2026-09-03 zh-CN rig this was visible enough that the AI build agent surfaced it to the end user every single round, asking them to decide whether to translate fields they had never declared. The cloud side is fixed; the English labels themselves are still shipped.

Why this is not a one-line label swap — the constraint that makes it a spec decision

applySystemFields' own comment blocks the obvious fix:

the definitions must stay byte-identical to the shipped tables, because the #7859 Layer-0 guard and the #4326 round-trip strip both read them by exact identity. Do not add keys here; consumers ask the API.

So localisation cannot be done by mutating the definitions in place, and it cannot be done by adding a key to them either. It needs a deliberate answer to "where does a system column's display name come from, and who resolves it against the tenant locale" — a presentation-layer resolution at the read exit, an i18n key alongside the identity-stable definition, or an explicit ruling that these stay English. That is a packages/spec seat call, which is why this is filed rather than fixed.

Dedupe

Searched before filing. The nearby i18n cards do not cover the injected column definitions, and all are closed:

Related epic: cloud#1841 (its objectstack sub-cards are tracked as links, hence a standalone card here rather than a sub-issue).

Filed unassigned, no priority label — grading is the triage seat's call.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions