# Story 1.3: Bilingual Infrastructure (Arabic/English) ## Epic Reference **Epic 1:** Core Foundation & Infrastructure ## User Story As a **user (admin or client)**, I want **full bilingual support with Arabic as primary and English as secondary language**, So that **I can use the platform in my preferred language with proper RTL/LTR layout**. ## Story Context ### Existing System Integration - **Integrates with:** Laravel localization, Tailwind CSS, user preferences - **Technology:** Laravel lang files, Tailwind RTL, Google Fonts - **Follows pattern:** Laravel localization best practices - **Touch points:** All views, navigation, date/time formatting ### Reference Documents - **PRD Section 4.2:** Language Support requirements (RTL/LTR, numerals, date/time formats) - **PRD Section 7.1.C:** Typography specifications (Arabic: Cairo/Tajawal, English: Montserrat/Lato) ## Acceptance Criteria ### Functional Requirements - [ ] Language files for Arabic (ar) and English (en) - [ ] Language toggle in navigation (visible on all pages) - [ ] User language preference stored in `users.preferred_language` - [ ] Guest language stored in session (persists across page loads) - [ ] RTL layout for Arabic, LTR for English - [ ] All UI elements translatable via `__()` helper - [ ] Language switch preserves current page (redirect back to same URL) - [ ] Form validation messages display in current locale - [ ] Missing translations fall back to key name (not break page) ### Date/Time Formatting - [ ] Arabic: DD/MM/YYYY format - [ ] English: MM/DD/YYYY format - [ ] Both: 12-hour time format (AM/PM) - [ ] Both: Western numerals (123) - no Arabic numerals ### Typography - [ ] Arabic fonts: Cairo or Tajawal (Google Fonts) - [ ] English fonts: Montserrat or Lato (Google Fonts) - [ ] Font weights: 300, 400, 600, 700 - [ ] font-display: swap for performance ### Integration Requirements - [ ] Language middleware sets locale from user preference or session - [ ] Direction attribute (`dir="rtl"` or `dir="ltr"`) on HTML element - [ ] Tailwind RTL utilities working - [ ] Forms align correctly in both directions ### Quality Requirements - [ ] No hardcoded strings in views - [ ] All translation keys organized by feature - [ ] Tests verify language switching - [ ] No layout breaks when switching languages ## Technical Notes ### Language Toggle Route & Controller ```php // routes/web.php Route::get('/language/{locale}', function (string $locale) { if (!in_array($locale, ['ar', 'en'])) { abort(400); } session(['locale' => $locale]); if (auth()->check()) { auth()->user()->update(['preferred_language' => $locale]); } return redirect()->back(); })->name('language.switch'); ``` ### Language Middleware ```php // app/Http/Middleware/SetLocale.php // Register in bootstrap/app.php: ->withMiddleware(fn($m) => $m->web(append: SetLocale::class)) public function handle($request, Closure $next) { $locale = session('locale', auth()->user()?->preferred_language ?? 'ar' ); app()->setLocale($locale); return $next($request); } ``` ### Translation File Structure ``` resources/lang/ ar/ auth.php pagination.php validation.php messages.php navigation.php en/ auth.php pagination.php validation.php messages.php navigation.php ``` ### RTL Support with Tailwind 4 ```css /* In app.css */ @import "tailwindcss"; @theme { /* RTL support via logical properties */ } ``` ### Font Configuration ```css /* Google Fonts import */ @import url('https://fonts.googleapis.com/css2?family=Cairo:wght@300;400;600;700&family=Montserrat:wght@300;400;600;700&display=swap'); @theme { --font-arabic: 'Cairo', 'Tajawal', sans-serif; --font-english: 'Montserrat', 'Lato', sans-serif; } ``` ### Layout Template ```blade
``` ### Date Formatting Helper ```php // In a helper or service (app/Helpers/DateHelper.php or as a service) public function formatDate($date, $locale = null): string { $locale = $locale ?? app()->getLocale(); $format = $locale === 'ar' ? 'd/m/Y' : 'm/d/Y'; return Carbon::parse($date)->format($format); } ``` ### Language Toggle Component ```blade ``` ## Testing Requirements ### Feature Tests - [ ] Test language toggle stores preference in session for guests - [ ] Test language toggle stores preference in database for authenticated users - [ ] Test locale middleware sets correct locale from user preference - [ ] Test locale middleware falls back to session for guests - [ ] Test locale middleware defaults to 'ar' when no preference set - [ ] Test date formatting helper returns DD/MM/YYYY for Arabic locale - [ ] Test date formatting helper returns MM/DD/YYYY for English locale - [ ] Test language switch redirects back to same page ### Browser Tests (Pest v4) - [ ] Test RTL layout renders correctly for Arabic (dir="rtl" on html) - [ ] Test LTR layout renders correctly for English (dir="ltr" on html) - [ ] Test no layout breaks when toggling languages - [ ] Test Arabic font (Cairo) loads for Arabic locale - [ ] Test English font (Montserrat) loads for English locale ### Manual Testing Checklist - [ ] Verify RTL alignment in navigation, forms, and content - [ ] Verify LTR alignment in navigation, forms, and content - [ ] Test on Chrome, Firefox, Safari for RTL rendering - [ ] Verify no horizontal scroll appears in either direction ## Definition of Done - [ ] Language toggle works in navigation - [ ] Arabic and English translations complete for core UI - [ ] RTL layout renders correctly for Arabic - [ ] LTR layout renders correctly for English - [ ] User preference persists in database - [ ] Guest preference persists in session - [ ] Dates format correctly per language - [ ] Fonts load properly for both languages - [ ] Tests pass for language switching - [ ] Code formatted with Pint ## Dependencies - **Story 1.1:** Database schema (users.preferred_language column) - **Story 1.4:** Base UI (navigation for language toggle) ## Risk Assessment - **Primary Risk:** RTL edge cases in complex layouts - **Mitigation:** Use Tailwind logical properties (start/end vs left/right), test early - **Rollback:** Fallback to LTR-only temporarily ## Estimation **Complexity:** Medium-High **Estimated Effort:** 4-5 hours