From f1589848a7e905e732d65ceb1a3849b00ab5906f Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 20 Sep 2026 15:50:05 +0000 Subject: [PATCH 1/4] fix(platform-objects): translate the report/dataset panel leaves this card decided Twelve label leaves and nine helpText leaves at the four keys #19355 names shipped byte-identical to their `en` source in `zh-CN`, `ja-JP` and `es-ES`. Each was judged per leaf; every one is an unauthored extractor fill, not a rendering decision, and the evidence is per key in the PR body. Claude-Session: https://claude.ai/code/session_01NcPSwnmJHczmTu6FG7NMjE Co-authored-by: Claude --- .../translations/es-ES.metadata-forms.generated.ts | 14 +++++++------- .../translations/ja-JP.metadata-forms.generated.ts | 14 +++++++------- .../translations/zh-CN.metadata-forms.generated.ts | 14 +++++++------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/packages/platform-objects/src/apps/translations/es-ES.metadata-forms.generated.ts b/packages/platform-objects/src/apps/translations/es-ES.metadata-forms.generated.ts index e7fee7c0876..bfef86d9c7c 100644 --- a/packages/platform-objects/src/apps/translations/es-ES.metadata-forms.generated.ts +++ b/packages/platform-objects/src/apps/translations/es-ES.metadata-forms.generated.ts @@ -1398,16 +1398,16 @@ export const esESMetadataForms: NonNullable = helpText: "Tipo de informe: tabular/summary/matrix/joined" }, dataset: { - label: "Dataset", - helpText: "Dataset to bind (measures/dimensions come from its semantic layer)" + label: "Conjunto de datos", + helpText: "Conjunto de datos a vincular (las medidas/dimensiones provienen de su capa semántica)" }, values: { - label: "Values", - helpText: "Measure names (from the dataset) to display" + label: "Medidas", + helpText: "Nombres de medida (del conjunto de datos) que se mostrarán" }, rows: { - label: "Rows", - helpText: "Dimension names (from the dataset) to group rows by" + label: "Filas", + helpText: "Nombres de dimensión (del conjunto de datos) por los que agrupar las filas" }, columns: { label: "Columnas", @@ -1540,7 +1540,7 @@ export const esESMetadataForms: NonNullable = label: "Granularidad de fecha" }, measures: { - label: "Measures", + label: "Medidas", helpText: "Cada medida: nombre, agregación, campo (opcional para count) y formato de visualización/moneda" }, "measures.name": { diff --git a/packages/platform-objects/src/apps/translations/ja-JP.metadata-forms.generated.ts b/packages/platform-objects/src/apps/translations/ja-JP.metadata-forms.generated.ts index 6537e9fd1b8..0fd43e68a36 100644 --- a/packages/platform-objects/src/apps/translations/ja-JP.metadata-forms.generated.ts +++ b/packages/platform-objects/src/apps/translations/ja-JP.metadata-forms.generated.ts @@ -1398,16 +1398,16 @@ export const jaJPMetadataForms: NonNullable = helpText: "レポート種別: tabular/summary/matrix/joined" }, dataset: { - label: "Dataset", - helpText: "Dataset to bind (measures/dimensions come from its semantic layer)" + label: "データセット", + helpText: "バインドするデータセット(メジャー/ディメンションはセマンティックレイヤーから取得)" }, values: { - label: "Values", - helpText: "Measure names (from the dataset) to display" + label: "メジャー", + helpText: "表示するメジャー名(データセットから取得)" }, rows: { - label: "Rows", - helpText: "Dimension names (from the dataset) to group rows by" + label: "行", + helpText: "行をグループ化するディメンション名(データセットから取得)" }, columns: { label: "列", @@ -1540,7 +1540,7 @@ export const jaJPMetadataForms: NonNullable = label: "日付の粒度" }, measures: { - label: "Measures", + label: "メジャー", helpText: "各メジャー:名前、集計関数、フィールド(count の場合は省略可)、表示形式/通貨" }, "measures.name": { diff --git a/packages/platform-objects/src/apps/translations/zh-CN.metadata-forms.generated.ts b/packages/platform-objects/src/apps/translations/zh-CN.metadata-forms.generated.ts index 5df9a8c39cf..34c532953ac 100644 --- a/packages/platform-objects/src/apps/translations/zh-CN.metadata-forms.generated.ts +++ b/packages/platform-objects/src/apps/translations/zh-CN.metadata-forms.generated.ts @@ -1398,16 +1398,16 @@ export const zhCNMetadataForms: NonNullable = helpText: "报表类型:tabular / summary / matrix / joined" }, dataset: { - label: "Dataset", - helpText: "Dataset to bind (measures/dimensions come from its semantic layer)" + label: "数据集", + helpText: "要绑定的数据集(度量/维度来自其语义层)" }, values: { - label: "Values", - helpText: "Measure names (from the dataset) to display" + label: "度量", + helpText: "要展示的度量名(来自该数据集)" }, rows: { - label: "Rows", - helpText: "Dimension names (from the dataset) to group rows by" + label: "行", + helpText: "用于分组行的维度名(来自该数据集)" }, columns: { label: "列", @@ -1540,7 +1540,7 @@ export const zhCNMetadataForms: NonNullable = label: "日期粒度" }, measures: { - label: "Measures", + label: "度量", helpText: "每个度量:名称、聚合函数、字段(count 时可省略)、显示格式/货币" }, "measures.name": { From cb33fdeafed3feec1bf4ce14c131c87457062a64 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 20 Sep 2026 15:50:33 +0000 Subject: [PATCH 2/4] chore(platform-objects): regenerate the i18n source-hash provenance tables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `pnpm i18n:extract` — the command this package's extract config documents. It rewrote all eleven bundles; the three translated `metadata-forms` bundles round-tripped byte-identical, and the only change is the 21 provenance rows for the leaves the previous commit translated, which the extractor drops because those leaves are no longer byte copies of their `en` source. Claude-Session: https://claude.ai/code/session_01NcPSwnmJHczmTu6FG7NMjE Co-authored-by: Claude --- .../src/apps/translations/es-ES.source-hashes.generated.ts | 7 ------- .../src/apps/translations/ja-JP.source-hashes.generated.ts | 7 ------- .../src/apps/translations/zh-CN.source-hashes.generated.ts | 7 ------- 3 files changed, 21 deletions(-) diff --git a/packages/platform-objects/src/apps/translations/es-ES.source-hashes.generated.ts b/packages/platform-objects/src/apps/translations/es-ES.source-hashes.generated.ts index e363a4f12aa..d9b9b79f661 100644 --- a/packages/platform-objects/src/apps/translations/es-ES.source-hashes.generated.ts +++ b/packages/platform-objects/src/apps/translations/es-ES.source-hashes.generated.ts @@ -47,7 +47,6 @@ export const esESGeneratedSourceHashes: Readonly> = { "metadataForms.dataset.fields.include.label": "45b27393fb9f3b2a", "metadataForms.dataset.fields.label.helpText": "f0cbad8e334db1d3", "metadataForms.dataset.fields.label.label": "c680364257b11569", - "metadataForms.dataset.fields.measures.label": "395dac46abcf1943", "metadataForms.dataset.fields.name.helpText": "8c3cae6dba12b42a", "metadataForms.dataset.fields.name.label": "5274417ff1ccaf01", "metadataForms.dataset.fields.object.helpText": "09a85579054a7197", @@ -195,16 +194,10 @@ export const esESGeneratedSourceHashes: Readonly> = { "metadataForms.page.fields.interfaceConfig.userFilters.label": "7e2bbb262bd29aa1", "metadataForms.page.sections.interface.description": "7e60b977279a05dc", "metadataForms.page.sections.interface.label": "e2280abc5267ddec", - "metadataForms.report.fields.dataset.helpText": "3cd157f274c985df", - "metadataForms.report.fields.dataset.label": "19647dcb84ce82d3", "metadataForms.report.fields.drilldown.helpText": "778174eac8057764", "metadataForms.report.fields.drilldown.label": "25ae77d240ced5f5", - "metadataForms.report.fields.rows.helpText": "4307edcc3f3097b5", - "metadataForms.report.fields.rows.label": "319af74cc41ea823", "metadataForms.report.fields.runtimeFilter.helpText": "eb9ba8aeb55b7d40", "metadataForms.report.fields.runtimeFilter.label": "90fe0e44293633fa", - "metadataForms.report.fields.values.helpText": "0cd8bc86069a89d1", - "metadataForms.report.fields.values.label": "3edea9880d8fee80", "metadataForms.report.sections.dataset_binding.description": "54650ff5f09fd1bd", "metadataForms.report.sections.dataset_binding.label": "34d97a3093d6fc56", "metadataForms.seed.description": "c22921feb0f06273", diff --git a/packages/platform-objects/src/apps/translations/ja-JP.source-hashes.generated.ts b/packages/platform-objects/src/apps/translations/ja-JP.source-hashes.generated.ts index 2962b7a4356..0f0cea2d343 100644 --- a/packages/platform-objects/src/apps/translations/ja-JP.source-hashes.generated.ts +++ b/packages/platform-objects/src/apps/translations/ja-JP.source-hashes.generated.ts @@ -47,7 +47,6 @@ export const jaJPGeneratedSourceHashes: Readonly> = { "metadataForms.dataset.fields.include.label": "45b27393fb9f3b2a", "metadataForms.dataset.fields.label.helpText": "f0cbad8e334db1d3", "metadataForms.dataset.fields.label.label": "c680364257b11569", - "metadataForms.dataset.fields.measures.label": "395dac46abcf1943", "metadataForms.dataset.fields.name.helpText": "8c3cae6dba12b42a", "metadataForms.dataset.fields.name.label": "5274417ff1ccaf01", "metadataForms.dataset.fields.object.helpText": "09a85579054a7197", @@ -195,16 +194,10 @@ export const jaJPGeneratedSourceHashes: Readonly> = { "metadataForms.page.fields.interfaceConfig.userFilters.label": "7e2bbb262bd29aa1", "metadataForms.page.sections.interface.description": "7e60b977279a05dc", "metadataForms.page.sections.interface.label": "e2280abc5267ddec", - "metadataForms.report.fields.dataset.helpText": "3cd157f274c985df", - "metadataForms.report.fields.dataset.label": "19647dcb84ce82d3", "metadataForms.report.fields.drilldown.helpText": "778174eac8057764", "metadataForms.report.fields.drilldown.label": "25ae77d240ced5f5", - "metadataForms.report.fields.rows.helpText": "4307edcc3f3097b5", - "metadataForms.report.fields.rows.label": "319af74cc41ea823", "metadataForms.report.fields.runtimeFilter.helpText": "eb9ba8aeb55b7d40", "metadataForms.report.fields.runtimeFilter.label": "90fe0e44293633fa", - "metadataForms.report.fields.values.helpText": "0cd8bc86069a89d1", - "metadataForms.report.fields.values.label": "3edea9880d8fee80", "metadataForms.report.sections.dataset_binding.description": "54650ff5f09fd1bd", "metadataForms.report.sections.dataset_binding.label": "34d97a3093d6fc56", "metadataForms.seed.description": "c22921feb0f06273", diff --git a/packages/platform-objects/src/apps/translations/zh-CN.source-hashes.generated.ts b/packages/platform-objects/src/apps/translations/zh-CN.source-hashes.generated.ts index 625e5efd321..64e90a33bdd 100644 --- a/packages/platform-objects/src/apps/translations/zh-CN.source-hashes.generated.ts +++ b/packages/platform-objects/src/apps/translations/zh-CN.source-hashes.generated.ts @@ -47,7 +47,6 @@ export const zhCNGeneratedSourceHashes: Readonly> = { "metadataForms.dataset.fields.include.label": "45b27393fb9f3b2a", "metadataForms.dataset.fields.label.helpText": "f0cbad8e334db1d3", "metadataForms.dataset.fields.label.label": "c680364257b11569", - "metadataForms.dataset.fields.measures.label": "395dac46abcf1943", "metadataForms.dataset.fields.name.helpText": "8c3cae6dba12b42a", "metadataForms.dataset.fields.name.label": "5274417ff1ccaf01", "metadataForms.dataset.fields.object.helpText": "09a85579054a7197", @@ -162,16 +161,10 @@ export const zhCNGeneratedSourceHashes: Readonly> = { "metadataForms.page.fields.interfaceConfig.userFilters.label": "7e2bbb262bd29aa1", "metadataForms.page.sections.interface.description": "7e60b977279a05dc", "metadataForms.page.sections.interface.label": "e2280abc5267ddec", - "metadataForms.report.fields.dataset.helpText": "3cd157f274c985df", - "metadataForms.report.fields.dataset.label": "19647dcb84ce82d3", "metadataForms.report.fields.drilldown.helpText": "778174eac8057764", "metadataForms.report.fields.drilldown.label": "25ae77d240ced5f5", - "metadataForms.report.fields.rows.helpText": "4307edcc3f3097b5", - "metadataForms.report.fields.rows.label": "319af74cc41ea823", "metadataForms.report.fields.runtimeFilter.helpText": "eb9ba8aeb55b7d40", "metadataForms.report.fields.runtimeFilter.label": "90fe0e44293633fa", - "metadataForms.report.fields.values.helpText": "0cd8bc86069a89d1", - "metadataForms.report.fields.values.label": "3edea9880d8fee80", "metadataForms.report.sections.dataset_binding.description": "54650ff5f09fd1bd", "metadataForms.report.sections.dataset_binding.label": "34d97a3093d6fc56", "metadataForms.seed.description": "c22921feb0f06273", From 02eb69bb6d9dbc20ec9e9b747e95fbbae6ca398e Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 20 Sep 2026 15:53:19 +0000 Subject: [PATCH 3/4] test(platform-objects): pin the report/dataset panel echo decisions as a ledger One row per string leaf of the four keys #19355 names, each carrying the verdict and the reason it was reached. The population is a list because the neighbouring derived pin cannot take these keys: widening its 124 enumerated repeater row properties to all 417 declared form-field paths lands red on 230 echo leaves across 82 keys nobody has decided yet. Claude-Session: https://claude.ai/code/session_01NcPSwnmJHczmTu6FG7NMjE Co-authored-by: Claude --- ...eport-dataset-panel-echo-decisions.test.ts | 224 ++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 packages/platform-objects/src/apps/translations/report-dataset-panel-echo-decisions.test.ts diff --git a/packages/platform-objects/src/apps/translations/report-dataset-panel-echo-decisions.test.ts b/packages/platform-objects/src/apps/translations/report-dataset-panel-echo-decisions.test.ts new file mode 100644 index 00000000000..a826b345d22 --- /dev/null +++ b/packages/platform-objects/src/apps/translations/report-dataset-panel-echo-decisions.test.ts @@ -0,0 +1,224 @@ +// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. +// +// #19355 — the DECISION LEDGER for the report / dataset panel en-echoes. +// +// An en-echo is not automatically a defect: a leaf that reads its English +// source may be an unauthored extractor fill, or it may be the right rendering +// for that locale. The two are byte-identical, so the distinction cannot be +// recovered from the catalog later — it has to be RECORDED when someone looks. +// This file is that record for the four keys #19355 names, one row per string +// leaf, each with the verdict and the reason it was reached. +// +// Why the population here is a LIST while `repeater-row-properties.test.ts` +// DERIVES its own. That file's population is the enumerated repeater row +// properties — 124 of them, measured on this base — and these four keys are +// top-level form fields, outside it. Widening that derivation to all declared +// form-field paths (417, same base) would be red on 230 further echo leaves +// across 82 keys the moment it landed: neighbouring debt nobody has decided +// yet. A pin that lands red is not a pin, so the derived population stays as +// #17508 drew it, and the DECIDED leaves are enumerated here instead. A key +// enters this list when someone judges it, never before. +// +// The instrument that measured the verdicts, with both of its controls, is the +// package's own provenance table `.source-hashes.generated.ts`: an +// entry exists exactly while the leaf is still a byte copy of the source +// revision. Every leaf this card found echoing carried one in all three +// locales (positive control); `dataset.fields.measures.helpText`, the one leaf +// at these keys that a translator had already written, carried none in any of +// them (negative control). `pnpm i18n:extract` dropped the 21 rows for the +// leaves this card translated, so the table now records them as authored. +// +// ⛔ Do not add a row here to make a red go away. A row is a decision someone +// took about one leaf; the `echo` verdict needs its own per-locale reason +// precisely so that recording "the English is right here" costs a sentence. + +import { describe, it, expect } from 'vitest'; + +import { enMetadataForms } from './en.metadata-forms.generated.js'; +import { zhCNMetadataForms } from './zh-CN.metadata-forms.generated.js'; +import { jaJPMetadataForms } from './ja-JP.metadata-forms.generated.js'; +import { esESMetadataForms } from './es-ES.metadata-forms.generated.js'; + +const TRANSLATED_LOCALES: ReadonlyArray]> = [ + ['zh-CN', zhCNMetadataForms as Record], + ['ja-JP', jaJPMetadataForms as Record], + ['es-ES', esESMetadataForms as Record], +]; + +/** `translate` — the echo was an unauthored fill. `echo` — the English IS the rendering. */ +type Verdict = 'translate' | 'echo'; + +interface Decision { + /** Metadata type owning the form panel. */ + type: string; + /** The bundle key under `.fields`. */ + key: string; + /** Which string leaf of that entry this row decides. */ + prop: 'label' | 'helpText'; + /** + * The `en` source the verdict was taken against. Held equal to the live + * bundle, so a reworded source reds this file instead of leaving a decision + * standing over text nobody judged. + */ + en: string; + /** The verdict per translated locale. */ + verdict: Readonly>; + /** Why — recorded for `translate` as much as for `echo`. */ + reason: string; + /** Required for every `echo` verdict: why the English is right in THAT locale. */ + departures?: Readonly>; +} + +const ALL_TRANSLATE: Readonly> = { + 'zh-CN': 'translate', + 'ja-JP': 'translate', + 'es-ES': 'translate', +}; + +const SIBLING_PRECEDENT = + 'The same panel carries the identical concept one repeater level down, with text #19345 authored deliberately in all three locales. A translator who judged the English word right at the top level would not have written the translated one a few entries below it, so the echo was a fill, not a rendering.'; + +const DECISIONS: readonly Decision[] = [ + { + type: 'report', + key: 'dataset', + prop: 'label', + en: 'Dataset', + verdict: ALL_TRANSLATE, + reason: `${SIBLING_PRECEDENT} Precedent: report.fields['blocks.dataset'].`, + }, + { + type: 'report', + key: 'dataset', + prop: 'helpText', + en: 'Dataset to bind (measures/dimensions come from its semantic layer)', + verdict: ALL_TRANSLATE, + reason: + 'Prose, not a term of art, and it was a byte copy in all three locales while the sibling helpTexts on the same panel (type, columns, order, chart) were authored. A fill.', + }, + { + type: 'report', + key: 'values', + prop: 'label', + en: 'Values', + verdict: ALL_TRANSLATE, + reason: `${SIBLING_PRECEDENT} Precedent: report.fields['blocks.values'].`, + }, + { + type: 'report', + key: 'values', + prop: 'helpText', + en: 'Measure names (from the dataset) to display', + verdict: ALL_TRANSLATE, + reason: + 'Prose. Its own sibling order.helpText names the same two vocabularies (rows/columns dimensions, values measures) in authored text in every locale, so the vocabulary existed and this leaf simply never got it.', + }, + { + type: 'report', + key: 'rows', + prop: 'label', + en: 'Rows', + verdict: ALL_TRANSLATE, + reason: `${SIBLING_PRECEDENT} Precedent: report.fields['blocks.rows'], and the adjacent top-level columns is authored on the same panel.`, + }, + { + type: 'report', + key: 'rows', + prop: 'helpText', + en: 'Dimension names (from the dataset) to group rows by', + verdict: ALL_TRANSLATE, + reason: + 'Prose, and the neighbouring columns.helpText — the same sentence for the other axis — is authored in all three locales. Nothing distinguishes the two but one having been reached.', + }, + { + type: 'dataset', + key: 'measures', + prop: 'label', + en: 'Measures', + verdict: ALL_TRANSLATE, + reason: + 'The sharpest case: the SAME leaf carried a hand-authored helpText in all three locales while its label was a byte copy of the source. One leaf cannot be a decision and a fill at once, and the helpText settles which one it was.', + }, + { + type: 'dataset', + key: 'measures', + prop: 'helpText', + en: 'Each: name, aggregate, field (optional for count), and display format/currency', + verdict: ALL_TRANSLATE, + reason: + 'Already authored before this card in all three locales — recorded because it is this ledger\'s negative control: the one leaf at these four keys that held no provenance-table entry, which is what an authored leaf looks like.', + }, +]; + +/** The leaf a row points at, in a given catalog. */ +function leafOf(forms: Record, d: Decision): unknown { + return forms[d.type]?.fields?.[d.key]?.[d.prop]; +} + +describe('#19355 — the ledger itself (controls before verdicts)', () => { + it('decides every string leaf of the four keys the card names, and nothing else', () => { + // Lit — the ledger is the size it claims: four keys, eight leaves, three + // locales, 24 decisions. + expect(DECISIONS.length).toBe(8); + expect(new Set(DECISIONS.map((d) => `${d.type}.fields.${d.key}`))).toEqual( + new Set(['report.fields.values', 'report.fields.rows', 'report.fields.dataset', 'dataset.fields.measures']), + ); + expect(DECISIONS.flatMap((d) => Object.keys(d.verdict)).length).toBe(24); + for (const d of DECISIONS) { + expect(Object.keys(d.verdict).sort(), `${d.type}.${d.key}.${d.prop} names every translated locale`).toEqual([ + 'es-ES', + 'ja-JP', + 'zh-CN', + ]); + } + }); + + it('every row is pinned to the live `en` source it was decided against', () => { + for (const d of DECISIONS) { + expect( + (enMetadataForms as Record)[d.type]?.fields?.[d.key]?.[d.prop], + `en ${d.type}.fields.${d.key}.${d.prop} moved — re-judge the decision, do not refresh this row`, + ).toBe(d.en); + } + }); + + it('the echo predicate can say "echo" — fed the `en` catalog, it flags every row', () => { + // Dark. `translated !== en` is the whole verdict test below; run it against + // the source catalog itself and it must fail for all 8 rows, or a green + // verdict run means nothing. + const flagged = DECISIONS.filter((d) => leafOf(enMetadataForms as Record, d) === d.en); + expect(flagged.length).toBe(DECISIONS.length); + }); + + it('every decision records a reason, and every `echo` records its per-locale departure', () => { + for (const d of DECISIONS) { + expect(d.reason.length, `${d.type}.fields.${d.key}.${d.prop} records no reason`).toBeGreaterThan(40); + for (const [locale, verdict] of Object.entries(d.verdict)) { + if (verdict !== 'echo') continue; + const departure = d.departures?.[locale] ?? ''; + expect( + departure.length, + `${locale} ${d.type}.fields.${d.key}.${d.prop} is a declared echo with no reason — an undeclared echo is the debt this ledger exists to tell apart`, + ).toBeGreaterThan(40); + } + } + }); +}); + +describe('#19355 — the catalogs hold what the ledger decided', () => { + for (const [locale, forms] of TRANSLATED_LOCALES) { + it(`${locale}: every decided leaf matches its verdict`, () => { + for (const d of DECISIONS) { + const id = `${locale} ${d.type}.fields.${d.key}.${d.prop}`; + const value = leafOf(forms, d); + expect(typeof value, `${id} is missing from the catalog`).toBe('string'); + expect((value as string).length, `${id} is empty`).toBeGreaterThan(0); + if (d.verdict[locale] === 'translate') { + expect(value, `${id} reads its en source again — the decision was that this echo is a fill`).not.toBe(d.en); + } else { + expect(value, `${id} is a declared echo and must stay the en source`).toBe(d.en); + } + } + }); + } +}); From 68049082b9db68def033820be0b7887b373c8205 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 20 Sep 2026 16:18:09 +0000 Subject: [PATCH 4/4] chore(changeset): patch @objectstack/platform-objects for the translated panel leaves MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Measured rather than assumed: the package is not `private`, `files[]` ships `dist`, and the new strings reach five published entry points there (`index.js`/`index.mjs`, `plugin.js`/`plugin.mjs`, `metadata-translations/index.*`) — the same five a pre-existing translated leaf on the same panel reaches. So the diff publishes and `skip-changeset` would be wrong. Claude-Session: https://claude.ai/code/session_01NcPSwnmJHczmTu6FG7NMjE Co-authored-by: Claude --- .changeset/lucky-pugs-repeat.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/lucky-pugs-repeat.md diff --git a/.changeset/lucky-pugs-repeat.md b/.changeset/lucky-pugs-repeat.md new file mode 100644 index 00000000000..b6d733200cc --- /dev/null +++ b/.changeset/lucky-pugs-repeat.md @@ -0,0 +1,7 @@ +--- +'@objectstack/platform-objects': patch +--- + +Translate the report and dataset form panel leaves that shipped their English source in every locale + +Four metadata-form keys — `report.fields.dataset`, `report.fields.values`, `report.fields.rows` and `dataset.fields.measures` — carried labels byte-identical to their `en` source in `zh-CN`, `ja-JP` and `es-ES`, so an author working in a translated locale read English on those two panels while everything around them was translated. Twelve label leaves and nine `helpText` leaves at the same four keys are now translated; each was judged individually, and the verdicts with their reasons are pinned in `report-dataset-panel-echo-decisions.test.ts`. No key was added, removed or renamed — the bundles' shape is unchanged.