139 lines
7.0 KiB
Markdown
139 lines
7.0 KiB
Markdown
---
|
|
phase: 17-bilingual-packages-and-softra-errors
|
|
plan: 01
|
|
subsystem: i18n
|
|
tags: [polylang, softra-errors, rest-api, protection-packages, bilingual]
|
|
|
|
requires:
|
|
- phase: 13-protection-packages
|
|
provides: panel WP pakietów SOFT/PREMIUM + REST /protection-packages
|
|
- phase: 16-i18n-plugin-refactor
|
|
provides: textdomain carei-reservation + __() we wszystkich plikach
|
|
|
|
provides:
|
|
- Pola name_en / description_en w panelu pakietów + zapis/odczyt
|
|
- REST /protection-packages zwraca wariant per locale (z fallbackiem PL)
|
|
- Carei_Softra_API::extract_softra_message() + map_error_message() ze słownikiem 13 komunikatów
|
|
- JS loadProtectionPackages() dodaje ?lang= na podstawie document.documentElement.lang
|
|
|
|
affects: [18-en-translation]
|
|
|
|
tech-stack:
|
|
added: []
|
|
patterns:
|
|
- "Locale resolution: ?lang= param → determine_locale() → get_locale() fallback"
|
|
- "Softra error mapping: exact match → fuzzy prefix match → graceful passthrough"
|
|
- "Bilingual fields pattern: base field + _en variant w tej samej WP option, fallback gdy _en puste"
|
|
|
|
key-files:
|
|
modified:
|
|
- 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-softra-api.php
|
|
- wp-content/plugins/carei-reservation/assets/js/carei-reservation.js
|
|
|
|
key-decisions:
|
|
- "Klucze _en nie wyciekają do REST response — frontend dostaje już rozwiązane name/description"
|
|
- "map_error_message przez __() zamiast surowych PL→EN — czeka na .mo (Phase 18) bez osobnego słownika angielskiego"
|
|
- "document.documentElement.lang zamiast explicit Polylang API — działa cross-plugin (TranslatePress, WPML) jeśli ktoś zmieni w przyszłości"
|
|
- "Default name_en w defaults (SOFT Protection / PREMIUM Protection) — admin dostaje sensowną propozycję od razu"
|
|
|
|
patterns-established:
|
|
- "Bilingual option: {base, base_en, base_description, description_en} — jedna opcja w WP DB, fallback gdy puste EN"
|
|
- "REST locale resolution z priorytetem ?lang=<pl|en> — explicit > implicit (determine_locale)"
|
|
|
|
duration: ~25min
|
|
started: 2026-04-22
|
|
completed: 2026-04-22
|
|
---
|
|
|
|
# Phase 17 Plan 01: Dwujęzyczne pakiety + mapowanie błędów Softra — Summary
|
|
|
|
**Panel admina pakietów ochronnych zyskał pola name_en/description_en, REST /protection-packages zwraca wariant per locale z fallbackiem, a błędy z Softra API przechodzą przez słownik 13 typowych komunikatów owinięty w __() — infrastruktura EN gotowa dla Phase 18.**
|
|
|
|
## Performance
|
|
|
|
| Metric | Value |
|
|
|--------|-------|
|
|
| Duration | ~25min |
|
|
| Tasks | 2 auto + 1 human-verify completed |
|
|
| Files modified | 4 |
|
|
| Delegation | 0 (inline — precyzyjne zmiany) |
|
|
|
|
## Acceptance Criteria Results
|
|
|
|
| Criterion | Status | Notes |
|
|
|-----------|--------|-------|
|
|
| AC-1: Panel pakietów obsługuje pola _en | Pass | 4 pola tekstowe per pakiet, sanitize + zapis w tej samej WP option, fallback gdy EN puste |
|
|
| AC-2: REST endpoint zwraca wariant per locale | Pass | ?lang= param + determine_locale fallback; _en klucze nie wyciekają |
|
|
| AC-3: Błędy Softra mapowane | Pass | 13 wpisów w słowniku + exact match + fuzzy prefix + graceful passthrough |
|
|
|
|
## Accomplishments
|
|
|
|
- **Admin panel:** 4 pola tekstowe per pakiet (PL + EN dla name i description) + placeholder + opis "Puste = fallback do wersji polskiej"
|
|
- **`Carei_REST_Proxy::resolve_locale()`** — helper z priorytetem `?lang=pl|en` → `determine_locale()` → `get_locale()`
|
|
- **`/protection-packages`** zwraca `name`/`description` rozwiązane per locale, `_en` klucze ukryte w payloadzie
|
|
- **`Carei_Softra_API::extract_softra_message()`** — parser JSON odpowiedzi Softra (pola `message`/`error`/`details`/`description`)
|
|
- **`Carei_Softra_API::map_error_message()`** — 13 typowych komunikatów PL → `__()` z textdomain, exact + fuzzy prefix match
|
|
- **Integracja w `request()`** — błędy HTTP 4xx/5xx przechodzą przez extract→map przed `WP_Error`
|
|
- **Frontend `loadProtectionPackages()`** dodaje `?lang=` na podstawie `document.documentElement.lang`
|
|
|
|
## Files Created/Modified
|
|
|
|
| File | Change | Purpose |
|
|
|------|--------|---------|
|
|
| `includes/class-admin-panel.php` | Modified | Pola _en + sanitize/save |
|
|
| `includes/class-rest-proxy.php` | Modified | resolve_locale() + per-locale response |
|
|
| `includes/class-softra-api.php` | Modified | extract_softra_message() + map_error_message() + integracja w request() |
|
|
| `assets/js/carei-reservation.js` | Modified | ?lang= param w loadProtectionPackages() |
|
|
|
|
## Decisions Made
|
|
|
|
| Decision | Rationale | Impact |
|
|
|----------|-----------|--------|
|
|
| `_en` keys nie w REST response | Czyste API — frontend nie wie o wariantach, dostaje już rozwiązany string | Brak zmian w JS poza lang= param |
|
|
| `map_error_message` przez `__()` a nie statyczne EN | Użyj istniejącej infrastruktury textdomain — Phase 18 automatycznie dostarcza tłumaczenia | Jeden słownik tłumaczeń, jedno miejsce aktualizacji |
|
|
| `document.documentElement.lang` zamiast Polylang-specific | Niezależne od konkretnego pluginu i18n; Polylang, TranslatePress, WPML wszystkie ustawiają html@lang | Future-proof przy zmianie wtyczki tłumaczeniowej |
|
|
|
|
## Deviations from Plan
|
|
|
|
### Summary
|
|
|
|
| Type | Count | Impact |
|
|
|------|-------|--------|
|
|
| Auto-fixed | 0 | — |
|
|
| Scope additions | 1 | Dodano `extract_softra_message()` — plan zakładał prostsze podejście, ale Softra zwraca różne struktury JSON |
|
|
| Deferred | 0 | — |
|
|
|
|
### Scope additions
|
|
|
|
**1. [Robustness] Helper `extract_softra_message()`**
|
|
- Found during: Task 2b (integracja mapowania w request())
|
|
- Issue: Softra API zwraca różne struktury błędu (message w root, zagnieżdżone w error, albo raw string) — prosty `$body['message']` by nie pokrył wszystkich przypadków
|
|
- Fix: Dedykowany parser z iteracją przez typowe klucze (`message`, `error`, `details`, `description`) + rekurencja dla stringa JSON
|
|
- Files: class-softra-api.php
|
|
- Verification: Edge cases sprawdzone w głowie — array passthrough, string JSON, nested, empty fallback
|
|
- Impact: +30 linii kodu, ale gwarantuje że mapowanie działa niezależnie od variantu odpowiedzi Softra
|
|
|
|
## Issues Encountered
|
|
|
|
None.
|
|
|
|
## Next Phase Readiness
|
|
|
|
**Ready:**
|
|
- Kompletna infrastruktura dla EN — Phase 18 tylko generuje `.po` → `.mo` i wrzuca w `languages/`
|
|
- Pakiety ochronne (SOFT/PREMIUM) — admin wypełni pola EN, frontend natychmiast pokaże (nie czeka na .mo)
|
|
- Błędy Softra — słownik 13 msgid gotowy do tłumaczenia w .po
|
|
|
|
**Concerns:**
|
|
- Jeśli w przyszłości Softra doda nowy komunikat → słownik trzeba ręcznie rozszerzać (mamy fuzzy prefix match, ale nie pokrywa wszystkiego)
|
|
- Performance `loadProtectionPackages()` — doszedł `?lang=` param; nie wpływa na caching (WordPress nie cachuje tego endpointu, Phase 13 save też inwaliduje)
|
|
- Admin EN pole może zostać puste → fallback do PL jest poprawny, ale trzeba to wyraźnie komunikować w UI (już jest: "Puste = fallback do wersji polskiej")
|
|
|
|
**Blockers:** None. Phase 18 może ruszyć.
|
|
|
|
---
|
|
*Phase: 17-bilingual-packages-and-softra-errors, Plan: 01*
|
|
*Completed: 2026-04-22*
|