From 6cbd03cbf4492c7ed508dfe38f9a36edfa4b8e98 Mon Sep 17 00:00:00 2001 From: delchev Date: Sat, 15 Aug 2026 22:27:51 +0300 Subject: [PATCH] spec: a report column of a multilingual entity is read in the caller's language Mirrors intent-specification#25 into the rendered chapter: a report column bound to a translatable property is served in the caller's requested language, while what a report MATCHES stays on the stored values - so translating content never changes which rows a report returns. Co-Authored-By: Claude Opus 5 --- docs/reference.md | 2 +- docs/spec/data.md | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/reference.md b/docs/reference.md index 48d8eae..10cdd29 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -51,7 +51,7 @@ The quick lookup surface: one line and a minimal snippet per construct. For rule | [`posts`](/spec/glue#posts-derived-rows-on-an-event) | derived ledger rows emitted idempotently on an event | | [`personal` / `partner`](/spec/surfaces#personal-and-partner-surfaces) | per-user and per-partner row-scoped surfaces | | [`seeds`](/spec/data#seeds) | initial data, CSV-backed sets, translations | -| [`multilingual` / `languages`](/spec/data#multilingual-data) | translation tables + read-time translation overlay | +| [`multilingual` / `languages`](/spec/data#multilingual-data) | translation tables + read-time translation overlay, on entity reads and report columns alike | | [`permissions`](/spec/surfaces#permissions) | roles | ## Snippets diff --git a/docs/spec/data.md b/docs/spec/data.md index d28763d..9d27343 100644 --- a/docs/spec/data.md +++ b/docs/spec/data.md @@ -96,6 +96,12 @@ entities: The set of languages the whole stack supports is a platform concern, never defined per module. The top-level `languages:` only declares which languages this module provides. +A [report](/spec/presentation#reports) reads the same data, so it reads it in the same language: a column bound to a translatable property is shown translated, whether the report is rooted at the multilingual entity or reaches it through a relation. A report grouping by a multilingual nomenclature therefore shows the same term as the pages beside it — before this was stated, a status column could read `DRAFT` next to a list reading the translated word, from the same record. + +::: info Normative +Every read of a translatable property of a `multilingual: true` entity is served in the caller's requested language, and a report column bound to such a property is such a read. What a report **matches** is unaffected: a report's `filter:`, its [`scope`](/spec/presentation#lifecycle-scope) and any condition applied to it are evaluated against the stored, untranslated values — so translating content can never change which rows a report returns, only how they read. A property with no translation for the requested language, and a caller who requested none, both read the stored value. +::: + ### UI labels Generation also emits a per-project translation catalogue for every generated label: entity names (a humanised singular plus a plural form), field labels, form and report names, and report column headers. The default locale is generated for you; a translator adds a sibling locale folder with the same keys. The UI renders through these keys, falling back to the baked default label for any key a locale has not translated.