Files
carei.pagedev.pl/.paul/phases/16-i18n-plugin-refactor/16-01-SUMMARY.md
2026-04-22 22:00:50 +02:00

157 lines
8.0 KiB
Markdown

---
phase: 16-i18n-plugin-refactor
plan: 01
subsystem: i18n
tags: [polylang, gettext, pot, wp-localize-script, textdomain, elementor]
requires:
- phase: 13-protection-packages
provides: panel WP pakietów SOFT/PREMIUM
- phase: 15-remove-softra-insurance
provides: czysty pricelist bez Softra-insurance
provides:
- textdomain 'carei-reservation' ładowany na plugins_loaded
- wszystkie user-facing PHP stringi w __()/esc_html__()/esc_attr__()
- helper I18N/t()/tFmt()/pluralPl() w carei-reservation.js
- wp_localize_script('careiI18n', [...]) z 78 kluczami
- languages/carei-reservation.pot (157 msgid)
affects: [17-bilingual-packages, 18-en-translation]
tech-stack:
added: []
patterns:
- "Helper I18N + t(key, fallback) w JS z obiektem window.careiI18n"
- "pluralPl(n, one, few, many) — polskie reguły pluralizacji (1=one, 2-4 bez 12-14=few, reszta=many)"
- "Drop Softra passthrough errors z tłumaczenia — mapowanie zostaje na Phase 17"
key-files:
created:
- wp-content/plugins/carei-reservation/languages/carei-reservation.pot
modified:
- wp-content/plugins/carei-reservation/carei-reservation.php
- wp-content/plugins/carei-reservation/includes/class-elementor-widget.php
- wp-content/plugins/carei-reservation/includes/class-admin-panel.php
- wp-content/plugins/carei-reservation/includes/class-rest-proxy.php
- wp-content/plugins/carei-reservation/includes/class-search-widget.php
- wp-content/plugins/carei-reservation/includes/class-cities-widget.php
- wp-content/plugins/carei-reservation/includes/class-map-widget.php
- wp-content/plugins/carei-reservation/includes/class-branches-widget.php
- wp-content/plugins/carei-reservation/assets/js/carei-reservation.js
key-decisions:
- "Bootstrap: wp_localize_script dla careiI18n leci w wp_enqueue_scripts (nie w Elementor widget render) — obiekt dostępny na każdej stronie gdzie ładowany jest skrypt"
- "Helper get_status_label() zamiast statycznej tablicy labels w Admin panelu — pozwala tłumaczyć w runtime po załadowaniu textdomain"
- "Softra API passthrough errors nietłumaczone w Phase 16 — Phase 17 zajmie się mapowaniem"
- "Fallback english w t()/tFmt() = oryginalny polski string (żeby bez .po strona dalej działała po polsku)"
patterns-established:
- "Klucze careiI18n: camelCase, grupowane semantycznie (selectX, btnX, labelX, errorX, thX, rejectX, announceX)"
- "Multi-line UI stringi z HTML (np. <strong>%count% %unit%</strong>) przez wp_kses po stronie PHP, renderowane jako innerHTML w JS"
duration: ~45min
started: 2026-04-22
completed: 2026-04-22
---
# Phase 16 Plan 01: i18n refactor pluginu — Summary
**Plugin carei-reservation przygotowany do dwujęzyczności: 8 plików PHP owiniętych w funkcje gettext, JS zmigrowany do obiektu `window.careiI18n` przez `wp_localize_script`, wygenerowany `.pot` z 157 unikalnymi msgid gotowy do tłumaczenia w Phase 18.**
## Performance
| Metric | Value |
|--------|-------|
| Duration | ~45min |
| Tasks | 3 auto + 1 human-verify completed |
| Files modified | 9 |
| Files created | 1 (.pot) |
| Delegation | 5 agentów równolegle (1 elementor-widget, 1 admin-panel, 1 JS, 1 dla 4 widgetów, 1 .pot) |
## Acceptance Criteria Results
| Criterion | Status | Notes |
|-----------|--------|-------|
| AC-1: PHP i18n kompletny, textdomain załadowany | Pass | `load_plugin_textdomain` na plugins_loaded; ~105 stringów PHP owiniętych |
| AC-2: JS migrated do careiI18n, brak regresji w PL | Pass | `window.careiI18n` = 78 kluczy, grep diakrytyków w JS = 0 poza fallbackami/API payloads; human-verify PL OK |
| AC-3: .pot wygenerowany | Pass | 157 msgid, UTF-8, nagłówek poprawny, msgstr puste |
## Accomplishments
- **8 plików PHP** z user-facing stringami w funkcjach i18n (carei-reservation, elementor-widget, admin-panel, rest-proxy, search/cities/map/branches widgets)
- **`carei-reservation.js`** (1573 linie) — ~70 literałów przez `t()`/`tFmt()` + helper `pluralPl()` dla polskich form
- **`wp_localize_script('careiI18n', [...])`** z 78 kluczami w bootstrapie
- **`.pot`** gotowy do tłumaczenia — 157 unikalnych msgid w `languages/`
- Dekonstrukcja admin-panelu: statyczna tablica labels statusów rozbita na helper `get_status_label()` (wymóg WP — translation w runtime)
- Zgoda RODO z osadzonym `<a>` — owinięcie przez `wp_kses(__(...))`
## Files Created/Modified
| File | Change | Purpose |
|------|--------|---------|
| `carei-reservation.php` | Modified | load_plugin_textdomain + wp_localize_script('careiI18n', 78 kluczy) |
| `includes/class-elementor-widget.php` | Modified | ~30 stringów (Elementor controls + HTML modal) |
| `includes/class-admin-panel.php` | Modified | ~55 stringów + helper get_status_label() |
| `includes/class-rest-proxy.php` | Modified | 2 stringi (Invalid nonce, Softra not configured) |
| `includes/class-search-widget.php` | Modified | 8 stringów (hero search form) |
| `includes/class-cities-widget.php` | Modified | 1 string (get_title) |
| `includes/class-map-widget.php` | Modified | 3 stringi (Oddział %s, ul. %s, get_title) |
| `includes/class-branches-widget.php` | Modified | 3 stringi |
| `assets/js/carei-reservation.js` | Modified | ~70 literałów → t()/tFmt() + helpery + pluralPl() |
| `languages/carei-reservation.pot` | Created | 157 msgid, UTF-8, ready for Phase 18 |
## Decisions Made
| Decision | Rationale | Impact |
|----------|-----------|--------|
| `careiI18n` w bootstrapie (nie w Elementor render) | Skrypt jest rejestrowany w bootstrapie → localize leci raz, dostępne globalnie | Upraszcza architekturę, nie ma per-widget duplikacji |
| Fallback w `t('key', 'polski string')` | Bez .mo plik dalej działa po polsku; bez niego crashowałoby `undefined` | Zero-downtime dla PL, bezpieczne wrap bez straty funkcjonalności |
| Softra error messages nietłumaczone | Zewnętrzne API zwraca polskie błędy — mapowanie = Phase 17 | Zostaje jasna granica między „nasze" a „Softra" stringami |
| Statuses slugi niezmienione (`nowe`/`przeczytane`/`zrealizowane`) | Dane w DB, klucze logiki; tylko UI labels idą przez `get_status_label()` | Brak regresji w filtrach i warunkach logicznych |
## Deviations from Plan
### Summary
| Type | Count | Impact |
|------|-------|--------|
| Auto-fixed | 1 | Admin panel: statyczna tablica statuses → helper (konieczne dla WP i18n timing) |
| Scope additions | 0 | — |
| Deferred | 1 | Softra API error mapping (świadomie przełożone na Phase 17) |
### Auto-fixed Issues
**1. [Admin panel] Statyczna tablica `$statuses` z labels nie może być tłumaczona przed init**
- Found during: Task 1 (admin-panel refactor)
- Issue: Tablica jako property klasy = translation wywoływane przed załadowaniem textdomain → pusty string
- Fix: Rozbicie na helper `get_status_label($key)` z switchem, wywoływany w runtime po plugins_loaded
- Files: class-admin-panel.php
- Verification: human-verify PL — statusy na liście, w dropdown i meta boxie wyglądają identycznie jak przed
### Deferred Items
- Phase 17: mapowanie ~10-15 typowych komunikatów Softra API na lokalizowane wersje (np. `Brak pojazdów w tym terminie` → reject key + tłumaczenie)
## Issues Encountered
None.
## Next Phase Readiness
**Ready:**
- `.pot` z 157 msgid — gotowy input dla Phase 18 (tłumaczenie na EN przez GPT-4.1 mini lub Loco Translate)
- Infrastruktura i18n kompletna — Phase 17 i 18 mogą budować na niej bez refactoru
- Polski UI działa bez regresji (confirmed by user: „język polski jest ok.")
**Concerns:**
- `window.careiI18n` rośnie (78 kluczy) — dla performance można rozważyć lazy-load w przyszłości, ale na razie ~3KB JSON to szum
- Niektóre msgid zawierają HTML (`Wybrano: <strong>%count% %unit%</strong>`) — wymagają translatora świadomego tagów; .pot ma to oznaczone wp_kses whitelist
- Softra error messages (Phase 17) — w JS są klucze `rejectCarNotFound` itd. jako fallbacki, ale aktualny kod Phase 16 nie używa jeszcze mapowania → Phase 17 musi dodać warstwę w rest-proxy lub softra-api
**Blockers:** None.
---
*Phase: 16-i18n-plugin-refactor, Plan: 01*
*Completed: 2026-04-22*