# Localisation (i18n)

## Setup

- **Config**: [`src/app/i18n.ts`](../../src/app/i18n.ts) — i18next + HTTP backend + language detector
- **Fallback language**: `en` (lingua franca for unsupported detected locales; keeps web/SW/Android push surfaces aligned — see §5.27 in docs/plans/dm_calls_techdebt.md)
- **Supported languages**: `en`, `ru` (set in `supportedLngs`; anything else normalises to `en`)
- **Locale files**: [`public/locales/en.json`](../../public/locales/en.json), [`public/locales/ru.json`](../../public/locales/ru.json)
- **Namespaces** (top-level keys in the JSON files): `Organisms`, `Auth`, `Settings`, `Search`, `Home`, `Direct`, `Room`, `Inbox`, `Explore`, `Create`, `RoomSettings`, `Push`

## Usage pattern

```tsx
import { useTranslation } from 'react-i18next';

const { t } = useTranslation();
return <Text>{t('RoomSettings.some_key')}</Text>;
```

Dynamic values:
```tsx
t('key', { count: 5 })
```

For the rare case where a translation contains HTML tags, use `dangerouslySetInnerHTML` (used sparingly, e.g. in `RoomAddress.tsx`).

## Conventions

- Every React component gets its own `useTranslation()` call — do not share `t` across components.
- Custom hooks with `useMemo` / `useCallback` must include `t` in their dependency array. This is what makes language switching actually re-render.
- Import order: `react-i18next` goes after framework imports (`react`, `folds`, `focus-trap-react`, …) and before local imports.
- After adding `useTranslation` inside a hook, always run `npm run lint` / check `exhaustive-deps` warnings.

## Russian translation quality standards

The developer reviews Russian translations as a native speaker would see them in UI context, and has specifically called out the following past failures:

- **Buttons are verbs, not nouns.** "Открыть" (not "Просмотр") for a View button. "Создать" (not "Создание"). Action labels in Russian must be infinitive or imperative verb forms.
- **Avoid calques from English.** "публичный каталог" sounds translated; "общий список" reads naturally. If a phrase feels like literal English in Cyrillic, rewrite it.
- **Kill ambiguous pronouns.** Passive constructions like "могут быть изменены" leave the reader asking *who/what is being changed*. Rewrite with an explicit subject.
- **Read it in context.** Translations are for UI, not documentation. Short, unambiguous, natural.

**Why this matters:** These came from real review corrections ("Просмотр" for a button, "Составить" for Compose, ambiguous `founders_desc`). The developer is Russian-native and will notice.

## Localisation progress

**Completed namespaces** (fully localised EN + RU):

- `Auth` — Login, register, password reset
- `Settings` — All user-settings sections
- `Search` — Global search
- `Home` — Home timeline
- `Direct` — DM list
- `Room` — Room UI
- `Inbox` — Notifications & invites
- `Explore` — Public rooms
- `Create` — Room/space creation
- `RoomSettings` — Room settings (general, members, permissions, emojis/stickers, developer tools, image pack editor, power level tags)
- `Organisms` — Complex UI pieces

**Still to localise** (snapshot taken 2026-04-14 — verify before acting):

- Room features: `MessageEditor`, `MembersDrawer`, `RoomTombstone`
- Lobby: `Lobby.tsx`, `RoomItem.tsx`
- `AddExisting` feature
- System pages: `ConfigConfig`, `FeatureCheck`, `SpecVersions`, `WelcomePage`, `ClientRoot`
- Auth: `OrDivider`
- Dialogs: `LogoutDialog`, `ManualVerification`, `BackupRestore`
- UIA stages: `ReCaptchaStage`, `EmailStage`, `RegistrationTokenStage`
- Components: `TimePicker`, `DatePicker`, `ImageViewer`, `PdfViewer`, `UploadCard`, `UserModeration`
- Various `aria-label` attributes throughout

When the developer asks to localise a new area, check this list first and update it after finishing.
