|
| 1 | +--- |
| 2 | +"@objectstack/spec": minor |
| 3 | +--- |
| 4 | + |
| 5 | +`translatePage` now reads a region-level `page:header` by **page name only**. The id route |
| 6 | +(`pages.<page>.components.<headerId>.*`) is no longer read for that component, even when it carries an `id`. |
| 7 | + |
| 8 | +**Behaviour change, stated plainly:** a bundle that overrode a region-level header's title through |
| 9 | +`pages.<page>.components.<headerId>.title` now falls back to `pages.<page>.title` (which itself falls back to |
| 10 | +`pages.<page>.label`). The components key still parses — nothing is removed from `TranslationBundleSchema` — it is |
| 11 | +simply no longer the address for this one component. |
| 12 | + |
| 13 | +``` |
| 14 | +FROM pages.<page>.components.<headerId>.title # region-level page:header — no longer read |
| 15 | +TO pages.<page>.title # …and .subtitle for the subtitle |
| 16 | +``` |
| 17 | + |
| 18 | +Fix in one line: move the string from the components entry up to the page's own `title` key, and delete the |
| 19 | +components entry for that header id. `os i18n extract` has always offered exactly the `TO` key, so a bundle |
| 20 | +generated or checked by the CLI already writes it. |
| 21 | + |
| 22 | +**Blast radius, as measured on the card (inherited, not re-measured here):** HotCRM found **zero** such overrides — |
| 23 | +all five of its region-level headers carry ids and none writes the components key. |
| 24 | + |
| 25 | +**Why.** Both sides were deliberate and they disagreed. The extractor skips a region-level `page:header` on purpose |
| 26 | +(its copy is offered under `pages.<page>.title` / `.subtitle`, and emitting it twice would put one string under two |
| 27 | +keys); the resolver read the id route on purpose (the more specific route wins). Together they produced the exact |
| 28 | +failure `walkAddressedPageComponents` was extracted to prevent — the resolver reading an id the extractor omits — so |
| 29 | +the key an author reached for won silently while the key the tooling reported as translated lost. The maintainer |
| 30 | +ruled (2026-09-06, decision batch #58, verbatim 「同意」) that the page-name route is canonical: one component, one |
| 31 | +address. `title` and `subtitle` now follow the same rule, closing the asymmetry where `title` had two addresses and |
| 32 | +`subtitle` — never in `PAGE_COMPONENT_COPY_KEYS` — had one. |
| 33 | + |
| 34 | +Unchanged: a `page:header` **nested** inside a container is reached by the id route only, as it always has been; and |
| 35 | +a region-level header's id still claims its bundle entry and still blocks a nested namesake, which is what the |
| 36 | +extractor does too. |
| 37 | + |
| 38 | +Not `major`: nothing an author can write is removed or renamed. `pages.<page>.components.<id>` remains a declared, |
| 39 | +parsing, resolving address for every other component — including a nested `page:header` — so there is no key to |
| 40 | +tombstone and no ADR-0087 conversion to register. Recorded here so the choice is checkable rather than assumed. |
0 commit comments