Skip to content

Commit 0ce44c9

Browse files
docs(skills): list relatedListTitle under fields.{field_name} in the i18n skill (#30068)
domain:skills#1 · huangyiirene · session_01J8VVAnMUWA9rufXzFaEh4J <!-- claude-projects-attribution: {"github_login":"huangyiirene"} --> _Requested by **Irene** · [project thread](https://claude.ai/code/project/chan_01TJXtQ1tVD26ecLDZxFS67x?thread=cmsg_01TJXtQ1tVD26ecLDZxFS67xVTwq3HPmiyw9pZNoX4FLXV)_ Fixes #29990 Clause-②: no Metadata-protocol: none The maintainer waived the model-tier mandate for `skills/**` while that tier had no quota; this PR was developed below it. ## 维护者速读 - 改了什么:objectstack-i18n 技能对象级翻译表的 `fields.{field_name}` 一行,在 `inlineTitle` 之后加上 `relatedListTitle`:lookup 或 master_detail 字段在父记录页上画出的相关列表标题;键在子对象的字段上,未翻译时保留作者原文,不会换成子对象的标签。另加一个 `'@objectstack/skills': patch` changeset。 - 为什么改:PR #29989 已让 `relatedListTitle` 可翻译(`translation.zod.ts` 的 `FieldTranslationSchema` 与 `i18n-resolver.ts` 的 `translateObject`),技能表还没列它。 - 风险与回滚:纯技能文本 + changeset。为新文字付账,删掉同文件 *Diff & Coverage Schemas* 下一段重复说明(`getCoverage()` / `suggestTranslations()` 无实现,*Service Contract* 一节已说);+219 / −222 字节;复审 S1 在 *Diff & Coverage Schemas* 开头句补回两个 schema 与 `getCoverage()` / `suggestTranslations()` 的对应(+111 字节),合计 5646 → 5673 tokens,上限 6333 未动,无 re-wrap。回滚即 revert。 - 先看:`skills/objectstack-i18n/SKILL.md` 第 162 行;对照 `packages/spec/src/system/translation.zod.ts` 的 `relatedListTitle` TSDoc。 - 需要你做的:Tier H 受管面(`skills/**`),需要 `GOVERNED_APPROVERS` 的批准;PR 保持 draft。 ## What changes `skills/objectstack-i18n/SKILL.md`, the `fields.{field_name}` row of the object-level table: after `inlineTitle` it now lists `relatedListTitle` (the title of the related list a `lookup` or `master_detail` field draws on its parent's record page — the key is the child's too; untranslated it keeps its authored text, never the child's label). The wording mirrors the `inlineTitle` entry beside it. Facts, read on `main` at `c23501b2` (the merged code of #29989): - `FieldSchema.relatedListTitle`: `packages/spec/src/data/field.zod.ts` L1952; the field form shows it for `lookup` and `master_detail` (`field.form.ts` L320). - Bundle slot: `FieldTranslationSchema.relatedListTitle` in `packages/spec/src/system/translation.zod.ts` L248-263, addressed `objects.<child>.fields.<field>.relatedListTitle`. - Untranslated fallback: `translateObject` in `packages/spec/src/system/i18n-resolver.ts` L4554-4561 overlays the title only when a bundle entry exists, so an authored title with no entry keeps its text; the child's label is never swapped in (docblock L4478-4487). The optional example line was not added: it would cost about 110 bytes the deletion below does not cover. ### Token ratchet (no ceiling row moved, no re-wrap) The added text (219 bytes) is paid by deleting a restatement in the same file: the paragraph under *Diff & Coverage Schemas* saying `getCoverage()` and `suggestTranslations()` have no shipped implementation and pointing at `os i18n check` (222 bytes with its blank line). Its homes stay in the file: *Integration with II18nService → Service Contract* says the same of the optional methods, and *Translation Coverage → `os i18n check`* opens "The working coverage path is the CLI". No test under `packages/**` or `scripts/**` pins the cut text. The cut paragraph was also the one place that tied the two schemas to the methods returning them (`packages/spec/src/contracts/i18n-service.ts` L215, L228). Per the contract review's S1, the section's opening sentence (L340) now carries that tie in one clause: "The spec models coverage results for tooling — the return shapes of the optional `getCoverage()` / `suggestTranslations()` (see *Service Contract* below):". Only that line changed; no other line is re-wrapped. | file | bytes before / after | tokens before / after / ceiling | |:--|:--|:--| | `skills/objectstack-i18n/SKILL.md` | 22604 / 22712 | 5646 / 5673 / 6333 (headroom 687 → 660) | `.changeset/29990-i18n-related-list-title.md`: `'@objectstack/skills': patch`, with both declaration lines. ## Tests - `node scripts/check-skills-token-ratchet.mjs`: exit 0, `skills/objectstack-i18n/SKILL.md is 5673 tokens (ceiling 6333; headroom 660)`. - No code changed, so no package test or typecheck is owed. ## Verification Head `290d1fc0` (two commits on `c23501b2`; `284424b8` is the reviewed head, `290d1fc0` adds the S1 clause and its changeset sentence). <details><summary>Local gates on 284424b and again on 290d1fc: 44 derived, 44 run with exit 0, 0 NOT MEASURED each time (`dispatch-gates --ran`)</summary> - `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derived 44 commands for the two changed files. All ran after `pnpm install --frozen-lockfile` and a full `pnpm build` (exit 0), each with a 900 s timeout and its exit code captured before any pipe. - All 44 exited 0, among them `check-skills-token-ratchet.mjs` (and `--self-test`), `check-adr-0087-registration.mjs --base origin/main`, `check-changeset-no-major.mjs`, `check-empty-changeset.mjs`, `check:changeset-gate-self-tests`, `check-comment-mask-corpus.mjs`, `check:doc-authoring`, `check:skill-docs`, `check:skill-compatibility`, `check:skill-frame-sync`, `check:skill-identifier-liveness`, `check:dts-closure` and `check:dual-build-cjs-loads`. - `pnpm check:changeset-fixed` (artifact roster under `.changeset`): exit 0. - `--ran` printed: `44 derived famil(ies) accounted for — 44 run, 0 NOT-MEASURED`. - `node scripts/check-commit-card-trailers.mjs --range origin/main..HEAD`: exit 0. </details> ## Human Minimum - [x] 1. Schemas start as Zod; `packages/spec` holds no runtime logic. (No schema touched.) - [x] 2. Every name I added uses the casing for its kind. - [x] 3. No formatter ran. - [x] 4. One issue, one branch off an up-to-date `main`, one pull request. - [x] 5. A change that publishes carries a changeset, and both declaration lines are filled in here and in the changeset. - [x] 6. `packages/spec` not touched. - [x] 7. No hand edits to `content/docs/references/`, `packages/*/CHANGELOG.md` or `content/docs/releases/`. - [x] 8. Title, body and comments are in English (the 维护者速读 block is the repo's own Chinese reading aid). 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01J8VVAomnWeZNN7jDS3HjjL --- _Generated by [Claude Code](https://claude.ai/code/session_01J8VVAomnWeZNN7jDS3HjjL)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 9f3b4bb commit 0ce44c9

2 files changed

Lines changed: 14 additions & 6 deletions

File tree

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
'@objectstack/skills': patch
3+
---
4+
5+
docs(skills): the i18n skill lists a lookup or master-detail field's translatable `relatedListTitle`
6+
7+
Clause-②: no
8+
Metadata-protocol: none
9+
10+
- **Before.** The `objectstack-i18n` object-level table listed `label`, `help`, `placeholder`, `options` and `inlineTitle` under `fields.{field_name}`, so an author had no word that the related-list title on a parent's record page is translatable.
11+
- **Now.** The row adds `relatedListTitle`: the title of the related list a `lookup` or `master_detail` field draws on its parent's record page. The key sits on the child object's field, and an untranslated title keeps its authored text, never the child's label.
12+
- The paragraph under *Diff & Coverage Schemas* saying `getCoverage()` / `suggestTranslations()` have no shipped implementation is cut; *Service Contract* in the same file says the same, and the section's opening sentence now names the two schemas as those methods' return shapes. No schema, key or behaviour changes.

‎skills/objectstack-i18n/SKILL.md‎

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ All translatable content for a single object is aggregated under
159159
| Sub-key | Holds |
160160
|:--------|:------|
161161
| `label` / `pluralLabel` / `description` | Object-level text (every key optional) |
162-
| `fields.{field_name}` | `label`, `help`, `placeholder`, `options` (option value → label), `inlineTitle` (the heading of the inline child grid a `master_detail` field draws on its parent's form — the field lives on the child object, so the key is the child's; untranslated it keeps its authored text, never the child's plural label) per field |
162+
| `fields.{field_name}` | `label`, `help`, `placeholder`, `options` (option value → label), `inlineTitle` (the heading of the inline child grid a `master_detail` field draws on its parent's form — the field lives on the child object, so the key is the child's; untranslated it keeps its authored text, never the child's plural label), `relatedListTitle` (the title of the related list a `lookup` or `master_detail` field draws on its parent's record page — the key is the child's too; untranslated it keeps its authored text, never the child's label) per field |
163163
| `_views.{view_name}` | `label`, `description`, `title` (a form view's own heading — only a form that authors one is translated; a list view has none), `submitBehavior.title` / `submitBehavior.message` (the thank-you panel of a form whose `submitBehavior` is `kind: 'thank-you'`; only the copy the form authors is translated, and the other kinds carry none), `emptyState.title` / `emptyState.message`, `bulkActions.{def_name}` (`label`, `confirmText`, `confirmLabel`, `params`) |
164164
| `_actions.{action_name}` | `label`, `description`, `confirmText`, `submitText` (the param dialog's button verb — only under an action that declares `params`), `successMessage`, `disabledReason` (the sentence a greyed action shows; absent keeps the console's default), `params.{param_name}` (and `.options.{value}` beneath it — an option's stored `value` in that param's inline `options`), `outcomeMessages.{outcome}` (an outcome the action's own `outcomeMessages` declares), `resultDialog.title` / `.description` / `.acknowledge` (only under an action that declares a `resultDialog`), `resultDialog.fields.{path}` (the literal `path` of a field in `resultDialog.fields[]`, dots included — `client.secret` is one key); the same keys hold under `globalActions.{action_name}` |
165165
| `_sections.{section_name}` | Form section `label`, `description`; `fields.{field_name}` — the `label`, `placeholder`, `helpText` an entry overrides for that form alone (`helpText` here, `help` under `fields.{field_name}` above: each spells what its source does) |
@@ -337,18 +337,14 @@ re-translation: an up-to-date bundle re-extracts byte-identically. Requires
337337

338338
### Diff & Coverage Schemas
339339

340-
The spec models coverage results for tooling: `TranslationCoverageResult`
340+
The spec models coverage results for tooling — the return shapes of the optional `getCoverage()` / `suggestTranslations()` (see *Service Contract* below): `TranslationCoverageResult`
341341
(totals, `coveragePercent`, per-group `breakdown`) and `TranslationDiffItem` —
342342
`key` (dot path), `status` (`missing | redundant | stale`), `locale`, optional
343343
`objectName`, optional `sourceHash` for stale detection, and AI-enrichment
344344
fields (`aiSuggested`, `aiConfidence`). Full Zod shape:
345345
`node_modules/@objectstack/spec/src/system/translation.zod.ts` —
346346
`TranslationCoverageResultSchema`, `TranslationDiffItemSchema`.
347347

348-
These schemas back the **optional** contract methods `getCoverage()` and
349-
`suggestTranslations()`, which **no shipped adapter implements** — point coverage
350-
workflows at `os i18n check` / `os lint --i18n-strict` instead.
351-
352348
---
353349

354350
## Integration with II18nService

0 commit comments

Comments
 (0)