- Add multi-language support with i18next and react-i18next - Implement user-selectable date format preferences (5 formats) - Add time format preferences (12-hour/24-hour) - Implement RTL (right-to-left) support for Arabic, Hebrew, Persian, Urdu - Add first day of week preference - Create LocalizationContext for managing i18n settings - Add LocalizationSettings component to Settings page - Include sample translations: English, Spanish, Arabic - Configure 10 languages: en, es, fr, de, ar, he, zh, ja, pt, ru - Add translation management documentation and Crowdin config - Create date formatting utilities that respect user preferences - Add RTL CSS styles for proper layout mirroring - Update Settings and ThemeToggle components to use translations - Add comprehensive documentation (implementation guide, quick reference, translation guide) All user preferences are persisted to localStorage and apply throughout the app.
10 KiB
Internationalization Implementation Guide
Overview
This document describes the comprehensive internationalization (i18n) implementation for Donetick, including language support, date format preferences, time format preferences, and right-to-left (RTL) language support.
Features Implemented
1. Multi-Language Support
- ✅ i18next and react-i18next integration
- ✅ Browser language detection
- ✅ Persistent language preference
- ✅ Translation namespaces (common, settings, chores)
- ✅ Sample translations: English, Spanish, Arabic
2. Date Format Preferences
- ✅ User-selectable date formats:
- MM/DD/YYYY (US format)
- DD/MM/YYYY (European format)
- YYYY-MM-DD (ISO format)
- Long format (e.g., January 1, 2024)
- Short format (e.g., Jan 1, 2024)
- ✅ Live preview of date formats
- ✅ Persistent user preferences
3. Time Format Preferences
- ✅ 12-hour format (with AM/PM)
- ✅ 24-hour format
- ✅ Live preview
4. RTL (Right-to-Left) Support
- ✅ Automatic RTL layout for Arabic, Hebrew, Persian, Urdu
- ✅ CSS styles for proper RTL rendering
- ✅ Direction attribute on HTML element
- ✅ Text alignment adjustments
5. First Day of Week
- ✅ Configurable first day of week (Sunday/Monday)
- ✅ Affects calendar displays
File Structure
donetick-frontend/
├── src/
│ ├── i18n/
│ │ ├── config.js # i18next configuration
│ │ └── README.md # i18n usage guide
│ ├── contexts/
│ │ └── LocalizationContext.jsx # Localization context and hooks
│ ├── utils/
│ │ └── DateFormatter.js # Date formatting utilities
│ └── views/
│ └── Settings/
│ └── LocalizationSettings.jsx # Settings UI component
├── public/
│ └── locales/
│ ├── en/ # English translations
│ │ ├── common.json
│ │ ├── settings.json
│ │ └── chores.json
│ ├── es/ # Spanish translations
│ └── ar/ # Arabic translations (RTL)
├── crowdin.yml # Crowdin configuration
└── TRANSLATION.md # Translation management guide
Usage Examples
1. Using Translations in Components
import { useTranslation } from 'react-i18next'
function MyComponent() {
const { t } = useTranslation('settings')
return (
<div>
<h1>{t('title')}</h1>
<p>{t('localization.description')}</p>
</div>
)
}
2. Using Date Formatting
import { useLocalization } from '@/contexts/LocalizationContext'
function MyComponent() {
const { formatDate, formatDateTime, formatRelative } = useLocalization()
const expirationDate = new Date('2024-12-31')
return (
<div>
<p>Expires: {formatDate(expirationDate)}</p>
<p>Due: {formatRelative(expirationDate)}</p>
</div>
)
}
3. Accessing Localization Settings
import { useLocalization } from '@/contexts/LocalizationContext'
function MyComponent() {
const {
language,
setLanguage,
dateFormat,
setDateFormat,
timeFormat,
setTimeFormat,
isRTL
} = useLocalization()
return (
<div dir={isRTL ? 'rtl' : 'ltr'}>
<select value={language} onChange={(e) => setLanguage(e.target.value)}>
<option value="en">English</option>
<option value="es">Español</option>
<option value="ar">العربية</option>
</select>
</div>
)
}
4. Example: Converting Existing Date Formatting
Before:
import moment from 'moment'
function SubscriptionInfo({ userProfile }) {
return (
<p>
Subscription expires on {moment(userProfile.expiration).format('MMM DD, YYYY')}
</p>
)
}
After:
import { useLocalization } from '@/contexts/LocalizationContext'
function SubscriptionInfo({ userProfile }) {
const { formatDate } = useLocalization()
return (
<p>
Subscription expires on {formatDate(userProfile.expiration)}
</p>
)
}
Settings UI
The localization settings are available in: Settings → Localization
Users can configure:
- Language: Select from available languages
- Date Format: Choose how dates are displayed
- Time Format: 12-hour or 24-hour
- First Day of Week: Sunday or Monday
Available Localization Hooks
useLocalization()
Returns an object with:
{
// Current settings
language: string,
dateFormat: string,
timeFormat: string,
firstDayOfWeek: number,
isRTL: boolean,
availableLanguages: Language[],
// Setters
setLanguage: (lang: string) => void,
setDateFormat: (format: string) => void,
setTimeFormat: (format: string) => void,
setFirstDayOfWeek: (day: number) => void,
// Formatters
formatDate: (date: Date | string, format?: string) => string,
formatDateTime: (date: Date | string, format?: string) => string,
formatTime: (date: Date | string, format?: string) => string,
formatRelative: (date: Date | string) => string,
formatCalendar: (date: Date | string) => string,
}
useTranslation(namespace)
From react-i18next:
{
t: (key: string, options?: object) => string,
i18n: i18n instance,
ready: boolean,
}
Translation Namespaces
common.json
General UI elements used throughout the app:
- Buttons (save, cancel, delete, etc.)
- Common actions
- Status messages
settings.json
All Settings page translations:
- Section titles
- Form labels
- Help text
- Notifications
chores.json
Chores/tasks related content:
- Task management
- Status labels
- Action buttons
RTL Languages
The following languages automatically enable RTL layout:
- Arabic (ar)
- Hebrew (he)
- Persian/Farsi (fa)
- Urdu (ur)
RTL features:
- Automatic
dir="rtl"on HTML element - Flipped layouts and icons
- Right-aligned text inputs
- Proper border radius handling
Date Format Constants
Available in LocalizationContext.jsx:
export const DATE_FORMATS = {
MDY: 'MM/DD/YYYY', // 01/15/2024
DMY: 'DD/MM/YYYY', // 15/01/2024
YMD: 'YYYY-MM-DD', // 2024-01-15
LONG: 'MMMM D, YYYY', // January 15, 2024
SHORT: 'MMM D, YYYY', // Jan 15, 2024
}
export const TIME_FORMATS = {
HOUR_12: 'h:mm A', // 2:30 PM
HOUR_24: 'HH:mm', // 14:30
}
Translation Management
Adding New Languages
- Create directory:
public/locales/{language-code}/ - Copy translation files from
public/locales/en/ - Translate content
- Add language to
AVAILABLE_LANGUAGESinLocalizationContext.jsx - If RTL, add to
RTL_LANGUAGESarray
Using Translation Platforms
See TRANSLATION.md for detailed instructions on:
- Setting up Crowdin (recommended)
- Setting up Lokalise
- Setting up POEditor
- Setting up Weblate
Translation Guidelines
- Keep placeholders:
{{variable}} - Maintain context awareness
- Use consistent terminology
- Test with actual UI
- Consider character limits
- Preserve formatting
Migration Guide
Converting Components to Use i18n
-
Add translation hook:
import { useTranslation } from 'react-i18next' const { t } = useTranslation('namespace') -
Replace hardcoded strings:
// Before <Button>Save</Button> // After <Button>{t('save')}</Button> -
Use localization for dates:
import { useLocalization } from '@/contexts/LocalizationContext' const { formatDate } = useLocalization() // Replace moment().format() with formatDate()
Batch Migration Strategy
- Start with Settings component (already done)
- Convert common components (buttons, headers)
- Convert page components
- Convert utility functions
- Test each language thoroughly
Testing
Testing Translations
- Change language in Settings → Localization
- Navigate through the app
- Check all translated components
- Verify formatting
Testing RTL
- Switch to Arabic or Hebrew
- Check layout direction
- Verify icons and navigation
- Test form inputs
Testing Date Formats
- Change date format in Settings
- Check all date displays update
- Verify calendar components
- Test relative dates
Performance Considerations
- Translations loaded on demand (lazy loading)
- Language detection runs once on init
- Format preferences stored in localStorage
- No re-renders unless language/format changes
Browser Support
- Modern browsers with ES6+ support
- localStorage support required
- CSS dir attribute support required
Accessibility
- Proper lang attribute on HTML element
- Screen reader compatible
- RTL support for assistive technologies
- High contrast mode compatible
Future Enhancements
Potential improvements:
- Automatic translation via AI
- Crowdsourced translation interface
- More granular date format options
- Regional number formatting
- Currency formatting
- Plural rules support
- Gender-specific translations
- Translation quality metrics
Troubleshooting
Translations not loading
- Check browser console for errors
- Verify JSON files in
public/locales/ - Check network tab for 404s
RTL not working
- Verify language in
RTL_LANGUAGESarray - Check CSS is loaded
- Inspect HTML dir attribute
Date format not applying
- Check localStorage for saved preferences
- Verify LocalizationContext is mounted
- Check component uses formatDate functions
Resources
- i18next Documentation
- react-i18next Documentation
- Moment.js Formatting
- TRANSLATION.md - Translation management
- src/i18n/README.md - Quick reference
Contributors
For questions or contributions related to internationalization:
- Create an issue on GitHub
- Tag with
i18nortranslation - Reference this document
License
All translations follow the same license as the main project.