Implemented comprehensive frontend localization infrastructure supporting 5 languages (English, Spanish, French, Portuguese, Chinese) with measurement unit preferences (Metric/Imperial). This lays the foundation for international user support. **Core Infrastructure:** - Installed i18next, react-i18next, i18next-browser-languagedetector - Created I18nProvider component integrated into app layout - Configured i18next with language detection and localStorage persistence - Created 35 translation files (5 languages × 7 namespaces) **Translation Namespaces:** - common: App-wide UI elements, navigation, actions - tracking: Activity tracking (feeding, sleep, diaper, milestones) - ai: AI assistant chat interface - auth: Authentication flows (login, signup, password reset) - settings: Settings and preferences - onboarding: Onboarding flow - errors: Error messages and validation **Custom Hooks:** - useTranslation: Type-safe translation wrapper - useLocale: Language and measurement system management - useFormatting: Date, time, number, and unit formatting **Measurement Unit Support:** - Created unit conversion utilities (weight, height, temperature, volume) - Metric: kg, cm, °C, ml - Imperial: lb, in, °F, oz - Bidirectional conversion functions **UI Components:** - LanguageSelector: Dropdown to change app language - MeasurementUnitSelector: Toggle between Metric/Imperial - Integrated both into Settings page Preferences section **Next Steps (Remaining):** - Add measurement preferences to backend user schema - Create onboarding flow with language/measurement selection - Apply translations to existing components (dashboard, tracking forms) - Implement multi-language AI responses - Add professional translations (currently using basic translations) **File Highlights:** - lib/i18n/config.ts: i18next configuration - hooks/useFormatting.ts: Formatting utilities with locale support - lib/utils/unitConversion.ts: Unit conversion logic - components/settings/*Selector.tsx: Language and measurement selectors - locales/*/: Translation files for 5 languages 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
16 KiB
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
- English (en-US) - Primary/Default
- Spanish (es-ES)
- French (fr-FR)
- Portuguese (pt-BR)
- 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 - latest versions only!
Files: package.json
npm install i18next react-i18next i18next-browser-languagedetector
npm install date-fns # Already installed, confirm locales
Packages:
i18next- Core i18n frameworkreact-i18next- React bindingsi18next-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:
{
"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)
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:
@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:
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:
- Language selection (Step 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): numberozToMl(oz: number): numberkgToLb(kg: number): numberlbToKg(lb: number): numbercmToIn(cm: number): numberinToCm(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:
-
Dashboard (
app/page.tsx)- Nav items, headings, button labels
- Activity type labels
- Summary labels
-
Authentication (
app/(auth)/)- Login, Register, Forgot Password
- Form labels, placeholders, errors
-
Tracking (
app/track/)- Feeding, Sleep, Diaper pages
- Form labels, unit labels
- Apply unit conversions
-
Children (
app/children/page.tsx)- Child management labels
- Form fields
-
Family (
app/family/page.tsx)- Family management labels
-
AI Assistant (
app/ai-assistant/page.tsx)- Chat interface labels
- Placeholder text
-
Analytics (
app/analytics/page.tsx)- Chart labels, insights
-
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:
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:
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: numberonChange: (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
- ✅ Install dependencies
- ✅ Create i18n configuration
- ✅ Create i18n provider
- ✅ Create hooks (useTranslation, useLocale, useFormatting)
- ✅ Set up translation file structure
- ✅ Create English base translations (common, auth, dashboard)
Day 2: Preferences & Components
- ✅ Backend schema update for measurementUnit
- ✅ Update User entity and DTOs
- ✅ Create LanguageSelector component
- ✅ Create MeasurementUnitSelector component
- ✅ Update onboarding flow
- ✅ Update settings page
- ✅ Create unit conversion utilities
Day 3: Apply Throughout App
- ✅ Update all pages with translations
- ✅ Apply unit conversions to tracking forms
- ✅ Apply date/time localization
- ✅ Complete all English translations
- ✅ Test language switching
- ✅ Test unit conversions
Post-Implementation (Optional)
- Professional translation for other 4 languages
- Native speaker review
- Documentation updates
Key Files Checklist
New Files (27 total)
lib/i18n/config.tscomponents/providers/I18nProvider.tsxhooks/useLocale.tshooks/useFormatting.tshooks/useUnitFormat.tslib/units/conversions.tslib/i18n/date-formats.tslib/i18n/number-formats.tscomponents/settings/LanguageSelector.tsxcomponents/settings/MeasurementUnitSelector.tsxcomponents/settings/LanguageSettings.tsxcomponents/settings/MeasurementSettings.tsxcomponents/onboarding/LanguageStep.tsxcomponents/onboarding/MeasurementStep.tsxcomponents/forms/UnitInput.tsxlocales/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.sqldocs/LOCALIZATION_GUIDE.md
Modified Files (15 total)
package.jsonapp/layout.tsxstore/slices/userSlice.tssrc/database/entities/user.entity.tssrc/modules/auth/dto/register.dto.tssrc/modules/auth/dto/update-profile.dto.tsapp/(auth)/onboarding/page.tsxapp/settings/page.tsxapp/page.tsx(dashboard)app/track/feeding/page.tsxapp/track/sleep/page.tsxapp/track/diaper/page.tsxapp/children/page.tsxapp/family/page.tsxdocs/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
- Use namespaces to organize translations
- Use interpolation for dynamic values:
t('welcome', { name }) - Use pluralization:
t('items', { count }) - Keep keys descriptive:
auth.login.emailLabelnotauth.e1 - 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)