WinterCMS research

This commit is contained in:
Jakub Zych
2026-02-18 01:31:41 +01:00
parent bec00a8bd5
commit 29766aee93
40 changed files with 8529 additions and 0 deletions

View File

@@ -0,0 +1,146 @@
---
phase: 15-locale-detection-routing
verified: 2026-02-02T01:12:14Z
status: passed
score: 11/11 must-haves verified
---
# Phase 15: Locale Detection & Routing Verification Report
**Phase Goal:** URL-based locale switching (/pl/, /de/), browser detection for first visit, persistent user preference, language switcher UI
**Verified:** 2026-02-02T01:12:14Z
**Status:** passed
**Re-verification:** No - initial verification
## Goal Achievement
### Observable Truths
| # | Truth | Status | Evidence |
|---|-------|--------|----------|
| 1 | Manual locale selection via LocalePicker sets 1-year cookie | VERIFIED | `plugins/golem15/quotify/Plugin.php:503-507` - Cookie::queue with manualSelectionCookie config key, 525600 min expiry |
| 2 | URL prefix visit (/pl/, /de/) sets manual selection cookie | VERIFIED | `plugins/golem15/translate/routes.php:31-35` - Cookie::queue after loadLocaleFromRequest() succeeds |
| 3 | Logged-in user's locale switch updates their DB preference | VERIFIED | `plugins/golem15/quotify/Plugin.php:510-513` - Auth::getUser()->preferred_locale = $locale; $user->save() |
| 4 | Browser detection skipped when manual selection cookie exists | VERIFIED | `plugins/golem15/translate/classes/LocaleMiddleware.php:214-228` - hasManualLocaleSelection() checks cookie |
| 5 | Language switcher dropdown visible in header | VERIFIED | `themes/quotify/partials/header.htm:15-17` - includes language-switcher partial in header-actions |
| 6 | Clicking language option switches locale and reloads page | VERIFIED | `themes/quotify/partials/language-switcher.htm:17` - data-request="localePicker::onSwitchLocale" |
| 7 | Current language name shown in native form (Polski, Deutsch, English) | VERIFIED | `themes/quotify/partials/language-switcher.htm:7` - displays activeLocaleName from LocalePicker |
| 8 | All pages have hreflang tags for SEO | VERIFIED | All 3 layouts (default, dashboard, empty) have alternateHrefLangElements component and {% component 'alternateHrefLangElements' %} |
| 9 | Account settings has language preference section | VERIFIED | `themes/quotify/partials/account/update.htm:97-118` - Language Preference section with dropdown |
| 10 | Logged-in users can select preferred language in profile | VERIFIED | `themes/quotify/partials/account/update.htm:107` - name="preferred_locale" select element in form_ajax onUpdate |
| 11 | Language suggestion banner appears when browser language differs | VERIFIED | `plugins/golem15/translate/components/LocaleSuggestionBanner.php` - shouldShowBanner() logic with Accept-Language detection |
| 12 | Dismissing banner sets cookie to prevent showing again | VERIFIED | `plugins/golem15/translate/components/LocaleSuggestionBanner.php:96` - locale_banner_dismissed cookie, 1 week expiry |
**Score:** 11/11 truths verified (12 listed but 11-12 are sub-items of the same truth)
### Required Artifacts
| Artifact | Expected | Status | Details |
|----------|----------|--------|---------|
| `plugins/golem15/quotify/Plugin.php` | LocalePicker extension with cookie and DB sync | VERIFIED | extendLocalePicker() method at lines 482-517 |
| `plugins/golem15/translate/routes.php` | Cookie setting on URL prefix detection | VERIFIED | Cookie::queue at lines 31-35 after locale loaded |
| `themes/quotify/partials/language-switcher.htm` | Dropdown language switcher UI | VERIFIED | 58 lines, accessible dropdown with ARIA, JS toggle |
| `themes/quotify/partials/header.htm` | Header with language switcher | VERIFIED | Lines 14-17 include language-switcher partial |
| `themes/quotify/layouts/default.htm` | Layout with hreflang and LocalePicker | VERIFIED | Components registered, hreflang output at line 23 |
| `themes/quotify/layouts/dashboard.htm` | Layout with hreflang and LocalePicker | VERIFIED | Components registered lines 7-9, hreflang output at line 22 |
| `themes/quotify/layouts/empty.htm` | Layout with hreflang and LocalePicker | VERIFIED | Components registered lines 4-5, hreflang output at line 15 |
| `themes/quotify/partials/account/update.htm` | Language preference section in account settings | VERIFIED | Language Preference section lines 97-118 with preferred_locale field |
| `plugins/golem15/translate/components/LocaleSuggestionBanner.php` | Component for language mismatch detection | VERIFIED | 120 lines, shouldShowBanner(), getSuggestedLocale(), onDismissBanner() |
| `plugins/golem15/translate/components/localesuggestionbanner/default.htm` | Banner template | VERIFIED | 35 lines, conditional banner with localized text |
| `themes/quotify/assets/css/components/language-switcher.css` | Language switcher styles | VERIFIED | 115 lines, responsive design |
| `themes/quotify/assets/css/components/locale-banner.css` | Banner styles | VERIFIED | 85 lines, sticky positioning, gradient background |
| `themes/quotify/assets/css/app.css` | Imports for both CSS files | VERIFIED | Lines 14-15 import language-switcher.css and locale-banner.css |
### Key Link Verification
| From | To | Via | Status | Details |
|------|-----|-----|--------|---------|
| LocalePicker::onSwitchLocale | Cookie::queue | Component extension in Plugin.php boot() | WIRED | `Plugin.php:503` - Cookie::queue call inside bindEvent handler |
| LocalePicker::onSwitchLocale | User::preferred_locale | Auth::getUser()->save() | WIRED | `Plugin.php:510-513` - Auth check + save |
| language-switcher.htm | localePicker::onSwitchLocale | data-request attribute | WIRED | `language-switcher.htm:17` - data-request present |
| routes.php | Cookie::queue | After loadLocaleFromRequest() | WIRED | `routes.php:31-35` - Cookie set after locale loaded |
| LocaleMiddleware | hasManualLocaleSelection | Cookie read in detection cascade | WIRED | `LocaleMiddleware.php:34` - calls hasManualLocaleSelection |
| default.htm | alternateHrefLangElements | Component registration | WIRED | Component registered line 8, output line 23 |
| account/update.htm | Account::onUpdate | Form submission with preferred_locale | WIRED | form_ajax('onUpdate') at line 95, preferred_locale field at line 107 |
| LocaleSuggestionBanner | Accept-Language detection | detectBrowserLocale() | WIRED | `LocaleSuggestionBanner.php:63-79` - Request::header parsing |
| onDismissBanner | Cookie::queue | locale_banner_dismissed cookie | WIRED | `LocaleSuggestionBanner.php:96` - 1-week cookie set |
### Requirements Coverage
Phase 15 requirements from ROADMAP.md:
- URL-based locale switching (/pl/, /de/) - SATISFIED
- Browser detection for first visit - SATISFIED
- Persistent user preference - SATISFIED
- Language switcher UI - SATISFIED
### Anti-Patterns Found
| File | Line | Pattern | Severity | Impact |
|------|------|---------|----------|--------|
| - | - | None found | - | - |
No stub patterns, placeholder content, or empty implementations detected in any verified artifacts.
### Human Verification Required
### 1. Visual Language Switcher Appearance
**Test:** Navigate to homepage, check header area
**Expected:** Language switcher dropdown visible near right side of header, styled consistently with site design
**Why human:** Visual appearance and styling cannot be verified programmatically
### 2. Language Switch Flow
**Test:** Click language switcher, select "Polski" or "Deutsch"
**Expected:** Page reloads in selected language, switcher shows new language name
**Why human:** Page reload and full interaction flow requires browser testing
### 3. Mobile Language Switcher
**Test:** View site on mobile viewport (< 768px)
**Expected:** Language label hidden, globe icon visible, touch targets adequate
**Why human:** Responsive behavior requires actual device/viewport testing
### 4. hreflang Tags in Source
**Test:** View page source, search for "hreflang"
**Expected:** `<link rel="alternate" hreflang="en/pl/de" href="...">` tags present for all locales
**Why human:** Need to verify rendered HTML output
### 5. Account Settings Language Preference
**Test:** Log in, go to account settings, select "Account Info" tab
**Expected:** Language Preference section visible with dropdown showing en/pl/de options
**Why human:** Requires authenticated session and UI interaction
### 6. Language Suggestion Banner
**Test:** Clear cookies, set browser language to German, visit English page
**Expected:** Banner appears at top: "Diese Seite ist auf Deutsch verfugbar" with switch button
**Why human:** Requires browser language configuration and cookie clearing
### 7. Banner Dismissal Persistence
**Test:** Dismiss the suggestion banner, refresh page
**Expected:** Banner does not reappear (cookie prevents)
**Why human:** Requires cookie behavior verification
### Gaps Summary
No gaps found. All must-haves verified as implemented:
**Plan 15-01 (Core Locale Infrastructure):**
- LocalePicker extension in Quotify Plugin.php sets 1-year cookie on manual locale switch
- routes.php sets cookie when URL prefix detected
- LocaleMiddleware correctly skips browser detection when cookie present
- Logged-in users' preferences saved to database
**Plan 15-02 (Language Switcher UI):**
- Language switcher partial created with accessible dropdown
- Integrated into header across all pages
- All three layouts register localePicker and alternateHrefLangElements components
- hreflang tags output in head section of all layouts
**Plan 15-03 (Account Settings & Suggestion Banner):**
- Language Preference section added to account settings
- LocaleSuggestionBanner component created with browser detection
- Banner template with localized text in target language
- Dismissal cookie (1 week) prevents repeated banner display
---
*Verified: 2026-02-02T01:12:14Z*
*Verifier: Claude (gsd-verifier)*