Mobile — Cross Platform Development
Internationalization (i18n) in React Native at Scale
Direct answer
For React Native at scale, the stack that holds up is i18next with react-i18next for translation management, the device locale detected via expo-localization, the built-in Intl APIs (supported by Hermes) for date, number, and currency formatting, and namespace-per-feature key organization so hundreds of screens stay maintainable. The hard parts at scale are not the library setup — they are key governance, plural and gender correctness, RTL layout support, and a translation pipeline that keeps releases from being blocked by missing strings.
Adding a second language to a React Native app is a weekend; supporting eight languages across hundreds of screens with a translation vendor in the loop is an architecture problem. I have set this up for apps expanding into new markets, and the difference between smooth and miserable comes down to a handful of early decisions.
Key facts, with sources
- In the Stack Overflow 2024 Developer Survey, Flutter was used by 9.4% of developers versus React Native's 8.4%, and among professional developers the gap nearly vanishes at 9.21% versus 9.14%. (Nomtek (citing Stack Overflow Developer Survey))
- Among developers who build cross-platform, Statista-based figures put Flutter at about 46% adoption versus 35% for React Native, with the two frameworks together dominating the cross-platform market. (Tech-Insider)
- Instagram shares 85 to 99% of its code between iOS and Android using React Native, and Shopify reports 86% unified code across its app portfolio. (CatDoes)
- According to Flutter.dev data, nearly 30% of new free iOS apps submitted to the App Store in 2025 were built with Flutter, up from roughly 10% in 2021. (Droids on Roids (citing Flutter.dev))
- The official React Native showcase lists production apps from Meta, Microsoft, Shopify, and Amazon, including desktop targets like Messenger Desktop and Microsoft apps on Windows and macOS. (React Native Showcase)
The foundation: i18next, locale detection, and typed keys
i18next with react-i18next is my default: mature, framework-agnostic, and rich in the features you will eventually need — namespaces, plural rules, interpolation, context. Device locale comes from expo-localization (or a config-plugin equivalent on bare projects), with an explicit in-app language override persisted separately, because users in multilingual regions frequently want an app language different from their OS language.
At scale, two additions matter from day one. First, TypeScript augmentation of i18next's resources type, so t('checkout.title') fails the build if the key does not exist — with hundreds of keys, typo-level bugs otherwise ship silently in every release. Second, a fallback chain that always ends in your source language, so a missing translation degrades to English rather than rendering a raw key on screen.
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import { getLocales } from 'expo-localization';
import en from './locales/en';
import de from './locales/de';
import ar from './locales/ar';
const deviceLanguage = getLocales()[0]?.languageCode ?? 'en';
i18n.use(initReactI18next).init({
lng: deviceLanguage,
fallbackLng: 'en',
resources: { en, de, ar },
defaultNS: 'common',
interpolation: { escapeValue: false }, // React already escapes
returnNull: false,
});
export default i18n;Key architecture: namespaces or chaos
A single flat translation file stops scaling somewhere in the hundreds of keys: merge conflicts multiply, translators lose context, and nobody dares delete anything. I organize keys as one namespace per feature — checkout, onboarding, settings — matching the codebase's feature folders, plus a common namespace for shared vocabulary like Save, Cancel, and error phrases.
Naming discipline matters more than the naming scheme: keys describe meaning, not English wording (confirmButton, not clickHereToConfirm), because the English will change and the key should not. Never concatenate translated fragments to build sentences — word order differs across languages, so 'Delete' + itemName + '?' produces broken grammar in half your locales; always use full-sentence keys with interpolation placeholders. And add a CI step that diffs keys across locale files, failing the build when a language is missing keys, which converts 'we forgot to translate the new screen' from a production bug into a red pull request.
Plurals, gender, and formatting: where correctness lives
English's two plural forms are the exception, not the rule — several languages have more plural categories with different rules, and hardcoding 'item' versus 'items' logic guarantees errors. i18next handles this through CLDR-driven plural suffixes: you supply item_one, item_other, and additional forms per language, and t('item', { count }) selects correctly everywhere.
Dates, numbers, and currency should never be hand-formatted. Hermes ships Intl support, so Intl.NumberFormat and Intl.DateTimeFormat with the active locale produce correct decimal separators, currency placement, and date order — differences that make hardcoded formats look broken abroad, particularly in finance and commerce apps.
// en/common.json: { "cartItems_one": "{{count}} item", "cartItems_other": "{{count}} items" }
// Other languages supply their own CLDR plural forms (e.g. _few, _many).
const label = t('cartItems', { count: cart.length });
// Currency and dates via Intl — Hermes supports these on both platforms.
const price = new Intl.NumberFormat(i18n.language, {
style: 'currency',
currency: 'EUR',
}).format(total);
const delivery = new Intl.DateTimeFormat(i18n.language, {
weekday: 'long',
day: 'numeric',
month: 'long',
}).format(deliveryDate);RTL: layout direction is an app-wide property
Supporting Arabic, Hebrew, or other right-to-left languages is the step teams underestimate most. React Native has solid RTL primitives — I18nManager reports and controls direction, and flexbox with start/end properties mirrors automatically — but only if the codebase never cheated. Every marginLeft that should have been marginStart, every absolutely-positioned left offset, and every directional icon (back arrows, chevrons) that is not flipped becomes a visible defect in RTL.
My approach on existing codebases: lint for physical direction properties and migrate them to logical ones, audit icons for a directional subset that needs mirroring, and test with the RTL developer toggle long before contracting Arabic translators. Note that switching I18nManager.forceRTL at runtime requires an app restart to fully apply, so in-app language switching into an RTL language needs a restart prompt in the UX. Animations and gestures deserve a pass too — swipe-to-go-back semantics invert.
The translation pipeline: keeping ten locales shippable
At scale the bottleneck moves from code to process. The pipeline that works: source-language strings live in the repo as the single source of truth; a translation management platform syncs new keys to translators automatically on merge; translated strings flow back as pull requests. Developers never wait on translators because the fallback chain keeps untranslated features shippable in English, and the missing-key CI diff report tells product exactly what is outstanding per locale.
Two practices prevent the classic quality failures. Give translators context — screenshots or key descriptions — because a bare string like 'Book' is untranslatable without knowing if it is a noun or a verb. And pseudo-localization in development builds (expanding strings with accents and padding) catches truncation and hardcoded text continuously, since German and Finnish routinely run much longer than English and will break any layout that only ever saw its source language.
When to hire senior help
The framework decision is a one-way door worth a short senior consultation, because switching stacks after a year of development is effectively a rewrite. A senior cross-platform engineer can also audit whether your planned feature set has hidden native-heavy corners, like payments hardware or background location, that change the cost math before you commit. If your stack includes React Native + Python + AI, a senior engineer who owns the full product beats coordinating multiple juniors.
Bottom line
Dhairya Senjaliya ships Mobile — Cross Platform Development projects worldwide — book a scoping call to discuss your specific situation.
Common pitfalls to avoid
- ✕Picking the framework by hype rather than team composition, such as a React web team adopting Flutter and forfeiting years of transferable JavaScript expertise
- ✕Budgeting for 100% code reuse and zero platform-specific time, then discovering payments, background tasks, and widgets all require per-platform native work
- ✕Recreating navigation and interaction patterns generically so iOS swipe-back gestures and Android back-button behavior both feel wrong to native users
- ✕Ignoring the maintenance tail: never budgeting for framework major-version upgrades, so the app rots on an unsupported runtime within two years
Frequently asked questions
What is the best i18n library for React Native?
i18next with react-i18next is the most battle-tested choice for React Native apps at scale: it handles namespaces, CLDR plural rules, interpolation, and fallback chains, and integrates with translation management platforms. Pair it with expo-localization for device locale detection and the built-in Intl APIs, which Hermes supports, for date, number, and currency formatting.
How do you handle right-to-left languages in React Native?
Use logical layout properties everywhere — marginStart instead of marginLeft, flexbox start/end alignment — so layouts mirror automatically, and flip directional icons like back arrows. I18nManager controls RTL mode, but changing it at runtime requires an app restart, so in-app switches to Arabic or Hebrew need a restart prompt. Lint against physical direction properties and test with the RTL toggle early.
How do you manage translations for a large mobile app?
Organize keys into one namespace per feature, keep source strings in the repo as the source of truth, and sync with a translation management platform so new keys reach translators automatically. Add a CI check that fails when locale files are missing keys, keep an English fallback so releases are never blocked, and give translators screenshots or descriptions for context.
Should we choose Flutter or React Native?
Adoption among professional developers is nearly tied (9.21% versus 9.14% in the Stack Overflow 2024 survey), so the deciding factor is your team: React or JavaScript experience strongly favors React Native, while a greenfield team with no web-code-sharing needs can prefer Flutter. Both run massive production apps, so neither choice is inherently risky.
How much money does cross-platform actually save versus two native apps?
Industry cost guides put savings around 30 to 40% versus parallel native builds, driven by one codebase and one team, with production apps sharing 85 to 95% of code. Real savings depend on how much platform-specific work your feature set demands, such as payments, widgets, and background processing.
When is fully native the better choice?
Heavy 3D or AR workloads, advanced camera or audio processing, platform-first experiences like watchOS apps, or a company that already employs strong separate iOS and Android teams. For typical business, marketplace, and content apps, cross-platform is now the default choice at both startups and large companies like Shopify and Microsoft.
Bottom line: Dhairya Senjaliya ships Mobile — Cross Platform Development projects worldwide. Book a scoping call at https://dhairyasenjaliya.com/#book-call.