localise chrome, smooth prose, in English and Bengali
The engine now owns the words it puts on a page that the author did not write (ADR-0034). `internal/render/chrome.go` holds the phrase table, Gregorian month names and decimal digits per language, keyed phrase-then-language so both forms sit side by side and a half-translated row is visible while reading. Templates reach it through `t`, `num` and `day`, registered before parsing so a site override's blocks may call them too. The reference theme stops hardcoding English: "Newer", "Page 2 of 2" and every date now come from the table, while `datetime` attributes stay ASCII because a parser reads them. Authored text gets goldmark's typographer and nothing else — quotes, dashes and ellipses smoothed, code spans untouched because it works on the parsed tree. It is a parser option rather than a function over a page, so the transforms counter does not move; state.md now says why, so the next reader does not miscount. Deliberately absent: relative dates, which need a validity window that only the cache entry will have, and body widow prevention, which cannot be done safely by a pass over rendered HTML.
This commit is contained in:
+23
-1
@@ -50,6 +50,28 @@ A listing page receives `.Title`, `.Lang`, `.Canonical`, `.Style` as above, plus
|
||||
| `.PrevURL`, `.NextURL` | empty at the ends; *newer* is `prev`, because the order is newest first |
|
||||
| `.Groups` | set instead of `.Items` when entries are grouped — a tag listing groups by section, each `.Name` and `.Items` |
|
||||
|
||||
## Chrome text and formatting
|
||||
|
||||
Three functions, available in every template including a site root's own blocks. They exist so no template
|
||||
hardcodes English: the words the engine supplies are the engine's to localise (ADR-0034).
|
||||
|
||||
| Call | Gives |
|
||||
|---|---|
|
||||
| `{{t .Lang "newer"}}` | one phrase in that language. Extra arguments fill `%s` placeholders in order |
|
||||
| `{{num .Lang .Page}}` | an integer in that language's digits — `12`, `১২` |
|
||||
| `{{day .Lang .Date}}` | a date as that language reads it — `8 March 2026`, `৮ মার্চ ২০২৬`; empty for a zero date |
|
||||
|
||||
Phrase keys today: `newer`, `older`, `empty`, `page-of` (two arguments), `position` (two arguments). An
|
||||
unknown language falls back to the default locale and an unknown key returns itself, so a missing
|
||||
translation can never blank a page or fail a render.
|
||||
|
||||
Two rules a theme must keep: put the machine-readable form in the attribute and the localised form in the
|
||||
text — `<time datetime="{{.Date.Format "2006-01-02"}}">{{day .Lang .Date}}</time>` — and never localise
|
||||
`.Title`, `.HTML` or anything else the author wrote.
|
||||
|
||||
A site root cannot add or override a phrase yet. A theme needing its own words writes them in its own
|
||||
block; site-supplied strings wait for the settings cascade (`ideas/deferred-decisions.md`).
|
||||
|
||||
## The stability rule
|
||||
|
||||
Fields and names are **added, never renamed or removed**. Absence is always legal: a template reading a
|
||||
@@ -69,7 +91,7 @@ Breaking the contract is not a feature — it is a new contract version, and it
|
||||
| named template lookup | per-type sets; a theme redefines a named block and inherits the rest (ADR-0019) |
|
||||
| URLs | every path the engine emits, so a theme never constructs one by hand |
|
||||
| per-page assets | the `styles` / `scripts` frontmatter lists, resolved relative to the bundle |
|
||||
| chrome strings | looked up by key and language, never hardcoded English in a template |
|
||||
| chrome strings | looked up by key and language, never hardcoded English in a template — live, see above |
|
||||
| validity windows | a template that renders time-dependent output declares one |
|
||||
|
||||
## Extras view
|
||||
|
||||
Reference in New Issue
Block a user