3.1 KiB
3.1 KiB
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 |
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
# 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:
{
"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:
- Detect the user's preferred language
- Load translations via
/api/i18n/locales/{code} - Apply translations to DOM elements