record ADR-0034: chrome text is the engine's, body text is the author's

Draws the line by who wrote the words. Labels, counts, month names and digits
come from an engine table keyed by (key, language) so no template hardcodes
English; authored prose is never localised and never rewritten beyond goldmark's
typographer. Machine-readable output stays ASCII in every locale.

Decided before the code, because the alternative — localising body text — is the
kind of choice that is expensive to walk back once published.
This commit is contained in:
2026-08-01 02:23:35 +06:00
parent 7789242185
commit 206974650d
+20
View File
@@ -402,3 +402,23 @@ needs a Query over some other field, not this; and membership now depends on the
ADR-0008 makes permanent, so re-parenting a chapter is a permalink event with an alias.
Revisit if: a real collection must span sections. Then it is a declared taxonomy (ADR-0032's second
half), not a change to how a series is joined.
## ADR-0034 — Chrome text is the engine's; body text is the author's
Date: 2026-07-30 · Status: accepted
Decision: every word the engine puts on a page that the author did not write — labels, page counts,
month names, digits — comes from a table in the engine keyed by (key, language), reached from templates
through `t`, `num` and `day`, so no template hardcodes English. Authored body text is never localised and
never rewritten beyond typographic smoothing, which is goldmark's typographer: quotes, dashes, ellipses,
code spans untouched. Machine-readable output — `datetime`, URLs, anything a parser reads — stays ASCII
whatever the locale.
Why: a Bengali page that says "Page 2 of 3" in English is broken, and a theme cannot fix it without
hardcoding the very strings a theme must not own (theme-contract.md). Meanwhile the opposite mistake is
worse: localising body text means the engine editing prose, and Bengali numerals inside an author's
sentence are the author's decision, not the renderer's. So the line is drawn by *who wrote the words*.
Consequence: cheap — a new label is one table row with both languages beside each other, and a missing
translation falls back to the default locale and then to the key, so it can never blank a page or fail a
render. Expensive — the engine now carries human-language strings, which is a small localisation surface
that grows with the theme; a site root cannot yet add or override a key, so a theme needing its own words
must write them in its own block.
Revisit if: a site root needs its own chrome strings. That is the settings cascade's problem
(`ideas/deferred-decisions.md`), not a second table.