Languages and right-to-left
The app ships in English and Hindi. Users pick a language in Settings, and the first launch follows the phone’s language when the app has it. Right-to-left languages such as Arabic or Urdu are supported: you add one with a single setting (ADR 0017).
How it works
Section titled “How it works”| Part | Where | What it does |
|---|---|---|
| Strings | src/shared/i18n/locales/en.json, hi.json |
One file per language, with the same keys |
| Languages | LANGUAGES in src/shared/i18n/index.ts |
Each language’s own name and whether it’s right-to-left |
| Engine | i18next and react-i18next | t('feed.title'), {{name}} placeholders and plurals |
| Device language | react-native-localize | Picks the phone’s language on first launch |
| Dates, numbers, “2 days ago” | useFormat() in src/shared/lib/format.ts |
Formats in the current language |
Translation keys are typed from en.json, so a wrong key fails pnpm typecheck, and lint rejects
hard-coded text in JSX.
Write text that translates
Section titled “Write text that translates”- Put every string a user sees in
en.jsonand read it witht('…'). Add the same key to every other locale file; a test fails if one is missing. - Plurals use i18next suffixes:
likes_oneandlikes_otherin English and Hindi. Other languages may need more forms (Arabic has six). - Format dates, numbers and relative times with
useFormat()in components, neverformatRelative(date)directly. The language can change while the app runs, and the React Compiler would keep the old text (lint enforces this). - Lay out with
startandend, neverleftandright(marginStart,paddingEnd,start: 0). Lint rejects physical sides andtextAlign: 'left' | 'right'. - Mark arrows and chevrons that point “forward” as
directionalonIcon, so they flip in right-to-left languages.
Add a language
Section titled “Add a language”- Copy
src/shared/i18n/locales/en.jsonto a file named after the language code, for exampleta.jsonfor Tamil, and translate it. - In
src/shared/i18n/index.ts, import it, add it toresources, and add an entry toLANGUAGESwith its own name:ta: { label: 'தமிழ்', rtl: false }. - In
src/shared/lib/format.ts, add its relative-time data:import ta from 'relative-time-format/locale/ta.json'andRelativeTimeFormat.addLocale(ta). - Run
pnpm check. Tests fail if a key or the relative-time data is missing.
pnpm gen adds new strings to every locale file as English copies, ready to translate.
Add a right-to-left language
Section titled “Add a right-to-left language”Follow the steps above and set rtl: true on the entry, for example
ar: { label: 'العربية', rtl: true }. Then:
- Switching to or from it changes the layout direction. React Native applies a new direction only at launch, so Settings asks the user to restart.
- Check every screen on both iOS and Android before you ship. On iOS, text inside rows doesn’t yet follow a right-to-left layout everywhere; fix that first.
Tests keep right-to-left working while no shipped language uses it: they switch the direction with the flag and check that directional icons mirror.
Remove a language
Section titled “Remove a language”Delete its locale file, its entry in LANGUAGES and resources, and its relative-time import. If only
English is left, consider hiding the language picker in Settings.
Made by Praveen Singh, Senior React Native engineer