Files
Oxicloud/doc/i18n.md
T
2026-04-01 23:14:42 +02:00

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
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

# 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:

  1. Detect the user's preferred language
  2. Load translations via /api/i18n/locales/{code}
  3. Apply translations to DOM elements