> For the complete documentation index, see [llms.txt](https://tyrix.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://tyrix.gitbook.io/docs/script-resources/tyrix-frames/localization.md).

# Localization

```lua
Config.Locale = 'en'
```

## Shipped languages

| Key  | Language               |
| ---- | ---------------------- |
| `en` | English                |
| `es` | Spanish                |
| `fr` | French                 |
| `pt` | Portuguese (Brazilian) |
| `de` | German                 |

Files live in `locales/json/`. All of them are outside escrow, so edit any string you like.

## Adding a language

{% stepper %}
{% step %}

## Copy the English locale file

Copy `locales/json/en.json` to `locales/json/<key>.json`.
{% endstep %}

{% step %}

## Translate the values

Translate the **values**. Leave the keys alone.
{% endstep %}

{% step %}

## Set the locale

Set `Config.Locale = '<key>'` and restart.
{% endstep %}
{% endstepper %}

No manifest change is needed — the resource globs `locales/json/*.json`.

## Two rules when editing

{% hint style="warning" %}
**Keep the key structure identical.** Values are what get translated; keys are what the code looks up.
{% endhint %}

{% hint style="warning" %}
**Preserve the `{1}`** **`{2}` placeholders.** They are positional and get replaced with real values at runtime. You may move one within the sentence if your language needs different word order — the number carries the meaning — but never renumber, drop or add one.
{% endhint %}

```json
"image_too_large": "Image is too large (max {1} MB)"
```

becomes, in German:

```json
"image_too_large": "Bild ist zu groß (max. {1} MB)"
```

## Missing keys fall back per key

If a translation is missing a key, **that one string** renders in English. The rest of the file still applies, and nothing errors or shows a raw key.

That makes partial translations perfectly usable — translate the strings your players actually see first, and the long-tail error messages later. It also means an update that adds a new string will not break an older translation; the new string just appears in English until you add it.

## Where each category shows up

| Category    | Surface                                                                   |
| ----------- | ------------------------------------------------------------------------- |
| `error`     | Red notification toasts                                                   |
| `success`   | Green notification toasts                                                 |
| `info`      | Item metadata — the "contains a photo" hint                               |
| `target`    | Third-eye / textui option labels. **Keep these short** — they are buttons |
| `placement` | The key legend title while placing, and the `[E]` prompt                  |
| `keybind`   | Descriptions in **Settings → Key Bindings → FiveM**                       |

Two notes on the last two. The placement legend has a `aim_title_count` variant carrying `{1}/{2}` for the placement counter — the plain `aim_title` is used when a player is unlimited.

And the `keybind` values render in GTA's pause menu, whose font does not reliably have an em dash glyph. The shipped files all use a plain hyphen there; keep that if you edit them.

## A note on length

English is a compact language and the UI was laid out against it. French and German both run noticeably longer — the shipped translations were written with that in mind, keeping button labels terse even where a literal translation would be verbose.

If you translate your own, check the third-eye options and the key legend in-game rather than trusting the JSON to look reasonable.
