# Internationalization

OxiCloud exposes a public translation API backed by JSON locale files on disk. Locales are loaded lazily, cached in memory, and served without authentication.

## Public API

All routes live under `/api/i18n`.

| Method | Path | Description |
| --- | --- | --- |
| `GET` | `/api/i18n/locales` | List available locales |
| `GET` | `/api/i18n/translate?key=...&locale=...` | Resolve a single key |
| `GET` | `/api/i18n/locales/{locale_code}` | Fetch all translations for one locale |

## Locale Files

Translations are stored as nested JSON files under `static/locales/`.

Example shape:

```json
{
  "app": {
    "title": "OxiCloud"
  },
  "nav": {
    "files": "Files",
    "trash": "Trash"
  }
}
```

Keys are resolved with dot notation, so `nav.files` maps to `Files`.

## Fallback Rules

- If a key is missing in the requested locale, OxiCloud falls back to English
- If the key is missing there as well, the API returns a not-found error for that key

## Caching Model

Translations are cached in memory with an `RwLock<HashMap<Locale, serde_json::Value>>` and loaded on first use for each locale.

## Frontend Usage

Typical frontend flow:

1. Detect the preferred locale
2. Request `/api/i18n/locales/{code}`
3. Apply translated strings to UI elements

## Example

```bash
# List locales
curl "https://oxicloud.example.com/api/i18n/locales"

# Fetch one translation
curl "https://oxicloud.example.com/api/i18n/translate?key=app.title&locale=es"
```

## Related Pages

- [Internal Architecture](/architecture/)
- [Environment Variables](/config/env)