Category pages now localized.

This commit is contained in:
2026-09-02 17:48:54 +00:00
parent 14a37f5ab3
commit af76277d68
6 changed files with 420 additions and 72 deletions
+38 -7
View File
@@ -74,6 +74,14 @@ Region tags normalize to their base subtag (`fi-FI` → `fi`).
- Navigation/sidebar titles come from the translation's title map, with
per-node fallback to the original title (a partially translated tree must
still render).
- Category placeholder pages (the 404s for content-less labels) select a
language like content pages, but over the **subtree's** combined
availability (`subtree_languages`) — they have no chunks of their own;
the heading, navigation and card text localize from the title map and
the target articles' translations.
- Card descriptions and cover picks run on the target article's hybrid
Markdown where that page is available in the served language, with
per-card fallback to the original.
- Fixed UI strings ("Not Found" etc.) and the editor UI stay English for now.
- The markdown typographer (SmartyPants) is English-centric; per-language
typographer options are a possible follow-up, not blocking.
@@ -211,13 +219,36 @@ def get_translation(path, lang, data) -> Translation | None:
### Editor flow
- `GET` of page Markdown for editing with a `lang` parameter returns the
hybrid (not the raw original) when the article has that language.
- `PUT`/WS save with `lang` does **not** touch `node.chunks`; it diffs
against the hybrid that was served and appends a `Patch`. (Serve a hybrid
generation token with the editor payload so a save based on a stale hybrid
can be rebased or rejected — simplest: recompute the diff against the
*current* hybrid and accept best-effort, matching the patch philosophy.)
The page editor has a language picker (flag + name; the same
country-flag-icons set as the analytics visitor cells) listing the primary
language and the union of the page's translations (`node.langs`) and the
site-wide `translate_langs`. It opens in the language the page was served
in (`<html lang>`). A note under the toolbar states the blast radius:
edits to the primary language re-chunk the original (invalidating the
affected translation fragments everywhere); edits to a translation stay
local to that language.
- WS `open` with a `lang` returns the effective **hybrid** Markdown and
title for that language (ungated by `node.langs` — a language without
any fragments yet starts from the original text), plus the language
metadata (`lang`, `primary_lang`, `langs`, `translate_langs`).
- The editor keeps a **shadow copy** of the Markdown it opened. WS `save`
with `lang` sends it as `base`; the server diffs `base` → submitted text
(`make_patch`) and appends a `Patch`. Diffing against the shadow (rather
than the current hybrid) keeps hunks correct when the original or the
machine translation moved under an open editor; application against the
then-current hybrid stays best-effort per hunk, as designed.
- A changed **title** on a translated save becomes a fragment in
`Data.trans` keyed by the original title's chunk hash — the same storage
as machine title translations. An untouched title field (holding the
served translation) is not sent, so saving never freezes a stale machine
title into an override.
- Saving never deletes; a translation additionally cannot be emptied (that
would render as a blank page in that language).
- The live preview renders the version being edited, whichever language
the page itself was loaded in (the render is just the edited Markdown +
title). A translated save keeps that preview in place — re-fetching the
page would come back in the header-selected language.
- Saving the primary-language version re-chunks the submitted Markdown and
updates `Data.chunks` / `node.chunks` — only genuinely new text lands in
the kanta change diff (see docs/migrate.md).