--- phase: 12-i18n-bugfixes plan: "02" subsystem: ui tags: [alpine, i18n, templates, jinja2, htmx] # Dependency graph requires: - phase: 12-i18n-bugfixes/12-01 provides: Alpine i18n store with FR/EN toggle and browser language auto-detection - phase: 11-ui-enhancements/11-03 provides: i18n store pattern (base.html Alpine translations dictionary) provides: - Extended translation dictionary in base.html with 60+ keys for all pages - All 13 templates fully wired — every UI string bound to $store.i18n.t() affects: - Any future template additions must use x-text=$store.i18n.t() pattern # Tech tracking tech-stack: added: [] patterns: - Alpine x-data x-text on standalone elements outside existing x-data scope - span-wrapper pattern for label text alongside inputs - Jinja2 conditional branches for Alpine-translated conditional values (color/collate/client) - Alpine ternary x-text for boolean fields (yes/no in table cells) key-files: created: [] modified: - imptune/templates/base.html - imptune/templates/dashboard.html - imptune/templates/printers.html - imptune/templates/printers_new.html - imptune/templates/clients.html - imptune/templates/client_detail.html - imptune/templates/drivers.html - imptune/templates/packages.html - imptune/templates/printer_detail.html - imptune/templates/partials/printer_list.html - imptune/templates/partials/printer_edit_modal.html - imptune/templates/partials/client_list.html - imptune/templates/partials/driver_list.html - tests/test_static.py - tests/test_printer_crud.py key-decisions: - "Span-wrapper pattern for label text: since x-text replaces all child nodes" - "Jinja2 conditional branches for Alpine bindings on boolean data (color_mode, collate, client_id) rather than Alpine ternary with Jinja2 boolean values" - "x-data added inline on individual elements without existing x-data ancestor; omitted when already inside x-data parent scope" patterns-established: - "Standalone element pattern:

Fallback

" - "Inside x-data parent: Fallback" - "Boolean table cell: Fallback" - "Jinja2 conditional for Alpine-translated values: {% if printer.color_mode %}
Color
{% else %}
Grayscale
{% endif %}" requirements-completed: [] # Metrics duration: 25min completed: 2026-04-15 --- # Phase 12 Plan 02: Full i18n Template Coverage Summary **60+ translation keys added to base.html and all 13 templates wired — FR/EN toggle now switches every heading, button, table header, label, and empty-state message across all pages** ## Performance - **Duration:** ~25 min - **Started:** 2026-04-15T13:48:00Z - **Completed:** 2026-04-15T14:13:00Z - **Tasks:** 3/3 complete - **Files modified:** 15 ## Accomplishments - Extended the Alpine i18n translations dictionary in base.html with 60+ new keys covering all pages - Wired all 13 templates (7 full-page + 6 partials) — every UI string now uses x-text=$store.i18n.t() binding - Boolean data fields (color mode, collate, client assignment) handled with clean Jinja2 conditional branches - Fixed 2 test assertions that matched strings now present in the i18n JS dictionary (not functional regressions) - Full non-E2E test suite: 122 tests passing ## Task Commits Each task was committed atomically: 1. **Task 1: Add missing translation keys to base.html dictionary** - `e8801ec` (feat) 2. **Task 2: Wire all template strings to i18n store** - `59fc8b1` (feat) 3. **Task 3: Human verification — full i18n coverage on all pages** - approved by user (2026-04-15) ## Files Created/Modified - `imptune/templates/base.html` - Extended translations.fr and translations.en with 60+ new keys - `imptune/templates/dashboard.html` - h1, quick actions, section headings, empty states wired - `imptune/templates/printers.html` - h1, add button, printer library heading wired - `imptune/templates/printers_new.html` - all form labels (span pattern), options, submit buttons wired - `imptune/templates/clients.html` - headings, label, submit button wired - `imptune/templates/client_detail.html` - back link and section heading wired - `imptune/templates/drivers.html` - all headings, label, buttons, upload spinner wired - `imptune/templates/packages.html` - heading, description, table headers, empty state wired - `imptune/templates/printer_detail.html` - all dt/dd labels, copy buttons, script/export links wired with Jinja2 conditionals for boolean fields - `imptune/templates/partials/printer_list.html` - table headers, Yes/No cells (Alpine ternary), delete button wired - `imptune/templates/partials/printer_edit_modal.html` - edit trigger, modal title, all labels (span pattern), options, save/cancel wired - `imptune/templates/partials/client_list.html` - empty state, table headers wired - `imptune/templates/partials/driver_list.html` - table headers, unknown values, empty state wired - `tests/test_static.py` - Fix test_dashboard_shows_recent_packages assertion - `tests/test_printer_crud.py` - Fix test_printers_library_no_form assertion ## Decisions Made - Span-wrapper pattern for label text (since x-text replaces all child nodes, a `` inside the label isolates the translated text from the input child) - Jinja2 conditional branches for boolean Alpine bindings rather than Alpine ternary with Jinja2 boolean values — cleaner and avoids Alpine/Jinja2 interpolation issues - x-data added inline on individual standalone elements; omitted when already inside an x-data parent scope ## Deviations from Plan ### Auto-fixed Issues **1. [Rule 1 - Bug] Fixed test_dashboard_shows_recent_packages assertion matching i18n dictionary** - **Found during:** Task 1 (adding translation keys) - **Issue:** Test checked `assert "No packages exported yet" not in response.text` — string now appears in base.html i18n JS dictionary, causing false failure - **Fix:** Changed assertion to `assert 'class="empty-state">No packages exported yet' not in response.text` matching the existing pattern used in test_dashboard_shows_recent_printers - **Files modified:** tests/test_static.py - **Verification:** test_static.py 6 passed - **Committed in:** e8801ec (Task 1 commit) **2. [Rule 1 - Bug] Fixed test_printers_library_no_form assertion matching i18n dictionary** - **Found during:** Task 2 (wiring templates) - **Issue:** Test checked `assert "Save Printer" not in html` — string now appears in base.html i18n JS dictionary, causing false failure - **Fix:** Changed assertion to `assert 'action="/printers" method="post"' not in html` — checks for the actual form element, not a label string - **Files modified:** tests/test_printer_crud.py - **Verification:** 122 tests passing - **Committed in:** 59fc8b1 (Task 2 commit) --- **Total deviations:** 2 auto-fixed (2 Rule 1 - Bug — test assertions now incorrectly matched i18n dictionary content) **Impact on plan:** Both fixes necessary for test correctness — not behavioral regressions. No scope creep. ## Issues Encountered None beyond the test assertion fixes documented above. ## User Setup Required None - no external service configuration required. ## Next Phase Readiness - All template strings are wired; FR/EN toggle will update all visible UI text - Human verification (Task 3) approved 2026-04-15 — user confirmed all strings switch correctly between FR and EN on every page - Plan 12-02 is complete; phase 12 can proceed to 12-03 (if any) or close --- *Phase: 12-i18n-bugfixes* *Completed: 2026-04-15*