Repository navigation
feat(spec,rest,cli): a doc book's title and section titles are translatable — books.<name> in the translation bundle - #26819
Conversation
…rough the bundle's books group (wip) Claude-Session: https://claude.ai/code/session_01WGufzf4dTFmjsttVz7Pm8j Co-Authored-By: Claude <noreply@anthropic.com>
…cs, changeset, showcase zh-CN book strings Claude-Session: https://claude.ai/code/session_01WGufzf4dTFmjsttVz7Pm8j Co-Authored-By: Claude <noreply@anthropic.com>
…synthetic orphan group Claude-Session: https://claude.ai/code/session_01WGufzf4dTFmjsttVz7Pm8j Co-Authored-By: Claude <noreply@anthropic.com>
…ale test Claude-Session: https://claude.ai/code/session_01WGufzf4dTFmjsttVz7Pm8j Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WGufzf4dTFmjsttVz7Pm8j Co-Authored-By: Claude <noreply@anthropic.com>
The wide layout wraps the book sidebar in an unlabelled nav, so filtering navigations by link count picked the wrapper too. Query the navigation by its name (the served book title) and pin that the authored title is absent for a zh-CN reader. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGufzf4dTFmjsttVz7Pm8j
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGufzf4dTFmjsttVz7Pm8j
📓 Docs Drift CheckThis PR changes 5 package(s): 6 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 4 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 159 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin e39bcb2b433a12d81fade431f99ab14ca48f07d7 && git checkout e39bcb2b433a12d81fade431f99ab14ca48f07d7
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 96e7a4335c0aa611a706664da6df339f672ec1ab 525ae464723b8994fec778d41e303a0049573e84 && git checkout -B drift-repro 96e7a4335c0aa611a706664da6df339f672ec1ab && git merge --no-ff 525ae464723b8994fec778d41e303a0049573e84
node scripts/docs-audit/affected-docs.mjs --json 96e7a4335c0aa611a706664da6df339f672ec1ab
|
Contract reviewServed-tier: Inputs read: card #26690 (body, triage 6443918209, claim 6446870967, os-dev-report 6449088056), PR #26819 body and file list, the net diff The rest of the diff (docs under ① Derived judgmentsAccept-set:
Public surface:
Nothing derived is judged wrong. ② Semver levelChangeset
Clause-②: yes (widening). Right — nothing an author could write before is refused now; the only prose that changed on a refusal (the retired ③ Boundary flags
④ Design judgment
Cited code read, as one change with the rule:
Must-fix: none. Implemented-by: VERDICT: PASS |
…onsole loader knows `books` translation-target-unknown gains a books arm: books.NAME resolves against the declared books (a sibling package's and a package id's implicit book included) and books.NAME.groups.KEY against that book's group keys. The console's language loader lists `books` among the spec translation groups, and the Studio translation-preview test counts the fifteenth category. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGufzf4dTFmjsttVz7Pm8j
Contract reviewServed-tier: DELTA record over the full review at Inputs read: card #26690 (body; triage 6443918209, claim 6446870967, os-dev-report 6449088056, claim amendment 6449487635), PR #26819 body, its 35-file list and the net diff against ① Derived judgmentsS1 is closed. The full record asked for a Accept-set (what
Public surface:
Five new lint tests, read for vacuity:
Re-affirmed from the full record at this head, unchanged by the delta: every accept-set line on ② Semver levelChangeset
Clause-②: yes (widening). Still right, judged against ③ Boundary flags
④ Design judgmentThe three
Must-fix: none. Implemented-by: VERDICT: PASS |
…ew books row Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGufzf4dTFmjsttVz7Pm8j
…nce after merging main Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGufzf4dTFmjsttVz7Pm8j
席位核对 · ACCEPT ·
|
⛔ merge queue 构建失败 — 先分诊,再决定要不要重排队列构建 40576208471 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集), 分类: 失败的 job(日志抽取,best effort):
跨 PR 相同签名(24h,按失败测试文件聚合):
历史信号:
分诊清单:
Generated by Claude Code · merge-queue-triage workflow (#4859) |
Requested by Yibo Wang · project thread
Fixes #26690
Clause-②: yes (widening)
Metadata-protocol: added
Skills-docs: #26820. The docs are updated here.
维护者速读
books分组,书名、书的描述和每个分组标题(按分组key)都能翻译;GET /meta/book(列表和单项)和GET /meta/book/:name/tree按请求语言返回,控制台/apps/<包>/docs侧栏随之显示译文。os i18n extract会生成这些键,os i18n check报缺失为i18n/missing-book。translations内联写法仍被拒绝,只是提示改为指向新键。回滚即还原本 PR。packages/spec/src/system/i18n-resolver.ts(translateBook)、packages/rest/src/meta-item-read-gate.ts(树接口翻译这一步)、packages/spec/src/system/translation.zod.ts(books分组形状)。pnpm --filter @objectstack/runtime exec vitest run src/domains/meta-list-projection-parity.test.ts -t 26690,预期 zh-CN 拿到「帮助中心 / 开始」,en-US 拿到「Help Centre / Start」,两个传输层一致。What changes
One translation path for a doc book's spine — the translation bundle, the same path an app's label and navigation labels take. No inline locale map comes back on the book (the retired 17.0.0 map stays a tombstone; sibling groups such as
apps.<name>.navigation.<id>.labelandpages.<name>.labeluse the bundle, not inline maps).@objectstack/spec—system/translation.zod.ts: abooksgroup on the shared per-app shape, so the bundle entry (TranslationData), the registeredtranslationitem and the platform bundle all accept it. Keyed by the bookname:label,description, andgroups.GROUP_KEY.label(by the group's stablekey, as a navigation node is keyed by itsid). Strict at every level;name/titlepoint atlabel,sections/chapters/tocpoint atgroups, the singularbookpoints atbooks. The group counts in thesettingsrefusal prose and the shape docblocks move fourteen → fifteen (and fifteen → sixteen for the platform face).@objectstack/spec—system/i18n-resolver.ts:translateBook, registered inMETADATA_DOCUMENT_TRANSLATORS.TRANSLATABLE_METADATA_TYPESis derived from that table and@objectstack/restreads it, soGET /meta/book(list and item, both transports) is served in the request locale with no further wiring. A key the bundle does not carry keeps the authored string; a document with nothing to translate comes back as the same reference.@objectstack/spec—system/book.zod.ts: the retired inline-translationsprescription now names the bundle keys to move the strings to (it used to say the tree and portal render verbatim, which this PR makes untrue). Booklabeland grouplabeldescribes name their bundle keys.@objectstack/rest—createMetaBookTreeAnswer: step 5 translates the resolved book throughtranslateMetaDocument(the same table) before rendering the spine, so the tree and the list the sidebar is built from agree. Translated after the §6.7 audience gate; a label is not an access input.MetaBookTreeSourcesgainsresolveI18nService();RestServer's route supplies it.@objectstack/runtime— dispatcher book-tree route: spreadsmetaTranslationSources, so it answers the localized treeRestServeranswers.@objectstack/cli:walkBooksinos i18n extractemitsbooks.NAME.label/.description(pushOptional) andbooks.NAME.groups.KEY.label(pushEntry, the label is required); coverage reports a gap asi18n/missing-book.translation/booksseededlivewith its reader, drilled tolabel,description,groupsandgroups.label.GET /meta/book(use-book-data.ts), the client sendsAccept-Languageon every request, and the console already remounts the metadata subtree on a language switch. A console test pins the chain.examples/app-showcase: zh-CN strings forshowcase_manual(title, description, three section titles), so the new walk does not growcheck:i18n-coverage.ui/doc-pages.mdxgains a "Translating the spine" section (the inline-map callout now points at it);ui/translations.mdxandprotocol/kernel/i18n-standard.mdxlist the new group.@objectstack/lint—translation-target-unknown: resolvesbooks.NAMEagainst the declared books (a sibling package's included) and the implicit per-package book (the package id, its oneallgroup read offderiveImplicitPackageBook), andbooks.NAME.groups.KEYagainst that book's group keys. A mistyped book name or group key is anerrorwith the nearest declared name. The rule's header and itsexplainRuleparagraph cover the new arm.@object-ui/i18n—SPEC_TRANSLATION_GROUPS: gainsbooks, so the console's language loader walks the served group (the existingloadLanguagepin requires it). The Studio translation-preview coverage pin moves to2/15 (13%)with thebookscategory key.Why
A package that ships its docs in two languages showed a half-translated manual. Each doc's body already followed the reader's locale (
doc.translations,NAME.LOCALE.md), but the book title and every sidebar section title stayed in the authoring language: the book's inlinetranslationsmap was retired in 17.0.0 because nothing read it, and the translation bundle had no key for a book. This gives the spine a translation slot on the one path navigation items and pages already use.Tests
packages/spec/src/system/i18n-book.test.ts(new, 11): the three doors acceptbooks; the face is closed; the aliases; the tombstone names the new keys; a zh-CN reader gets title, description and every section title; the translated book renders a translated spine throughresolveBookTree; an en-US reader gets the same reference; per-key fallback; BCP-47 ladder and fallback chain; no mutation.packages/cli/test/i18n-book-walk.test.ts(new, 4): the walk, seeding, a bundle written at the extracted paths parses, and thebookcoverage bucket.packages/runtime/src/domains/meta-list-projection-parity.test.ts: the census fixture bundle gains abooksentry, so every list, item and tree cell compares both transports underAccept-Language: zh-CN/?locale=zh-CNas well. New reference pins: the zh-CN book list (and en-US unchanged), the zh-CN book item, and the tree on BOTH transports — zh-CN title and section title, en-US authored, the doc entry still localized bydoc.translations.ui/apps/console/src/pages/docs-portal.bookLocale-26690.test.tsx(new, 2): the real/apps/:appName/docsroutes, layout, reader and sidebar over an adapter that answersGET /meta/bookby running the authored book through the spec's translator with a bundle (bundle → served book → sidebar): zh-CN shows the translated title (aria-label) and section titles; en-US is unchanged.packages/lint/src/validate-translation-references.test.ts(5 new): a declared book and its group keys are clean; an unknown book name; unknown group keys, a group label among them; a sibling package's book; the implicit per-package book and an orphan group under it. Removing thebooksloop reds three of them.Acceptance notes
MetaBookTreeSources.resolveI18nServiceis a required member. Both in-repo transports supply it. A third-party implementer of this exported port would need to add it; making it optional would let a transport silently serve untranslated labels. Flagged for the contract review: the seat may prefer it optional.resolveBookTreehardcodes its label; it is not an authored group and has no bundle key. Pre-existing, unchanged by this PR.books.PACKAGE_ID.labelif a bundle carries it — an effect of translating whatever book the tree resolves, not a declared feature.translation-target-unknownresolvesbooks.NAMEandbooks.NAME.groups.KEYagainst the declared books (a sibling package's included) and the implicit per-package book (the package id, oneallgroup read offderiveImplicitPackageBook): a mistyped book name or group key is anerrorwith the nearest declared name. Added in the review's patch round (claim amendment 6449487635).!in the title and no(narrowing)arm, so no full dogfood run is owed.Verification
Head
1f17d1834for the suites below. The patch round at4b8fb9a1b(thebookslint arm and the two UI fixes) re-ran:@objectstack/linttest 7435 passed, typecheck exit 0; the UIloadLanguage,@object-ui/i18nand app-shell preview suites, 235 files passed;check:generatedexit 0; the 31 lint, changeset, i18n and UI gate families fromdispatch-gates, every exit 0 (the derived set is still 123). Every build and test ran throughscripts/pm/os-verify-lock.shon a shared box.Build and package suites
pnpm build: 116/116 tasks, exit 0 (the first run found the Studio translation preview's exhaustive group table missingbooks; fixed in this PR).@objectstack/spectest: 735 files, 22021 passed; typecheck exit 0.@objectstack/resttest: 6498 passed; typecheck exit 0.@objectstack/runtimetest: 7448 passed; typecheck exit 0.@objectstack/cliunit: 4938 passed; typecheck exit 0.vitest runof the console book-locale test and the Studio translation-preview test: 2 files, 23 passed.type-checkof@object-ui/app-shelland@object-ui/console: exit 0.eslintover the 16 touched TS/TSX files: 0 errors, 0 warnings.Ablations (each red, then restored;
git diff HEADempty)book: translateBookfromMETADATA_DOCUMENT_TRANSLATORS:i18n-book.test.ts2 of 11 fail; 3 runtime parity tests fail (list, item, tree).walkBooks(config, out):i18n-book-walk.test.ts4 of 4 fail.Derived gates
dispatch-gates --commands: 123 commands;dispatch-gates --ran: 123 derived, 123 run, 0 NOT-MEASURED, 0 UNRUN; every exit 0. The three build-output gates (check:skill-examples,check:dual-build-cjs-loads,check:i18n-coverage) andcheck:test-source-alias,check:i18n,check:i18n-walk-paritywere re-run after the full build.check-published-list-mirrors,check:meta-url-spelling,check:authz-resolver,check:changeset-fixed,check:engine-double-contract,check:error-code-casing,check:filter-alias-parity,check:i18n-stale-fill,check:published-readme-exports,check:route-ledger-census,check-dts-references,check:stack-collection-maps): all exit 0.check:generatedexit 0;check:livenessexit 0 (translation state counts 38 → 41).Human Minimum
packages/specholds no runtime logic. (translateBookjoins the existing translators insystem/i18n-resolver.ts, the table the readers already dispatch through.)pnpm lintpasses (eslint over the touched files, above).main, one pull request.packages/spectouched: its generated artifacts are regenerated and committed.content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.Generated by Claude Code
🤖 Generated with Claude Code
https://claude.ai/code/session_01WGufzf4dTFmjsttVz7Pm8j