# 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`, `Boot`, `Settings`, `Search`, `Home`, `Direct`, `Room`, `Inbox`, `Explore`, `Create`, `RoomSettings`, `Push` ## Usage pattern ```tsx import { useTranslation } from 'react-i18next'; const { t } = useTranslation(); return {t('RoomSettings.some_key')}; ``` 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 - `Boot` — Boot/splash error screens (`ConfigConfigError`, `SpecVersions` error, `ClientRoot` init/start error) **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: `FeatureCheck`, `WelcomePage` - 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.