record ADR-0035: a slug belongs to the bundle, not to a variant

Confirms ADR-0009's "same path" clause against the alternative that was on the
table: a Bengali variant at its own Bengali address. Chosen: one path per bundle,
prefixed per language, so identity stays stable across translations (invariant 3)
and the resolver keeps one lookup direction.

The declined option is named in the ADR so it is not re-proposed as new. Cost is
stated too — a Bengali reader sees a Latin address, and reversing this later needs
an alias for every published path.

No code moves: `slug` is still unread. Recorded now because nothing is published
yet, which is the only cheap moment a permalink decision has.
This commit is contained in:
Claude Opus 5
2026-07-30 10:12:18 +06:00
committed by bdeshi
parent df46cd517c
commit 374a4a6e99
2 changed files with 22 additions and 3 deletions
+4 -3
View File
@@ -72,7 +72,7 @@ readable by templates (ADR-0002). Never add a required field.
| `title` | string | Only required field | | `title` | string | Only required field |
| `date` / `updated` | date | Publication; `updated` drives feeds and `Last-Modified`. An unquoted `2026-07-30` or an RFC 3339 timestamp; undated bundles sort after dated ones | | `date` / `updated` | date | Publication; `updated` drives feeds and `Last-Modified`. An unquoted `2026-07-30` or an RFC 3339 timestamp; undated bundles sort after dated ones |
| `type` | string | Post type; defaults from the top-level section | | `type` | string | Post type; defaults from the top-level section |
| `slug` | string | Overrides the derived slug. The engine serves the new path only; the old one 404s unless it appears in `aliases` | | `slug` | string | Overrides the derived slug for the bundle in **every** language (ADR-0035). The engine serves the new path only; the old one 404s unless it appears in `aliases`. Two variants declaring different slugs is ambiguous — logged, dropped, derived path kept |
| `aliases` | []string | Paths the engine redirects permanently to this bundle's canonical URL (ADR-0008). A scalar or a list; surrounding slashes optional. An alias naming a real bundle, or claimed by two bundles, is ambiguous — logged and dropped, and the real bundle keeps its URL | | `aliases` | []string | Paths the engine redirects permanently to this bundle's canonical URL (ADR-0008). A scalar or a list; surrounding slashes optional. An alias naming a real bundle, or claimed by two bundles, is ambiguous — logged and dropped, and the real bundle keeps its URL |
| `draft` | bool | Excluded from queries and feeds | | `draft` | bool | Excluded from queries and feeds |
| `nocache` | bool | Never cache this bundle's render. Named so absence means cacheable, per ADR-0002 | | `nocache` | bool | Never cache this bundle's render. Named so absence means cacheable, per ADR-0002 |
@@ -146,8 +146,9 @@ bundle between sections changes the URL the engine emits, and the old path resol
**No path segment is ever localised.** Reserved segments stay `page` and `tags` in every language, page **No path segment is ever localised.** Reserved segments stay `page` and `tags` in every language, page
numbers stay ASCII digits, and a slug is whatever the key says: `/bn/lekha/page/2/`, never a translated numbers stay ASCII digits, and a slug is whatever the key says: `/bn/lekha/page/2/`, never a translated
spelling of it. Localisation is for the words around the content, never the address of it (ADR-0034). A spelling of it. Localisation is for the words around the content, never the address of it (ADR-0034). A
Bengali variant is therefore reached at the English key under a prefix — `/bn/posts/hello-world/` — and Bengali variant is therefore reached at the same key under a prefix — `/bn/posts/hello-world/`. A `slug`
the only thing that can change a variant's path is a `slug` override, which the parser does not read yet. override renames the bundle in every language at once (ADR-0035); nothing gives one variant an address of
its own. The parser does not read `slug` yet.
A language prefix wins over a section of the same name, so a site with Bengali content may not also have A language prefix wins over a section of the same name, so a site with Bengali content may not also have
a section called `bn`. The engine treats a leading segment as a language only when some bundle is written a section called `bn`. The engine treats a leading segment as a language only when some bundle is written
+18
View File
@@ -422,3 +422,21 @@ that grows with the theme; a site root cannot yet add or override a key, so a th
must write them in its own block. must write them in its own block.
Revisit if: a site root needs its own chrome strings. That is the settings cascade's problem 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. (`ideas/deferred-decisions.md`), not a second table.
## ADR-0035 — A slug belongs to the bundle, not to a variant
Date: 2026-07-30 · Status: accepted (confirms ADR-0009's "same path" clause against a per-language address)
Decision: `slug` renames the bundle in every language, so a variant is always reached at the bundle's one
path under its language prefix — `/posts/hello-world/` and `/bn/posts/hello-world/`, never a Bengali
spelling of the address. Where two variants declare different slugs the declaration is ambiguous: log both
and keep the derived path, the same way colliding keys and contested aliases are handled (ADR-0029). The
engine never derives a slug from a title in any language; a path changes only because an author wrote one.
Why: the alternative makes the path a function of (key, language) rather than of the key alone, which
costs a second lookup direction in the resolver and a permalink shape that differs per language — while
invariant 3 says identity is stable across translations and ADR-0009 already promised the same path under
a prefix. A Bengali-looking address is a real reader benefit, but not one worth a second identity rule
before anything is published.
Consequence: cheap — one path shape, one lookup direction, `/bn/` stays pure prefixing, and a translation
can be added or dropped without touching a URL. Expensive — a Bengali reader sees a Latin address, and
changing that later needs this decision reversed plus an alias for every path already published.
Revisit if: Bengali becomes the dominant language of the site — the trigger ADR-0009 already names. That
is a default-language change, not per-variant slugs.