81 lines
4.9 KiB
Markdown
81 lines
4.9 KiB
Markdown
# ISSUE-277 Artifact — shared i18n registry parity report (Django ↔ Angular MVP)
|
|
|
|
Issue: **#277** (`[READY][#175][P3] Shared i18n registry artifact: backend/frontend keyspace parity report`)
|
|
|
|
## Artifact metadata
|
|
|
|
- `artifact_id`: `issue-277-shared-i18n-parity-report`
|
|
- `artifact_version`: `1.0`
|
|
- `catalog_source`: `shared/i18n/lobby.json`
|
|
- `generator`: `scripts/report_i18n_parity.py`
|
|
|
|
## Naming/version rules (email-manager-inspired strategy)
|
|
|
|
- **Single canonical artifact per issue**: issue-bundne rapporter navngives `docs/ISSUE-<nr>-<slug>-ARTIFACT.md`.
|
|
- **Stable artifact identity**: `artifact_id` ændres ikke ved tekstlige opdateringer i samme rapporttype; det er den faste reference i review/ops.
|
|
- **Explicit artifact versioning**: `artifact_version` bumpes, når rapportlogik eller scope ændres, så drift/review kan se forskel på format- vs. dataændringer.
|
|
- **Shared namespace first**: keys refereres med fulde navnerum (`frontend.ui.*`, `frontend.errors.*`, `backend.error_codes.*`, `backend.errors.*`) i stedet for lokale aliases i artefakter.
|
|
- **Source-of-truth before consumers**: rapporten afledes fra `shared/i18n/lobby.json`; Django/Angular beskrives som consumers af samme registry og ikke som parallelle kontrakter.
|
|
|
|
## MVP-critical parity summary
|
|
|
|
- Frontend UI gameplay keys checked: **16** → `OK`
|
|
- Frontend error keys checked: **7** → `OK`
|
|
- Backend gameplay/error codes checked: **9** → `OK`
|
|
- Distinct frontend error keys reached from backend MVP flow: **6** (`join_failed, nickname_invalid, nickname_taken, session_code_required, session_not_found, start_round_failed`)
|
|
|
|
Status: **Shared locale matrix is aligned (`en`, `da`) and backend→frontend error handling is contract-complete for MVP-critical flow.**
|
|
|
|
## Django ↔ Angular parity matrix (MVP-critical error contract)
|
|
|
|
| Backend code (`backend.error_codes.*`) | Django message key (`backend.errors.*`) | Angular key (`frontend.errors.*`) | Locales `en/da` | Parity note |
|
|
|---|---|---|---|---|
|
|
| `session_code_required` | `session_code_required` | `session_code_required` | `OK` | 1:1 |
|
|
| `nickname_invalid` | `nickname_invalid` | `nickname_invalid` | `OK` | 1:1 |
|
|
| `session_not_found` | `session_not_found` | `session_not_found` | `OK` | 1:1 |
|
|
| `session_not_joinable` | `session_not_joinable` | `join_failed` | `OK` | mapped alias |
|
|
| `nickname_taken` | `nickname_taken` | `nickname_taken` | `OK` | 1:1 |
|
|
| `category_slug_required` | `category_slug_required` | `start_round_failed` | `OK` | many:1 collapse |
|
|
| `category_not_found` | `category_not_found` | `start_round_failed` | `OK` | many:1 collapse |
|
|
| `round_start_invalid_phase` | `round_start_invalid_phase` | `start_round_failed` | `OK` | many:1 collapse |
|
|
| `round_already_configured` | `round_already_configured` | `start_round_failed` | `OK` | many:1 collapse |
|
|
|
|
## Scope notes
|
|
|
|
- **Django** consumes backend codes/messages directly from `shared/i18n/lobby.json` via `lobby/i18n.py`.
|
|
- **Angular** consumes the same registry via `frontend/shared/i18n/lobby-loader.ts` and runtime helpers in `frontend/angular/src/app/lobby-i18n.ts`.
|
|
- **Parity in MVP** is therefore strongest on the shared error contract and locale matrix; gameplay UI labels are frontend-owned but still live in the same registry.
|
|
|
|
## Verified MVP gameplay UI keyspace present in the shared registry
|
|
|
|
- `frontend.ui.host.title`
|
|
- `frontend.ui.player.title`
|
|
- `frontend.ui.common.session_code`
|
|
- `frontend.ui.player.nickname`
|
|
- `frontend.ui.player.join`
|
|
- `frontend.ui.host.start_round`
|
|
- `frontend.ui.host.show_question`
|
|
- `frontend.ui.player.lie_label`
|
|
- `frontend.ui.player.submit_lie`
|
|
- `frontend.ui.player.submit_guess`
|
|
- `frontend.ui.host.mix_answers`
|
|
- `frontend.ui.host.calculate_scores`
|
|
- `frontend.ui.host.load_scoreboard`
|
|
- `frontend.ui.host.final_leaderboard`
|
|
- `frontend.ui.player.final_leaderboard`
|
|
- `frontend.ui.common.points_short`
|
|
|
|
## Concrete deviations / follow-up items
|
|
|
|
1. **Error granularity collapse remains intentional**: backend codes `category_slug_required, category_not_found, round_start_invalid_phase, round_already_configured` all map to `frontend.errors.start_round_failed`. Follow-up only if product wants case-specific Angular copy instead of one shared host failure message.
|
|
2. **Frontend-only fallback copy is not mirrored in Django**: `frontend.errors.unknown` and `frontend.errors.session_fetch_failed` are Angular-side resilience keys, not backend contract keys. Follow-up if API responses should expose stable backend equivalents for these states.
|
|
3. **Gameplay UI labels are registry-shared but not backend-rendered**: `frontend.ui.host.*`, `frontend.ui.player.*`, and `frontend.ui.common.*` are available in the shared artifact, but Django currently consumes only the backend error slice. Follow-up only if server-rendered views must guarantee the same UI label surface as Angular.
|
|
|
|
## Re-run
|
|
|
|
```bash
|
|
python3 scripts/check_i18n_drift.py
|
|
python3 scripts/report_i18n_parity.py
|
|
python3 scripts/check_i18n_parity_artifact.py
|
|
```
|