Skip to content

i18n(service-realtime): ship the presence object in all eleven platform languages - #30536

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/project-thread-o3y7uf
Nov 5, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/project-thread-o3y7uf

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Bill · project thread

domain:server#2 · os-bill · session_01Utp6Cai5CRdAs4u9gTipWU

Refs #30512 — package 1 of 11 (@objectstack/service-realtime). The card stays open: the last PR of the series flips the bundle check to the platform locale table.

Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么: 在线状态对象(sys_presence)的名称、字段、选项和帮助文字补上 7 种语言:繁体中文、阿拉伯语、法语、巴西葡萄牙语、俄语、德语、韩语,加上原有 4 种共 11 种,与平台语言表一致。
  • 为什么改: 平台语言表(Platform locale table (ruling F of #29349): one list of 11 languages in spec, complete on every surface #29428 裁决 F)要求每个界面都带齐 11 种语言;这是第 3 期按包补齐的第一个包,最小的一个(25 条)。
  • 风险与回滚: 只加翻译数据,不动代码逻辑、schema 或接口;原有 4 种语言文件一字未改。回滚即撤 PR。
  • 先看: src/translations/index.ts(新语言按表标签注册,zh-CN 排在 zh-Hant 前)、scripts/i18n-extract.config.ts(提取命令加 7 个标签),再抽看 ar.objects.generated.ts。
  • 两分钟验证: node scripts/check-i18n-bundles.mjs --filter=realtime 应输出 in sync (21 bundle(s)) 并退出 0。
  • 需要你做的: 无,席位落地。

What changes

  • Seven new locales for sys_presence, registered under the platform locale table's tags: zh-Hant, ar, fr, pt-BR, ru, de, ko. Each is a TAG.objects.generated.ts with all 25 leaves and a TAG.source-hashes.generated.ts companion, both written by the repo's own os i18n extract --fill=default --source-hashes, and each is served through withSourceFallback exactly like the existing three.
  • The extract command in scripts/i18n-extract.config.ts (which check-i18n-bundles reads) lists the seven tags, and the config's merge baseline imports the seven bundles, so a re-extract keeps the translations and the existing check:i18n bundle check now covers them.
  • index.ts lists zh-CN before zh-Hant, so a bare zh / zh-Hans request still expands to Simplified Chinese.
  • Existing zh-CN / ja-JP / es-ES files are untouched (no rename, no content change: the re-extract wrote them byte-identical).
  • bundle-ownership.test.ts: one message sentence said "the four locale bundles"; now "every locale bundle".

Acceptance notes

  • Quality bar ([Decision] Repeater row-property localisation: 604 catalog leaves across four locales — who authors the translated copy? #17508 / PR feat(spec): a repeater property panel names its columns in every locale, not only English #19345): every leaf is written for the reader, placeholders and code spans byte-identical (checked mechanically: same key set as en, same backtick spans and {…} tokens per leaf). Arabic text is written as RTL prose with code identifiers (PresenceStateSchema.metadata) left in Latin script.
  • Leaves equal to English, on purpose: words that are the native word in that language — fr Session, Mobile; pt-BR Status, Online, Offline, Desktop, Tablet; de Status, Online, Offline, Desktop, Tablet. The extractor records those as source copies in the source-hash companions (2 entries in fr, 5 each in pt-BR and de), which is the mechanism working as designed: if the English source changes, those leaves fall back to the new source rather than serve stale text.
  • Not changed, noted: the existing zh-CN / ja-JP / es-ES bundles still carry display_title.label / .help as English copies (two source-hash entries each). Out of this card's scope (it adds locales, it does not re-translate existing ones).

Verification

Package suite, typecheck, build (verify lock)
pnpm --filter @objectstack/service-realtime build && test && typecheck
 Test Files  5 passed (5)
      Tests  35 passed (35)
os-verify-lock: VERDICT command-exit 0
Bundle check covers the new locales (red when one leaf is removed)
node scripts/check-i18n-bundles.mjs --filter=realtime
  services/service-realtime      in sync (21 bundle(s))
check-i18n-bundles: OK (1 package(s) — all bundles in sync, no undeclared authoring keys).   EXIT 0

# one-off: delete `device.options.other` from ko.objects.generated.ts, re-run, restore from HEAD
  services/service-realtime      DRIFTED (2)                                                  EXIT 1
# restored: git diff HEAD empty

node scripts/check-i18n-stale-fill.mjs
check-i18n-stale-fill: OK (11 bundle set(s) — no new stale fills, 0 baselined).               EXIT 0
Derived gate families at head 28ebd23 (dispatch-gates --commands, reconciled with --ran)
dispatch-gates --ran: 62 derived famil(ies) accounted for — 61 run, 1 NOT-MEASURED (1 DERIVED from a recorded exit 3).
  NOT MEASURED: node scripts/check-plugin-teardown-shape.mjs --self-test — exit 3, prerequisite: this shallow clone cannot read the
  self-test's pinned positive-control commit; CI runs it on a full checkout. Not read by anything this PR changes.
every other family exit 0, including pnpm check:i18n (all 10 bundle sets) and pnpm check:i18n-stale-fill
eslint --no-inline-config on the changed .ts files: exit 0 · check-nul-bytes: exit 0
changed lines 733 (+731 / -2), 18 files: under the 3000-line human-merge threshold

Full record: the seat's project folder, server-seat2/30512/gates-realtime-ran.txt.

Dogfood: not run — content-only package PR, no ! in the title and no (narrowing) arm (dispatch order: package suite + check:i18n + typecheck suffice).


Generated by Claude Code

@github-actions github-actions Bot added size/l documentation Improvements or additions to documentation tests tooling Fix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface labels Nov 5, 2026
@github-actions

github-actions Bot commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/service-realtime, touching 16 documentable anchor(s).

1 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/plugins/packages.mdx (via sys_presence (symbol, a field of const object arObjects; a field of const object deObjects; a field of const object frObjects; a field of const object koObjects; a field of const object ptBRObjects; a field of const object ruObjects; a field of const object zhHantObjects))

⛔ 1 release-owned page(s) also name something this change touched. These are read-only:

  • content/docs/releases/v16.mdx (via sys_presence (symbol, a field of const object arObjects; a field of const object deObjects; a field of const object frObjects; a field of const object koObjects; a field of const object ptBRObjects; a field of const object ruObjects; a field of const object zhHantObjects))

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

What this run could not see
  • the SDK route bridge reached 61 of 219 client-bound route-ledger rows — the other 158 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 158: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 103 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 8 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json fa9c0aa2a0a8c2752f83b57765f3aae978ae196a → packageMentionDocs.

Which tree this was computed on

This run read content/docs from c22f43180eea1d4f625e170fc2930897edb694e9 — the merge of head 28ebd23538960465127b51dce81e107659927e8a into base fa9c0aa2a0a8c2752f83b57765f3aae978ae196a, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin c22f43180eea1d4f625e170fc2930897edb694e9 && git checkout c22f43180eea1d4f625e170fc2930897edb694e9
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin fa9c0aa2a0a8c2752f83b57765f3aae978ae196a 28ebd23538960465127b51dce81e107659927e8a && git checkout -B drift-repro fa9c0aa2a0a8c2752f83b57765f3aae978ae196a && git merge --no-ff 28ebd23538960465127b51dce81e107659927e8a

node scripts/docs-audit/affected-docs.mjs --json fa9c0aa2a0a8c2752f83b57765f3aae978ae196a

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs fa9c0aa2a0a8c2752f83b57765f3aae978ae196a → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:server#2 · os-bill · session_01Utp6Cbvcmv8YWFhFJwzjKL

维护者速读

  • 改了什么: service-realtime 的在线状态对象(sys_presence)补齐 7 种语言:繁體中文、阿拉伯语、法语、巴西葡语、俄语、德语、韩语。按平台语言表的标签注册,原有 4 种语言不动。
  • 为什么改: 平台语言表定了 11 种语言,每种都要在所有界面上完整(Platform locale table (ruling F of #29349): one list of 11 languages in spec, complete on every surface #29428 裁定 F)。平台元数据原来只有 4 种(i18n phase 3 (platform metadata and built-in emails): extraction and bundle checks read PLATFORM_LOCALES; backfill the seven missing locales #30512,11 个包中的第 1 个)。
  • 风险与回滚: 只加翻译内容和注册行,不改任何行为;没有翻译的请求照旧回落英文。回滚即撤本 PR。
  • 先看: packages/services/service-realtime/src/translations/index.ts 的注册行,再挑一种语言的 *.objects.generated.ts 看译文。
  • 两分钟验证: pnpm --filter @objectstack/service-realtime test。
  • 需要您做的: 无,席位经合并队列落地(非受管面,733 行,非 BREAKING)。
  • 席位意见: ACCEPT。席位抽查了繁中、阿语、韩语译文,术语一致、通顺;与英文相同的值(如德语的 Status、Online)由 source-hashes 记录,下次抽取不会误判为过期。

席位核对 — ACCEPT · domain:server#2 · head 28ebd23538960465127b51dce81e107659927e8a

  • 形态: draft, author objectstack-fleet[bot] (relay pr_create), no assignee, no review request; 18 files, +731 −2; check-governed-merges --pr 30536: NOT governed (0 of 18 paths), 733 lines ≤ 3000. Title has no !. Refs #30512 (package 1 of 11; the card stays open).
  • Review face: TIER_DEFAULT (Clause-②: no: translated content for locales the platform table already declares, plus registration lines; no spec, governed or narrowing path), written here by the seat.
  • Seat rulings held: new files under the table tags (zh-Hant, ar, fr, pt-BR, ru, de, ko); existing zh-CN / ja-JP / es-ES untouched; zh-CN registered ahead of zh-Hant (the resolver's prefix fallback keeps today's zh-TW → zh-CN answer; the resolver gap is filed separately from the dev's report).
  • Seat read: index.ts and scripts/i18n-extract.config.ts register the seven bundles and their source hashes; the extract docstring's --locales now lists all eleven, so the existing check-i18n-bundles covers this package for the new locales (no new gate, ruling F). Source-hash files carry only the keys whose value equals English (none for ko/ar/ru/zh-Hant; e.g. de Status, Online, Offline, Desktop, Tablet), as the generator writes them. bundle-ownership.test.ts: one message wording ("every locale bundle"). Spot check of zh-Hant (線上狀態 / 建立時間), ar (الحضور / تاريخ الإنشاء, RTL text, no Latin left), ko (접속 상태 / 생성 일시): consistent with the existing three translations' terms.
  • Dev readings (28ebd235): package tests 35/35, typecheck, check:i18n, stale-fill green; derived gates 62 — 61 exit 0, 1 NOT MEASURED (check-plugin-teardown-shape --self-test, exit 3: shallow clone without its pinned fixture commit; the PR touches no plugin teardown, and CI runs the family). Content-only package PR: full dogfood owed on the last PR of the series, per the order. os-dev-report 6660732929.
  • Out of scope → carrier: the locale resolver does not read platformLocaleTagOf (zh-TW / zh-HK keep resolving to zh-CN even once zh-Hant exists) — the seat files it from the report.
  • 门禁 check-runs: in progress at ACCEPT; the seat queues once every check is green or an expected skip.
  • 落地条款: Refs i18n phase 3 (platform metadata and built-in emails): extraction and bundle checks read PLATFORM_LOCALES; backfill the seven missing locales #30512. Ordinary queue landing by this seat: pr_ready + automerge_enable on this head; the card ticks service-realtime when it merges.

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review November 5, 2026 15:01
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge November 5, 2026 15:01
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Nov 5, 2026
Any commits made after this event will not be merged.
Merged via the queue into main with commit ab159a9 Nov 5, 2026
49 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-o3y7uf branch November 5, 2026 16:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/l tests tooling Fix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant