<!-- Markdown mirror. Canonical: https://empryo.com/docs/tools/languages -->

# Languages

> Switch the interface language live, mirrored right-to-left layout on desktop, locale-aware numbers and dates, and a public repo translators can PR.

## Overview

Every user-visible string in Empryo goes through one localization catalog - the TUI, the desktop app and headless output alike. Five catalogs ship today, and the four translations are complete:

| Language | Tag | Direction | Coverage |
|----------|-----|-----------|----------|
| English | `en` | left-to-right | the source catalog |
| العربية Arabic | `ar` | **right-to-left** | 100% |
| français French | `fr` | left-to-right | 100% |
| 한국어 Korean | `ko` | left-to-right | 100% |
| Русский Russian | `ru` | left-to-right | 100% |

The language settings show live coverage. A key a translation lacks falls back to English rather than blanking, so a partial translation is always shippable.

## Switching

| Surface | How |
|---------|-----|
| TUI | `/language` - the interface repaints in place |
| Desktop | Settings → Language - the window reloads in the new language |
| Headless / CI | `--locale <tag>` per run, or `EMPRYO_LOCALE` in the environment |

The flag beats the config, the config beats the OS locale. Headless runs read cached catalogs only - they never fetch.

## Right-to-left

Arabic mirrors the desktop app, and mirroring is more than flipped padding:

- **The layout mirrors.** Spacing, borders and alignment are written as logical properties, so the whole interface reflects rather than being re-specified per direction.
- **The controls mirror too.** Sliders, dropdown and context menus, tabs and toggle groups take the interface direction from React context, not from the stylesheet. Without that a mirrored build still *thinks* it is left-to-right: the slider runs backwards, submenus open off the wrong edge, and <kbd>←</kbd>/<kbd>→</kbd> step the wrong way.
- **Direction is decided per paragraph, by counting.** The browser's `dir="auto"` looks only at the first strongly-directional character, which is the wrong rule for a coding agent - prompts routinely open with a path or a command. `src/auth.ts فيه خطأ في السطر ٤٢` would resolve left-to-right off that leading `s` and strand the Arabic against the wrong base. Empryo drops the code-shaped words and counts the rest, so the line reads the way it was written.
- **Code stays left-to-right, and isolated.** Paths, identifiers, inline code, fenced blocks and diffs keep their own direction inside right-to-left prose, so the text around them keeps its order.
- **The chrome keeps its own direction.** An Arabic message in an English interface is laid out right-to-left without dragging the surrounding UI with it, and the reverse.

The **terminal interface does not mirror** and cannot - terminals do not reorder bidirectional text. Translations are still correct there. The layout around them stays left-to-right.

## Numbers, dates and counts

Digits, grouping separators, compact suffixes and relative times are formatted through `Intl` in the reader's locale, so a token count renders `12.4K` in English, `12,4 k` in French and with Arabic-Indic digits and separators in Arabic. Relative times use CLDR phrasing rather than English templates - "yesterday", «вчера», "أمس" - including the plural category and the side the unit sits on.

Costs stay in US dollars in every language, because that is what models bill in, only the digits and the suffix are localized.

## Chinese, Japanese, Korean

CJK text gets automatic spacing where Latin words meet ideographs, and strict line-breaking rules so a line does not break before a small kana or a closing bracket.

## Live translations

Between releases, `liveTranslations` (opt-in) fetches newer catalogs from the public translations repo, validates them through the same security gate every bundled catalog passes, and caches them locally. A bad or hostile catalog never reaches the screen.

## Localized commands

`localizedCommands` (opt-in, off by default) accepts translated slash-command names as aliases of the English ones - `/لغة` runs `/language`.

## Contributing a language

Translations live in a public repo ([proxysoul/Empryo](https://github.com/proxysoul/Empryo)) that translators open PRs against. The English catalog is published there on every release, merged translations flow back into the next build.
