diff --git a/docs/.duckversions/LOCALIZATION_IMPLEMENTATION_PLAN-20251003115405.029.md b/docs/.duckversions/LOCALIZATION_IMPLEMENTATION_PLAN-20251003115405.029.md
new file mode 100644
index 0000000..8949da6
--- /dev/null
+++ b/docs/.duckversions/LOCALIZATION_IMPLEMENTATION_PLAN-20251003115405.029.md
@@ -0,0 +1,784 @@
+# 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 - Updated October 3, 2025
+
+### ✅ Already Completed (Backend)
+- Backend multilanguage support for AI responses
+- AI safety responses in 5 languages
+- MultiLanguageService with language detection
+
+### ✅ Completed (Frontend - Phases 1-9)
+- ✅ **Phase 1**: i18next framework installed and configured
+- ✅ **Phase 2**: Translation files structure created (40 files: 5 languages × 8 namespaces)
+- ✅ **Phase 3**: Custom hooks created (useTranslation, useLocale, useFormatting)
+- ✅ **Phase 4**: Backend user schema updated with measurementUnit in preferences JSONB
+- ✅ **Phase 5**: Language & measurement selectors in Settings page
+- ✅ **Phase 7**: Settings page fully localized with preferences
+- ✅ **Phase 8**: Measurement unit conversion utilities implemented
+- ✅ **Phase 9**: Applied localization to core pages:
+ - Login & authentication pages
+ - Dashboard with welcome message, quick actions, summary
+ - Navigation (AppShell, MobileNav, TabBar)
+ - Track main page (activity selection)
+ - Children page (with age formatting & pluralization)
+ - All connection status indicators
+
+### ✅ Translation Files Created (40 files)
+- `common.json` - UI strings, navigation, connection (all 5 languages)
+- `auth.json` - Authentication pages (all 5 languages)
+- `dashboard.json` - Dashboard/home page (all 5 languages)
+- `tracking.json` - Activity tracking (all 5 languages)
+- `children.json` - Child management (all 5 languages)
+- `settings.json` - Settings page (all 5 languages)
+- `ai.json` - AI assistant (all 5 languages)
+- `errors.json` - Error messages (all 5 languages)
+
+### ⏳ Remaining To Be Implemented
+- Language selector in onboarding flow (Phase 6)
+- Individual tracking pages (feeding, sleep, diaper, medicine) with unit conversions (Phase 12)
+- Family management page localization
+- Analytics/insights page localization
+- Date/time localization throughout app (Phase 10)
+- Number formatting per locale (Phase 11)
+- Professional translation review (Phase 13.2)
+- Comprehensive testing (Phase 14)
+
+---
+
+## Phase 1: Framework Setup ✅ COMPLETED
+
+### 1.1 Install Dependencies - latest versions only! ✅
+**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` (CREATED)
+
+- ✅ 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` (CREATED)
+
+- ✅ Wrap app with I18nextProvider
+- ✅ Initialize i18n on mount
+- ✅ Handle language loading states
+
+### 1.4 Update Root Layout ✅
+**File**: `app/layout.tsx` (MODIFIED)
+
+- ✅ Add I18nProvider to provider stack
+- ⏳ Set html lang attribute dynamically (TODO)
+
+---
+
+## Phase 2: Translation Files Structure ✅ COMPLETED
+
+### 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 ✅ COMPLETED
+
+### 3.1 useTranslation Hook ✅
+**File**: `hooks/useTranslation.ts` (CREATED)
+
+- ✅ Re-export from react-i18next with type safety
+- ✅ Custom hook for easier usage
+
+### 3.2 useLocale Hook ✅
+**File**: `hooks/useLocale.ts` (CREATED)
+
+- ✅ Get current locale
+- ✅ Change locale
+- ✅ Get available locales
+- ✅ Get locale display name
+- ✅ Measurement system management
+
+### 3.3 useFormatting Hook ✅
+**File**: `hooks/useFormatting.ts` (CREATED)
+
+- ✅ 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 ✅ COMPLETED
+
+### 4.1 Backend Schema Update ✅
+**Implementation**: Used existing `preferences` JSONB column from V005_add_user_preferences.sql
+- No new migration needed - reused existing preferences column
+- Added `measurementUnit` as optional field in preferences object
+
+### 4.2 Update User Entity ✅
+**File**: `src/database/entities/user.entity.ts` (MODIFIED)
+
+Added to preferences type:
+```typescript
+@Column({ type: 'jsonb', nullable: true })
+preferences?: {
+ notifications?: boolean;
+ emailUpdates?: boolean;
+ darkMode?: boolean;
+ measurementUnit?: 'metric' | 'imperial';
+};
+```
+
+### 4.3 Update User DTOs ✅
+**File**: `src/modules/auth/dto/update-profile.dto.ts` (CREATED)
+
+Created with validation:
+```typescript
+export class UserPreferencesDto {
+ @IsOptional()
+ @IsIn(['metric', 'imperial'])
+ measurementUnit?: 'metric' | 'imperial';
+}
+```
+
+### 4.4 API Endpoints ✅
+**File**: `src/modules/auth/auth.controller.ts` (MODIFIED)
+
+- PATCH `/api/v1/auth/profile` - Updated to use UpdateProfileDto with measurementUnit support
+- Properly typed and validated
+
+---
+
+## Phase 5: Frontend User Preferences ✅ PARTIALLY COMPLETED
+
+### 5.1 Redux State ⏳
+**File**: `store/slices/userSlice.ts` (TODO)
+
+Add to user state:
+```typescript
+interface UserState {
+ // ... existing fields
+ language: string;
+ measurementUnit: 'metric' | 'imperial';
+}
+```
+
+### 5.2 Language Selector Component ✅
+**File**: `components/settings/LanguageSelector.tsx` (CREATED)
+
+Features:
+- ✅ Dropdown with 5 language options
+- ✅ Shows language names in native script
+- ✅ Updates user preference on change
+- ⏳ Persists to backend (pending backend schema)
+- ✅ Updates i18n instance
+
+### 5.3 Measurement Unit Selector Component ✅
+**File**: `components/settings/MeasurementUnitSelector.tsx` (CREATED)
+
+Features:
+- ✅ Dropdown (Metric/Imperial)
+- ✅ Updates user preference on change
+- ⏳ Persists to backend (pending backend schema)
+- ✅ Shows unit examples
+
+---
+
+## Phase 6: Onboarding Flow Integration ❌ TODO
+
+### 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 ✅ COMPLETED
+
+### 7.1 Update Settings Page ✅
+**File**: `app/settings/page.tsx` (MODIFIED)
+
+Add new sections:
+- ✅ **Preferences** section
+ - ✅ Language selector
+ - ✅ Measurement unit selector
+
+### 7.2 Settings UI Components ✅
+**Files**:
+- ✅ `components/settings/LanguageSelector.tsx` (CREATED)
+- ✅ `components/settings/MeasurementUnitSelector.tsx` (CREATED)
+
+---
+
+## Phase 8: Unit Conversion Utilities ✅ COMPLETED
+
+### 8.1 Conversion Utility ✅
+**File**: `lib/utils/unitConversion.ts` (CREATED)
+
+Functions:
+- ✅ `convertWeight` / `convertWeightToKg`
+- ✅ `convertHeight` / `convertHeightToCm`
+- ✅ `convertTemperature` / `convertTemperatureToCelsius`
+- ✅ `convertVolume` / `convertVolumeToMl`
+- ✅ `getUnitSymbol`
+- ✅ `getConversionFactor`
+
+### 8.2 Format Unit Hook ✅
+**File**: `hooks/useFormatting.ts` (CREATED)
+
+- ✅ Get user's measurement preference
+- ✅ Format value with correct unit
+- ✅ Convert between units
+- ✅ Display with locale-specific formatting
+
+---
+
+## Phase 9: Apply Localization Throughout App ✅ PARTIALLY COMPLETED
+
+### 9.1 Update All Pages - Status
+
+**✅ Completed Priority Pages**:
+1. ✅ **Dashboard** (`app/page.tsx`)
+ - Welcome message with user name interpolation
+ - Quick actions (all 6 activity cards)
+ - Today's summary with child name interpolation
+ - Next predicted activity with variable interpolation
+ - All UI labels translated in 5 languages
+
+2. ✅ **Authentication** (`app/(auth)/login/page.tsx`)
+ - Login form labels (email, password)
+ - Submit button, forgot password link
+ - Social login buttons (Google, Apple)
+ - Biometric authentication (Face ID/Touch ID)
+ - Sign up link and all helper text
+
+3. ✅ **Track Main Page** (`app/track/page.tsx`)
+ - Track Activity title and subtitle
+ - All 5 activity type labels (Feeding, Sleep, Diaper, Medicine, Activity)
+ - Translated in all 5 languages
+
+4. ✅ **Children** (`app/children/page.tsx`)
+ - Page title and subtitle
+ - Add/Edit child buttons
+ - Empty state messages
+ - Age calculation with proper pluralization (year/years, month/months)
+ - All error messages
+ - Gender labels
+
+**❌ Remaining Pages**:
+5. ⏳ **Individual Tracking Pages** (`app/track/feeding/`, etc.)
+ - Feeding, Sleep, Diaper, Medicine detail pages
+ - Form labels, unit labels
+ - Apply unit conversions (Phase 12)
+
+6. ❌ **Family** (`app/family/page.tsx`)
+ - Family management labels
+
+7. ⏳ **AI Assistant** (`app/ai-assistant/page.tsx`)
+ - Chat interface already uses AI translations from backend
+ - Frontend labels may need localization
+
+8. ❌ **Analytics** (`app/analytics/page.tsx`)
+ - Chart labels, insights
+
+9. ✅ **Settings** (`app/settings/page.tsx`)
+ - Already completed in Phase 7
+
+### 9.2 Update Components - Status
+
+**✅ Completed Components**:
+- ✅ `components/layouts/AppShell/AppShell.tsx` - Connection status, presence indicators
+- ✅ `components/layouts/MobileNav/MobileNav.tsx` - Navigation menu items, logout
+- ✅ `components/layouts/TabBar/TabBar.tsx` - Bottom navigation tabs
+- ✅ `components/settings/LanguageSelector.tsx` - Language preference UI
+- ✅ `components/settings/MeasurementUnitSelector.tsx` - Measurement preference UI
+
+**❌ Remaining Components**:
+- ⏳ `components/common/` - Common dialogs, buttons (may need review)
+- ⏳ `components/features/` - Activity cards, forms (need review)
+- ⏳ `components/children/` - Child dialogs (ChildDialog, DeleteConfirmDialog)
+- ⏳ `components/family/` - Family components
+
+---
+
+## 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)
+
+---
+
+## Remaining Tasks Summary
+
+### 🔴 High Priority (Core Functionality)
+
+1. **Individual Tracking Pages with Unit Conversions** (Phase 12)
+ - `/app/track/feeding/page.tsx` - Volume conversion (ml ↔ oz)
+ - `/app/track/sleep/page.tsx` - Duration formatting
+ - `/app/track/diaper/page.tsx` - Type labels
+ - `/app/track/medicine/page.tsx` - Dosage with units
+ - Implement UnitInput component for automatic conversion
+ - **Estimated Effort**: 4-6 hours
+
+2. **Child Dialog Components Localization**
+ - `components/children/ChildDialog.tsx` - Form labels
+ - `components/children/DeleteConfirmDialog.tsx` - Confirmation text
+ - **Estimated Effort**: 1 hour
+
+3. **Date/Time Localization** (Phase 10)
+ - Apply date-fns with locale to all date displays
+ - Activity timestamps
+ - Child birth dates
+ - Analytics date ranges
+ - **Estimated Effort**: 2-3 hours
+
+### 🟡 Medium Priority (Nice to Have)
+
+4. **Onboarding Flow** (Phase 6)
+ - Add language selection step
+ - Add measurement unit selection step
+ - Save preferences during onboarding
+ - **Estimated Effort**: 2-3 hours
+
+5. **Family Management Page**
+ - `app/family/page.tsx` localization
+ - Family member labels, invitation flow
+ - **Estimated Effort**: 1-2 hours
+
+6. **Number Formatting** (Phase 11)
+ - Apply Intl.NumberFormat throughout
+ - Weight/height values
+ - Activity counts
+ - **Estimated Effort**: 1-2 hours
+
+### 🟢 Low Priority (Future Enhancements)
+
+7. **Analytics/Insights Page**
+ - Chart labels
+ - Insight descriptions
+ - **Estimated Effort**: 2-3 hours
+
+8. **Professional Translation Review** (Phase 13.2)
+ - Review all 4 non-English languages
+ - Native speaker validation
+ - Cultural appropriateness check
+ - **Estimated Effort**: External service, 1-2 weeks
+
+9. **Comprehensive Testing** (Phase 14)
+ - Translation coverage test
+ - Language switching test
+ - Unit conversion test
+ - Date/time formatting test
+ - **Estimated Effort**: 2-4 hours
+
+10. **Documentation** (Phase 15)
+ - Create LOCALIZATION_GUIDE.md
+ - Update implementation-gaps.md
+ - Developer best practices
+ - **Estimated Effort**: 1-2 hours
+
+### 📊 Progress Tracking
+
+**Completed**: 9 phases (1-5, 7-9)
+**In Progress**: 0 phases
+**Remaining**: 6 major phases (6, 10-15)
+
+**Overall Completion**: ~65% (core functionality)
+
+**Estimated Time to Full Completion**:
+- High Priority: 8-11 hours
+- Medium Priority: 4-7 hours
+- Low Priority: 5-9 hours
+- **Total Remaining**: 17-27 hours (2-3.5 days)
+
+---
+
+**Total Project Effort**: 2-3 days (completed) + 2-3.5 days (remaining) = 4-6.5 days
+**Complexity**: Medium
+**Priority**: HIGH (Pre-Launch)
+**Current Status**: Core functionality 65% complete, production-ready for MVP
diff --git a/docs/LOCALIZATION_IMPLEMENTATION_PLAN.md b/docs/LOCALIZATION_IMPLEMENTATION_PLAN.md
index 8949da6..2c39173 100644
--- a/docs/LOCALIZATION_IMPLEMENTATION_PLAN.md
+++ b/docs/LOCALIZATION_IMPLEMENTATION_PLAN.md
@@ -54,6 +54,7 @@ Implement comprehensive internationalization (i18n) support for the Maternal App
- Individual tracking pages (feeding, sleep, diaper, medicine) with unit conversions (Phase 12)
- Family management page localization
- Analytics/insights page localization
+- Settings page localization
- Date/time localization throughout app (Phase 10)
- Number formatting per locale (Phase 11)
- Professional translation review (Phase 13.2)
diff --git a/maternal-web/app/settings/page.tsx b/maternal-web/app/settings/page.tsx
index 3851e36..faf8cfa 100644
--- a/maternal-web/app/settings/page.tsx
+++ b/maternal-web/app/settings/page.tsx
@@ -22,6 +22,8 @@ import { motion } from 'framer-motion';
export default function SettingsPage() {
const { user, logout, refreshUser } = useAuth();
const [name, setName] = useState(user?.name || '');
+ const [timezone, setTimezone] = useState(user?.timezone || 'UTC');
+ const [timeFormat, setTimeFormat] = useState<'12h' | '24h'>(user?.preferences?.timeFormat || '12h');
const [settings, setSettings] = useState({
notifications: true,
emailUpdates: false,
@@ -40,17 +42,48 @@ export default function SettingsPage() {
emailUpdates: user.preferences.emailUpdates ?? false,
darkMode: user.preferences.darkMode ?? false,
});
+ setTimeFormat(user.preferences.timeFormat || '12h');
}
}, [user?.preferences]);
- // Sync name state when user data changes
+ // Sync name and timezone state when user data changes
useEffect(() => {
if (user?.name) {
setName(user.name);
}
+ if (user?.timezone) {
+ setTimezone(user.timezone);
+ }
}, [user]);
- const handleSave = async () => {
+ const handleSavePreferences = async () => {
+ setIsLoading(true);
+ setError(null);
+
+ try {
+ const response = await usersApi.updateProfile({
+ timezone,
+ preferences: {
+ ...settings,
+ timeFormat,
+ }
+ });
+ console.log('✅ Preferences updated successfully:', response);
+
+ // Refresh user to get latest data from server
+ await refreshUser();
+
+ setSuccessMessage('Preferences saved successfully!');
+ } catch (err: any) {
+ console.error('❌ Failed to update preferences:', err);
+ console.error('Error response:', err.response);
+ setError(err.response?.data?.message || err.message || 'Failed to save preferences. Please try again.');
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ const handleSaveProfile = async () => {
// Validate name
if (!name || name.trim() === '') {
setNameError('Name cannot be empty');
@@ -64,7 +97,6 @@ export default function SettingsPage() {
try {
const response = await usersApi.updateProfile({
name: name.trim(),
- preferences: settings
});
console.log('✅ Profile updated successfully:', response);
@@ -143,11 +175,11 @@ export default function SettingsPage() {
: }
- onClick={handleSave}
+ onClick={handleSaveProfile}
disabled={isLoading}
sx={{ alignSelf: 'flex-start' }}
>
- {isLoading ? 'Saving...' : 'Save Changes'}
+ {isLoading ? 'Saving...' : 'Save Profile'}
@@ -170,10 +202,19 @@ export default function SettingsPage() {
-
+
-
+
+ : }
+ onClick={handleSavePreferences}
+ disabled={isLoading}
+ sx={{ mt: 3, alignSelf: 'flex-start' }}
+ >
+ {isLoading ? 'Saving...' : 'Save Preferences'}
+
@@ -214,11 +255,11 @@ export default function SettingsPage() {
: }
- onClick={handleSave}
+ onClick={handleSavePreferences}
disabled={isLoading}
sx={{ mt: 2, alignSelf: 'flex-start' }}
>
- {isLoading ? 'Saving...' : 'Save Preferences'}
+ {isLoading ? 'Saving...' : 'Save Notification Settings'}
diff --git a/maternal-web/components/settings/TimeFormatSelector.tsx b/maternal-web/components/settings/TimeFormatSelector.tsx
index 381c8fc..3a2821b 100644
--- a/maternal-web/components/settings/TimeFormatSelector.tsx
+++ b/maternal-web/components/settings/TimeFormatSelector.tsx
@@ -1,53 +1,33 @@
'use client';
-import { useState } from 'react';
+import { useEffect } from 'react';
import {
Box,
FormControl,
RadioGroup,
FormControlLabel,
Radio,
- Button,
- CircularProgress,
- Alert,
Typography,
} from '@mui/material';
-import { Save, Schedule } from '@mui/icons-material';
+import { Schedule } from '@mui/icons-material';
import { useAuth } from '@/lib/auth/AuthContext';
-import { usersApi } from '@/lib/api/users';
import { useTranslation } from '@/hooks/useTranslation';
-export function TimeFormatSelector() {
- const { user, refreshUser } = useAuth();
+interface TimeFormatSelectorProps {
+ value: '12h' | '24h';
+ onChange: (timeFormat: '12h' | '24h') => void;
+}
+
+export function TimeFormatSelector({ value, onChange }: TimeFormatSelectorProps) {
+ const { user } = useAuth();
const { t } = useTranslation('settings');
- const [timeFormat, setTimeFormat] = useState<'12h' | '24h'>(
- user?.preferences?.timeFormat || '12h'
- );
- const [isLoading, setIsLoading] = useState(false);
- const [error, setError] = useState(null);
- const [successMessage, setSuccessMessage] = useState(null);
- const handleSave = async () => {
- setIsLoading(true);
- setError(null);
- setSuccessMessage(null);
-
- try {
- await usersApi.updateProfile({
- preferences: {
- ...user?.preferences,
- timeFormat,
- },
- });
- await refreshUser();
- setSuccessMessage('Time format updated successfully');
- } catch (err: any) {
- console.error('Failed to update time format:', err);
- setError(err.response?.data?.message || 'Failed to update time format');
- } finally {
- setIsLoading(false);
+ // Initialize with user's time format on mount
+ useEffect(() => {
+ if (user?.preferences?.timeFormat && !value) {
+ onChange(user.preferences.timeFormat);
}
- };
+ }, [user?.preferences?.timeFormat]);
const currentTime = new Date();
const preview12h = currentTime.toLocaleTimeString('en-US', {
@@ -70,26 +50,14 @@ export function TimeFormatSelector() {
- {error && (
- setError(null)}>
- {error}
-
- )}
-
- {successMessage && (
- setSuccessMessage(null)}>
- {successMessage}
-
- )}
-
-
+
setTimeFormat(e.target.value as '12h' | '24h')}
+ value={value || user?.preferences?.timeFormat || '12h'}
+ onChange={(e) => onChange(e.target.value as '12h' | '24h')}
>
}
+ control={}
label={
12-hour format
@@ -101,7 +69,7 @@ export function TimeFormatSelector() {
/>
}
+ control={}
label={
24-hour format
@@ -113,15 +81,6 @@ export function TimeFormatSelector() {
/>
-
- : }
- onClick={handleSave}
- disabled={isLoading || timeFormat === user?.preferences?.timeFormat}
- >
- {isLoading ? 'Saving...' : 'Save'}
-
);
}
diff --git a/maternal-web/components/settings/TimeZoneSelector.tsx b/maternal-web/components/settings/TimeZoneSelector.tsx
index 17aa6cf..a637163 100644
--- a/maternal-web/components/settings/TimeZoneSelector.tsx
+++ b/maternal-web/components/settings/TimeZoneSelector.tsx
@@ -1,6 +1,6 @@
'use client';
-import { useState } from 'react';
+import { useEffect } from 'react';
import {
Box,
FormControl,
@@ -8,13 +8,10 @@ import {
Select,
MenuItem,
Button,
- CircularProgress,
- Alert,
Typography,
} from '@mui/material';
-import { Save, AccessTime } from '@mui/icons-material';
+import { AccessTime } from '@mui/icons-material';
import { useAuth } from '@/lib/auth/AuthContext';
-import { usersApi } from '@/lib/api/users';
import { useTranslation } from '@/hooks/useTranslation';
// Common timezones grouped by region
@@ -71,35 +68,25 @@ const TIMEZONES = {
],
};
-export function TimeZoneSelector() {
- const { user, refreshUser } = useAuth();
+interface TimeZoneSelectorProps {
+ value: string;
+ onChange: (timezone: string) => void;
+}
+
+export function TimeZoneSelector({ value, onChange }: TimeZoneSelectorProps) {
+ const { user } = useAuth();
const { t } = useTranslation('settings');
- const [timezone, setTimezone] = useState(user?.timezone || 'UTC');
- const [isLoading, setIsLoading] = useState(false);
- const [error, setError] = useState(null);
- const [successMessage, setSuccessMessage] = useState(null);
- const handleSave = async () => {
- setIsLoading(true);
- setError(null);
- setSuccessMessage(null);
-
- try {
- await usersApi.updateProfile({ timezone });
- await refreshUser();
- setSuccessMessage('Timezone updated successfully');
- } catch (err: any) {
- console.error('Failed to update timezone:', err);
- setError(err.response?.data?.message || 'Failed to update timezone');
- } finally {
- setIsLoading(false);
+ // Initialize with user's timezone on mount
+ useEffect(() => {
+ if (user?.timezone && !value) {
+ onChange(user.timezone);
}
- };
+ }, [user?.timezone]);
const handleAutoDetect = () => {
const detectedTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
- setTimezone(detectedTimezone);
- setSuccessMessage(`Auto-detected timezone: ${detectedTimezone}`);
+ onChange(detectedTimezone);
};
return (
@@ -111,25 +98,12 @@ export function TimeZoneSelector() {
- {error && (
- setError(null)}>
- {error}
-
- )}
-
- {successMessage && (
- setSuccessMessage(null)}>
- {successMessage}
-
- )}
-
Time Zone
-
-
- : }
- onClick={handleSave}
- disabled={isLoading || timezone === user?.timezone}
- >
- {isLoading ? 'Saving...' : 'Save'}
-
-
+
);
}