update
This commit is contained in:
283
.paul/phases/18-en-translation/18-01-PLAN.md
Normal file
283
.paul/phases/18-en-translation/18-01-PLAN.md
Normal file
@@ -0,0 +1,283 @@
|
||||
---
|
||||
phase: 18-en-translation
|
||||
plan: 01
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on: ["16-01", "17-01"]
|
||||
files_modified:
|
||||
- wp-content/plugins/carei-reservation/languages/carei-reservation-en_US.po (nowy)
|
||||
- wp-content/plugins/carei-reservation/languages/carei-reservation-en_GB.po (nowy, symlink/kopia en_US)
|
||||
- wp-content/plugins/carei-reservation/languages/carei-reservation-en_US.mo (nowy, binarny)
|
||||
- wp-content/plugins/carei-reservation/languages/carei-reservation-en_GB.mo (nowy, binarny)
|
||||
autonomous: false
|
||||
delegation: off
|
||||
---
|
||||
|
||||
<objective>
|
||||
## Goal
|
||||
Dostarczyć kompletne tłumaczenie EN dla pluginu carei-reservation: przetłumaczyć wszystkie 157 msgid z `carei-reservation.pot` na `msgstr` angielskie w pliku `carei-reservation-en_US.po`, skompilować do `.mo`, zduplikować jako `en_GB` (Polylang w WordPress może używać różnych locale EN — pokrywamy oba najczęstsze warianty). Po uploadzie plików UI pluginu na wersji angielskiej przełącza się całkowicie.
|
||||
|
||||
## Purpose
|
||||
Phase 16 dostarczyła infrastrukturę (`__()`, textdomain, `.pot`), Phase 17 dodała bilingual pakiety + mapowanie błędów Softra. **Phase 18 to jedyna faza, która wizualnie przełączy cały plugin na EN.** Do tej pory użytkownik EN widzi oryginalne polskie stringi — brak `.mo` = brak tłumaczeń, `__('Wybierz segment pojazdu', ...)` zwraca polski msgid.
|
||||
|
||||
## Output
|
||||
- `carei-reservation-en_US.po` — 157 msgstr wypełnionych profesjonalnym angielskim tłumaczeniem branży wynajmu samochodów
|
||||
- `carei-reservation-en_US.mo` — binarny plik zgodny z formatem gettext (magic bytes `0x950412de`, big-endian byte order)
|
||||
- `carei-reservation-en_GB.po` + `.mo` — identyczna kopia (lub drobne różnice `rental` vs `hire`, `license` vs `licence` — opcjonalne)
|
||||
- Po załadowaniu przez `load_plugin_textdomain` (już wpięte w Phase 16) — wszystkie `__()`/`esc_html__()` i `wp_localize_script('careiI18n')` zwracają EN w locale `en_*`
|
||||
</objective>
|
||||
|
||||
<context>
|
||||
@.paul/PROJECT.md
|
||||
@.paul/ROADMAP.md
|
||||
@.paul/STATE.md
|
||||
@.paul/phases/16-i18n-plugin-refactor/16-01-SUMMARY.md
|
||||
@.paul/phases/17-bilingual-packages-and-softra-errors/17-01-SUMMARY.md
|
||||
@wp-content/plugins/carei-reservation/languages/carei-reservation.pot
|
||||
</context>
|
||||
|
||||
<acceptance_criteria>
|
||||
|
||||
## AC-1: Plik .po kompletnie przetłumaczony
|
||||
```gherkin
|
||||
Given istnieje plik `languages/carei-reservation-en_US.po`
|
||||
When policzymy niepuste msgstr (`grep -c '^msgstr "[^"]' plik.po`)
|
||||
Then wszystkie 157 wpisów ma wypełnione msgstr (nie-puste)
|
||||
And nagłówek zawiera Language: en_US, poprawne Plural-Forms (nplurals=2; plural=(n != 1))
|
||||
And msgid zawierające placeholdery `%count%`, `%name%`, `%price%`, `%status%` itp. mają je **zachowane w msgstr** (nietknięte — te same tokeny)
|
||||
And msgid zawierające tagi HTML (`<strong>...</strong>`) mają je zachowane
|
||||
And tłumaczenie zachowuje branżowy ton: `doba` → `day`, `oddział` → `location`, `pakiet ochronny` → `protection package`, `rezerwacja` → `reservation`, `zł` → `PLN`, itp.
|
||||
```
|
||||
|
||||
## AC-2: Plik .mo poprawny binarnie
|
||||
```gherkin
|
||||
Given istnieje plik `languages/carei-reservation-en_US.mo`
|
||||
When otworzymy go jako binary
|
||||
Then pierwsze 4 bajty to magic number `0xde120495` (little-endian) LUB `0x950412de` (big-endian)
|
||||
And zawiera wszystkie tłumaczenia z .po
|
||||
And daje się poprawnie sparsować przez `gettext` (WordPress i18n czyta go bez błędu)
|
||||
And jest < 50 KB (typowy rozmiar dla 157 wpisów)
|
||||
```
|
||||
|
||||
## AC-3: EN UI działa po uploadzie
|
||||
```gherkin
|
||||
Given administrator ustawił Polylang locale na en_US albo en_GB
|
||||
When użytkownik otwiera stronę w EN
|
||||
Then modal rezerwacji ma WSZYSTKIE etykiety po angielsku (segment, dates, location, protection packages, booking summary, success)
|
||||
And hero search form po angielsku
|
||||
And widgety (mapa, grid miast, grid oddziałów) po angielsku gdzie są stringi UI
|
||||
And wp-admin → Rezerwacje (dla administratora z EN locale) po angielsku
|
||||
And błędy z Softra API (dla znanych komunikatów) po angielsku
|
||||
And pakiety ochronne pokazują wartości z pól `_en` (lub PL fallback gdy puste — z Phase 17)
|
||||
```
|
||||
|
||||
</acceptance_criteria>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Translate .pot → carei-reservation-en_US.po</name>
|
||||
<files>wp-content/plugins/carei-reservation/languages/carei-reservation-en_US.po</files>
|
||||
<action>
|
||||
1. Przeczytaj `languages/carei-reservation.pot` (157 msgid, ~13.7 KB)
|
||||
2. Dla każdego wpisu msgid wygeneruj angielskie tłumaczenie w msgstr:
|
||||
- **Ton:** profesjonalny, branża wynajmu samochodów (car rental)
|
||||
- **Kluczowe terminy:**
|
||||
- „doba" / „dób" / „doby" → `day` / `days` (bez skomplikowanej pluralizacji — EN ma tylko one/other)
|
||||
- „oddział" → `location` (nie `branch` — bardziej rental-naturalne)
|
||||
- „pakiet ochronny" → `protection package`
|
||||
- „rezerwacja" → `reservation` (nie `booking` — spójne z nazwą pluginu)
|
||||
- „Złóż zapytanie o rezerwację" → `Request a reservation` (skrócone, CTA-friendly)
|
||||
- „klient" → `customer`
|
||||
- „zł" → `PLN`
|
||||
- „Wyjazd zagraniczny" → `International travel`
|
||||
- „Zniesienie udziału" → `Deductible waiver` (jeśli gdzieś zostało)
|
||||
- „najemca" → `renter`
|
||||
- „segment pojazdu" → `vehicle segment`
|
||||
- „miejsce odbioru" / „miejsce zwrotu" → `pickup location` / `return location`
|
||||
- „politykę prywatności" → `privacy policy`
|
||||
- „Pakiet SOFT" → `SOFT Package` (nazwy własne bez zmian)
|
||||
- **Placeholdery:** tokeny typu `%name%`, `%count%`, `%price%`, `%status%`, `%days%`, `%total%`, `%unit%`, `%no%`, `%msg%`, `%perDay%`, `%min%`, `%max%`, `%label%` → **ZACHOWAJ DOKŁADNIE** jak w oryginale (nie tłumacz, nie zmieniaj kolejności placeholderów jeśli to zmieniałoby znaczenie; ale możesz zmienić kolejność słów wokół nich)
|
||||
- **HTML tagi:** `<strong>...</strong>` → ZACHOWAJ
|
||||
- **%s** (sprintf) → ZACHOWAJ
|
||||
3. Zapisz jako `wp-content/plugins/carei-reservation/languages/carei-reservation-en_US.po` z nagłówkiem:
|
||||
```
|
||||
# English (US) translation for Carei Reservation
|
||||
# This file is distributed under the same license as the Carei Reservation plugin.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Carei Reservation 1.0.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-04-22 12:00+0000\n"
|
||||
"PO-Revision-Date: 2026-04-22 12:00+0000\n"
|
||||
"Last-Translator: Carei\n"
|
||||
"Language-Team: English\n"
|
||||
"Language: en_US\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Domain: carei-reservation\n"
|
||||
```
|
||||
4. Zachowaj komentarze `#:` z referencjami plik:linia (dla kontekstu tłumacza przy przyszłych zmianach)
|
||||
5. Sanity check per wpis:
|
||||
- msgid niepuste → msgstr niepuste
|
||||
- `%TOKEN%` w msgid → `%TOKEN%` w msgstr (ten sam token)
|
||||
- `<strong>` w msgid → `<strong>` w msgstr (dokładnie ten sam tag)
|
||||
|
||||
Unikaj:
|
||||
- Dosłownego tłumaczenia słowo-w-słowo (kluczowe są frazy rental, nie słownikowe mapowania)
|
||||
- Zachowywania polskich diakrytyków w EN (ąćęłńóśźż nie powinny być w msgstr)
|
||||
- Tłumaczenia nazw własnych (`SOFT`, `PREMIUM`, `Carei`, `Softra`)
|
||||
- Zmiany placeholderów (`%count%` → `%iloscDni%` = katastrofa w runtime)
|
||||
</action>
|
||||
<verify>
|
||||
1. Plik `carei-reservation-en_US.po` istnieje
|
||||
2. `grep -c '^msgid "[^"]' plik.po` ≈ 158 (157 + header)
|
||||
3. `grep -c '^msgstr "[^"]' plik.po` ≈ 158 (wszystkie wypełnione)
|
||||
4. `grep -cP "[ąćęłńóśźż]" plik.po` → tylko w msgid (oryginalne PL), zero w msgstr
|
||||
5. Spot-check 10 wpisów: ton angielski branżowy, placeholdery zachowane, HTML zachowany
|
||||
</verify>
|
||||
<done>AC-1 satysfakcjonowane.</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Kompilacja .po → .mo (+ kopia en_GB)</name>
|
||||
<files>
|
||||
wp-content/plugins/carei-reservation/languages/carei-reservation-en_US.mo,
|
||||
wp-content/plugins/carei-reservation/languages/carei-reservation-en_GB.po,
|
||||
wp-content/plugins/carei-reservation/languages/carei-reservation-en_GB.mo
|
||||
</files>
|
||||
<action>
|
||||
**Problem:** `msgfmt` (standardowy kompilator gettext) nie jest dostępny w systemie developera. Python `msgfmt.py` również nie dostępny.
|
||||
|
||||
**Rozwiązanie:** Wygeneruj plik `.mo` binarnie programistycznie. Możliwe ścieżki (wybierz dostępną):
|
||||
|
||||
1. **Preferowana:** Napisz tymczasowy skrypt Node.js w sandbox używający pakietu `gettext-parser` (dostępny przez npm):
|
||||
```js
|
||||
// Wymaga: npm i gettext-parser
|
||||
const fs = require('fs');
|
||||
const gp = require('gettext-parser');
|
||||
const po = fs.readFileSync('carei-reservation-en_US.po');
|
||||
const parsed = gp.po.parse(po);
|
||||
const mo = gp.mo.compile(parsed);
|
||||
fs.writeFileSync('carei-reservation-en_US.mo', mo);
|
||||
```
|
||||
2. **Alternatywa PHP:** Napisz własny skrypt PHP implementujący format `.mo` (magic 0x950412de, header 7×uint32, offset tables, string data). Format jest w dokumentacji gettext: https://www.gnu.org/software/gettext/manual/html_node/MO-Files.html
|
||||
- Parsuj `.po` ręcznie (rozpoznaj msgid/msgstr, unescape)
|
||||
- Zbuduj binarny layout: header → offset/length tables for originals → offset/length tables for translations → string blobs (null-terminated)
|
||||
- Zapisz jako binary file
|
||||
3. **Loco Translate (wp-admin):** gdyby powyższe zawiodły — upload `.po` do wp-content/languages/plugins/ i niech Loco Translate w `wp-admin → Loco Translate → Plugins → Carei Reservation → en_US → Sync → Save` wygeneruje `.mo` w server-side.
|
||||
|
||||
**Preferuj opcję 1** (Node.js + gettext-parser) — działa deterministycznie w dev environment, bez potrzeby wp-admin.
|
||||
|
||||
**Po skompilowaniu en_US:**
|
||||
- Skopiuj `.po` jako `carei-reservation-en_GB.po` (zmień `Language: en_US\n` → `Language: en_GB\n` w nagłówku)
|
||||
- Opcjonalnie: drobne poprawki UK-english (license→licence, color→colour, itp.) — na tym etapie zostaw identyczne
|
||||
- Skompiluj `.po` → `.mo` tym samym skryptem
|
||||
|
||||
**Weryfikacja binarnej poprawności `.mo`:**
|
||||
```bash
|
||||
# Pierwsze 4 bajty = magic number (little-endian 0x950412de)
|
||||
xxd -l 4 carei-reservation-en_US.mo
|
||||
# Powinno pokazać: 0000000: de12 0495 (le) lub 9504 12de (be)
|
||||
```
|
||||
</action>
|
||||
<verify>
|
||||
1. Pliki istnieją: `en_US.po`, `en_US.mo`, `en_GB.po`, `en_GB.mo` w `languages/`
|
||||
2. Rozmiar `.mo` między 5–50 KB
|
||||
3. Magic number poprawny (xxd/hexdump pierwsze 4 bajty)
|
||||
4. PHP sanity check (opcjonalny): `php -r "$mo=file_get_contents('path.mo'); echo bin2hex(substr($mo,0,4));"` → `de120495` lub `950412de`
|
||||
</verify>
|
||||
<done>AC-2 satysfakcjonowane.</done>
|
||||
</task>
|
||||
|
||||
<task type="checkpoint:human-verify" gate="blocking">
|
||||
<what-built>
|
||||
- `carei-reservation-en_US.po` + `.mo` z 157 przetłumaczonymi wpisami
|
||||
- `carei-reservation-en_GB.po` + `.mo` jako kopia en_US
|
||||
- Po uploadzie wszystkie `__()`/`esc_html__()` + `careiI18n` w pluginie zwracają EN przy locale en_*
|
||||
</what-built>
|
||||
<how-to-verify>
|
||||
1. **Deploy:** wypchnij 4 nowe pliki (`carei-reservation-en_US.po`, `.mo`, `en_GB.po`, `.mo`) do `wp-content/plugins/carei-reservation/languages/` na serwer
|
||||
2. **Cache:** wyczyść cache pluginu (jeśli masz WP Rocket / Autoptimize) + opcache PHP (zwykle wystarczy reboot fpm, albo `wp cache flush`)
|
||||
3. **Admin panel pakietów:**
|
||||
- Zaloguj się do wp-admin (jeśli twoja konto admina jest PL → zostawcie PL dla admina, albo zmień WP user locale na EN w Users → Profile → Language: English (United States))
|
||||
- `Rezerwacje → Pakiety ochronne` — labele powinny być po EN (jeśli admin locale = EN)
|
||||
- Uzupełnij pola EN dla SOFT i PREMIUM (np. `SOFT Protection` + `Basic damage coverage with 2000 PLN deductible`; `PREMIUM Protection` + `Full damage waiver, zero deductible`)
|
||||
- Zapisz
|
||||
4. **Frontend EN — modal rezerwacji:**
|
||||
- Przełącz Polylang switcher na EN
|
||||
- Otwórz stronę z przyciskiem → przycisk pokazuje `Request a reservation` (lub podobne)
|
||||
- Modal otwiera się, WSZYSTKIE labele po angielsku: `Vehicle segment`, `From`, `To`, `Pickup location`, `Return location`, `Protection packages`, `Additional options`, `International travel`, `First name`, `Last name`, `Email`, `Phone`, `I agree to the privacy policy`, `Send request`
|
||||
- Pakiety ochronne: `SOFT Protection` / `PREMIUM Protection` z angielskim opisem (z Phase 17)
|
||||
- Komunikaty walidacji (spróbuj wysłać pusty form) po EN: `Enter first name`, `Enter a valid email`, itp.
|
||||
- Podsumowanie → `Reservation summary`, `Subtotal`, `VAT`, `Total`, `Confirm reservation`
|
||||
- Success: `Reservation confirmed`, `Order number: X`
|
||||
5. **Hero search form:** `Vehicle segment`, `From`, `To`, `Pickup location`, `Check availability`
|
||||
6. **Widgety:**
|
||||
- Mapa Polski: tooltipy `Location: {city}`, `ul. {street}` → po EN
|
||||
- Grid miast, grid oddziałów → po EN
|
||||
7. **Błędy Softra:**
|
||||
- Spróbuj zarezerwować niedostępny pojazd / nieprawidłową datę — komunikat po EN (z słownika Phase 17 via `__()`)
|
||||
8. **DevTools sanity:**
|
||||
- `window.careiI18n.selectSegment` → `"Select vehicle segment"` (lub podobne)
|
||||
- `window.careiI18n.dayOne` → `"day"`, `dayOther` → `"days"` (jeśli dodałeś `dayOther` jako en-plural)
|
||||
- Network: `/wp-json/carei/v1/protection-packages?lang=en` → response z EN treścią
|
||||
9. **Powrót do PL:**
|
||||
- Przełącz Polylang na PL
|
||||
- Wszystko wraca do polskiego bez regresji (oryginał zachowany)
|
||||
|
||||
**Kryterium przejścia:** cała UI pluginu w EN (modal + hero + widgety + admin + error messages). Zero polskich literałów przy locale EN (poza treściami z DB które admin zostawił puste → fallback PL z Phase 17).
|
||||
|
||||
**Znane limitacje (NIE blokują approve):**
|
||||
- Treści stron Elementora (nagłówki hero, sekcje marketingowe) — tłumaczone osobno przez Polylang addon (poza scope tej fazy)
|
||||
- Menu, footer, inne treści WP — Polylang / Polylang Strings Translation (poza scope)
|
||||
</how-to-verify>
|
||||
<resume-signal>Napisz "approved" aby zamknąć Milestone v0.7, albo wskaż stringi które pozostały po polsku pomimo EN locale.</resume-signal>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<boundaries>
|
||||
|
||||
## DO NOT CHANGE
|
||||
- Żaden plik PHP/JS pluginu (Phase 16–17 już to załatwiły)
|
||||
- Plik `.pot` (baseline — nie nadpisujemy bazowego template)
|
||||
- Textdomain, mechanizm `load_plugin_textdomain` (Phase 16)
|
||||
- Panel admina pakietów — tylko DANE w bazie mogą być wypełnione przez admina (to nie zmiana kodu)
|
||||
- `carei-reservation.css` — styling niezależny od języka
|
||||
- `mu-plugins/fix-sprintf-global.php` — dalej potrzebny dla Polylang addon
|
||||
|
||||
## SCOPE LIMITS
|
||||
- Nie tłumaczymy innych pluginów (tylko carei-reservation)
|
||||
- Nie tłumaczymy Elementora ani treści stron (Polylang addon)
|
||||
- Nie tłumaczymy nazw krajów w sekcji wyjazdu zagranicznego (dane biznesowe COUNTRY_FLAGS — pozostają po polsku bo backend tak zwraca)
|
||||
- Nie tłumaczymy slugów URL, permalink structures
|
||||
- Nie generujemy dodatkowych locale (fr, de, itp.) — tylko en_US + en_GB
|
||||
- Nie zmieniamy generatora .pot ani pipeline-u i18n
|
||||
</boundaries>
|
||||
|
||||
<verification>
|
||||
Przed zamknięciem planu:
|
||||
- [ ] `carei-reservation-en_US.po` istnieje, 157 wpisów, msgstr wszystkie wypełnione
|
||||
- [ ] `carei-reservation-en_US.mo` istnieje, magic number poprawny
|
||||
- [ ] `carei-reservation-en_GB.po` + `.mo` — kopia en_US
|
||||
- [ ] Brak polskich diakrytyków w msgstr
|
||||
- [ ] Placeholdery `%TOKEN%` zachowane 1:1 między msgid i msgstr
|
||||
- [ ] HTML tagi zachowane w msgstr
|
||||
- [ ] Human-verify — pełen flow EN bez regresji PL
|
||||
- [ ] AC-1, AC-2, AC-3 pass
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- Task 1–2 ukończone
|
||||
- Checkpoint zatwierdzony
|
||||
- Milestone v0.7 — 100% complete
|
||||
- Plugin carei-reservation pełnoprawnie dwujęzyczny (PL + EN)
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
Po zakończeniu: `.paul/phases/18-en-translation/18-01-SUMMARY.md`
|
||||
Następnie: `/paul:complete-milestone v0.7`
|
||||
</output>
|
||||
168
.paul/phases/18-en-translation/18-01-SUMMARY.md
Normal file
168
.paul/phases/18-en-translation/18-01-SUMMARY.md
Normal file
@@ -0,0 +1,168 @@
|
||||
---
|
||||
phase: 18-en-translation
|
||||
plan: 01
|
||||
subsystem: i18n
|
||||
tags: [gettext, po, mo, translation, flatpickr, bilingual]
|
||||
|
||||
requires:
|
||||
- phase: 16-i18n-plugin-refactor
|
||||
provides: .pot (157 msgid) + textdomain carei-reservation
|
||||
- phase: 17-bilingual-packages-and-softra-errors
|
||||
provides: bilingual pakiety + mapowanie Softra przez __()
|
||||
|
||||
provides:
|
||||
- carei-reservation-en_US.po + .mo (158 wpisów przetłumaczonych)
|
||||
- carei-reservation-en_GB.po + .mo (kopia en_US)
|
||||
- PHP mini-kompilator po2mo.php (bez potrzeby msgfmt)
|
||||
- Flatpickr jako cross-browser date picker z PL/EN locale (scope addition)
|
||||
- Kompaktowy CSS theme dla flatpickr w kolorach Carei
|
||||
|
||||
affects: []
|
||||
|
||||
tech-stack:
|
||||
added:
|
||||
- Flatpickr 4.6.13 (CDN jsdelivr, enqueued z dependencies)
|
||||
patterns:
|
||||
- "MO compilation: własny parser+packer PHP bez msgfmt/Python"
|
||||
- "Flatpickr static:true dla modala (popup w container) + default dla hero"
|
||||
- "disableMobile:true dla spójności UX PL/EN na wszystkich urządzeniach"
|
||||
|
||||
key-files:
|
||||
created:
|
||||
- wp-content/plugins/carei-reservation/languages/carei-reservation-en_US.po
|
||||
- wp-content/plugins/carei-reservation/languages/carei-reservation-en_US.mo
|
||||
- wp-content/plugins/carei-reservation/languages/carei-reservation-en_GB.po
|
||||
- wp-content/plugins/carei-reservation/languages/carei-reservation-en_GB.mo
|
||||
modified:
|
||||
- wp-content/plugins/carei-reservation/carei-reservation.php
|
||||
- wp-content/plugins/carei-reservation/assets/js/carei-reservation.js
|
||||
- wp-content/plugins/carei-reservation/assets/css/carei-reservation.css
|
||||
|
||||
key-decisions:
|
||||
- "Tłumaczenie przez agenta z pre-zdefiniowanym słownikiem terminów branżowych (~50 mapowań PL→EN car rental)"
|
||||
- "Własny kompilator PHP zamiast msgfmt/Loco — deterministyczny, niezależny od środowiska"
|
||||
- "Flatpickr z CDN jsdelivr — brak lokalnych plików, szybki deploy; fallback do native picker jeśli CDN padnie"
|
||||
- "static:true dla modala — rozwiązuje konflikt focus-trap + z-index"
|
||||
- "disableMobile:true — jednolity UX zamiast native iOS spinner / Android Material"
|
||||
- "en_GB = kopia en_US — brak realnej potrzeby różnicowania UK/US na tym etapie"
|
||||
|
||||
patterns-established:
|
||||
- "Własny po2mo compiler w PHP (stored w ~/temp) — reusable dla przyszłych tłumaczeń"
|
||||
- "CSS override per-klasa flatpickr (compact height/width/spacing) w kolorach Carei #2F2482"
|
||||
|
||||
duration: ~40min
|
||||
started: 2026-04-22
|
||||
completed: 2026-04-22
|
||||
---
|
||||
|
||||
# Phase 18 Plan 01: EN translation (.po/.mo) + QA — Summary
|
||||
|
||||
**Plugin carei-reservation dostarczony w wersji dwujęzycznej: 158 wpisów przetłumaczonych na EN, skompilowanych do .mo (en_US + en_GB), plus cross-browser Flatpickr jako date picker z locale PL/EN. Milestone v0.7 — 100% complete.**
|
||||
|
||||
## Performance
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Duration | ~40min |
|
||||
| Tasks | 2 auto + 1 human-verify + 1 scope addition (Flatpickr) |
|
||||
| Files created | 4 (.po + .mo × 2 locale) |
|
||||
| Files modified | 3 (bootstrap PHP, JS, CSS) |
|
||||
| Delegation | 1 agent (tłumaczenie .pot → .po) |
|
||||
|
||||
## Acceptance Criteria Results
|
||||
|
||||
| Criterion | Status | Notes |
|
||||
|-----------|--------|-------|
|
||||
| AC-1: Plik .po kompletnie przetłumaczony | Pass | 158 msgstr, placeholdery zachowane, HTML OK, zero PL diakrytyków |
|
||||
| AC-2: Plik .mo poprawny binarnie | Pass | Magic 0x950412de, version 0, N=158, 9455 bytes |
|
||||
| AC-3: EN UI działa po uploadzie | Pass | User confirmed "approved" po pełnym teście |
|
||||
|
||||
## Accomplishments
|
||||
|
||||
- **158 wpisów PL→EN** przez agenta z uzgodnionym słownikiem terminów rental (`doba→day`, `oddział→location`, `zł→PLN`, `pakiet ochronny→protection package`, etc.)
|
||||
- **Własny PHP `.mo` compiler** (po2mo.php, ~150 linii) — parsuje .po, sortuje, pakuje binarnie wg gettext spec
|
||||
- **en_US + en_GB** — dwa locale EN pokryte (Polylang może używać dowolnego)
|
||||
- **Flatpickr scope addition:** CDN enqueue + JS init + kompaktowy CSS w kolorach Carei. Modal z `static:true` (popup w container, bypass focus-trap). Hero z default renderowaniem. Jednolity UX desktop + mobile (`disableMobile:true`).
|
||||
- **Weryfikacja binarna `.mo`** przez PHP: `Magic: 0x950412de, Version: 0, N: 158`
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
| File | Change | Purpose |
|
||||
|------|--------|---------|
|
||||
| `languages/carei-reservation-en_US.po` | Created | 158 wpisów PL→EN |
|
||||
| `languages/carei-reservation-en_US.mo` | Created | Binarka gettext, 9455 bytes |
|
||||
| `languages/carei-reservation-en_GB.po` | Created | Kopia en_US z `Language: en_GB\n` |
|
||||
| `languages/carei-reservation-en_GB.mo` | Created | Skompilowana en_GB |
|
||||
| `carei-reservation.php` | Modified | Flatpickr enqueue (CDN + pl locale) + deps |
|
||||
| `assets/js/carei-reservation.js` | Modified | `initDatePickers()` + static:true dla modal + graceful fallback |
|
||||
| `assets/css/carei-reservation.css` | Modified | Kompaktowy flatpickr theme w kolorach Carei |
|
||||
|
||||
## Decisions Made
|
||||
|
||||
| Decision | Rationale | Impact |
|
||||
|----------|-----------|--------|
|
||||
| Własny po2mo.php zamiast msgfmt | msgfmt/Python msgfmt niedostępne w dev env; Loco Translate wymaga wp-admin flow | Deterministic compilation, reusable dla przyszłych locale (fr, de) |
|
||||
| Flatpickr scope addition | User zgłosił potrzebę tłumaczenia kalendarza natywnego (browser używa OS locale) — flatpickr jedyne sensowne rozwiązanie | +40KB JS (CDN), ale spójne UX + locale-aware |
|
||||
| CDN jsdelivr | Szybki deploy, brak zarządzania plikami lokalnymi | Dependency na CDN; graceful fallback do native picker |
|
||||
| `static:true` dla modal | Default popup w body → konflikt z focus-trap + z-index modala | Picker w containerze inputa — kompatybilne z modalem |
|
||||
| `disableMobile:true` | Native mobile (iOS spinner, Android Material) ignoruje strony locale | Jednolity UX PL/EN niezależnie od OS użytkownika |
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
### Summary
|
||||
|
||||
| Type | Count | Impact |
|
||||
|------|-------|--------|
|
||||
| Auto-fixed | 2 | Flatpickr popup ukryty w modalu (static:true), native mobile picker (disableMobile:true) |
|
||||
| Scope additions | 1 | Flatpickr integracja (cross-browser date picker z i18n) — user request podczas apply |
|
||||
| Deferred | 0 | — |
|
||||
|
||||
### Scope additions
|
||||
|
||||
**1. [UX] Flatpickr date picker z i18n**
|
||||
- Found during: Task 3 (human-verify) — user zapytał o tłumaczenie kalendarza
|
||||
- Problem: Natywny `<input type="datetime-local">` używa locale OS przeglądarki, ignoruje WP locale
|
||||
- Fix: Integracja Flatpickr 4.6.13 z CDN — enqueue + init per input + kompaktowy CSS theme
|
||||
- Files: carei-reservation.php, carei-reservation.js, carei-reservation.css
|
||||
- Verification: User "jest ok" po kompaktowym themie; PL kalendarz, EN kalendarz, oba na desktop + mobile
|
||||
|
||||
### Auto-fixed Issues
|
||||
|
||||
**1. [Modal] Flatpickr popup nie otwierał się w modalu**
|
||||
- Issue: Default append do body + focus-trap z Phase 4 → picker focus tracony przed interakcją
|
||||
- Fix: `static: true` w opts — popup renderowany wewnątrz `.carei-form__date-wrap`
|
||||
- Verification: User confirmed kalendarz otwiera się w modalu po zmianie
|
||||
|
||||
**2. [Mobile] Inny kalendarz na mobile vs desktop**
|
||||
- Issue: Flatpickr default `disableMobile: false` → na mobile fallback do native OS picker (iOS spinner / Android Material)
|
||||
- Fix: `disableMobile: true` — flatpickr wszędzie, jednolity wygląd + locale
|
||||
- Verification: User confirmed "na obu jest flatpickr"
|
||||
|
||||
## Issues Encountered
|
||||
|
||||
| Issue | Resolution |
|
||||
|-------|------------|
|
||||
| msgfmt niedostępny lokalnie | Własny PHP kompilator (po2mo.php) — reusable |
|
||||
| Modal calendar nie otwiera | static:true flatpickr option |
|
||||
| Mobile inny picker | disableMobile:true |
|
||||
| Hero kalendarz po polsku mimo EN | Dodanie hero inputs do initDatePickers() (wcześniej tylko modal) |
|
||||
|
||||
## Next Phase Readiness
|
||||
|
||||
**Milestone v0.7 COMPLETE** — plugin carei-reservation pełnoprawnie dwujęzyczny (PL + EN):
|
||||
- Infrastruktura: textdomain + __() + careiI18n (Phase 16)
|
||||
- Bilingual dane: pakiety pól _en + mapowanie Softra errors (Phase 17)
|
||||
- Tłumaczenia: .po/.mo dla en_US + en_GB (Phase 18)
|
||||
- UX: Flatpickr cross-browser + locale-aware (Phase 18 scope addition)
|
||||
|
||||
**Out of scope dla kolejnych milestones:**
|
||||
- Tłumaczenie treści stron Elementora (Polylang Automatic Translate Addon)
|
||||
- Menu, footer, theme stringi (Polylang String Translation)
|
||||
- Nazwy miast/krajów (dane biznesowe z API Softra)
|
||||
- Inne locale (fr, de) — dodaje się przez sam `.po/.mo` bez zmian w kodzie
|
||||
|
||||
**Blockers:** None.
|
||||
|
||||
---
|
||||
*Phase: 18-en-translation, Plan: 01*
|
||||
*Completed: 2026-04-22*
|
||||
Reference in New Issue
Block a user