From 553f1bffe0db2dcfcae7caa0d3dcc5bc2db8caab Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 27 Jul 2026 13:46:26 +0000 Subject: [PATCH] fix(i18n): clear the accumulated drift in the generated translation bundles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Finishes what #3659 deliberately left alone. That PR regenerated only the `*.objects.generated.ts` bundles and explicitly EXCLUDED the metadata-forms ones, because the same run deleted keys and I had not yet checked whether it was discarding curated translations. It was not — I checked: capabilities.trash / capabilities.mru enable.trash/mru retired in 16.x (#2377); the schema now REJECTS them, with tombstone guidance in UNKNOWN_KEY_GUIDANCE. agent `visibility` removed 2026-07 (#1901). Those are the only deletions in the whole diff, and all three are translations for keys no author can write any more. Nothing live is lost. The same sweep also picks up what the bundles never learned: summaryOperations.{object,function,field,relationshipField,filter} sys_invitation.{business_unit_id,positions} (ADR-0105 D8) and fixes a third, separate problem: `sys_migration`'s labels and help text sat committed as EMPTY STRINGS in the ja-JP and es-ES bundles. An empty string is not an untranslated key — it renders blank, so that object had no readable labels at all in those locales. They now carry the schema text like every other untranslated key. Run in merge mode, so every existing translation is preserved; the only removals are the three dead keys above. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01UYLC8TfjzHGwatNxZKdX7H --- .changeset/i18n-bundle-drift-sweep.md | 30 ++++++++++++ .../en.metadata-forms.generated.ts | 30 ++++++++---- .../apps/translations/en.objects.generated.ts | 8 ++++ .../es-ES.metadata-forms.generated.ts | 30 ++++++++---- .../translations/es-ES.objects.generated.ts | 46 +++++++++++-------- .../ja-JP.metadata-forms.generated.ts | 30 ++++++++---- .../translations/ja-JP.objects.generated.ts | 46 +++++++++++-------- .../zh-CN.metadata-forms.generated.ts | 30 ++++++++---- .../translations/zh-CN.objects.generated.ts | 8 ++++ 9 files changed, 180 insertions(+), 78 deletions(-) create mode 100644 .changeset/i18n-bundle-drift-sweep.md diff --git a/.changeset/i18n-bundle-drift-sweep.md b/.changeset/i18n-bundle-drift-sweep.md new file mode 100644 index 0000000000..42fb467b73 --- /dev/null +++ b/.changeset/i18n-bundle-drift-sweep.md @@ -0,0 +1,30 @@ +--- +"@objectstack/platform-objects": patch +--- + +fix(i18n): clear the accumulated drift in the generated translation bundles + +The committed bundles had fallen behind the spec on three independent axes. +`os i18n extract` (merge mode — every existing translation is preserved) +reconciles all of them: + +**Keys the spec no longer has**, still carrying translations in +`*.metadata-forms.generated.ts`. All three were removed deliberately and are +now *rejected* by the schema, so their entries were dead weight: + +- `capabilities.trash` / `capabilities.mru` — `enable.trash`/`enable.mru` + retired in the 16.x line (#2377), with tombstone guidance in + `UNKNOWN_KEY_GUIDANCE`. +- agent `visibility` — removed 2026-07 (#1901). + +**Keys the spec gained** but the bundles never learned: the +`summaryOperations.*` sub-fields (`object` / `function` / `field` / +`relationshipField` / `filter`), and `sys_invitation.business_unit_id` / +`positions` from the ADR-0105 D8 placement work. + +**Objects stuck on empty strings.** `sys_migration`'s labels and help text were +committed as `""` in the ja-JP and es-ES bundles, which renders as *blank* in +those locales rather than falling back to anything readable. They now carry the +schema text like every other untranslated key. + +No API or schema change — this only affects what the UI displays. diff --git a/packages/platform-objects/src/apps/translations/en.metadata-forms.generated.ts b/packages/platform-objects/src/apps/translations/en.metadata-forms.generated.ts index 26e1073b58..e68b84143c 100644 --- a/packages/platform-objects/src/apps/translations/en.metadata-forms.generated.ts +++ b/packages/platform-objects/src/apps/translations/en.metadata-forms.generated.ts @@ -248,12 +248,6 @@ export const enMetadataForms: NonNullable = { "capabilities.activities": { label: "Activities" }, - "capabilities.trash": { - label: "Trash" - }, - "capabilities.mru": { - label: "Mru" - }, "capabilities.clone": { label: "Clone" }, @@ -428,6 +422,26 @@ export const enMetadataForms: NonNullable = { label: "Summary Operations", helpText: "Roll-up summary configuration (for parent-child relationships)" }, + "summaryOperations.object": { + label: "Object", + helpText: "Child object to aggregate" + }, + "summaryOperations.function": { + label: "Function", + helpText: "Aggregation function" + }, + "summaryOperations.field": { + label: "Field", + helpText: "Child field to aggregate (ignored for count)" + }, + "summaryOperations.relationshipField": { + label: "Relationship Field", + helpText: "Child FK back to this parent (auto-detected when omitted)" + }, + "summaryOperations.filter": { + label: "Filter", + helpText: "Only child rows matching this predicate are aggregated (e.g. status == received)" + }, externalId: { label: "External Id", helpText: "Mark as external ID for upsert operations" @@ -1612,10 +1626,6 @@ export const enMetadataForms: NonNullable = { label: "Knowledge", helpText: "RAG knowledge access configuration" }, - visibility: { - label: "Visibility", - helpText: "Scope: global, organization, or private" - }, access: { label: "Access", helpText: "User IDs or role names who can chat with this agent" diff --git a/packages/platform-objects/src/apps/translations/en.objects.generated.ts b/packages/platform-objects/src/apps/translations/en.objects.generated.ts index c0f045fc36..15bd7814f7 100644 --- a/packages/platform-objects/src/apps/translations/en.objects.generated.ts +++ b/packages/platform-objects/src/apps/translations/en.objects.generated.ts @@ -664,6 +664,14 @@ export const enObjects: NonNullable = { team_id: { label: "Team", help: "Optional team to assign upon acceptance" + }, + business_unit_id: { + label: "Placement Business Unit", + help: "Business unit the invitee is placed under on acceptance (ADR-0105 D8). Must lie inside the issuer's delegated subtree." + }, + positions: { + label: "Placement Positions", + help: "sys_position names assigned on acceptance (ADR-0105 D8). Every position's permission sets must be allowlisted by the issuer's adminScope." } }, _views: { 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 ca592f2ba9..5404014358 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 @@ -248,12 +248,6 @@ export const esESMetadataForms: NonNullable = "capabilities.activities": { label: "Actividades" }, - "capabilities.trash": { - label: "Papelera" - }, - "capabilities.mru": { - label: "Uso reciente" - }, "capabilities.clone": { label: "Clonar" }, @@ -428,6 +422,26 @@ export const esESMetadataForms: NonNullable = label: "Operaciones de resumen", helpText: "Configuración de resumen roll-up (para relaciones padre-hijo)" }, + "summaryOperations.object": { + label: "Object", + helpText: "Child object to aggregate" + }, + "summaryOperations.function": { + label: "Function", + helpText: "Aggregation function" + }, + "summaryOperations.field": { + label: "Field", + helpText: "Child field to aggregate (ignored for count)" + }, + "summaryOperations.relationshipField": { + label: "Relationship Field", + helpText: "Child FK back to this parent (auto-detected when omitted)" + }, + "summaryOperations.filter": { + label: "Filter", + helpText: "Only child rows matching this predicate are aggregated (e.g. status == received)" + }, externalId: { label: "ID externo", helpText: "Marca como ID externo para operaciones upsert" @@ -1612,10 +1626,6 @@ export const esESMetadataForms: NonNullable = label: "Conocimiento", helpText: "Configuración de acceso a conocimiento RAG" }, - visibility: { - label: "Visibilidad", - helpText: "Ámbito: global, organization o private" - }, access: { label: "Acceso", helpText: "IDs de usuario o nombres de rol que pueden chatear con este agente" diff --git a/packages/platform-objects/src/apps/translations/es-ES.objects.generated.ts b/packages/platform-objects/src/apps/translations/es-ES.objects.generated.ts index 196da80060..da367b9647 100644 --- a/packages/platform-objects/src/apps/translations/es-ES.objects.generated.ts +++ b/packages/platform-objects/src/apps/translations/es-ES.objects.generated.ts @@ -664,6 +664,14 @@ export const esESObjects: NonNullable = { team_id: { label: "Equipo", help: "Equipo opcional que se asignará al aceptar." + }, + business_unit_id: { + label: "Placement Business Unit", + help: "Business unit the invitee is placed under on acceptance (ADR-0105 D8). Must lie inside the issuer's delegated subtree." + }, + positions: { + label: "Placement Positions", + help: "sys_position names assigned on acceptance (ADR-0105 D8). Every position's permission sets must be allowlisted by the issuer's adminScope." } }, _views: { @@ -3072,43 +3080,43 @@ export const esESObjects: NonNullable = { } }, sys_migration: { - label: "", - pluralLabel: "", - description: "", + label: "Data Migration", + pluralLabel: "Data Migrations", + description: "Deployment-level data-migration flags: which gated data migrations ran here and whether their self-check passed.", fields: { id: { - label: "", - help: "" + label: "Migration ID", + help: "Well-known migration id (e.g. adr-0104-file-references). One row per migration." }, last_run_at: { - label: "", - help: "" + label: "Last Run At", + help: "When this migration last completed a gated (apply-mode) run on this deployment." }, verified_at: { - label: "", - help: "" + label: "Verified At", + help: "When the self-check last PASSED. Null until it does, and cleared again by a later failing run — a regression closes the gate. Consumers require this to be set AND blocking = 0." }, applied_at: { - label: "", - help: "" + label: "Applied At", + help: "When the backfill last ran in apply mode (writes enabled)." }, blocking: { - label: "", - help: "" + label: "Blocking Discrepancies", + help: "Blocking discrepancies reported by the last self-check. The gate requires 0." }, advisory: { - label: "", - help: "" + label: "Advisory Findings", + help: "Advisory findings from the last run (external URLs, stale owners, …) — cost storage or need a modelling decision, never block the gate." }, details: { - label: "", - help: "" + label: "Details (JSON)", + help: "JSON-encoded counts from the last run, for diagnostics." }, created_at: { - label: "" + label: "Created At" }, updated_at: { - label: "" + label: "Updated At" } } } 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 605f3a7575..e8cc63576d 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 @@ -248,12 +248,6 @@ export const jaJPMetadataForms: NonNullable = "capabilities.activities": { label: "活動" }, - "capabilities.trash": { - label: "ごみ箱" - }, - "capabilities.mru": { - label: "最近使用" - }, "capabilities.clone": { label: "複製" }, @@ -428,6 +422,26 @@ export const jaJPMetadataForms: NonNullable = label: "集計操作", helpText: "ロールアップ集計設定(親子関係用)" }, + "summaryOperations.object": { + label: "Object", + helpText: "Child object to aggregate" + }, + "summaryOperations.function": { + label: "Function", + helpText: "Aggregation function" + }, + "summaryOperations.field": { + label: "Field", + helpText: "Child field to aggregate (ignored for count)" + }, + "summaryOperations.relationshipField": { + label: "Relationship Field", + helpText: "Child FK back to this parent (auto-detected when omitted)" + }, + "summaryOperations.filter": { + label: "Filter", + helpText: "Only child rows matching this predicate are aggregated (e.g. status == received)" + }, externalId: { label: "外部 ID", helpText: "upsert 操作用の外部 ID としてマーク" @@ -1612,10 +1626,6 @@ export const jaJPMetadataForms: NonNullable = label: "ナレッジ", helpText: "RAG ナレッジアクセス設定" }, - visibility: { - label: "可視範囲", - helpText: "スコープ: global, organization, または private" - }, access: { label: "アクセス", helpText: "このエージェントとチャット可能なユーザー ID またはロール名" diff --git a/packages/platform-objects/src/apps/translations/ja-JP.objects.generated.ts b/packages/platform-objects/src/apps/translations/ja-JP.objects.generated.ts index 53c6e8ff72..e1c4208c9b 100644 --- a/packages/platform-objects/src/apps/translations/ja-JP.objects.generated.ts +++ b/packages/platform-objects/src/apps/translations/ja-JP.objects.generated.ts @@ -664,6 +664,14 @@ export const jaJPObjects: NonNullable = { team_id: { label: "チーム", help: "承認時に割り当てるオプションのチーム" + }, + business_unit_id: { + label: "Placement Business Unit", + help: "Business unit the invitee is placed under on acceptance (ADR-0105 D8). Must lie inside the issuer's delegated subtree." + }, + positions: { + label: "Placement Positions", + help: "sys_position names assigned on acceptance (ADR-0105 D8). Every position's permission sets must be allowlisted by the issuer's adminScope." } }, _views: { @@ -3072,43 +3080,43 @@ export const jaJPObjects: NonNullable = { } }, sys_migration: { - label: "", - pluralLabel: "", - description: "", + label: "Data Migration", + pluralLabel: "Data Migrations", + description: "Deployment-level data-migration flags: which gated data migrations ran here and whether their self-check passed.", fields: { id: { - label: "", - help: "" + label: "Migration ID", + help: "Well-known migration id (e.g. adr-0104-file-references). One row per migration." }, last_run_at: { - label: "", - help: "" + label: "Last Run At", + help: "When this migration last completed a gated (apply-mode) run on this deployment." }, verified_at: { - label: "", - help: "" + label: "Verified At", + help: "When the self-check last PASSED. Null until it does, and cleared again by a later failing run — a regression closes the gate. Consumers require this to be set AND blocking = 0." }, applied_at: { - label: "", - help: "" + label: "Applied At", + help: "When the backfill last ran in apply mode (writes enabled)." }, blocking: { - label: "", - help: "" + label: "Blocking Discrepancies", + help: "Blocking discrepancies reported by the last self-check. The gate requires 0." }, advisory: { - label: "", - help: "" + label: "Advisory Findings", + help: "Advisory findings from the last run (external URLs, stale owners, …) — cost storage or need a modelling decision, never block the gate." }, details: { - label: "", - help: "" + label: "Details (JSON)", + help: "JSON-encoded counts from the last run, for diagnostics." }, created_at: { - label: "" + label: "Created At" }, updated_at: { - label: "" + label: "Updated At" } } } 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 94bdb4f935..b6ec4c4fe7 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 @@ -248,12 +248,6 @@ export const zhCNMetadataForms: NonNullable = "capabilities.activities": { label: "活动" }, - "capabilities.trash": { - label: "回收站" - }, - "capabilities.mru": { - label: "最近使用" - }, "capabilities.clone": { label: "克隆" }, @@ -428,6 +422,26 @@ export const zhCNMetadataForms: NonNullable = label: "汇总操作", helpText: "父子关系下的汇总聚合配置" }, + "summaryOperations.object": { + label: "Object", + helpText: "Child object to aggregate" + }, + "summaryOperations.function": { + label: "Function", + helpText: "Aggregation function" + }, + "summaryOperations.field": { + label: "Field", + helpText: "Child field to aggregate (ignored for count)" + }, + "summaryOperations.relationshipField": { + label: "Relationship Field", + helpText: "Child FK back to this parent (auto-detected when omitted)" + }, + "summaryOperations.filter": { + label: "Filter", + helpText: "Only child rows matching this predicate are aggregated (e.g. status == received)" + }, externalId: { label: "外部 ID", helpText: "标记为外部 ID 用于 upsert 操作" @@ -1612,10 +1626,6 @@ export const zhCNMetadataForms: NonNullable = label: "知识", helpText: "RAG 知识访问配置" }, - visibility: { - label: "可见范围", - helpText: "范围:全局、组织或私有" - }, access: { label: "访问", helpText: "可以与此代理对话的用户 ID 或角色名" diff --git a/packages/platform-objects/src/apps/translations/zh-CN.objects.generated.ts b/packages/platform-objects/src/apps/translations/zh-CN.objects.generated.ts index 9215d5eadc..de242374f5 100644 --- a/packages/platform-objects/src/apps/translations/zh-CN.objects.generated.ts +++ b/packages/platform-objects/src/apps/translations/zh-CN.objects.generated.ts @@ -664,6 +664,14 @@ export const zhCNObjects: NonNullable = { team_id: { label: "团队", help: "接受邀请后可选分配的团队" + }, + business_unit_id: { + label: "Placement Business Unit", + help: "Business unit the invitee is placed under on acceptance (ADR-0105 D8). Must lie inside the issuer's delegated subtree." + }, + positions: { + label: "Placement Positions", + help: "sys_position names assigned on acceptance (ADR-0105 D8). Every position's permission sets must be allowlisted by the issuer's adminScope." } }, _views: {