update
This commit is contained in:
303
.paul/phases/19-extras-translations-admin/19-01-PLAN.md
Normal file
303
.paul/phases/19-extras-translations-admin/19-01-PLAN.md
Normal file
@@ -0,0 +1,303 @@
|
||||
---
|
||||
phase: 19-extras-translations-admin
|
||||
plan: 01
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on: ["17-01"]
|
||||
files_modified:
|
||||
- wp-content/plugins/carei-reservation/includes/class-admin-panel.php
|
||||
- wp-content/plugins/carei-reservation/includes/class-rest-proxy.php
|
||||
autonomous: false
|
||||
delegation: off
|
||||
---
|
||||
|
||||
<objective>
|
||||
## Goal
|
||||
Panel administratora do tłumaczenia nazw dodatkowych opcji (extras) zwracanych dynamicznie z API Softra. Plugin auto-zbiera wszystkie napotkane polskie nazwy extras do opcji WP (`carei_extras_seen`). W panelu `Rezerwacje → Tłumaczenia extras` admin widzi listę zebranych nazw PL i obok pole EN do wypełnienia. Gdy frontend pobiera pricelist w locale EN, REST endpoint automatycznie podmienia PL na EN override'y (fallback: PL gdy brak tłumaczenia).
|
||||
|
||||
## Purpose
|
||||
Phase 18 przetłumaczyła statyczne stringi pluginu. Phase 17 zrobiła słownik błędów Softra (13 ręcznych mapowań). Ale dynamiczne pozycje z `/pricelist/list` (fotelik, GPS, dodatkowy kierowca, łańcuchy śniegowe itp.) są nadal po polsku w wersji EN — bo backend Softra zawsze odpowiada po polsku. Phase 19 zamyka tę lukę: admin ma UI gdzie raz wpisze tłumaczenia, plugin używa ich automatycznie.
|
||||
|
||||
## Output
|
||||
- Option `carei_extras_seen` (array of unique PL names, updated runtime przy każdym pricelist request)
|
||||
- Option `carei_extras_translations` (map PL → EN, managed przez admin)
|
||||
- Submenu `wp-admin → Rezerwacje → Tłumaczenia extras` z formularzem: lista seen names + input EN + submit
|
||||
- Helper `Carei_Admin_Panel::translate_extra_name($pl_name, $locale)` — wg locale + override'u, z fallbackiem do PL
|
||||
- `Carei_REST_Proxy` przy zwracaniu pricelist: dla każdego `$item['name']` → dopisuje do seen + podmienia na EN jeśli locale = en
|
||||
- Frontend bez zmian (JS już ma `?lang=` w requeście)
|
||||
</objective>
|
||||
|
||||
<context>
|
||||
@.paul/PROJECT.md
|
||||
@.paul/ROADMAP.md
|
||||
@.paul/STATE.md
|
||||
@.paul/phases/17-bilingual-packages-and-softra-errors/17-01-SUMMARY.md
|
||||
@.paul/phases/18-en-translation/18-01-SUMMARY.md
|
||||
@wp-content/plugins/carei-reservation/includes/class-admin-panel.php
|
||||
@wp-content/plugins/carei-reservation/includes/class-rest-proxy.php
|
||||
</context>
|
||||
|
||||
<acceptance_criteria>
|
||||
|
||||
## AC-1: Auto-collect PL names
|
||||
```gherkin
|
||||
Given frontend woła `/wp-json/carei/v1/pricelist` (PL lub EN)
|
||||
When Softra API zwraca `additionalItems` z polskimi nazwami
|
||||
Then każda unikalna nazwa jest dopisana do opcji `carei_extras_seen`
|
||||
And opcja jest arrayem stringów (deduplikowana)
|
||||
And zapis do `carei_extras_seen` NIE blokuje response (fire-and-forget lub szybki update_option)
|
||||
And kolejne żądania nie duplikują wpisów
|
||||
```
|
||||
|
||||
## AC-2: Panel admin zarządza tłumaczeniami
|
||||
```gherkin
|
||||
Given admin wchodzi w `wp-admin → Rezerwacje → Tłumaczenia extras`
|
||||
When widzi listę zebranych PL nazw
|
||||
Then dla każdej nazwy jest pole `text` z obecnym tłumaczeniem EN (lub puste)
|
||||
And istnieje przycisk `Zapisz tłumaczenia`
|
||||
And nagłówek strony i etykiety są po EN/PL zgodnie z admin locale (przez __())
|
||||
|
||||
When admin wpisuje tłumaczenia i klika Zapisz
|
||||
Then opcja `carei_extras_translations` zostaje zaktualizowana (sanitize_text_field na każdym value)
|
||||
And redirect z flagą `?carei_saved=1` pokazuje komunikat "Zapisano."
|
||||
And przy następnej wizycie panelu tłumaczenia są wyświetlone zgodnie z zapisem
|
||||
```
|
||||
|
||||
## AC-3: REST pricelist zwraca EN nazwy gdy są override
|
||||
```gherkin
|
||||
Given w `carei_extras_translations` są zapisane tłumaczenia np. "Fotelik dziecięcy" → "Child car seat"
|
||||
When frontend EN (Polylang = EN albo `?lang=en`) woła `/pricelist`
|
||||
Then response zawiera `additionalItems` z `name` podmienionym wg override
|
||||
And dla nazw bez override response zawiera oryginalny PL (graceful fallback)
|
||||
And inne pola pozycji (`price`, `code`, `maxPrice` itp.) nietknięte
|
||||
|
||||
When frontend PL woła ten sam endpoint
|
||||
Then response zawiera oryginalne PL nazwy (bez zmian względem obecnego zachowania — zero regresji)
|
||||
```
|
||||
|
||||
</acceptance_criteria>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Admin panel submenu + helper + zapisy w options</name>
|
||||
<files>wp-content/plugins/carei-reservation/includes/class-admin-panel.php</files>
|
||||
<action>
|
||||
1. Dodaj stałe klasy:
|
||||
```php
|
||||
const EXTRAS_SEEN_OPTION = 'carei_extras_seen';
|
||||
const EXTRAS_TRANSLATIONS_OPTION = 'carei_extras_translations';
|
||||
```
|
||||
2. Dodaj static helpery:
|
||||
```php
|
||||
public static function get_extras_seen() {
|
||||
$seen = get_option( self::EXTRAS_SEEN_OPTION, array() );
|
||||
return is_array( $seen ) ? array_values( array_unique( array_filter( array_map( 'strval', $seen ) ) ) ) : array();
|
||||
}
|
||||
|
||||
public static function get_extras_translations() {
|
||||
$map = get_option( self::EXTRAS_TRANSLATIONS_OPTION, array() );
|
||||
return is_array( $map ) ? $map : array();
|
||||
}
|
||||
|
||||
public static function remember_extra_name( $pl_name ) {
|
||||
$pl_name = trim( (string) $pl_name );
|
||||
if ( $pl_name === '' ) return;
|
||||
$seen = self::get_extras_seen();
|
||||
if ( ! in_array( $pl_name, $seen, true ) ) {
|
||||
$seen[] = $pl_name;
|
||||
sort( $seen );
|
||||
update_option( self::EXTRAS_SEEN_OPTION, $seen, false ); // autoload=false (może być duża lista)
|
||||
}
|
||||
}
|
||||
|
||||
public static function translate_extra_name( $pl_name, $locale = null ) {
|
||||
if ( $locale === null ) {
|
||||
$locale = function_exists( 'determine_locale' ) ? determine_locale() : get_locale();
|
||||
$locale = ( 0 === strpos( (string) $locale, 'en' ) ) ? 'en' : 'pl';
|
||||
}
|
||||
if ( $locale !== 'en' ) return $pl_name;
|
||||
$map = self::get_extras_translations();
|
||||
if ( isset( $map[ $pl_name ] ) && $map[ $pl_name ] !== '' ) {
|
||||
return $map[ $pl_name ];
|
||||
}
|
||||
return $pl_name; // fallback
|
||||
}
|
||||
```
|
||||
3. Zarejestruj submenu w `register_protection_packages_page()` lub osobną metodą `register_extras_translations_page()` (prefer osobną dla czystości):
|
||||
```php
|
||||
add_action( 'admin_menu', array( $this, 'register_extras_translations_page' ) );
|
||||
add_action( 'admin_post_carei_save_extras_translations', array( $this, 'handle_extras_translations_save' ) );
|
||||
```
|
||||
I w konstruktorze dopisz akcje.
|
||||
4. Metoda `register_extras_translations_page()`:
|
||||
```php
|
||||
public function register_extras_translations_page() {
|
||||
add_submenu_page(
|
||||
'edit.php?post_type=' . self::POST_TYPE,
|
||||
__( 'Tłumaczenia extras', 'carei-reservation' ),
|
||||
__( 'Tłumaczenia extras', 'carei-reservation' ),
|
||||
'manage_options',
|
||||
'carei-extras-translations',
|
||||
array( $this, 'render_extras_translations_page' )
|
||||
);
|
||||
}
|
||||
```
|
||||
5. Metoda `render_extras_translations_page()`:
|
||||
- Tytuł strony, komunikat `?carei_saved=1`
|
||||
- Formularz POST do `admin-post.php` z nonce
|
||||
- Tabela 2 kolumny: `Nazwa PL` (readonly text), `Nazwa EN` (input text)
|
||||
- Dla każdej nazwy z `get_extras_seen()` — wiersz z inputem `name="translations[PL_NAME]"` i obecnym value
|
||||
- Submit button `Zapisz tłumaczenia`
|
||||
- Info tekst: "Puste pole = fallback do wersji polskiej w wersji EN strony."
|
||||
- Jeśli `get_extras_seen()` pusty: info "Brak zebranych pozycji — otwórz formularz rezerwacji aby załadować pricelist."
|
||||
6. Metoda `handle_extras_translations_save()`:
|
||||
- Check nonce + capability
|
||||
- Iteracja po `$_POST['translations']` (array) — każdy klucz PL, value EN
|
||||
- Sanitize: `sanitize_text_field( wp_unslash( $value ) )`
|
||||
- Zbuduj clean map
|
||||
- `update_option( self::EXTRAS_TRANSLATIONS_OPTION, $clean, false )`
|
||||
- Redirect z `?carei_saved=1`
|
||||
7. Wszystkie user-facing stringi przez `__()`/`esc_html__()`/`esc_attr__()` z textdomain `carei-reservation`.
|
||||
|
||||
Unikaj:
|
||||
- Blokowania request frontendu na zapis seen — `update_option` z autoload=false jest szybki, ale jeśli zaburza latency — użyj `wp_cache_set` przed `update_option` (mikro-optymalizacja, na razie pomiń)
|
||||
- Duplikowania nazw (array_unique)
|
||||
- Auto-tłumaczenia przez AI (scope tego planu: tylko admin override)
|
||||
</action>
|
||||
<verify>
|
||||
1. `wp-admin → Rezerwacje → Tłumaczenia extras` — strona się renderuje, widać info "Brak zebranych pozycji" (bo option jeszcze pusta)
|
||||
2. `php -l` class-admin-panel.php → No syntax errors
|
||||
3. Wywołanie helpera: `var_dump( Carei_Admin_Panel::translate_extra_name( 'Test', 'en' ) )` → `'Test'` (fallback)
|
||||
</verify>
|
||||
<done>AC-2 (częściowo — render panelu), infrastruktura dla AC-1 i AC-3.</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: REST /pricelist auto-collect + per-locale name replacement</name>
|
||||
<files>wp-content/plugins/carei-reservation/includes/class-rest-proxy.php</files>
|
||||
<action>
|
||||
1. Znajdź handler endpointu `/pricelist` (prawdopodobnie `get_pricelist()` lub podobna metoda) w class-rest-proxy.php.
|
||||
2. Przed zwrotem response — iteracja po `additionalItems` (lub odpowiedniku):
|
||||
```php
|
||||
$locale = $this->resolve_locale( $request ); // helper z Phase 17
|
||||
$translations = Carei_Admin_Panel::get_extras_translations();
|
||||
foreach ( $pricelists as &$pricelist ) {
|
||||
if ( ! isset( $pricelist['additionalItems'] ) || ! is_array( $pricelist['additionalItems'] ) ) continue;
|
||||
foreach ( $pricelist['additionalItems'] as &$item ) {
|
||||
if ( ! isset( $item['name'] ) || ! is_string( $item['name'] ) ) continue;
|
||||
$pl_name = trim( $item['name'] );
|
||||
if ( $pl_name === '' ) continue;
|
||||
|
||||
// Auto-collect
|
||||
Carei_Admin_Panel::remember_extra_name( $pl_name );
|
||||
|
||||
// Translate if locale=en and override exists
|
||||
if ( $locale === 'en' && isset( $translations[ $pl_name ] ) && $translations[ $pl_name ] !== '' ) {
|
||||
$item['name'] = $translations[ $pl_name ];
|
||||
}
|
||||
}
|
||||
unset( $item );
|
||||
}
|
||||
unset( $pricelist );
|
||||
```
|
||||
3. Upewnij się że resolve_locale działa tutaj (jest publiczny lub private dostępny w tej samej klasie — Phase 17 dodał jako private, więc OK bo to ta sama klasa).
|
||||
4. Struktura response NIE zmienia się — frontend JS dostaje te same klucze, tylko `name` może być podmienione.
|
||||
5. Jeśli Softra zwraca `error` zamiast success — nie ruszamy, passthrough.
|
||||
|
||||
Unikaj:
|
||||
- Modyfikacji cached response (jeśli pricelist jest cached — lepiej żeby cache też uwzględniał locale, ale na razie zostaw cache PL a mapowanie w locie; jeśli `/pricelist` NIE ma cache po stronie PHP, to proste)
|
||||
- Dodawania `name_en` w response — zachowujemy schemat (tylko `name` rozwiązane per locale)
|
||||
</action>
|
||||
<verify>
|
||||
1. `php -l` class-rest-proxy.php → No syntax errors
|
||||
2. Wywołanie z fronta w PL: pricelist names po polsku (bez zmian)
|
||||
3. Wywołanie z fronta w EN: nazwy spotkane po raz pierwszy → zapisane w `carei_extras_seen`, nadal po polsku w response (bo brak tłumaczeń)
|
||||
4. Po wypełnieniu tłumaczeń w adminie i kolejnym requeście EN: nazwy z override podmienione
|
||||
</verify>
|
||||
<done>AC-1 i AC-3 satysfakcjonowane.</done>
|
||||
</task>
|
||||
|
||||
<task type="checkpoint:human-verify" gate="blocking">
|
||||
<what-built>
|
||||
- Submenu `wp-admin → Rezerwacje → Tłumaczenia extras` z listą zebranych nazw + pola EN
|
||||
- Helpery w Admin_Panel: `remember_extra_name()`, `get_extras_seen()`, `get_extras_translations()`, `translate_extra_name()`
|
||||
- Auto-collect: każdy request `/pricelist` zbiera unikalne nazwy PL do option `carei_extras_seen`
|
||||
- Per-locale replacement: EN requesty dostają override z `carei_extras_translations` (fallback: PL)
|
||||
- Zero zmian w JS frontendu (już jest `?lang=` z Phase 17)
|
||||
</what-built>
|
||||
<how-to-verify>
|
||||
1. Deploy 2 pliki PHP (`class-admin-panel.php`, `class-rest-proxy.php`) przez SFTP
|
||||
2. **Auto-collect test:**
|
||||
- Otwórz stronę z modalem rezerwacji w PL, wypełnij krok 1 (daty + oddział + klasa) — pricelist się załaduje
|
||||
- Wejdź `wp-admin → Rezerwacje → Tłumaczenia extras` → lista PL nazw jest wypełniona (powinno być ~5–15 pozycji, zależnie od Softra)
|
||||
3. **Admin zapis:**
|
||||
- Wypełnij kilka tłumaczeń EN (np. "Fotelik dziecięcy" → "Child car seat", "GPS / Nawigacja" → "GPS / Navigation", "Dodatkowy kierowca" → "Additional driver")
|
||||
- Kliknij "Zapisz tłumaczenia" → komunikat "Zapisano" pojawia się
|
||||
- Odśwież stronę → tłumaczenia wciąż tam
|
||||
4. **Frontend PL:**
|
||||
- Modal w PL, sekcja "Opcje dodatkowe" — nazwy po polsku (identyczne jak przed zmianą)
|
||||
5. **Frontend EN:**
|
||||
- Polylang switcher → EN
|
||||
- Modal otwiera się, "Additional options" → nazwy które wypełniłeś = EN, reszta = PL (fallback)
|
||||
- `document.documentElement.lang` = "en-*" → `?lang=en` w requeście → backend zwraca EN names
|
||||
6. **DevTools Network:**
|
||||
- `GET /wp-json/carei/v1/pricelist?...&lang=en` → response zawiera `additionalItems[i].name` z EN (gdzie jest override) lub PL (gdzie brak)
|
||||
- `GET ...&lang=pl` → wszystko po PL
|
||||
7. **Test pustego override:**
|
||||
- Wyczyść jedno pole EN w adminie, zapisz
|
||||
- Frontend EN → ta pozycja wraca do PL (fallback)
|
||||
8. **Zero regresji:**
|
||||
- Pełen flow rezerwacji w PL działa bez zmian
|
||||
- Panel pakietów ochronnych (Phase 13/17) bez zmian
|
||||
- Inne widgety (mapa, miasta, oddziały) bez zmian
|
||||
|
||||
**Kryterium przejścia:** admin może raz wypełnić tłumaczenia → frontend EN automatycznie używa. Zero regresji w PL.
|
||||
</how-to-verify>
|
||||
<resume-signal>Napisz "approved" aby zamknąć plan, albo opisz problemy.</resume-signal>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<boundaries>
|
||||
|
||||
## DO NOT CHANGE
|
||||
- Phase 17 struktura `Carei_REST_Proxy::resolve_locale()` (reuse, nie refactor)
|
||||
- Phase 17 helper `Carei_Softra_API::map_error_message()` — osobny mechanizm dla błędów
|
||||
- Phase 13 panel pakietów ochronnych — osobna strona w menu
|
||||
- Schema CPT `carei_reservation`, meta keys, slugi statusów
|
||||
- Struktura payloadów do Softra (klucze JSON `additionalItems`, `price`, `code` itp.) — tylko `name` per locale
|
||||
- Frontend JS — bez zmian (już pobiera z `?lang=`)
|
||||
- Phase 18 `.po`/`.mo` — statyczne stringi, nie ruszamy
|
||||
|
||||
## SCOPE LIMITS
|
||||
- Nie tłumaczymy nazw krajów w sekcji wyjazdu zagranicznego (lookup keys, dane biznesowe COUNTRY_FLAGS)
|
||||
- Nie tłumaczymy nazw klas pojazdów z Softra (np. „Opel Astra Combi") — dane biznesowe
|
||||
- Nie auto-tłumaczymy przez AI — tylko admin override
|
||||
- Nie dodajemy CSV export/import tłumaczeń — jeśli user zgłosi potrzebę, osobna faza
|
||||
- Nie cacheujemy mapy tłumaczeń separately — WP options autoload cache wystarczy
|
||||
- Nie ruszamy `/protection-packages` endpoint (Phase 17 territory)
|
||||
</boundaries>
|
||||
|
||||
<verification>
|
||||
Przed zamknięciem planu:
|
||||
- [ ] `grep -n "carei_extras_seen\|carei_extras_translations" includes/` → oba klucze w kodzie
|
||||
- [ ] Panel `wp-admin → Rezerwacje → Tłumaczenia extras` renderuje się bez błędów
|
||||
- [ ] Auto-collect działa (po jednym request pricelist, lista seen nie pusta)
|
||||
- [ ] Save tłumaczeń update'uje option z komunikatem success
|
||||
- [ ] REST pricelist PL = PL names, EN z override = EN, EN bez override = PL fallback
|
||||
- [ ] `php -l` na obu plikach → No syntax errors
|
||||
- [ ] Zero regresji w PL (human-verify)
|
||||
- [ ] AC-1, AC-2, AC-3 pass
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- 2 auto tasks ukończone
|
||||
- Checkpoint human-verify zatwierdzony
|
||||
- Plugin pozwala adminowi zarządzać tłumaczeniami extras przez UI
|
||||
- Kompletna dwujęzyczność (Phase 16+17+18+19 razem) — żadna część UI nie pokazuje PL gdy user jest w EN (poza świadomymi wyjątkami: nazwy miast, krajów, klas pojazdów)
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
Po zakończeniu: `.paul/phases/19-extras-translations-admin/19-01-SUMMARY.md`
|
||||
</output>
|
||||
129
.paul/phases/19-extras-translations-admin/19-01-SUMMARY.md
Normal file
129
.paul/phases/19-extras-translations-admin/19-01-SUMMARY.md
Normal file
@@ -0,0 +1,129 @@
|
||||
---
|
||||
phase: 19-extras-translations-admin
|
||||
plan: 01
|
||||
subsystem: i18n
|
||||
tags: [admin-panel, extras, polylang, softra-pricelist, bilingual]
|
||||
|
||||
requires:
|
||||
- phase: 17-bilingual-packages-and-softra-errors
|
||||
provides: resolve_locale() helper w REST proxy
|
||||
|
||||
provides:
|
||||
- Option carei_extras_seen (auto-collected PL names z Softra pricelist)
|
||||
- Option carei_extras_translations (admin override PL → EN)
|
||||
- Submenu wp-admin → Rezerwacje → Tłumaczenia extras
|
||||
- Helpery: remember_extra_name, get_extras_seen, get_extras_translations, translate_extra_name
|
||||
- REST /pricelist per-locale name replacement z fallbackiem do PL
|
||||
|
||||
affects: []
|
||||
|
||||
tech-stack:
|
||||
added: []
|
||||
patterns:
|
||||
- "Auto-collect + admin override: seen list zbiera się runtime, admin wypełnia override, fallback do oryginału"
|
||||
- "Option z autoload=false — lista seen może rosnąć, nie blokuje boot WP"
|
||||
|
||||
key-files:
|
||||
modified:
|
||||
- wp-content/plugins/carei-reservation/includes/class-admin-panel.php
|
||||
- wp-content/plugins/carei-reservation/includes/class-rest-proxy.php
|
||||
|
||||
key-decisions:
|
||||
- "Auto-collect przez update_option z autoload=false — prosty, brak wymogu osobnej tabeli DB"
|
||||
- "Sortowanie seen alphabetically z SORT_NATURAL | SORT_FLAG_CASE — przyjazna kolejność w UI"
|
||||
- "Zero zmian w JS frontendu — `?lang=` z Phase 17 wystarcza"
|
||||
- "Nonce + sanitize_text_field na EN inputach — standardowa walidacja WP"
|
||||
- "Fallback do PL dla pustych/niezdefiniowanych override'ów — graceful degradation"
|
||||
|
||||
patterns-established:
|
||||
- "Admin panel UI pattern: lista seen (readonly) + input override (editable) + submit z nonce"
|
||||
|
||||
duration: ~20min
|
||||
started: 2026-04-22
|
||||
completed: 2026-04-22
|
||||
---
|
||||
|
||||
# Phase 19 Plan 01: Extras translations admin panel — Summary
|
||||
|
||||
**Panel `wp-admin → Rezerwacje → Tłumaczenia extras` pozwala administratorowi zarządzać tłumaczeniami dynamicznych nazw opcji dodatkowych zwracanych z Softra API. Auto-collect PL nazw + override EN + fallback do PL. Milestone v0.8 — 100% complete.**
|
||||
|
||||
## Performance
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Duration | ~20min |
|
||||
| Tasks | 2 auto + 1 human-verify completed |
|
||||
| Files modified | 2 |
|
||||
| New options in WP DB | 2 (seen, translations) |
|
||||
|
||||
## Acceptance Criteria Results
|
||||
|
||||
| Criterion | Status | Notes |
|
||||
|-----------|--------|-------|
|
||||
| AC-1: Auto-collect PL names | Pass | Każdy request `/pricelist` dopisuje nowe nazwy do `carei_extras_seen` |
|
||||
| AC-2: Panel admin zarządza tłumaczeniami | Pass | Submenu, formularz z nonce, sanitize, redirect z komunikatem |
|
||||
| AC-3: REST pricelist zwraca EN gdy override | Pass | Per-locale replacement z fallbackiem do PL |
|
||||
|
||||
## Accomplishments
|
||||
|
||||
- **2 nowe WP options:** `carei_extras_seen` (lista PL names) + `carei_extras_translations` (map PL → EN)
|
||||
- **4 static helpery** w `Carei_Admin_Panel` — czysta API do używania z innych klas
|
||||
- **Submenu admin** z pełnym UX: lista alfabetyczna, info placeholder dla pustej listy, komunikaty sukcesu, nonce protection
|
||||
- **REST `/pricelist` integration** — runtime auto-collect + per-locale replacement, bez dotykania JS frontendu
|
||||
- **Reuse Phase 17** `resolve_locale()` helper — brak duplikacji logiki
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
| File | Change | Purpose |
|
||||
|------|--------|---------|
|
||||
| `includes/class-admin-panel.php` | Modified | Stałe, helpery, submenu, render, save handler |
|
||||
| `includes/class-rest-proxy.php` | Modified | `get_pricelist()` auto-collect + per-locale replacement |
|
||||
|
||||
## Decisions Made
|
||||
|
||||
| Decision | Rationale | Impact |
|
||||
|----------|-----------|--------|
|
||||
| WP options zamiast custom table | Lista seen i map override są małe (<100 wpisów) — nadmierna inżynieria | Szybki deploy, standardowy WP pattern |
|
||||
| `autoload=false` dla options | Lista seen rośnie z czasem — nie ładujemy jej przy każdym request | Zero impact na WP boot performance |
|
||||
| Fallback do PL dla pustego override | User może nie tłumaczyć wszystkiego — nigdy nie crashujemy | Graceful degradation, spójna z Phase 17 |
|
||||
| Sortowanie SORT_NATURAL | UX: "Fotelik 1+2" przed "Fotelik 10" w liście | Przyjazna kolejność w panelu admin |
|
||||
| Zero zmian w JS | Phase 17 `?lang=` już działa, frontend nie musi wiedzieć o override | Minimalna surface area zmian |
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
### Summary
|
||||
|
||||
| Type | Count | Impact |
|
||||
|------|-------|--------|
|
||||
| Auto-fixed | 0 | — |
|
||||
| Scope additions | 0 | — |
|
||||
| Deferred | 0 | — |
|
||||
|
||||
**Total impact:** Plan wykonany 1:1.
|
||||
|
||||
## Issues Encountered
|
||||
|
||||
None.
|
||||
|
||||
## Next Phase Readiness
|
||||
|
||||
**Milestone v0.8 COMPLETE.**
|
||||
|
||||
**System tłumaczeń teraz kompletny:**
|
||||
- Statyczne stringi PHP/JS: `.po`/`.mo` (Phase 16+18)
|
||||
- Pakiety ochronne: pola `_en` w DB (Phase 17)
|
||||
- Błędy Softra: słownik 13 wpisów w `map_error_message()` (Phase 17)
|
||||
- Dynamiczne extras: admin override (Phase 19)
|
||||
|
||||
**Co pozostaje po polsku w wersji EN (świadome):**
|
||||
- Nazwy miast w widgetach mapa/miasta/oddziały — dane biznesowe
|
||||
- Nazwy krajów w sekcji wyjazdu zagranicznego — lookup COUNTRY_FLAGS
|
||||
- Nazwy klas pojazdów z Softra (np. "Opel Astra Combi") — dane biznesowe
|
||||
|
||||
**Concerns:** None. Admin musi wypełnić override dla nowych Softra extras — akceptowalny manual overhead.
|
||||
|
||||
**Blockers:** None.
|
||||
|
||||
---
|
||||
*Phase: 19-extras-translations-admin, Plan: 01*
|
||||
*Completed: 2026-04-22*
|
||||
Reference in New Issue
Block a user