1f695d3932
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
47 lines
3.8 KiB
Markdown
47 lines
3.8 KiB
Markdown
# I18N_SPEC.md
|
||
|
||
## 1. Architecture summary
|
||
|
||
Three i18n concerns, three mechanisms — never mixed:
|
||
|
||
| Concern | Mechanism | Examples |
|
||
|---|---|---|
|
||
| **Routes** | Astro built-in i18n (defaultLocale `en` at root, `no` prefixed) + slug map module | `/projects/jobtrack` ↔ `/no/prosjekter/jobtrack` |
|
||
| **UI strings** (~60 keys) | Typed dictionary modules per locale + `t(key)` accessor, compile-time checked | `nav.projects`, `cv.download`, `form.error.email`, `a11y.skipLink` |
|
||
| **Content** (prose, case studies, experience) | Content collections with per-locale entries sharing one zod schema | `projects/en/jobtrack.md` + `projects/no/jobtrack.md` |
|
||
|
||
No runtime i18n library. Locale is resolved from the URL at build time; every page is rendered once per locale into static HTML.
|
||
|
||
## 2. Dictionary spec
|
||
|
||
- Shape: nested typed object; both locale files implement the same interface → a missing key is a **compile error**, not a runtime fallback.
|
||
- Keys are semantic (`cv.download`), never English-sentence keys.
|
||
- Interpolation: simple `{param}` tokens only; no plural engine (the ~3 plural cases are written out per locale).
|
||
- A11y strings are first-class dictionary entries: skip-link, lang-switch announcement ("Bytt til norsk" labelled *in the target language* per MICRO_INTERACTIONS), image alt patterns, form validation messages.
|
||
|
||
## 3. Content collection localisation
|
||
|
||
- Each collection folder splits `en/` and `no/`; entries share the same filename (`jobtrack.md`) = the join key.
|
||
- One schema validates both locales (DATA_MODEL.md); locale-invariant fields (dates, stack chips, links, image refs, status) live in the EN entry and are **inherited** by the NO entry at load time (a small content-loader utility merges them) — this is the anti-duplication mechanism: facts exist once, prose exists twice.
|
||
- Section anchors: schema field `anchorId` per section, per locale (`architecture`/`arkitektur`) with the pageId-level mapping used by the language switch to land on the equivalent section (J5).
|
||
|
||
## 4. Fallback rules (build-time, never runtime)
|
||
|
||
1. **Full parity is the shipping rule.** CI parity test: every EN content entry has a NO twin and vice versa; every dictionary key present in both.
|
||
2. **Temporary asymmetry** (a new case study written EN-first): the NO twin must still exist, containing a native-Norwegian summary + link "Full versjon på engelsk" (CONTENT_STRATEGY rule). The schema supports `summaryOnly: true` for this state; CI allows it but the sitemap/hreflang still emit correctly.
|
||
3. No silent English fallback ever renders on a `/no/` page — a Norwegian reader must never hit unexplained English mid-page. (Machine translation is banned outright.)
|
||
|
||
## 5. Locale-sensitive rendering rules
|
||
|
||
- `<html lang>`: `en-GB` / `nb-NO` per page. Date formatting: `2015–2023` style is locale-neutral; long dates use locale month names via `Intl` at build time.
|
||
- Quotes: “ ” (EN) / « » (NO) — enforced in content review, not code.
|
||
- The CV split-button defaults to the *current page locale's* CV; stored language preference overrides on EN pages only if the user previously chose NO (subtle: preference sets default, page locale is tiebreak).
|
||
- OG/meta per locale (SEO_SPEC). `hreflang` emitted from the slug map: `en`, `nb`, `x-default → en`.
|
||
|
||
## 6. Translation management workflow
|
||
|
||
- Author EN and NO in the same PR (content files sit side by side; the parity test enforces it).
|
||
- Norwegian quality gate before launch: native/fluent review pass of all NO content (tracked as a Phase 3 exit criterion; the reviewer reviews *markdown files in a PR*, which keeps review diffs clean — a deliberate benefit of content-in-git).
|
||
- Glossary (CONTENT_STRATEGY §5.3) lives as a comment header in the NO dictionary file so it's in front of whoever edits translations.
|
||
- No TMS tooling: two locales, one author, git history is the audit trail.
|