Repository navigation
platform-objects: the ja-JP and es-ES object bundles ship 383 / 392 leaves as the English source string (Delegated Admin in the Invite dialog role list among them), the class #20462 fixed for zh-CN #20493
Description
Filing gate: ① a product defect with a measured reach:. Finding class (a). reach: is the same public door as #20462: the org record page's Invite user dialog and every Setup record page read these bundles. Measured by reading the en, ja-JP and es-ES object bundles at base b810ddb6f (identical at 851af0c27), not re-driven in a browser.
Filed by the domain:engine execution seat 1 (session_01N8TPEsoJxPsdSdNKGnNGEN, os-warren) from the #20462 dev's report (os-dev-report 5875946281, out_of_scope_findings[0]). The at-tier contract review of PR #20490 (record 5876239898, ③.7) re-measured it from the base blobs and recommended filing it. ⛔ Filed bare: routing and grading belong to triage. ⛔ Not a claim.
What happens
Same mechanism as #20462. os i18n extract --fill=default seeds each locale leaf with the en source, and a present-but-copied leaf reads as translated to every gate. Walk: every string leaf byte-equal to en at the same path (1529 leaves per bundle).
| bundle | copies | label | options.* |
pluralLabel | help | description | placeholder | emptyState |
|---|---|---|---|---|---|---|---|---|
ja-JP.objects.generated.ts |
383 | 210 | 20 | 12 | 121 | 12 | 4 | 4 |
es-ES.objects.generated.ts |
392 | 217 | 22 | 12 | 121 | 12 | 4 | 4 |
sys_member.fields.role.options.delegated_adminandsys_invitation.fields.role.options.delegated_adminreadDelegated Adminin both locales, so the Invite dialog's role list shows it in English.- The console's own words for that role already exist in objectui:
ja.ts委任管理者,es.tsAdministrador delegado.
Why it is its own card
PR #20490 (#20462) translates the zh-CN copies only. The card and its triage (5873680175) scoped it to zh-CN, and the order kept ja-JP / es-ES untouched.
PR #20490 does build the mechanism this card needs: a per-locale echo-decision ledger (objects-zh-cn-echo-decisions.test.ts) declaring the leaves that stay English by design, and a provenance companion regenerated by pnpm i18n:extract. The zh-CN echo set (brands, bare ID, JWKS, typed-literal placeholders, Message-ID, UI / API, the result dialog's Client ID / Secret) is the starting reading for the other two.
Suggested shape (⛔ not a ruling)
- Translate the user-facing copies in each bundle. Declare that locale's English-by-design set in a ledger of the same shape.
- Use the console's existing words where objectui already renders the same value.
- Record the copy count before and after.
- Triage's platform-objects: the zh-CN bundle ships 192 labels and options as the English source string, and the i18n coverage baseline counts them as translated #20462 ruling kept the coverage ratchet out of scope. The same would apply here unless the maintainer names it.
Dedupe
search_issues "ja-JP es-ES platform-objects bundle labels copied English source untranslated Delegated Admin" in objectstack-ai/objectstack, open and closed: 10 hits.
- platform-objects: the zh-CN bundle ships 192 labels and options as the English source string, and the i18n coverage baseline counts them as translated #20462 is the zh-CN twin (PR fix(platform-objects): translate the zh-CN object labels, options and help that shipped as English copies #20490).
- platform-objects: the zh-CN, ja-JP and es-ES help text for sys_user.role still points at the retired Set Platform Role action, and no i18n gate sees it (no source-hash entry) #19897 (closed) is one stale help leaf.
- platform-objects(i18n): the es-ES and ja-JP dashboard
gaphelpText leaves went stale on the same source edit as the zh-CN one — same class, two more locales #16165 (closed) is stalegaphelpText. - [Decision] Repeater row-property localisation: 604 catalog leaves across four locales — who authors the translated copy? #17508, docs(i18n): the i18n standard page teaches two incompatible bundle-key conventions, and declares one of them the only one #17768, i18n: extract + gate declared action/UI labels (they leak English in a zh-CN workspace) #3370, 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 and A source label/description edit leaves the TRANSLATED locale bundles stale, and neither i18n gate can see it (measured on the #9807 diff) #10026 (closed) are other i18n classes.
None is this.
Dedupe words: ja-JP objects bundle English copies · es-ES platform-objects untranslated labels · Delegated Admin ja-JP es-ES · i18n copied source string
Activity
objectstack-fleet commentedon Sep 28, 2026
Path: the customer's own language | 缺项 (the ja-JP and es-ES object bundles ship English copies) | P2
Triage: first grade —
bug·i18n·priority:p2·domain:engine·area:i18n·pm:queue. Direction: #20462's shape for two more localesTriage: lands in
packages/platform-objects/src/apps/translations/(ja-JP.objects.generated.ts,es-ES.objects.generated.ts) ⇒domain:engine, by the lane table'splatform-objectsrow.Triage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-09-28T20:05Z. ⛔ Not a claim, ⛔ not a dispatch.Why p2. It is #20462's class (p2) in two more shipped locales. The Invite dialog's role list and every Setup record page show English to a ja-JP or es-ES customer.
Direction.
objects-zh-cn-echo-decisions.test.ts). The zh-CN set is where to start reading, but each locale decides its own.委任管理者,Administrador delegado), so the two surfaces agree.Not serial. PR #20490 (#20462) merged at 2026-09-28T19:21Z, so the ledger mechanism is on
main.objectstack-fleet commentedon Sep 28, 2026
Claim: PM loop round 23
Session:
session_01N8TPEsoJxPsdSdNKGnNGENAccount:
os-warren(the seat's linked user asGET /useranswers it; always the card's assignee)Branch:
claude/issue-20493-ja-es-object-labelsWorktree:
objectstack-issue-20493Domain:
domain:engineSeat:
domain:engine#1File surface (#20462's shape, PR #20490
9bf5e67af, applied to two more locales; triage 5877552039):packages/platform-objects/src/apps/translations/ja-JP.objects.generated.tsandes-ES.objects.generated.ts, leaf string values only. The user-facing copies byte-equal to theensource get ja-JP or es-ES values. ⛔ No structure edit, andpnpm check:i18nstays green.objects-zh-cn-echo-decisions.test.ts:objects-ja-jp-echo-decisions.test.tsandobjects-es-es-echo-decisions.test.ts. Each declares, with a reason, every leaf that locale keeps in English by design. Each locale decides its own set, and the zh-CN set is only where to start reading.ja-JP.source-hashes.generated.ts,es-ES.source-hashes.generated.ts), regenerated bypnpm i18n:extract, never by hand.*-echo-decisions.test.tsledgers, only where one reads a ja-JP or es-ES objects-bundle leaf that this card translates and must follow it, as PR fix(platform-objects): translate the zh-CN object labels, options and help that shipped as English copies #20490 did for zh-CN.sys_member.fields.role.options.delegated_adminandsys_invitation.fields.role.options.delegated_adminunder both locales, using the console's words where objectui already renders the value (委任管理者, Administrador delegado; triage)..changeset/20493-*.md.Stop on breach and explain in the report.
scripts/i18n-coverage-baseline.json,check-i18n-coverage): triage keeps it out (「新增门禁默认否」). The PR records each bundle's copy count before and after.*.metadata-forms.generated.ts: PR fix(driver-sql): a declared index that can never be built is logged at error and reported in drift #20519 ([finding] a misspelt field name in a field'srelatedListColumns,lookupColumns,lookupFilters[].fieldordependsOnpasses every authoring door, and fails only at view or picker time #20432) holds all four.ja-JP.ts/es-ES.ts.Container & model:
L,mode:subagent,model: opus(dispatch-gates --tier: no path-derived mandate, floor sonnet · default opus · ceiling fable)Clause-②: no
Thread-read: 5877552039
Serial constraints cleared: at 2026-09-28T23:10Z, a census of all 10 open PRs' file lists finds none on
ja-JP.objects.generated.ts,es-ES.objects.generated.ts, theirsource-hashescompanions orscripts/i18n-coverage-baseline.json. PR fix(driver-sql): a declared index that can never be built is logged at error and reported in drift #20519 ([finding] a misspelt field name in a field'srelatedListColumns,lookupColumns,lookupFilters[].fieldordependsOnpasses every authoring door, and fails only at view or picker time #20432) touches only the four*.metadata-forms.generated.tsbundles, which are other files. PR chore: version packages #17076 (version packages) touches no translation file. record validator: adatefield written as a non-ISO string ("2026/07/15") answers 201 and is stored verbatim as"2026/07/15", a non-day, on memory and SQLite, because thedatearm admits anyDate.parse-readable string #20481's dev (no PR yet) holdsobjectqlvalidation, which is another package. The mechanism's last holder, PR fix(platform-objects): translate the zh-CN object labels, options and help that shipped as English copies #20490 (platform-objects: the zh-CN bundle ships 192 labels and options as the English source string, and the i18n coverage baseline counts them as translated #20462), landed as9bf5e67af.objectstack-fleet commentedon Sep 29, 2026
os-dev-report
{ "issue": 20493, "status": "done", "branch": "claude/issue-20493-ja-es-object-labels", "pr": "https://github.com/objectstack-ai/objectstack/pull/20530", "session": "session_01N8TPEsoJxPsdSdNKGnNGEN — mode:subagent, the parent's harness-stamped id (container cse_01N8TPEsoJxPsdSdNKGnNGEN; Claude-Session line on every commit). The newest Claim: (5880394970) names this session and branch claude/issue-20493-ja-es-object-labels; verified before any edit, no claim of my own posted.", "premise_still_valid": true, "summary": "One draft PR for both locales. ja-JP: 340 of the 383 objects-bundle leaves that were byte copies of their en source now carry Japanese; 43 stay as written by design. es-ES: 338 of 392 now carry Spanish; 54 stay as written. Each locale's kept set is declared with reasons in its own ledger (objects-ja-jp-echo-decisions.test.ts, objects-es-es-echo-decisions.test.ts), the exact shape of the zh-CN ledger; both provenance companions were regenerated by pnpm i18n:extract (-340 / -338 rows, 0 added, remaining rows set-equal to the declared echoes). delegated_admin reads 委任管理者 / Administrador delegado on sys_member and sys_invitation, pinned equal to objectui main 797a30f packages/i18n/src/locales/{ja,es}.ts organization.roles.delegatedAdmin. One sibling ledger (object-lifecycle-panel) pinned access_token_ttl as a ja/es fill and now asserts all three locales authored with TTL kept. H1-H6 all held: counts reproduce the card exactly at base 397572ed5; the zh-CN mechanism carried over unchanged (check:i18n 0 / 1 DRIFTED (2) / 0); each locale decided its own set (ja-JP adds Web and Cc/Bcc, and never had the result-dialog credentials as copies; es-ES adds 8 same-spelling words, 5 bundle loanwords and Cc); one term one rendering; help/description/emptyState translated, placeholders all typed literals; 2787 changed lines, under 5000. Coverage ratchet untouched per triage.", "tests": "All at head d616c8cc3 (true merge of origin/main fb386074f; parents 8f3e7cae3 + fb386074f; CLI closure rebuilt after the merge). pnpm --filter @objectstack/platform-objects exec vitest run --maxWorkers=2: 58 files / 942 tests passed (lock VERDICT command-exit 0; same before the merge). pnpm --filter @objectstack/platform-objects typecheck: exit 0; tsc -p tsconfig.test.json --listFilesOnly lists both new ledgers (2 hits). check:i18n: exit 0 with both bundles restored to their 397572ed5 bytes; exit 1 after the leaf edits alone ('platform-objects DRIFTED (2)', the two companions); exit 0 after pnpm i18n:extract (companions only: -340/-338 rows, bundles byte-identical); exit 0 at d616c8cc3. check:i18n-coverage: exit 0, '621 baselined untranslated string(s), none new'. Reverse verification, 5 legs via scripts/ablation-replace.mjs (anchor count declared, blob change proved, each restore proved blob == HEAD and git diff HEAD empty): (1) ja-JP delegated_admin x2 -> 'Delegated Admin': 2 failed / 9 passed; (2) es-ES delegated_admin x2 -> 'Delegated Admin': 2 failed / 8 passed; (3) ja-JP echo google 'Google' -> 'グーグル': 1 failed / 10 passed ('is a declared echo and must stay the en source'); (4) es-ES echo global 'Global' x2 -> 'Mundial': 1 failed / 9 passed; (5) ja-JP 委任管理者 x2 -> 委託管理者: 1 failed / 10 passed, only the console-word pin. Sibling leg: object-lifecycle-panel ledger restored to its 397572ed5 bytes: 1 failed / 34 passed ('expected アクセストークン TTL to be Access Token TTL'), then restored to HEAD (blob equal). Narrowed ESLint: --no-inline-config --format json over the 7 changed .ts files: 7 linted (isPathIgnored false for each under the repo config), 0 errors, 0 warnings; eslint.config.mjs never enables type-aware linting (its own comment: no parserOptions.project, no typed rules), so no untouched file's verdict can move; repo-wide pnpm lint declared to CI. No build/dist ablation applies: every mutated subject is imported by relative path from src.", "gates": { "measured_head": "d616c8cc3", "derivation": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack at d616c8cc3: 61 commands (31 pnpm, 30 direct node)", "local": "61/61 run, each exit code written to a file before any pipe: 60 exit 0 on first run; pnpm check:dual-build-cjs-loads first answered PREREQUISITE NOT MET (exit 3, dist/ missing outside the CLI closure) — not a measurement — rerun after a workspace build (71/71 turbo tasks cached): exit 0", "ran_reconciliation": "dispatch-gates --ran: 61 derived, 61 run, 0 NOT-MEASURED, 0 UNRUN (exit 0)", "extra": "check:i18n-coverage exit 0 (ratchet unchanged); platform-objects vitest 58/942 pass; typecheck exit 0", "not_measured": "NOT MEASURED: the 6 workflow-valued families, the 11 wide-population families and the path-scheduled CI jobs (reason: CI-only values/populations, declared to CI); NOT MEASURED: browser rendering of the Invite dialog (reason: leaves read directly from the bundles, as the card measured)", "ci": "in_progress at report time: 31 check runs on d616c8cc3 — 11 success, 3 skipped, 17 in_progress, 0 failure" }, "line_budget": "2787 changed lines (+1416 / -1371) over 8 files; node scripts/pm/check-governed-merges.mjs --pr 20530: NOT governed (0 of 8 paths hit the register), 2787 ≤ 5000, under the human-merge threshold", "deviations": [ "Both ledgers carry a third pinned translate row, sys_team.fields.member_count.label, mirroring the zh-CN ledger's three rows; the card named only the delegated_admin pair for ja/es.", "The objectui-word pin is an exact-value assertion inside the existing role-word test, not a new Decision field, so the ledger shape stays identical to zh-CN's.", "es-ES has no script to test, so its translate verdict asserts 'not the en source' only (zh-CN and ja-JP also assert Han / Japanese script); its role test uses the en catalog as the negative instead.", "The harness attribution reminder asked for a model-named Co-Authored-By trailer and a claude.com PR footer; AGENTS.md (which the repo's CLAUDE.md makes binding) requires the model-free trailer pair and the session-URL footer, so those were used.", "Cleanup (rm -rf node_modules, git worktree remove) runs after this comment is posted, as the final step." ], "files_changed": [ ".changeset/20493-ja-es-object-labels.md", "packages/platform-objects/src/apps/translations/ja-JP.objects.generated.ts", "packages/platform-objects/src/apps/translations/es-ES.objects.generated.ts", "packages/platform-objects/src/apps/translations/ja-JP.source-hashes.generated.ts", "packages/platform-objects/src/apps/translations/es-ES.source-hashes.generated.ts", "packages/platform-objects/src/apps/translations/objects-ja-jp-echo-decisions.test.ts", "packages/platform-objects/src/apps/translations/objects-es-es-echo-decisions.test.ts", "packages/platform-objects/src/apps/translations/object-lifecycle-panel-echo-decisions.test.ts" ], "mcp_calls": "0 — no MCP GitHub tool was called", "api_writes": "3 — pr_create POST /repos/objectstack-ai/objectstack/pulls (fleet relay run 36501023664, draft, PR #20530); assign POST /repos/objectstack-ai/objectstack/issues/20530/assignees os-warren via label-write.mjs (relay run 36501099150, read back MATCHES); comment POST /repos/objectstack-ai/objectstack/issues/20493/comments (this report, post-stamped.mjs). issue_patch: 0. Plus git push of the branch (not REST). PR body read back byte-identical (16512 bytes).", "open_questions": [], "out_of_scope_findings": [ "carrier: 承接者:无 · noted, not filed: es-ES renders Parent as 'principal' bundle-wide, so the pre-existing sys_business_unit.fields.parent_business_unit_id.label and sys_user.fields.primary_business_unit_id.label both read 'Unidad de negocio principal' (read from es-ES.objects.generated.ts at 397572ed5, not driven in a browser); this PR follows the bundle word for Parent Organization; in the PR's Acceptance notes", "carrier: 承接者:无 · noted, not filed: some AUTHORED ja-JP/es-ES leaves no longer match their moved en source, e.g. sys_two_factor.fields.backup_codes.help still says JSON-serialized where en says an opaque ciphertext, and sys_notification.description; authored leaves are legacy-trusted by the provenance design and outside the copy class; no public-door reading taken · dedupe words: stale authored translation ja-JP es-ES; backup_codes help ciphertext JSON; present-but-stale leaf", "carrier: 承接者:无 · noted, not filed: the existing ja-JP bundle renders 'Locked Until' two ways (sys_user ロック解除日時, sys_job_queue ロック期限); this card uses ロック解除日時 for sys_two_factor; in the PR's Acceptance notes", "carrier: 承接者:无 · noted, not filed: ja-JP 'Managed By' is 管理者 (sys_metadata's word), so sys_email_template reads 管理者 as label and as the admin option; 管理元 would disambiguate; in the PR's Acceptance notes", "carrier: 承接者:无 · noted, not filed: the eight sibling ledgers' greater-than-zero floor comments name only zh-CN ('since #20462 zh-CN's objects slice holds only its declared English-by-design leaves'); the floors hold for all three locales now; comment-only drift outside the file surface" ] }Generated by Claude Code
objectstack-fleet commentedon Sep 29, 2026
ACCEPT — PR #20530 at
d616c8cc3f875fbd993787920c60160ccc0c2d68domain:engine#1·session_01N8TPEsoJxPsdSdNKGnNGEN(os-warren) · written 2026-09-29T00:34Z. Contract review of record: 5881349451 on PR #20530, at-tier, read-only, PASS on this head. All 340 ja-JP and 338 es-ES changed leaves were read, not sampled.Checklist, verified against GitHub rather than the reports:
Form: draft, base
main, first lineFixes #20493, and that is the only closing keyword in the body. Claim 5880394970 names the branchclaude/issue-20493-ja-es-object-labelsand readsClause-②: no, which is also the line in the changeset and the PR body.Scope: 8 files, +1416 / −1371:
en, 1529 leaves each. 340 / 338 values change, and every one was a byte copy ofenat base, so no authored translation was overwritten;access_token_ttl);Every file is inside the claim. zh-CN, the
*.metadata-forms.generated.tsbundles, the hand-authoredja-JP.ts/es-ES.tsand the coverage baseline are untouched.Changeset:
@objectstack/platform-objectspatch,Clause-②: no. It is user-visible copy only, and no key, export or API moves.PR body: one parenthesis the review found FALSE ("tombstone … no prior rendering in any ja-JP bundle"; the service-storage ja-JP bundle already renders トゥームストーン) was corrected by the seat before landing, through the relay
issue_patch. The squash carries the body intomain's history.Governed surface: none.
check-governed-merges --pr 20530finds the PR not governed. It is 2,787 changed lines, under the human-merge threshold.CI: 34 check-runs on the head: 31
success, 3skippedby roster, 0 failures.check:i18n(in Lint & Repo Gates) is green.Behaviour: on a ja-JP or es-ES console, 340 / 338 platform-object leaves that shipped as English copies now read in the customer's language: labels, plural labels, options, help, descriptions and empty states.
delegated_adminreads 委任管理者 / Administrador delegado onsys_memberandsys_invitation. These are objectui's own words, verified at objectuimain.ID, protocol names, typed placeholders,Web,Cc/Bcc, and in es-ES, words Spanish spells the same.Deviations 1–5: accepted as the review answers them in ③.
Carried out of this card:
ensource moved. For example,sys_two_factor.fields.backup_codes.helpstill says "JSON-serialized" whereennow says opaque ciphertext, the opposite of the source (review ③.8). The card is named in the seat's next note.principalbundle-wide;Locked Untiltwo ways, which is pre-existing;sys_email_templatereads 管理者 as both themanaged_bylabel and itsadminoption. The option set disambiguates it, and a change would be a text-only follow-up on both labels, if the maintainer wants one;Landing:
ready, then auto-merge through the queue. The merge closes this card (Fixes). The seat then verifies the squash onmainand removespm:dispatchedin the same act.objectstack-fleet commentedon Sep 29, 2026
Landing record: PR #20530 merged. This card is closed
completedby itsFixeslinedomain:engine#1·session_01N8TPEsoJxPsdSdNKGnNGEN(os-warren) · written 2026-09-29T00:56Z.Verified on
main:6427e2cf560680888da444647e4c787e8be566ee, merged 2026-09-29T00:54Z by the queue, with one parent. It is an ancestor oforigin/main, and theorigin/maintip is the squash itself.d616c8cc3's changes against its merge basefb386074f(the same md5 over every added and removed line).委任管理者is present at the squash and absent at its parent, and so is the20493-ja-es-object-labelschangeset.Fixes #20493, so no other card was closed. The body carries the seat's pre-landing correction of one parenthesis.Delivered: on a ja-JP or es-ES console, 340 / 338 platform-object leaves that shipped as English copies now read in the customer's language: labels, plural labels, options, help, descriptions and empty states.
delegated_adminreads 委任管理者 / Administrador delegado, objectui's own words.objects-ja-jp-echo-decisions.test.tsandobjects-es-es-echo-decisions.test.ts.@objectstack/platform-objectsshipspatch,Clause-②: no.Carried out of this card:
ensource (backup_codeshelp).principalfor Parent / Primary; ja-JPLocked Untiltwo ways; ja-JP 管理者 as both themanaged_bylabel and itsadminoption; the sibling ledgers' zh-CN-only floor comments; the coverage ratchet is out, per triage.pm:dispatchedis removed in the same act as this record. The domain, area and type labels stay.fix(platform-objects): translate the ja-JP and es-ES object labels, o…