101 lines
3.1 KiB
Markdown
101 lines
3.1 KiB
Markdown
# 16 - Internationalization
|
|
|
|
JSON-based translation system. Translations are loaded from static files, cached in memory, and served via a public REST API (no auth required).
|
|
|
|
## Supported Languages
|
|
|
|
| Locale | Code | File |
|
|
|---|---|---|
|
|
| English | `en` | `static/locales/en.json` |
|
|
| Spanish | `es` | `static/locales/es.json` |
|
|
| French | `fr` | `static/locales/fr.json` |
|
|
| German | `de` | `static/locales/de.json` |
|
|
| Portuguese | `pt` | `static/locales/pt.json` |
|
|
| Persian | `fa` | `static/locales/fa.json` |
|
|
| Chinese | `zh` | `static/locales/zh.json` |
|
|
| Dutch | `nl` | `static/locales/nl.json` |
|
|
|
|
Default locale: **en** (English).
|
|
|
|
## Architecture
|
|
|
|
| Layer | Component | File |
|
|
|---|---|---|
|
|
| Domain Port | **I18nService** trait, **Locale** enum | `src/domain/services/i18n_service.rs` |
|
|
| Application Service | **I18nApplicationService** | `src/application/services/i18n_application_service.rs` |
|
|
| Application DTOs | **LocaleDto**, **TranslationRequestDto**, etc. | `src/application/dtos/i18n_dto.rs` |
|
|
| Infrastructure | **FileSystemI18nService** | `src/infrastructure/services/file_system_i18n_service.rs` |
|
|
| Interfaces | **I18nHandler** | `src/interfaces/api/handlers/i18n_handler.rs` |
|
|
|
|
## REST API
|
|
|
|
Public endpoints (no authentication), under `/api/i18n`:
|
|
|
|
| Method | Path | Handler | Description |
|
|
|---|---|---|---|
|
|
| `GET` | `/api/i18n/locales` | `get_locales` | List available locales |
|
|
| `GET` | `/api/i18n/translate` | `translate` | Translate a key (`?key=...&locale=...`) |
|
|
| `GET` | `/api/i18n/locales/{locale_code}` | `get_translations_by_locale` | Get all translations for a locale |
|
|
|
|
### Examples
|
|
|
|
```bash
|
|
# List available locales
|
|
curl "https://oxicloud.example.com/api/i18n/locales"
|
|
# [{"code":"en","name":"English"},{"code":"es","name":"Spanish"}, ...]
|
|
|
|
# Translate a key
|
|
curl "https://oxicloud.example.com/api/i18n/translate?key=app.title&locale=es"
|
|
# {"key":"app.title","locale":"es","text":"OxiCloud"}
|
|
|
|
# Get all translations for a locale
|
|
curl "https://oxicloud.example.com/api/i18n/locales/en"
|
|
# { "app": { "title": "OxiCloud", ... }, "nav": { ... }, ... }
|
|
```
|
|
|
|
## Translation File Format
|
|
|
|
Nested JSON with dot-delimited key lookups:
|
|
|
|
```json
|
|
{
|
|
"app": {
|
|
"title": "OxiCloud",
|
|
"description": "Your personal cloud storage"
|
|
},
|
|
"nav": {
|
|
"files": "Files",
|
|
"shared": "Shared",
|
|
"recent": "Recent",
|
|
"favorites": "Favorites",
|
|
"trash": "Trash"
|
|
},
|
|
"actions": {
|
|
"search": "Search files...",
|
|
"new_folder": "New folder",
|
|
"upload": "Upload",
|
|
"download": "Download",
|
|
"delete": "Delete"
|
|
},
|
|
"share": { ... },
|
|
"user_menu": { ... }
|
|
}
|
|
```
|
|
|
|
Key lookup: `"nav.files"` resolves to `"Files"`.
|
|
|
|
## Fallback Behavior
|
|
|
|
If a key is missing in the requested locale, the system falls back to English (`en`). If still not found, returns an `I18nError::KeyNotFound`.
|
|
|
|
## Caching
|
|
|
|
Translations are cached in-memory via `RwLock<HashMap<Locale, serde_json::Value>>`. Loaded lazily on first request per locale.
|
|
|
|
## Frontend Integration
|
|
|
|
The frontend uses `static/js/i18n.js` and `static/js/languageSelector.js` to:
|
|
1. Detect the user's preferred language
|
|
2. Load translations via `/api/i18n/locales/{code}`
|
|
3. Apply translations to DOM elements
|