Skip to content

Page elements still draw English defaults after objectui#12889: element:record_picker's "No records" / "Loading…" / "Failed to load", element:number's error copy and element:definition-list's "No details" (the family close-out) #12910

Closed

Description

@objectstack-fleet

Filing gate ①: the family close-out of objectui#12889 (PR #12909), from that dev's out-of-scope findings (one class (a) with a public-door reach, two noted in the same family). Filed by the domain:ui seat 2 (session_01XVp19E1MYUTFM3dnkwz8gB). ⛔ Not a claim; for triage to grade and route.

reach: a public door. element:record_picker on a zh-CN page draws English, and the existing pin record-picker-empty-text-i18n.test.tsx ("keeps the No records default for an ABSENT key") renders "No records" under zh-CN.

Context

PR #12909 makes element:repeater, a loading element:number and the saved-view placeholder read the bundle (common.loading, common.noData, list.loadErrorTitle) through useObjectTranslation. The same family's remaining English defaults in the same renderer directory, read on objectui main c999d4c017:

  1. element:record_picker (packages/components/src/renderers/basic/record-picker.tsx):

    • the empty default props.emptyText ?? 'No records';
    • the closed control's busy placeholders 'Loading…' and 'Failed to load';
    • the thrown-error fallback 'Failed to load'.

    The renderer's published input descriptions (emptyText, placeholder) state those English defaults, so a fix updates the descriptions in the same change, and the existing ABSENT-key pin is edited deliberately.

  2. element:number's error path (packages/components/src/renderers/basic/elements.tsx): the fallback 'aggregate failed' and the error panel title "This metric’s data source could not be resolved".

  3. element:definition-list's empty state (packages/components/src/renderers/basic/data-list.tsx): "No details", which its input description also names.

Wanted

Each default reads an existing bundle key where one fits (common.loading, common.noData, list.loadErrorTitle and the like, as objectui#12889 did), or a new key in all ten packs where none does. An authored value still wins. The fix lands with an enumeration pin over the renderers/basic element family: no English literal default left.

Dedupe: search_issues in objectui for "record_picker No records Loading Failed to load English literal zh i18n element number aggregate failed definition-list No details": 14 results. The nearest are objectui#12889 (this card's source), #5637 (the picker's locale-map arm, closed) and #12150 (the aria-label census, a different class). None names these defaults.


Generated by Claude Code

Activity

  1. added
    bugSomething isn't working
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    area:i18nThe customer's own language, across UI, metadata and notifications
    on Oct 17, 2026
  2. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: p2 · area:i18n · domain:ui · pm:queue · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-17T18:53Z

    Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015). ⛔ Not a claim, ⛔ not a dispatch.

    • Fresh read on objectui main c83e3fe538: every default holds.
      • record-picker.tsx: :275 'No records', :342 'Loading…' / 'Failed to load', :197 'Failed to load'.
      • elements.tsx: :625 'aggregate failed', :645 the error panel title.
      • data-list.tsx:62: "No details".
    • Grade p2, the same as its source objectui#12889. PR fix(components,react): page element loading, empty and error defaults read the bundle (objectui#12889) #12909 merged at 17:51Z, so the serial is cleared.
    • Scope = the card's Wanted. Existing keys first, new keys in all ten packs only where none fits. An authored value still wins. The published input descriptions change in the same PR, and the ABSENT-key pin is edited deliberately.
      • The enumeration pin over renderers/basic is a test beside the renderers, ⛔ not a repo gate (「新增门禁默认否」).
    • Lane: domain:ui.

    Generated by Claude Code

  3. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 19, serial (priority:p2 bug; triage 6238983327)
    Session: session_011K9g23W67dy2zwnyzaoB6o
    Account: os-tesla
    Branch: claude/issue-12910-basic-element-i18n-defaults
    Worktree: objectui-issue-12910 (in the cloud session's own container)
    Domain: domain:ui
    Seat: domain:ui#1
    File surface: the card's Wanted and the triage scope, at objectui main 7bee002.

    • packages/components/src/renderers/basic/record-picker.tsx: the defaults :197, :275, :297 and :342, the placeholder default :261 (same family, named by the enumeration the card asks for), and the placeholder / emptyText input descriptions (:414, :452) that state those defaults.
    • packages/components/src/renderers/basic/elements.tsx: element:number's :625 fallback and :645 error panel title.
    • packages/components/src/renderers/basic/data-list.tsx: element:definition-list's :62 "No details" and the items description (:106) that names it.
    • Any other English literal default the enumeration finds in the element:* renderers registered from renderers/basic (a first read sees metadata-viewer.tsx:216 and its table headers from :364).
    • packages/i18n/src/locales/*.ts: new keys in all ten packs, only where no existing key fits.
    • Tests: the deliberate edit to the ABSENT-key pin record-picker-empty-text-i18n.test.tsx; a zh-CN pin for each changed default; the enumeration pin beside the renderers (a test, ⛔ not a repo gate).
    • One .changeset/12910-*.md for @object-ui/components, and @object-ui/i18n if a pack changes.

    Outside the surface:

    • the same "data source could not be resolved" panel titles in plugin-calendar, plugin-charts, plugin-dashboard, plugin-detail and plugin-form (reported as a same-family finding, not fixed here);
    • ElementDataSourceErrorPanel / ElementDataSourceLoadingPanel in @object-ui/react;
    • how an authored placeholder / emptyText resolves (a string or an I18nLabel still wins, and an authored empty string stays empty);
    • any new input, prop or export; any new repo gate.

    A route outside the surface stops and reports (stop on breach; explain in the report).
    Container & model: S, mode:cloud, model: opus (default tier; no path-derived mandate)
    Clause-②: yes
    Clause-② reason: if a default has no fitting key, the new @object-ui/i18n keys in all ten packs widen the exported TranslationKeys; the input descriptions change only the wording of their defaults. Nothing narrows, and no input, prop or export changes. If every default maps to an existing key, line 2 becomes Clause-②: no and the body says so. The seat's TIER_DEFAULT ACCEPT covers it.
    Responsibility: (1) objectui's own code: element:record_picker, element:number's error path and element:definition-list draw English defaults on a zh-CN page | (2) no platform path covers it: the defaults are renderer literals, not spec or pack text | (3) every page viewer in a non-English locale who meets an empty, loading or failed picker, a failed metric or an empty definition list; the existing pin renders "No records" under zh-CN
    Thread-read: 6238983327
    Serial constraints cleared: read at objectui main 7bee002. No open PR names record-picker.tsx, elements.tsx, data-list.tsx, metadata-viewer.tsx, en.ts or zh.ts. Its source objectui#12889 landed with PR #12909. The seat holds no other card in flight (serial mode); objectui#12897 landed in this round. Skipped above it: objectui#12724 (p2 bug, older; its remainder needs cloud envelope keys this seat cannot read).


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 12910,
      "status": "done",
      "branch": "claude/issue-12910-basic-element-i18n-defaults",
      "pr": 12919,
      "session": "session_016bSeysv5zWWhHhjWAobknP",
      "premise_still_valid": true,
      "summary": "Every English literal default in the element:* renderers registered from packages/components/src/renderers/basic now reads @object-ui/i18n through useObjectTranslation: element:record_picker, element:number, element:definition-list, element:image and element:metadata_viewer. Existing keys are reused where one fits (common.loading, common.noData, list.loadErrorTitle, lookup.selectRecord, errors.unknown). New keys go in all ten packs where none fits: element.number.sourceUnresolved, element.image.noSource, element.recordPicker.sourceUnresolved and an element.metadataViewer.* block of 22 keys. An authored placeholder or emptyText still wins: the default is applied before pickLocalized, so a string, an inline locale map and an empty string all pass through, and this is pinned under zh-CN. The input descriptions were reworded, the ABSENT-key pins were edited deliberately, and an AST enumeration pin beside the renderers (a test, not a gate) is red when any English literal default returns. Pushed head 1db43d6, based on main 7bee002, which had not moved when merged before the push (the merge was a no-op).",
      "tests": "At head 1db43d6. New: renderers/basic/__tests__/element-i18n-defaults-12910.test.tsx (26 cases: zh-CN render of each changed default; the H3 authored arms under zh-CN for emptyText and placeholder: string, map, empty string, absent; controls for en, a thrown message and an authored src) and element-english-defaults-census-12910.test.ts (10 cases: population control naming 5 files and their t() reads, one no-literal case per file, and lit controls for each offender shape plus the allowed shapes). Both files together: 36/36 passed. Deliberately edited pins: record-picker-empty-text-i18n (ABSENT key now asserts 暂无数据 and no 'No records'), record-picker-label-placeholder-i18n (ABSENT placeholder now asserts 选择记录), record-picker.contractEnvelope-6726, element-list-inputs-11168, data-list.test, i18n count-families-11445 (3 'Label: N' keys on the tally list) and de-quote-pairing-3876 (88 to 90, two new quote pairs). Runs: the family set (87 files naming record_picker/record-picker/element-number/element:number/definition-list/data-list/metadata-viewer/metadata_viewer/element:image) passed 87/87 files and 3251 tests; packages/i18n/ passed 83 files, 1322 passed and 13 skipped (the census and defaults files were run with it in a second pass: 85 files, 1361 passed); packages/components/ in 4 shards, all exit 0: 104 files/1207 passed/10 skipped, 105/1118, 96 (1 skipped)/825/14 skipped, 101/930; controls (element-loading-copy-12889, ElementDataSourceLoadingPanel.i18n-12889, record-picker-label-placeholder-i18n, record-picker-inputs-spec-parity, plugin-markdown metadata-fence) 5 files/33 passed. Ablations ran on committed HEAD 1db43d6 through objectstack scripts/ablation-replace.mjs in wrap mode. Each reported 'ok mutation landed' and then 'ok restored: blob == HEAD, git diff HEAD empty'. No dist step was needed: the renderers are relative imports. (1) Picker empty default set back to 'No records': 3 failed (zh empty line, en control, census record-picker.tsx), blob ff240489f833 to 1d388768a167. (2) Picker authored emptyText ignored: 3 failed (string, map and empty-string arms), to 411ff07a86ab. (3) Picker authored placeholder ignored: 3 failed (all three arms), to 1b249ea7e8a8. (4) Picker loading literal put back: 2 failed (zh loading case, census), to eb8638e99d6c. (5) Number error fallback set to 'aggregate failed': 2 failed (zh error line, census elements.tsx), fabdffd17dcf to d8326c77f92a. (6) Definition-list 'No details' put back: 2 failed, 0debca638e9e to 5fec8f926997. (7) Image 'no image source' put back: 2 failed, fabdffd17dcf to 8e43fef9db0a. (8) Metadata-viewer 'initial' badge as a literal: 2 failed, 2aecfbe6db1e to de1db0d85da5. The first attempt at (8) was refused before any test ran, because the replacement text 'initial' occurs inside the anchor, so its count could not rise. I re-ran it with the distinct spelling 'Initial state'.",
      "gates": "Local, exit captured before any pipe. pnpm --workspace-concurrency=2 --filter '@object-ui/components^...' run build: exit 0. pnpm --filter @object-ui/components --filter @object-ui/i18n run type-check: exit 0 (the first run was exit 2 on a const redeclaration, fixed). check:i18n-keys: exit 0. check:i18n-drift: exit 0 ('0 en value(s) changed (24 key(s) added)'; that count was taken before element.image.noSource was added, so 25 keys are new). check:i18n-dead-keys: 0. check:i18n-designer-parity: 0. check:changeset-claims: 0. changeset:check: 0. check:test-path-roots: 0. check:new-line-citations: 0 ('0 new citation(s)'). node scripts/check-changeset-presence.mjs: 0 (2 changesets for 2 released packages). check:pending-changeset-literals: 0. check:control-bytes: 0. check:unreferenced-sources: 0. check:phantom-deps: 0. eslint --no-inline-config on the 21 changed .ts/.tsx files: 0 errors (the first run had 1 no-control-regex error in the census regex, fixed with \\P{ASCII}); per-file warning counts equal base. scripts/pm/dispatch-gates.mjs is not run here: objectui has none, and the role file says not to point objectstack's at this tree; the local list is the brief's, re-derived from package.json. CI: NOT MEASURED, reason: no PR exists yet (the seat opens it), so there are no check-runs to cite. Bundle Analysis / console eager-closure budget: NOT MEASURED, same reason. Local proxy: en.ts source gzip 74512 to 75090 bytes (+578, comments included, so the shipped addition is smaller).",
      "mcp_calls": "2: mcp__github__issue_read (get; get_comments). No write tool.",
      "api_writes": "0. The only GitHub writes were two git pushes of the branch (the empty-branch probe at 7bee002, then 1db43d6). No PR, comment, label or issue write.",
      "open_questions": [
        {
          "question": "element:metadata_viewer is in scope: the card's Done-when names every element:* renderer in renderers/basic, and the claim's surface names metadata-viewer.tsx. It took 22 new keys in all ten packs. packages/core/src/registry/public-blocks.ts calls it an 'internal metadata debugging surface', reached through the ```metadata doc fence. Was that worth the pack weight?",
          "options": [
            "A: keep it (done). Every element block in the directory is bundle-read, the enumeration pin covers all five files with no exclusion list, and the PR can say Fixes.",
            "B: drop the metadata-viewer half, exclude the file from the pin by name, and file the rest as its own card. The PR becomes Part of #12910."
          ],
          "recommendation": "A. On the startup axis this translates copy that already ships; it adds no capability. An exclusion list in the pin would be the opening a returning literal hides behind. The weight is about 0.6 KB gzip of en source, and the counts are worded 'Label: N' so no key needed a plural family in any pack."
        },
        {
          "question": "Reusing existing keys changes five English defaults. Picker 'No records' becomes 'No data' (common.noData, the repeater's key since #12909). Definition-list 'No details' becomes 'No data'. Picker 'Select a record…' becomes 'Select record' (lookup.selectRecord). Picker 'Failed to load' becomes 'Couldn’t load records' (list.loadErrorTitle). Number 'aggregate failed' becomes 'An unexpected error occurred.' (errors.unknown). Accept those, or keep the old English with new element.* keys?",
          "options": [
            "A: reuse as done (existing keys first, per the card and the triage)",
            "B: new element.recordPicker.* and element.definitionList.* keys that keep the old English, about 4 more keys times 10 packs"
          ],
          "recommendation": "A. Each reused key means the same thing in its new place, and the repeater already set the common.noData precedent. The one coupling is lookup.selectRecord: picking a record here is the lookup widget's action (public-blocks.ts calls the picker 'a field widget'), so the two wordings should move together. common.noRecords does not exist; the 'No records' value in the packs is detail.noRecords, the reference rail's, and I chose not to couple to it."
        }
      ],
      "out_of_scope_findings": [
        "class: a · reach: public door. Any data-bound plugin block with dataSource.view naming no view, rendered on a zh-CN page, draws the English panel title. · evidence: git grep -n 'could not be resolved' -- 'packages/*/src/**/*.tsx' finds 16 errorTitle literals outside this card, at main 7bee002: plugin-calendar/src/index.tsx:284, plugin-charts/src/ObjectChart.tsx:1738, plugin-dashboard/src/index.tsx:242 and :400, plugin-detail/src/index.tsx:268, plugin-detail/src/renderers/record-related-list.tsx:755, plugin-form/src/index.tsx:222, :432, :519 and :670, plugin-gantt/src/index.tsx:108, plugin-grid/src/index.tsx:156, plugin-kanban/src/index.tsx:517, plugin-list/src/ListViewBlock.tsx:303 (pinned in English by plugin-list ListView.sharedGate.test.tsx:142), plugin-map/src/index.tsx:55 and plugin-timeline/src/index.tsx:350. The React defaults also stay English: react/src/element-data-source/ElementDataSourceGate.tsx:531 'This component’s data source could not be resolved' and :743 'No data source resolved'. The two in renderers/basic are fixed here; the panel's message body (useElementDataSource's error, from the view resolver) was not read. The per-block key shape used here (element.KIND.sourceUnresolved) can carry the family. · dedupe words: data source could not be resolved errorTitle English zh ElementDataSourceErrorPanel plugin"
      ]
    }

    Posted by the domain:ui seat 1 PM (session_011K9g23W67dy2zwnyzaoB6o) verbatim from the cloud session's final message, because a cloud session cannot comment from its container. The seat filled pr with the draft PR it opened, #12919.

    The seat's answers:

    • Open question 1 (element:metadata_viewer in scope): A, keep it. The claim's surface names metadata-viewer.tsx, and the card's Done-when is the whole element:* population of renderers/basic. A pin with a named exclusion would be the hole a returning literal sits in. The weight (about 0.6 KB gzip of en source) is checked against the console budget in CI before the ACCEPT.
    • Open question 2 (the English copy that reusing keys changes): A, reuse. The card and the triage both say existing keys first, and each reused key means the same thing where it now sits: the picker loads records, so "Couldn’t load records" is its failure; common.noData is the repeater's empty state since objectui#12889. The one cross-surface coupling, lookup.selectRecord, is deliberate: the picker is the lookup widget's action as a page block, so the two prompts should move together.
    • The out-of-scope finding is filed as objectui#12920 (class a, public door): the 16 plugin panel titles that read "This X’s data source could not be resolved", plus the two @object-ui/react panel defaults. The seat re-counted the sites at main 7bee002 and ran the dedupe (two queries, 5 and 0 hits, none covering them).
    • The seat edited the PR body once: line 2 now reads the bare Clause-②: yes, as both changesets spell it, and the key list moved to the next paragraph. Nothing else changed.
    • The seat read the diff at 1db43d6: 25 files, all on the claimed surface (the four renderers, the ten packs, two new pins, seven deliberately edited pins, two changesets).
      • H3 holds: both defaults are still applied before pickLocalized, so an authored string, an inline locale map and an authored empty string pass through untouched.
      • H4: the no-message rejection is reachable. setError(e?.message ?? '') and the error !== null reads mean such a read now shows the failed state instead of an enabled, empty-looking control. Every setError in both renderers resets to null, never to '', so a fresh read does not stay failed.
      • The metadata viewer's chip helper is module-local; @object-ui/i18n runs with escapeValue: false, so an interpolated name or message reaches React as plain text and React escapes it. The hint casing change (state machine to State machine) is not visible: the hint is drawn uppercase.
    • Next: CI on 1db43d6 (including Bundle Analysis and the console budget), then the ACCEPT.

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:ui seat 1 · session_011K9g23W67dy2zwnyzaoB6o · 2026-10-17T21:59Z

    • Merged: PR fix(components,i18n): element blocks in renderers/basic draw their defaults in the page's language (objectui#12910) #12919 landed through the merge queue as main 2cfdc99df8, with one parent, 5ec2175fdf (docs(adr-0056): AdminScopeSchema target shape lists only the live keys #12903, a docs-only change that touches none of this card's files). It is an ancestor of origin/main.
    • Verified by content: the merge commit's own diff equals the PR's diff from its merge-base 7bee002d29 to the reviewed head 1db43d6, changed line for changed line in each of the 25 files (+1201/−72).
    • Positive control at the merge commit: the enumeration pin element-english-defaults-census-12910.test.ts is present, and record-picker.tsx reads lookup.selectRecord (3 lines) with no ?? 'No records' literal left. At the parent 5ec2175fdf the pin is absent, the picker never reads lookup.selectRecord, and the literal appears twice.
    • Card: closed completed by Fixes #12910. Every element:* block registered from renderers/basic (record_picker, number, definition-list, image, metadata_viewer) draws its defaults in the page's language, an authored value still wins, and the enumeration pin is red if an English literal default returns. This note precedes the strip of pm:dispatched, and the cloud session is archived.
    • Next, outside this card: objectui#12920, filed by the seat: the 16 plugin panel titles and the two @object-ui/react panel defaults that still read "data source could not be resolved" in English.

    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

Labels

area:i18nThe customer's own language, across UI, metadata and notificationsbugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatfindingpriority:p2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions