4.8 KiB
Localisation (i18n)
Setup
- Config:
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 insupportedLngs; anything else normalises toen) - Locale files:
public/locales/en.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
import { useTranslation } from 'react-i18next';
const { t } = useTranslation();
return <Text>{t('RoomSettings.some_key')}</Text>;
Dynamic values:
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 sharetacross components. - Custom hooks with
useMemo/useCallbackmust includetin their dependency array. This is what makes language switching actually re-render. - Import order:
react-i18nextgoes after framework imports (react,folds,focus-trap-react, …) and before local imports. - After adding
useTranslationinside a hook, always runnpm run lint/ checkexhaustive-depswarnings.
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 resetSettings— All user-settings sectionsSearch— Global searchHome— Home timelineDirect— DM listRoom— Room UIInbox— Notifications & invitesExplore— Public roomsCreate— Room/space creationRoomSettings— Room settings (general, members, permissions, emojis/stickers, developer tools, image pack editor, power level tags)Organisms— Complex UI piecesBoot— Boot/splash error screens (ConfigConfigError,SpecVersionserror,ClientRootinit/start error)
Still to localise (snapshot taken 2026-06-12 — verify before acting):
- Room features:
MembersDrawer,RoomTombstone AddExistingfeature- System pages:
FeatureCheck,WelcomePage - Auth:
OrDivider - UIA stages:
ReCaptchaStage,RegistrationTokenStage - Components:
TimePicker,DatePicker,ImageViewer,PdfViewer - Various
aria-labelattributes throughout
Localised 2026-06-12 (the hardcoded-English sweep): UserModeration,
call screens (CallControls/PrescreenControls/CallView/CallMemberCard),
lobby (Lobby/RoomItem/SpaceItem/LobbyHeader), MessageSearch
(aria-label), LeaveSpacePrompt, the device-verification cluster
(DeviceVerification/DeviceVerificationSetup/ManualVerification/
BackupRestore/settings Verification), ComposerAttachments
(spoiler/retry/cancel/size-error — the attachment strip that replaced the
UploadBoard window), editor Toolbar tooltips, EmailStage,
MediaViewerBody aria-labels (MediaViewer.*/Common.*). MessageEditor
was deleted (editing moved into the composer); LogoutDialog was rewritten
as a localized self-contained card. Dead Settings.email_*notification*
strings removed from both locale files (the section is never rendered), as
were the keys orphaned by the dropped room-permissions page
(RoomSettings.perm_* room-only set), the user emoji-pack settings page,
and the old upload-size-limit concatenation fragments.
When the developer asks to localise a new area, check this list first and update it after finishing.