docs(backlog): add WP-18..22 (productie-volwassenheid phase)
Some checks failed
CI / storybook-a11y (push) Successful in 4m12s
CI / backend (push) Successful in 1m6s
CI / api-client-drift (push) Successful in 1m37s
CI / frontend (push) Successful in 1m31s
CI / codeql (csharp) (push) Failing after 1m51s
CI / codeql (javascript-typescript) (push) Failing after 1m24s
Some checks failed
CI / storybook-a11y (push) Successful in 4m12s
CI / backend (push) Successful in 1m6s
CI / api-client-drift (push) Successful in 1m37s
CI / frontend (push) Successful in 1m31s
CI / codeql (csharp) (push) Failing after 1m51s
CI / codeql (javascript-typescript) (push) Failing after 1m24s
Gap analysis found the POC's designed-but-unbuilt strategic gaps: ABAC authorization (ADR-0002/PRD-0002 phase P1), no e2e coverage, unproven i18n second-locale seam, thin resilience seams (correlation-id, idempotency, retry), and in-memory-only persistence. Each WP is grounded in the current code (file paths + line numbers), not just the analysis. Also corrects PRD-0001's stale 'Proposed' status header — the Mijn aanvragen vertical is fully built. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
101
docs/backlog/WP-20-second-locale.md
Normal file
101
docs/backlog/WP-20-second-locale.md
Normal file
@@ -0,0 +1,101 @@
|
||||
# WP-20 — Second locale proof
|
||||
|
||||
Status: todo
|
||||
Phase: 5 — productie-volwassenheid
|
||||
|
||||
## Why
|
||||
|
||||
CLAUDE.md's conventions claim "a second locale is a translation file, not a code
|
||||
change (the seam)" — every user-facing string is already wrapped in `$localize`
|
||||
with a stable `@@context.key` id. But `angular.json` has no `i18n` block, no
|
||||
`locales` config, and there is no extracted `.xlf` file anywhere in the repo. The
|
||||
seam is built into every component but never proven to actually work end to end.
|
||||
|
||||
## Read first
|
||||
|
||||
- `CLAUDE.md` "User-facing copy = `$localize`" convention
|
||||
- `angular.json` (current build config — no `i18n` section)
|
||||
- A handful of `$localize` call sites to confirm id conventions are consistent
|
||||
enough to extract cleanly: `src/app/shared/application/submit.ts`
|
||||
(`@@submit.failed`), `src/app/registratie/domain/value-objects/postcode.ts`
|
||||
(`@@validation.postcode`)
|
||||
- Angular's `@angular/localize` extraction tooling (`ng extract-i18n`) — no new
|
||||
dependency needed, it ships with the Angular CLI already in use
|
||||
|
||||
## Decisions (pre-made, don't relitigate)
|
||||
|
||||
- **English (`en`) is the second locale** — arbitrary but concrete; proves the
|
||||
mechanism without requiring a real translator. Machine-translate or hand-write a
|
||||
handful of strings, mark the rest with an obvious placeholder prefix if time-boxed
|
||||
(e.g. `[EN] ` prefix) rather than leaving them silently untranslated — silent
|
||||
fallback-to-source would look like the feature works when it's actually untested.
|
||||
- **Source locale stays `nl`**, unchanged (CLAUDE.md is explicit about this).
|
||||
- **Build-time locale switching** (Angular's standard `i18n` merge, separate output
|
||||
per locale), not a runtime-swappable locale — that matches how `$localize` +
|
||||
Angular CLI actually work and avoids inventing a custom i18n runtime.
|
||||
- This WP proves the seam; it does not translate the whole app to production
|
||||
quality. A partial/placeholder `en` file is acceptable if every string has _some_
|
||||
translation (even if imperfect) — the acceptance bar is "the build seam works and
|
||||
every id resolves," not "the English copy is publication-ready."
|
||||
|
||||
## Files
|
||||
|
||||
- `angular.json` — add `i18n.sourceLocale: "nl"` and `i18n.locales.en` pointing at
|
||||
the new translation file; add an `en` configuration under `build`/`serve` that
|
||||
merges it (standard Angular CLI i18n scaffolding, `ng add @angular/localize` if
|
||||
the schematic isn't already fully wired).
|
||||
- New `src/locale/messages.en.xlf` (or `.json`, whichever `ng extract-i18n`
|
||||
defaults to) — the translation file, generated then filled in.
|
||||
- `package.json` — add `"extract-i18n": "ng extract-i18n --output-path src/locale"`
|
||||
script.
|
||||
- `.github/workflows/ci.yml` — extend the `frontend` job (or add a step) to build
|
||||
both locales: `ng build --localize` (builds all configured locales in one pass)
|
||||
or two explicit `ng build --configuration=production,en` invocations — pick
|
||||
whichever the Angular 22 CLI supports cleanly and document the choice inline.
|
||||
- `README.md` — note the second-locale build under "Tech notes," replacing the
|
||||
implicit claim with a demonstrated one (link to how to build/run the `en` locale).
|
||||
|
||||
## Steps
|
||||
|
||||
1. Run `ng extract-i18n` once to generate the master translation file from every
|
||||
`$localize`/`i18n="@@id"` call site; commit it as the `nl` reference (or the tool's
|
||||
default source-language artifact, per Angular's convention).
|
||||
2. Copy it to `messages.en.xlf`, fill in English text for every `<trans-unit>`
|
||||
(or your chosen placeholder strategy per the Decisions above).
|
||||
3. Wire `angular.json`'s `i18n` block + an `en` build configuration.
|
||||
4. `ng build --localize` (or the two-configuration equivalent) — confirm two output
|
||||
bundles (`dist/.../nl/`, `dist/.../en/`) each serve correctly with `ng serve
|
||||
--configuration=en` or a static server against the `en` output.
|
||||
5. Wire CI to build both locales as part of the existing `build` step (or a
|
||||
parallel step) so a broken translation file fails CI, not just a local build.
|
||||
6. Spot-check the `en` build in a browser: login page, dashboard, one wizard step —
|
||||
confirm English strings render, layout doesn't break on longer/shorter text.
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- [ ] `ng extract-i18n` runs clean (no missing/duplicate `@@id`s).
|
||||
- [ ] `messages.en.xlf` exists with a translation for every extracted unit.
|
||||
- [ ] `ng build --localize` (or equivalent) produces both an `nl` and an `en` output
|
||||
bundle in CI, and CI fails if the `en` file is missing a unit the source gains.
|
||||
- [ ] Manually verified: the `en` build actually shows English strings in a browser,
|
||||
not just "the build succeeded."
|
||||
|
||||
## Verification
|
||||
|
||||
`npm run extract-i18n` locally, diff against the committed file to confirm no drift;
|
||||
`ng build --localize` locally, serve the `en` output, click through login →
|
||||
dashboard → one wizard. GREEN gate stays green (the `nl` build is unaffected).
|
||||
|
||||
## Out of scope
|
||||
|
||||
Professional/accurate English translation (placeholder-quality is acceptable per
|
||||
Decisions); a locale switcher in the running app UI (build-time locale selection
|
||||
only, per Decisions); RTL locales or pluralization edge cases beyond what
|
||||
`$localize` already handles by default.
|
||||
|
||||
## Risks
|
||||
|
||||
`ng extract-i18n` may surface `$localize` call sites with inconsistent or missing
|
||||
`@@id`s that currently work fine at runtime (ids are optional for `$localize` to
|
||||
function, but required for clean extraction) — budget time to add ids where
|
||||
missing rather than treating every gap as a bug to fix elsewhere.
|
||||
Reference in New Issue
Block a user