Remove Translation instruction
This commit is contained in:
@@ -1,423 +0,0 @@
|
||||
# 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
|
||||
|
||||
```jsx
|
||||
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
|
||||
|
||||
```jsx
|
||||
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
|
||||
|
||||
```jsx
|
||||
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:**
|
||||
```jsx
|
||||
import moment from 'moment'
|
||||
|
||||
function SubscriptionInfo({ userProfile }) {
|
||||
return (
|
||||
<p>
|
||||
Subscription expires on {moment(userProfile.expiration).format('MMM DD, YYYY')}
|
||||
</p>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
**After:**
|
||||
```jsx
|
||||
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:
|
||||
1. **Language**: Select from available languages
|
||||
2. **Date Format**: Choose how dates are displayed
|
||||
3. **Time Format**: 12-hour or 24-hour
|
||||
4. **First Day of Week**: Sunday or Monday
|
||||
|
||||
## Available Localization Hooks
|
||||
|
||||
### `useLocalization()`
|
||||
|
||||
Returns an object with:
|
||||
|
||||
```typescript
|
||||
{
|
||||
// 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:
|
||||
|
||||
```typescript
|
||||
{
|
||||
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`:
|
||||
|
||||
```javascript
|
||||
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
|
||||
|
||||
1. Create directory: `public/locales/{language-code}/`
|
||||
2. Copy translation files from `public/locales/en/`
|
||||
3. Translate content
|
||||
4. Add language to `AVAILABLE_LANGUAGES` in `LocalizationContext.jsx`
|
||||
5. If RTL, add to `RTL_LANGUAGES` array
|
||||
|
||||
### 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
|
||||
|
||||
1. Keep placeholders: `{{variable}}`
|
||||
2. Maintain context awareness
|
||||
3. Use consistent terminology
|
||||
4. Test with actual UI
|
||||
5. Consider character limits
|
||||
6. Preserve formatting
|
||||
|
||||
## Migration Guide
|
||||
|
||||
### Converting Components to Use i18n
|
||||
|
||||
1. **Add translation hook:**
|
||||
```jsx
|
||||
import { useTranslation } from 'react-i18next'
|
||||
const { t } = useTranslation('namespace')
|
||||
```
|
||||
|
||||
2. **Replace hardcoded strings:**
|
||||
```jsx
|
||||
// Before
|
||||
<Button>Save</Button>
|
||||
|
||||
// After
|
||||
<Button>{t('save')}</Button>
|
||||
```
|
||||
|
||||
3. **Use localization for dates:**
|
||||
```jsx
|
||||
import { useLocalization } from '@/contexts/LocalizationContext'
|
||||
const { formatDate } = useLocalization()
|
||||
|
||||
// Replace moment().format() with formatDate()
|
||||
```
|
||||
|
||||
### Batch Migration Strategy
|
||||
|
||||
1. Start with Settings component (already done)
|
||||
2. Convert common components (buttons, headers)
|
||||
3. Convert page components
|
||||
4. Convert utility functions
|
||||
5. Test each language thoroughly
|
||||
|
||||
## Testing
|
||||
|
||||
### Testing Translations
|
||||
|
||||
1. Change language in Settings → Localization
|
||||
2. Navigate through the app
|
||||
3. Check all translated components
|
||||
4. Verify formatting
|
||||
|
||||
### Testing RTL
|
||||
|
||||
1. Switch to Arabic or Hebrew
|
||||
2. Check layout direction
|
||||
3. Verify icons and navigation
|
||||
4. Test form inputs
|
||||
|
||||
### Testing Date Formats
|
||||
|
||||
1. Change date format in Settings
|
||||
2. Check all date displays update
|
||||
3. Verify calendar components
|
||||
4. 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_LANGUAGES` array
|
||||
- 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](https://www.i18next.com/)
|
||||
- [react-i18next Documentation](https://react.i18next.com/)
|
||||
- [Moment.js Formatting](https://momentjs.com/docs/#/displaying/)
|
||||
- [TRANSLATION.md](./TRANSLATION.md) - Translation management
|
||||
- [src/i18n/README.md](./src/i18n/README.md) - Quick reference
|
||||
|
||||
## Contributors
|
||||
|
||||
For questions or contributions related to internationalization:
|
||||
- Create an issue on GitHub
|
||||
- Tag with `i18n` or `translation`
|
||||
- Reference this document
|
||||
|
||||
## License
|
||||
|
||||
All translations follow the same license as the main project.
|
||||
@@ -1,178 +0,0 @@
|
||||
# i18n Quick Reference
|
||||
|
||||
## Common Imports
|
||||
|
||||
```jsx
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useLocalization } from '@/contexts/LocalizationContext'
|
||||
```
|
||||
|
||||
## Translation Hook
|
||||
|
||||
```jsx
|
||||
const { t } = useTranslation('namespace')
|
||||
|
||||
// Usage
|
||||
<h1>{t('title')}</h1>
|
||||
<p>{t('section.description')}</p>
|
||||
```
|
||||
|
||||
**Namespaces**: `common`, `settings`, `chores`
|
||||
|
||||
## Date Formatting Hook
|
||||
|
||||
```jsx
|
||||
const { formatDate, formatDateTime, formatTime, formatRelative } = useLocalization()
|
||||
|
||||
// Usage
|
||||
<p>{formatDate(date)}</p> // Uses user's preferred format
|
||||
<p>{formatDateTime(date)}</p> // Date + time
|
||||
<p>{formatTime(date)}</p> // Time only
|
||||
<p>{formatRelative(date)}</p> // "2 hours ago"
|
||||
```
|
||||
|
||||
## Language/Format Settings
|
||||
|
||||
```jsx
|
||||
const {
|
||||
language, // Current language code
|
||||
setLanguage, // Change language
|
||||
dateFormat, // Current date format
|
||||
setDateFormat, // Change date format
|
||||
timeFormat, // Current time format
|
||||
setTimeFormat, // Change time format
|
||||
isRTL // Is current language RTL?
|
||||
} = useLocalization()
|
||||
```
|
||||
|
||||
## Adding Translations
|
||||
|
||||
### 1. Add to JSON
|
||||
`public/locales/en/settings.json`:
|
||||
```json
|
||||
{
|
||||
"mySection": {
|
||||
"title": "My Section",
|
||||
"description": "Section description"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Use in Component
|
||||
```jsx
|
||||
const { t } = useTranslation('settings')
|
||||
<h1>{t('mySection.title')}</h1>
|
||||
```
|
||||
|
||||
## Date Format Migration
|
||||
|
||||
### Before
|
||||
```jsx
|
||||
moment(date).format('MMM DD, YYYY')
|
||||
```
|
||||
|
||||
### After
|
||||
```jsx
|
||||
const { formatDate } = useLocalization()
|
||||
formatDate(date)
|
||||
```
|
||||
|
||||
## Available Date Formats
|
||||
|
||||
- `MM/DD/YYYY` - 01/15/2024
|
||||
- `DD/MM/YYYY` - 15/01/2024
|
||||
- `YYYY-MM-DD` - 2024-01-15
|
||||
- `MMMM D, YYYY` - January 15, 2024
|
||||
- `MMM D, YYYY` - Jan 15, 2024
|
||||
|
||||
## RTL Languages
|
||||
|
||||
Automatically supported: `ar`, `he`, `fa`, `ur`
|
||||
|
||||
## File Locations
|
||||
|
||||
- **Translations**: `public/locales/{lang}/*.json`
|
||||
- **Config**: `src/i18n/config.js`
|
||||
- **Context**: `src/contexts/LocalizationContext.jsx`
|
||||
- **Settings UI**: `src/views/Settings/LocalizationSettings.jsx`
|
||||
|
||||
## Translation Namespaces
|
||||
|
||||
| Namespace | Purpose | Example Keys |
|
||||
|-----------|---------|--------------|
|
||||
| common | General UI | save, cancel, delete, edit |
|
||||
| settings | Settings page | title, localization.*, theme.* |
|
||||
| chores | Tasks/Chores | myChores, addChore, dueDate |
|
||||
|
||||
## Quick Examples
|
||||
|
||||
### Button with Translation
|
||||
```jsx
|
||||
const { t } = useTranslation('common')
|
||||
<Button>{t('save')}</Button>
|
||||
```
|
||||
|
||||
### Date Display
|
||||
```jsx
|
||||
const { formatDate } = useLocalization()
|
||||
<p>Due: {formatDate(task.dueDate)}</p>
|
||||
```
|
||||
|
||||
### RTL-Aware Layout
|
||||
```jsx
|
||||
const { isRTL } = useLocalization()
|
||||
<div dir={isRTL ? 'rtl' : 'ltr'}>Content</div>
|
||||
```
|
||||
|
||||
### Language Selector
|
||||
```jsx
|
||||
const { language, setLanguage, availableLanguages } = useLocalization()
|
||||
|
||||
<select value={language} onChange={e => setLanguage(e.target.value)}>
|
||||
{availableLanguages.map(lang => (
|
||||
<option key={lang.code} value={lang.code}>
|
||||
{lang.nativeName}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
```
|
||||
|
||||
## Testing Locally
|
||||
|
||||
1. Go to Settings → Localization
|
||||
2. Change language to Spanish
|
||||
3. Verify translations appear
|
||||
4. Change date format
|
||||
5. Verify dates update throughout app
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Page Title
|
||||
```jsx
|
||||
const { t } = useTranslation('settings')
|
||||
<Typography level='h3'>{t('title')}</Typography>
|
||||
```
|
||||
|
||||
### Form Label
|
||||
```jsx
|
||||
const { t } = useTranslation('settings')
|
||||
<FormLabel>{t('localization.language')}</FormLabel>
|
||||
```
|
||||
|
||||
### Date in Text
|
||||
```jsx
|
||||
const { formatDate } = useLocalization()
|
||||
<p>Your subscription expires on {formatDate(expiration)}.</p>
|
||||
```
|
||||
|
||||
### Relative Time
|
||||
```jsx
|
||||
const { formatRelative } = useLocalization()
|
||||
<p>Updated {formatRelative(lastUpdate)}</p>
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
- **Full Guide**: I18N_IMPLEMENTATION.md
|
||||
- **Translation Setup**: TRANSLATION.md
|
||||
- **Summary**: INTERNATIONALIZATION_SUMMARY.md
|
||||
@@ -1,348 +0,0 @@
|
||||
# Internationalization Implementation Summary
|
||||
|
||||
## What Was Implemented
|
||||
|
||||
This document summarizes the internationalization (i18n) features added to Donetick.
|
||||
|
||||
## ✅ Completed Features
|
||||
|
||||
### 1. Language Support
|
||||
- **Multi-language framework**: Integrated i18next and react-i18next
|
||||
- **Automatic detection**: Browser language detection on first load
|
||||
- **Persistent preferences**: User language choice saved to localStorage
|
||||
- **Sample translations**: English, Spanish (es), and Arabic (ar) included
|
||||
- **10 languages configured**: English, Spanish, French, German, Arabic, Hebrew, Chinese, Japanese, Portuguese, Russian
|
||||
|
||||
### 2. Date Format Preferences
|
||||
Users can now select their preferred date format from Settings:
|
||||
- **MM/DD/YYYY** - US format (e.g., 01/15/2024)
|
||||
- **DD/MM/YYYY** - European format (e.g., 15/01/2024)
|
||||
- **YYYY-MM-DD** - ISO format (e.g., 2024-01-15)
|
||||
- **Long format** - e.g., January 15, 2024
|
||||
- **Short format** - e.g., Jan 15, 2024
|
||||
|
||||
The selected format applies to all date displays throughout the application.
|
||||
|
||||
### 3. Time Format Preferences
|
||||
Users can choose between:
|
||||
- **12-hour format** with AM/PM (e.g., 2:30 PM)
|
||||
- **24-hour format** (e.g., 14:30)
|
||||
|
||||
### 4. Right-to-Left (RTL) Support
|
||||
Automatic RTL support for languages that use it:
|
||||
- **Supported RTL languages**: Arabic, Hebrew, Persian, Urdu
|
||||
- **Automatic layout flip**: UI elements properly mirror for RTL
|
||||
- **CSS styles**: Custom RTL styles for proper text direction
|
||||
- **Dynamic direction**: `dir` attribute automatically set on HTML element
|
||||
|
||||
### 5. Calendar Preferences
|
||||
- **First day of week**: Users can choose Sunday or Monday as the week start
|
||||
|
||||
### 6. Settings UI
|
||||
New "Localization" section in Settings page with:
|
||||
- Language selector with native language names
|
||||
- Date format selector with live preview
|
||||
- Time format selector with live preview
|
||||
- First day of week selector
|
||||
- Visual feedback for RTL languages
|
||||
|
||||
## 📁 Files Created/Modified
|
||||
|
||||
### New Files Created
|
||||
```
|
||||
src/
|
||||
├── i18n/
|
||||
│ ├── config.js # i18next configuration
|
||||
│ └── README.md # i18n usage documentation
|
||||
├── contexts/
|
||||
│ └── LocalizationContext.jsx # Localization state management
|
||||
├── 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
|
||||
│ ├── common.json
|
||||
│ ├── settings.json
|
||||
│ └── chores.json
|
||||
└── ar/ # Arabic translations (RTL)
|
||||
├── common.json
|
||||
├── settings.json
|
||||
└── chores.json
|
||||
|
||||
Documentation:
|
||||
├── I18N_IMPLEMENTATION.md # Detailed implementation guide
|
||||
├── TRANSLATION.md # Translation management guide
|
||||
├── crowdin.yml # Crowdin configuration
|
||||
└── INTERNATIONALIZATION_SUMMARY.md # This file
|
||||
```
|
||||
|
||||
### Modified Files
|
||||
```
|
||||
src/
|
||||
├── main.jsx # Added i18n import
|
||||
├── index.css # Added RTL CSS styles
|
||||
├── contexts/
|
||||
│ └── Contexts.jsx # Added LocalizationProvider
|
||||
└── views/Settings/
|
||||
├── Settings.jsx # Added LocalizationSettings + example usage
|
||||
└── ThemeToggle.jsx # Added translations example
|
||||
```
|
||||
|
||||
## 🔧 How to Use
|
||||
|
||||
### For Users
|
||||
1. Go to **Settings → Localization**
|
||||
2. Select your preferred language
|
||||
3. Choose your date format
|
||||
4. Choose your time format
|
||||
5. Select first day of week
|
||||
6. Settings are saved automatically and apply immediately
|
||||
|
||||
### For Developers
|
||||
|
||||
#### Using translations in components:
|
||||
```jsx
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
function MyComponent() {
|
||||
const { t } = useTranslation('settings')
|
||||
return <h1>{t('title')}</h1>
|
||||
}
|
||||
```
|
||||
|
||||
#### Using date formatting:
|
||||
```jsx
|
||||
import { useLocalization } from '@/contexts/LocalizationContext'
|
||||
|
||||
function MyComponent() {
|
||||
const { formatDate } = useLocalization()
|
||||
const date = new Date('2024-01-15')
|
||||
return <p>Date: {formatDate(date)}</p>
|
||||
}
|
||||
```
|
||||
|
||||
## 🌐 Translation Management
|
||||
|
||||
### Recommended Platform: Crowdin
|
||||
Crowdin is recommended for managing translations (free for open-source):
|
||||
1. Sign up at https://crowdin.com/
|
||||
2. Apply for open-source plan
|
||||
3. Upload translation files from `public/locales/en/`
|
||||
4. Invite community translators
|
||||
5. Set up GitHub integration for automatic syncing
|
||||
|
||||
See **TRANSLATION.md** for detailed setup instructions.
|
||||
|
||||
### Alternative Platforms
|
||||
- **Lokalise** - Advanced features, free for open-source
|
||||
- **POEditor** - Simple interface, free tier available
|
||||
- **Weblate** - Completely free, self-hosted option
|
||||
|
||||
## 📝 Translation Namespaces
|
||||
|
||||
### common.json
|
||||
General UI elements used throughout the app
|
||||
- Buttons: save, cancel, delete, edit, close
|
||||
- Status messages: success, error, warning, loading
|
||||
- Common actions: copy, refresh, confirm
|
||||
|
||||
### settings.json
|
||||
All Settings page content
|
||||
- Section titles and descriptions
|
||||
- Form labels and help text
|
||||
- Button labels
|
||||
- Notification messages
|
||||
|
||||
### chores.json
|
||||
Task/chores related content
|
||||
- Task management UI
|
||||
- Status labels
|
||||
- Action buttons
|
||||
- Form fields
|
||||
|
||||
## 🔄 Migration from Hardcoded Dates
|
||||
|
||||
### Before:
|
||||
```jsx
|
||||
import moment from 'moment'
|
||||
|
||||
<p>Expires: {moment(date).format('MMM DD, YYYY')}</p>
|
||||
```
|
||||
|
||||
### After:
|
||||
```jsx
|
||||
import { useLocalization } from '@/contexts/LocalizationContext'
|
||||
|
||||
function Component() {
|
||||
const { formatDate } = useLocalization()
|
||||
return <p>Expires: {formatDate(date)}</p>
|
||||
}
|
||||
```
|
||||
|
||||
**Benefit**: Users now see dates in their preferred format!
|
||||
|
||||
## 🎨 RTL Example
|
||||
|
||||
When a user selects Arabic or Hebrew:
|
||||
1. The entire UI automatically flips to RTL
|
||||
2. Text aligns to the right
|
||||
3. Icons and navigation reverse
|
||||
4. All layouts mirror appropriately
|
||||
|
||||
No additional code needed in components!
|
||||
|
||||
## 📊 Technical Details
|
||||
|
||||
### Dependencies Added
|
||||
```json
|
||||
{
|
||||
"i18next": "^latest",
|
||||
"react-i18next": "^latest",
|
||||
"i18next-browser-languagedetector": "^latest",
|
||||
"i18next-http-backend": "^latest"
|
||||
}
|
||||
```
|
||||
|
||||
### Storage Keys
|
||||
User preferences stored in localStorage:
|
||||
- `i18nextLng` - Selected language
|
||||
- `dateFormat` - Date format preference
|
||||
- `timeFormat` - Time format preference
|
||||
- `firstDayOfWeek` - Week start day (0=Sunday, 1=Monday)
|
||||
- `language` - Language code
|
||||
|
||||
### Context API
|
||||
`LocalizationContext` provides:
|
||||
- Current language and setter
|
||||
- Date/time format preferences and setters
|
||||
- Format functions (formatDate, formatDateTime, formatTime, formatRelative)
|
||||
- RTL detection
|
||||
- Available languages list
|
||||
|
||||
## 🧪 Testing
|
||||
|
||||
### Test Language Switching
|
||||
1. Go to Settings → Localization
|
||||
2. Change language to Spanish
|
||||
3. Verify UI updates (e.g., Theme preferences → "Preferencias de tema")
|
||||
|
||||
### Test Date Format
|
||||
1. Go to Settings → Localization
|
||||
2. Change date format (e.g., to DD/MM/YYYY)
|
||||
3. Check subscription dates update in Settings
|
||||
|
||||
### Test RTL
|
||||
1. Change language to Arabic
|
||||
2. Verify layout flips to right-to-left
|
||||
3. Check text alignment and icons
|
||||
|
||||
## 🚀 Next Steps
|
||||
|
||||
### For Complete i18n Implementation
|
||||
1. **Translate more components**: Apply translations to remaining components
|
||||
2. **Add more languages**: Create translation files for other languages
|
||||
3. **Set up translation platform**: Configure Crowdin or alternative
|
||||
4. **Community contributions**: Invite community to contribute translations
|
||||
5. **Update all moment() calls**: Replace with formatDate() throughout app
|
||||
|
||||
### Recommended Translation Priority
|
||||
1. ✅ Settings page (completed)
|
||||
2. Navigation and menus
|
||||
3. Chores/tasks interface
|
||||
4. Form validation messages
|
||||
5. Error messages
|
||||
6. Help text and tooltips
|
||||
|
||||
## 📖 Documentation
|
||||
|
||||
- **I18N_IMPLEMENTATION.md** - Complete implementation guide with examples
|
||||
- **TRANSLATION.md** - How to manage and contribute translations
|
||||
- **src/i18n/README.md** - Quick reference for developers
|
||||
- **crowdin.yml** - Ready-to-use Crowdin configuration
|
||||
|
||||
## ✨ Example Translations Included
|
||||
|
||||
### English (en) - Complete
|
||||
- common.json: 15 terms
|
||||
- settings.json: 50+ terms
|
||||
- chores.json: 10+ terms
|
||||
|
||||
### Spanish (es) - Complete
|
||||
- Fully translated as example
|
||||
- Professional translations included
|
||||
|
||||
### Arabic (ar) - Complete
|
||||
- RTL demonstration
|
||||
- Proper Arabic translations
|
||||
- Shows RTL layout in action
|
||||
|
||||
## 🎯 Benefits
|
||||
|
||||
1. **User Experience**: Users see dates in their familiar format
|
||||
2. **Global Reach**: Support for 10+ languages out of the box
|
||||
3. **Accessibility**: RTL support for Arabic/Hebrew speakers
|
||||
4. **Flexibility**: Easy to add new languages
|
||||
5. **Community**: Translation platform enables community contributions
|
||||
6. **Maintainability**: Centralized translation management
|
||||
|
||||
## 🤝 Contributing Translations
|
||||
|
||||
### For Translators
|
||||
1. Visit the project on Crowdin (once set up)
|
||||
2. Select a language you want to contribute to
|
||||
3. Start translating!
|
||||
4. Translations sync automatically to GitHub
|
||||
|
||||
### For Developers
|
||||
1. Add new translation keys to `public/locales/en/*.json`
|
||||
2. Use in components with `t('key')`
|
||||
3. Upload to translation platform
|
||||
4. Community translates other languages
|
||||
|
||||
## 📞 Support
|
||||
|
||||
For questions about internationalization:
|
||||
- Check **I18N_IMPLEMENTATION.md** for detailed examples
|
||||
- Check **TRANSLATION.md** for translation platform setup
|
||||
- Create GitHub issue with `i18n` label
|
||||
- Tag with specific language code if language-specific
|
||||
|
||||
## 🏆 Achievement
|
||||
|
||||
The application now supports:
|
||||
- ✅ 10 languages configured
|
||||
- ✅ 3 languages with sample translations (en, es, ar)
|
||||
- ✅ 5 date format options
|
||||
- ✅ 2 time format options
|
||||
- ✅ RTL support for 4 language families
|
||||
- ✅ User preferences persisted
|
||||
- ✅ Live preview of formats
|
||||
- ✅ Translation platform ready
|
||||
- ✅ Full documentation
|
||||
|
||||
## 📈 Impact
|
||||
|
||||
Users can now:
|
||||
1. Use the app in their native language
|
||||
2. See dates in their familiar format
|
||||
3. Use 12 or 24-hour time
|
||||
4. Have proper RTL layout for Arabic/Hebrew
|
||||
5. Configure week start day
|
||||
|
||||
Developers can:
|
||||
1. Easily add translations with `t('key')`
|
||||
2. Format dates with user preferences automatically
|
||||
3. Add new languages by creating JSON files
|
||||
4. Leverage translation platforms for community help
|
||||
|
||||
---
|
||||
|
||||
**Status**: ✅ Complete and production-ready
|
||||
**Build**: ✅ Verified - No errors
|
||||
**Documentation**: ✅ Comprehensive guides included
|
||||
246
TRANSLATION.md
246
TRANSLATION.md
@@ -1,246 +0,0 @@
|
||||
# Translation Management
|
||||
|
||||
This document explains how to manage translations for Donetick using free translation platforms available for open-source projects.
|
||||
|
||||
## Translation Structure
|
||||
|
||||
Translations are organized in the `/public/locales/{language}/` directory:
|
||||
|
||||
```
|
||||
public/locales/
|
||||
├── en/
|
||||
│ ├── common.json # Common UI elements
|
||||
│ ├── settings.json # Settings page translations
|
||||
│ └── chores.json # Chores-related translations
|
||||
├── es/ # Spanish translations
|
||||
├── fr/ # French translations
|
||||
└── ...
|
||||
```
|
||||
|
||||
## Supported Languages
|
||||
|
||||
The application currently supports the following languages:
|
||||
|
||||
- English (en) - Default
|
||||
- Spanish (es)
|
||||
- French (fr)
|
||||
- German (de)
|
||||
- Arabic (ar) - RTL supported
|
||||
- Hebrew (he) - RTL supported
|
||||
- Chinese (zh)
|
||||
- Japanese (ja)
|
||||
- Portuguese (pt)
|
||||
- Russian (ru)
|
||||
|
||||
## Translation Platforms
|
||||
|
||||
### Recommended Platforms (Free for Open Source)
|
||||
|
||||
#### 1. Crowdin (Recommended)
|
||||
**Website:** https://crowdin.com/
|
||||
|
||||
**Features:**
|
||||
- Free for open-source projects
|
||||
- Easy GitHub integration
|
||||
- Automatic pull requests
|
||||
- Translation memory
|
||||
- Context and screenshots
|
||||
- Collaborative translation
|
||||
- Quality assurance checks
|
||||
|
||||
**Setup Steps:**
|
||||
1. Sign up at https://crowdin.com/
|
||||
2. Create a new project and apply for open-source plan
|
||||
3. Connect your GitHub repository
|
||||
4. Upload translation files from `public/locales/en/`
|
||||
5. Configure the `crowdin.yml` file (see example below)
|
||||
6. Invite translators or open for community contributions
|
||||
|
||||
**crowdin.yml Example:**
|
||||
```yaml
|
||||
project_id: "your-project-id"
|
||||
api_token_env: CROWDIN_API_TOKEN
|
||||
preserve_hierarchy: true
|
||||
files:
|
||||
- source: /public/locales/en/*.json
|
||||
translation: /public/locales/%two_letters_code%/%original_file_name%
|
||||
```
|
||||
|
||||
#### 2. Lokalise
|
||||
**Website:** https://lokalise.com/
|
||||
|
||||
**Features:**
|
||||
- Free for open-source projects (contact for approval)
|
||||
- GitHub integration
|
||||
- Translation memory
|
||||
- Advanced filtering
|
||||
- Glossary management
|
||||
- API access
|
||||
|
||||
**Setup Steps:**
|
||||
1. Sign up at https://lokalise.com/
|
||||
2. Apply for open-source plan
|
||||
3. Create a project
|
||||
4. Upload translation files
|
||||
5. Set up GitHub integration
|
||||
6. Configure auto-pull/push
|
||||
|
||||
#### 3. POEditor
|
||||
**Website:** https://poeditor.com/
|
||||
|
||||
**Features:**
|
||||
- Free tier available
|
||||
- Open-source friendly
|
||||
- Simple interface
|
||||
- API access
|
||||
- GitHub integration
|
||||
- Translation memory
|
||||
|
||||
**Setup Steps:**
|
||||
1. Sign up at https://poeditor.com/
|
||||
2. Create a new project
|
||||
3. Import JSON files from `public/locales/en/`
|
||||
4. Add languages you want to support
|
||||
5. Invite contributors
|
||||
6. Set up GitHub integration for auto-sync
|
||||
|
||||
#### 4. Weblate
|
||||
**Website:** https://weblate.org/
|
||||
|
||||
**Features:**
|
||||
- Completely free for open-source
|
||||
- Self-hosted or hosted option
|
||||
- Git integration
|
||||
- Quality checks
|
||||
- Translation memory
|
||||
- Glossary
|
||||
|
||||
**Setup Steps:**
|
||||
1. Go to https://hosted.weblate.org/
|
||||
2. Sign in with GitHub
|
||||
3. Add a new component
|
||||
4. Configure repository access
|
||||
5. Set file format to JSON
|
||||
6. Invite translators
|
||||
|
||||
## Adding a New Language
|
||||
|
||||
1. Create a new directory in `public/locales/` with the language code
|
||||
2. Copy all JSON files from `public/locales/en/` to the new directory
|
||||
3. Translate the content
|
||||
4. Add the language to `AVAILABLE_LANGUAGES` in `src/contexts/LocalizationContext.jsx`
|
||||
5. If the language is RTL, add it to `RTL_LANGUAGES` array
|
||||
|
||||
Example:
|
||||
```javascript
|
||||
export const AVAILABLE_LANGUAGES = [
|
||||
// ... existing languages
|
||||
{ code: 'it', name: 'Italian', nativeName: 'Italiano' },
|
||||
]
|
||||
|
||||
export const RTL_LANGUAGES = ['ar', 'he', 'fa', 'ur']
|
||||
```
|
||||
|
||||
## Translation Files
|
||||
|
||||
### common.json
|
||||
Contains general UI elements used across the application:
|
||||
- Buttons (save, cancel, delete, etc.)
|
||||
- Common messages
|
||||
- Navigation items
|
||||
|
||||
### settings.json
|
||||
Contains all text from the Settings page:
|
||||
- Section titles
|
||||
- Form labels
|
||||
- Help text
|
||||
- Notifications
|
||||
|
||||
### chores.json
|
||||
Contains chores-related translations:
|
||||
- Task management
|
||||
- Status labels
|
||||
- Action buttons
|
||||
|
||||
## Contributing Translations
|
||||
|
||||
### For Translators
|
||||
|
||||
1. **Via Translation Platform:**
|
||||
- Visit our project on [Platform Name]
|
||||
- Sign up and request access
|
||||
- Select a language you want to contribute to
|
||||
- Start translating!
|
||||
|
||||
2. **Via GitHub (Direct):**
|
||||
- Fork the repository
|
||||
- Create a new branch: `git checkout -b translation/language-code`
|
||||
- Add your translations to `public/locales/{language}/`
|
||||
- Submit a pull request
|
||||
|
||||
### Translation Guidelines
|
||||
|
||||
1. **Keep formatting:** Preserve placeholders like `{{variable}}`
|
||||
2. **Context matters:** Consider the UI context when translating
|
||||
3. **Be consistent:** Use the same terminology throughout
|
||||
4. **Character limits:** Some UI elements have space constraints
|
||||
5. **Test your translations:** If possible, test in the actual application
|
||||
6. **RTL languages:** Ensure proper text direction is maintained
|
||||
|
||||
## Testing Translations
|
||||
|
||||
To test translations locally:
|
||||
|
||||
1. Add your translation files to `public/locales/{language}/`
|
||||
2. Start the development server: `npm run dev`
|
||||
3. Change language in Settings → Localization
|
||||
4. Navigate through the app to verify translations
|
||||
|
||||
## CI/CD Integration
|
||||
|
||||
### GitHub Actions for Crowdin
|
||||
|
||||
Create `.github/workflows/crowdin.yml`:
|
||||
|
||||
```yaml
|
||||
name: Crowdin Sync
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: crowdin/github-action@v1
|
||||
with:
|
||||
upload_sources: true
|
||||
upload_translations: false
|
||||
download_translations: true
|
||||
create_pull_request: true
|
||||
env:
|
||||
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
|
||||
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
|
||||
```
|
||||
|
||||
## Translation Coverage
|
||||
|
||||
Track translation progress:
|
||||
- Use platform analytics to monitor completion
|
||||
- Set up automated reports
|
||||
- Create issues for missing translations
|
||||
|
||||
## Questions?
|
||||
|
||||
For translation-related questions:
|
||||
- Create an issue on GitHub
|
||||
- Contact the maintainers
|
||||
- Join our community discussions
|
||||
|
||||
## License
|
||||
|
||||
All translations are subject to the same license as the main project.
|
||||
Reference in New Issue
Block a user