# Localization Implementation Plan **Created**: October 3, 2025 **Priority**: HIGH (Pre-Launch) **Estimated Duration**: 2-3 days ## Overview Implement comprehensive internationalization (i18n) support for the Maternal App with 5 languages and measurement unit preferences. ## Supported Languages 1. **English (en-US)** - Primary/Default 2. **Spanish (es-ES)** 3. **French (fr-FR)** 4. **Portuguese (pt-BR)** 5. **Simplified Chinese (zh-CN)** ## Current Status ### ✅ Already Completed - Backend multilanguage support for AI responses - AI safety responses in 5 languages - MultiLanguageService with language detection ### ❌ To Be Implemented - Frontend i18next framework - Translation files for all UI strings - Language selector in onboarding - Language selector in settings - Date/time localization - Measurement unit preferences (Metric/Imperial) - Number formatting per locale --- ## Phase 1: Framework Setup ### 1.1 Install Dependencies **Files**: `package.json` ```bash npm install i18next react-i18next i18next-browser-languagedetector npm install date-fns # Already installed, confirm locales ``` **Packages**: - `i18next` - Core i18n framework - `react-i18next` - React bindings - `i18next-browser-languagedetector` - Auto-detect user language ### 1.2 Create i18n Configuration **File**: `lib/i18n/config.ts` (NEW) - Initialize i18next - Configure language detector - Set up fallback language (en-US) - Configure interpolation - Load translation resources ### 1.3 Create i18n Provider **File**: `components/providers/I18nProvider.tsx` (NEW) - Wrap app with I18nextProvider - Initialize i18n on mount - Handle language loading states ### 1.4 Update Root Layout **File**: `app/layout.tsx` (MODIFY) - Add I18nProvider to provider stack - Set html lang attribute dynamically --- ## Phase 2: Translation Files Structure ### 2.1 Directory Structure ``` locales/ ├── en/ │ ├── common.json # Common UI strings (buttons, labels, etc.) │ ├── auth.json # Authentication pages │ ├── dashboard.json # Dashboard/home page │ ├── tracking.json # Activity tracking │ ├── children.json # Child management │ ├── family.json # Family management │ ├── ai.json # AI assistant │ ├── analytics.json # Analytics/insights │ ├── settings.json # Settings page │ ├── onboarding.json # Onboarding flow │ ├── errors.json # Error messages │ └── validation.json # Form validation messages ├── es/ │ └── [same structure] ├── fr/ │ └── [same structure] ├── pt/ │ └── [same structure] └── zh/ └── [same structure] ``` ### 2.2 Translation Keys Structure **Example - common.json**: ```json { "nav": { "dashboard": "Dashboard", "track": "Track", "children": "Children", "family": "Family", "ai": "AI Assistant", "analytics": "Analytics", "settings": "Settings" }, "buttons": { "save": "Save", "cancel": "Cancel", "delete": "Delete", "edit": "Edit", "add": "Add", "submit": "Submit", "back": "Back", "next": "Next", "confirm": "Confirm" }, "units": { "metric": "Metric", "imperial": "Imperial", "ml": "ml", "oz": "oz", "cm": "cm", "in": "in", "kg": "kg", "lb": "lb" } } ``` --- ## Phase 3: Custom Hooks ### 3.1 useTranslation Hook **File**: `hooks/useTranslation.ts` (NEW) - Re-export from react-i18next with type safety - Custom hook for easier usage ### 3.2 useLocale Hook **File**: `hooks/useLocale.ts` (NEW) - Get current locale - Change locale - Get available locales - Get locale display name ### 3.3 useFormatting Hook **File**: `hooks/useFormatting.ts` (NEW) - Format dates based on locale - Format numbers based on locale - Format currency based on locale - Format units based on preference --- ## Phase 4: Measurement Unit Preference ### 4.1 Backend Schema Update **File**: `src/database/migrations/V0XX_add_measurement_preference.sql` (NEW) ```sql ALTER TABLE users ADD COLUMN measurement_unit VARCHAR(10) DEFAULT 'metric'; -- Values: 'metric' or 'imperial' ``` ### 4.2 Update User Entity **File**: `src/database/entities/user.entity.ts` (MODIFY) Add field: ```typescript @Column({ name: 'measurement_unit', default: 'metric' }) measurementUnit: 'metric' | 'imperial'; ``` ### 4.3 Update User DTOs **Files**: - `src/modules/auth/dto/register.dto.ts` (MODIFY) - `src/modules/auth/dto/update-profile.dto.ts` (MODIFY) Add optional `measurementUnit` field. ### 4.4 API Endpoints **File**: `src/modules/auth/auth.controller.ts` (MODIFY) - PATCH `/api/v1/auth/profile` - Include measurementUnit in update --- ## Phase 5: Frontend User Preferences ### 5.1 Redux State **File**: `store/slices/userSlice.ts` (MODIFY) Add to user state: ```typescript interface UserState { // ... existing fields language: string; measurementUnit: 'metric' | 'imperial'; } ``` ### 5.2 Language Selector Component **File**: `components/settings/LanguageSelector.tsx` (NEW) Features: - Dropdown with 5 language options - Flag icons for each language - Updates user preference on change - Persists to backend - Updates i18n instance ### 5.3 Measurement Unit Selector Component **File**: `components/settings/MeasurementUnitSelector.tsx` (NEW) Features: - Toggle or dropdown (Metric/Imperial) - Updates user preference on change - Persists to backend - Shows example conversions --- ## Phase 6: Onboarding Flow Integration ### 6.1 Update Onboarding Page **File**: `app/(auth)/onboarding/page.tsx` (MODIFY) Add new steps: 1. Language selection (Step 2) 2. Measurement unit selection (Step 3) ### 6.2 Onboarding Language Step Component **File**: `components/onboarding/LanguageStep.tsx` (NEW) - Large, visual language selector - Show language names in native script - Save to Redux state - Update i18n immediately ### 6.3 Onboarding Measurement Step Component **File**: `components/onboarding/MeasurementStep.tsx` (NEW) - Visual metric/imperial selector - Show examples (ml vs oz, cm vs in) - Save to Redux state ### 6.4 Update Onboarding API Call **File**: `app/(auth)/onboarding/page.tsx` (MODIFY) Include language and measurementUnit in profile update call. --- ## Phase 7: Settings Page Integration ### 7.1 Update Settings Page **File**: `app/settings/page.tsx` (MODIFY) Add new sections: - **Language & Region** section - Language selector - Measurement unit selector ### 7.2 Settings UI Components **Files**: - `components/settings/LanguageSettings.tsx` (NEW) - `components/settings/MeasurementSettings.tsx` (NEW) --- ## Phase 8: Unit Conversion Utilities ### 8.1 Conversion Utility **File**: `lib/units/conversions.ts` (NEW) Functions: - `mlToOz(ml: number): number` - `ozToMl(oz: number): number` - `kgToLb(kg: number): number` - `lbToKg(lb: number): number` - `cmToIn(cm: number): number` - `inToCm(in: number): number` ### 8.2 Format Unit Hook **File**: `hooks/useUnitFormat.ts` (NEW) - Get user's measurement preference - Format value with correct unit - Convert between units - Display with locale-specific formatting --- ## Phase 9: Apply Localization Throughout App ### 9.1 Update All Pages Replace hardcoded strings with translation keys: **Priority Pages**: 1. **Dashboard** (`app/page.tsx`) - Nav items, headings, button labels - Activity type labels - Summary labels 2. **Authentication** (`app/(auth)/`) - Login, Register, Forgot Password - Form labels, placeholders, errors 3. **Tracking** (`app/track/`) - Feeding, Sleep, Diaper pages - Form labels, unit labels - Apply unit conversions 4. **Children** (`app/children/page.tsx`) - Child management labels - Form fields 5. **Family** (`app/family/page.tsx`) - Family management labels 6. **AI Assistant** (`app/ai-assistant/page.tsx`) - Chat interface labels - Placeholder text 7. **Analytics** (`app/analytics/page.tsx`) - Chart labels, insights 8. **Settings** (`app/settings/page.tsx`) - All settings labels ### 9.2 Update Components Replace hardcoded strings in shared components: - `components/layouts/AppShell/` (navigation) - `components/common/` (buttons, dialogs) - `components/features/` (activity cards, etc.) --- ## Phase 10: Date/Time Localization ### 10.1 Date Formatting Utility **File**: `lib/i18n/date-formats.ts` (NEW) Using date-fns with locales: ```typescript import { format } from 'date-fns'; import { enUS, es, fr, ptBR, zhCN } from 'date-fns/locale'; const locales = { en: enUS, es, fr, pt: ptBR, zh: zhCN }; export function formatDate(date: Date, formatStr: string, locale: string) { return format(date, formatStr, { locale: locales[locale] }); } ``` ### 10.2 Update Date Displays Apply locale-aware date formatting: - Activity timestamps - Child birth dates - Analytics date ranges --- ## Phase 11: Number Localization ### 11.1 Number Formatting Utility **File**: `lib/i18n/number-formats.ts` (NEW) Using Intl.NumberFormat: ```typescript export function formatNumber(value: number, locale: string) { return new Intl.NumberFormat(locale).format(value); } export function formatDecimal(value: number, locale: string, decimals = 1) { return new Intl.NumberFormat(locale, { minimumFractionDigits: decimals, maximumFractionDigits: decimals, }).format(value); } ``` ### 11.2 Apply Number Formatting - Activity amounts (ml/oz) - Sleep duration (hours) - Weight/height measurements --- ## Phase 12: Tracking Forms with Unit Preferences ### 12.1 Update Feeding Form **File**: `app/track/feeding/page.tsx` (MODIFY) - Show ml or oz input based on preference - Convert to metric for API storage - Display in user's preferred unit ### 12.2 Update Child Profile Form **File**: `app/children/page.tsx` (MODIFY) - Weight input (kg/lb) - Height input (cm/in) - Convert for API storage ### 12.3 Universal Input Component **File**: `components/forms/UnitInput.tsx` (NEW) Props: - `type: 'volume' | 'weight' | 'height'` - `value: number` - `onChange: (value: number) => void` - Auto-convert based on user preference --- ## Phase 13: Translation Files Content ### 13.1 English Translations (Base) **Estimate**: ~500-800 translation keys across all files Create complete English translations for: - All UI strings - All form labels/placeholders - All error messages - All validation messages ### 13.2 Professional Translation **Recommendation**: Use professional translation service for: - Spanish (es-ES) - French (fr-FR) - Portuguese (pt-BR) - Simplified Chinese (zh-CN) **Alternative**: Use AI-assisted translation + native speaker review --- ## Phase 14: Testing ### 14.1 Translation Coverage Test - Verify all strings are externalized - No hardcoded English strings remain - All translation keys exist in all languages ### 14.2 Language Switching Test - Switch between all 5 languages - Verify UI updates correctly - Verify no layout breaks ### 14.3 Unit Conversion Test - Test all conversions (ml↔oz, kg↔lb, cm↔in) - Verify correct rounding - Verify storage in consistent units (metric) ### 14.4 Date/Time Test - Verify dates display correctly per locale - Test all date formats (short, long, relative) ### 14.5 RTL Support (Future) **Note**: Chinese doesn't require RTL, but document for future Arabic support --- ## Phase 15: Documentation ### 15.1 Update Implementation Gaps **File**: `docs/implementation-gaps.md` (MODIFY) Mark localization as ✅ COMPLETED ### 15.2 Developer Guide **File**: `docs/LOCALIZATION_GUIDE.md` (NEW) Document: - How to add new translation keys - How to add new languages - Translation file structure - Best practices ### 15.3 Update User Documentation Document language and measurement preferences in user guide --- ## Implementation Order ### Day 1: Framework & Structure 1. ✅ Install dependencies 2. ✅ Create i18n configuration 3. ✅ Create i18n provider 4. ✅ Create hooks (useTranslation, useLocale, useFormatting) 5. ✅ Set up translation file structure 6. ✅ Create English base translations (common, auth, dashboard) ### Day 2: Preferences & Components 7. ✅ Backend schema update for measurementUnit 8. ✅ Update User entity and DTOs 9. ✅ Create LanguageSelector component 10. ✅ Create MeasurementUnitSelector component 11. ✅ Update onboarding flow 12. ✅ Update settings page 13. ✅ Create unit conversion utilities ### Day 3: Apply Throughout App 14. ✅ Update all pages with translations 15. ✅ Apply unit conversions to tracking forms 16. ✅ Apply date/time localization 17. ✅ Complete all English translations 18. ✅ Test language switching 19. ✅ Test unit conversions ### Post-Implementation (Optional) 20. Professional translation for other 4 languages 21. Native speaker review 22. Documentation updates --- ## Key Files Checklist ### New Files (27 total) - [ ] `lib/i18n/config.ts` - [ ] `components/providers/I18nProvider.tsx` - [ ] `hooks/useLocale.ts` - [ ] `hooks/useFormatting.ts` - [ ] `hooks/useUnitFormat.ts` - [ ] `lib/units/conversions.ts` - [ ] `lib/i18n/date-formats.ts` - [ ] `lib/i18n/number-formats.ts` - [ ] `components/settings/LanguageSelector.tsx` - [ ] `components/settings/MeasurementUnitSelector.tsx` - [ ] `components/settings/LanguageSettings.tsx` - [ ] `components/settings/MeasurementSettings.tsx` - [ ] `components/onboarding/LanguageStep.tsx` - [ ] `components/onboarding/MeasurementStep.tsx` - [ ] `components/forms/UnitInput.tsx` - [ ] `locales/en/*.json` (11 files) - [ ] `locales/es/*.json` (11 files - future) - [ ] `locales/fr/*.json` (11 files - future) - [ ] `locales/pt/*.json` (11 files - future) - [ ] `locales/zh/*.json` (11 files - future) - [ ] `src/database/migrations/V0XX_add_measurement_preference.sql` - [ ] `docs/LOCALIZATION_GUIDE.md` ### Modified Files (15 total) - [ ] `package.json` - [ ] `app/layout.tsx` - [ ] `store/slices/userSlice.ts` - [ ] `src/database/entities/user.entity.ts` - [ ] `src/modules/auth/dto/register.dto.ts` - [ ] `src/modules/auth/dto/update-profile.dto.ts` - [ ] `app/(auth)/onboarding/page.tsx` - [ ] `app/settings/page.tsx` - [ ] `app/page.tsx` (dashboard) - [ ] `app/track/feeding/page.tsx` - [ ] `app/track/sleep/page.tsx` - [ ] `app/track/diaper/page.tsx` - [ ] `app/children/page.tsx` - [ ] `app/family/page.tsx` - [ ] `docs/implementation-gaps.md` --- ## Success Criteria ### ✅ Functionality - [ ] All 5 languages selectable and functional - [ ] Language preference persists across sessions - [ ] Measurement unit preference persists across sessions - [ ] All UI strings externalized (no hardcoded English) - [ ] Unit conversions work correctly (ml↔oz, kg↔lb, cm↔in) - [ ] Dates display correctly per locale - [ ] Numbers format correctly per locale ### ✅ User Experience - [ ] Language can be selected in onboarding - [ ] Language can be changed in settings - [ ] Measurement unit can be selected in onboarding - [ ] Measurement unit can be changed in settings - [ ] UI updates immediately when language changes - [ ] No layout breaks when changing languages - [ ] Form inputs show correct units based on preference ### ✅ Technical - [ ] All translation keys defined - [ ] No missing translation warnings - [ ] Type-safe translation usage (TypeScript) - [ ] Backend stores preferences correctly - [ ] Redux state syncs with backend --- ## Notes ### Translation Best Practices 1. Use namespaces to organize translations 2. Use interpolation for dynamic values: `t('welcome', { name })` 3. Use pluralization: `t('items', { count })` 4. Keep keys descriptive: `auth.login.emailLabel` not `auth.e1` 5. Avoid concatenation, use complete sentences ### Unit Conversion Strategy - **Storage**: Always store in metric (ml, kg, cm) in database - **Display**: Convert to user's preferred unit for display - **Input**: Accept user's preferred unit, convert to metric before API call - **Consistency**: Ensure all measurements use the same preference ### Performance Considerations - Lazy load translation files per namespace - Cache translations in browser - Preload critical translations (common, errors) ### Future Enhancements - Add more languages (Arabic, German, Hindi, etc.) - Add more units (temperature: °C/°F) - Add regional date formats (MM/DD vs DD/MM) - Add time format preferences (12h vs 24h) --- **Total Estimated Effort**: 2-3 days **Complexity**: Medium **Priority**: HIGH (Pre-Launch) **Dependencies**: None (can start immediately)