# 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
