Skip to main content

React Native Localization: A Complete Guide

· 5 min read
Full Stack Developer
Last updated on May 17, 2026

react native localization

Localization is more than translating strings. A production React Native app needs stable translation keys, locale detection, fallback behavior, date and number formatting, right-to-left layout checks, long-copy testing, and release verification on real screens.

This guide shows a modern localization setup using expo-localization and a small translation layer. If your Instamobile app already includes localization, follow its existing helper and use this article as the checklist for extending it safely.

Quick Answer

Use expo-localization to read the user's preferred locale, store translations in JSON files, keep keys stable, enable fallback behavior, and test every supported language before release.

corepack yarn expo install expo-localization
corepack yarn add i18n-js

For Instamobile apps, start with the existing translation system:

Choose Translation Keys Carefully

Most React Native apps use JSON dictionaries:

{
"Welcome": "Welcome",
"Create Account": "Create Account",
"No messages yet": "No messages yet"
}

Keep keys readable and stable. Avoid generated names like copy_17 unless your team has a translation management system that owns those IDs.

For Spanish:

{
"Welcome": "Bienvenido",
"Create Account": "Crear cuenta",
"No messages yet": "Aun no hay mensajes"
}

For French:

{
"Welcome": "Bienvenue",
"Create Account": "Creer un compte",
"No messages yet": "Aucun message pour le moment"
}

Read the Device Locale

expo-localization exposes the user's preferred locales and calendar settings:

import { getLocales, getCalendars } from 'expo-localization';

const primaryLocale = getLocales()[0];
const primaryCalendar = getCalendars()[0];

export const deviceLocale = {
languageCode: primaryLocale?.languageCode ?? 'en',
languageTag: primaryLocale?.languageTag ?? 'en',
textDirection: primaryLocale?.textDirection ?? 'ltr',
currencyCode: primaryLocale?.currencyCode,
timeZone: primaryCalendar?.timeZone,
uses24HourClock: primaryCalendar?.uses24hourClock,
};

Avoid older examples that read Localization.locale directly. Use getLocales() so your app can work with the user's locale preference list.

Mega Bundle Sale is ON! Get ALL of our React Native codebases at 90% OFF discount 🔥

Get the Mega Bundle

Create a Small Translation Helper

This example uses i18n-js, but the same structure works with other i18n libraries:

import { I18n } from 'i18n-js';
import { getLocales } from 'expo-localization';

import en from './translations/en.json';
import es from './translations/es.json';
import fr from './translations/fr.json';

const i18n = new I18n({
en,
es,
fr,
});

i18n.enableFallback = true;
i18n.defaultLocale = 'en';
i18n.locale = getLocales()[0]?.languageCode ?? 'en';

export function localized(key: string, params?: Record<string, unknown>) {
return i18n.t(key, params);
}

Then use the helper in UI:

import { Text, View } from 'react-native';
import { localized } from './localized';

export function WelcomeScreen() {
return (
<View>
<Text>{localized('Welcome')}</Text>
<Text>{localized('Create Account')}</Text>
</View>
);
}

If your app exposes a hook such as useTranslations, prefer that local pattern instead of creating a second localization layer.

Format Dates, Numbers, and Currency

Do not translate dates and currency by hand. Use JavaScript internationalization APIs:

export function formatPrice(amount: number, currency = 'USD') {
const locale = getLocales()[0]?.languageTag ?? 'en-US';

return new Intl.NumberFormat(locale, {
style: 'currency',
currency,
}).format(amount);
}

For booking, delivery, ecommerce, and subscription apps, verify time zones and currency symbols with real user flows.

Organize Translation Files by Product Area

Small apps can keep all strings in one JSON file per language. Larger React Native apps are easier to maintain when translations follow product areas:

src/translations/
en/
auth.json
checkout.json
chat.json
es/
auth.json
checkout.json
chat.json

The structure matters less than consistency. Keep every language complete, keep keys stable, and make missing translations obvious during development.

For product teams, a useful review rule is simple: any pull request that adds visible copy also adds the matching translation key to every supported language. That prevents English-only strings from slowly leaking into localized screens.

RTL Support

For Arabic, Hebrew, Persian, Urdu, and other RTL languages, translation is only half of the work. Layout direction must also be correct.

React Native exposes I18nManager for RTL checks. Use it to adapt directional icons, alignment, and animations:

import { I18nManager } from 'react-native';

export const isRTL = I18nManager.isRTL;

Avoid forcing RTL in production as part of normal runtime switching. React Native RTL changes take full effect on the next app start, and force switches are mainly useful during development. For product work, enable RTL support in the app configuration and test the app after restart.

Localization Release Checklist

Before shipping a localized app:

  • every visible string uses the localization helper;
  • every key exists in every supported language file;
  • fallback behavior is acceptable for missing keys during development;
  • long translations fit in buttons, tabs, cards, and headers;
  • dates, numbers, currencies, and units match the active locale;
  • RTL screens are tested if supported;
  • App Store and Google Play screenshots use the intended language;
  • push notification copy is translated if generated by the app or backend.
Looking for a custom mobile application?

Our team of expert mobile developers can help you build a custom mobile app that meets your specific needs.

Get in Touch

FAQ

Should I use expo-localization by itself?

Use it for locale data. Pair it with a translation library or your app's existing translation helper to resolve keys into text.

Should I call I18nManager.forceRTL in production?

Usually no. It requires an app restart to fully apply and is mainly useful for development testing. Configure RTL support intentionally and test the restarted app.

What should I do when text becomes too long?

Fix the layout. Do not shorten only one language in code. Buttons, tabs, cards, and headers should allow realistic translated copy.