# Translations

## Choose the language

Set `Config.Locale` in `shared/config.lua` to the name of a file in `locales/` and restart the resource.

```lua title="shared/config.lua"
Config.Locale = 'pl'
```

Two languages ship: `en` (English) and `pl` (Polish). The language is the same for every player on the server.

English is always loaded as the fallback. A key that is missing in your file is shown in English, so a partial translation still works. A key missing in both shows the key itself.

## How the files are organised

Each file is JSON with two parts:

| Part | Used by | Placeholders |
|---|---|---|
| `game` | Lua: notifications, radio traffic, caller and field messages, the station screen, key mapping names, categories, questions, instructions, call lines, admin notifications | `%s`, `%d` (Lua `string.format`, in order) |
| `ui` | The CAD, the admin menu and the field toasts (NUI) | `{name}`, `{count}`... (by name) |

Examples:

```json title="locales/en.json"
{
  "game": {
    "caller": {
      "usage": "Describe your emergency: /%s <message>"
    }
  },
  "ui": {
    "calls": {
      "handled_by": "Handled by {name}"
    }
  }
}
```

Keep the placeholders exactly as they are, in the same order for `%s` and `%d`. The admin setting labels and hints are in `ui.admin.set.<key>` and `ui.admin.set.<key>_hint`, for example `ui.admin.set.mode.calls`.

## Add a language

1. Copy `locales/en.json` to `locales/<code>.json`, for example `locales/de.json`.
2. Translate the values. Do not rename or remove keys.
3. Set `Config.Locale = 'de'` and restart.

The `locales/` folder is not escrowed and is sent to clients through `files`, so new files are picked up after a restart without other changes.

## What is not in the locale files

| Text | Where it is |
|---|---|
| Scenario opening lines and caller answers | `shared/scenarios.lua`, `shared/scenarios/*.lua` and the training scenario. They are English; translate them there if you want. |
| Call locations | `shared/locations.lua` |
| Custom scenarios | Written in the admin menu's scenario editor, in any language. |
| Department and unit type labels | `Config.Departments` and `Config.UnitTypes` |
| Station and AI station names | Admin menu or `Config.Consoles` / `Config.AiUnits.stations` |
| Rank names | `Config.Career.ranks[].label` is used in game; `ui.career.rank` in the CAD |
| Discord embed titles | English, in the Discord module |

## Caller voices are English audio

The recorded caller voices are English audio files in `web/build/voices`. A line is played only when its text matches a recorded line exactly. When you translate `game.lines`, `game.questions`, `game.instructions` or the scenario texts, those lines are shown as text without audio. Everything else keeps working.

Live AI callers (`Config.AI`) speak the language in `Config.AI.language`, so with AI callers on, calls can be voiced in your language.
