Provides an interface for native user localization information in React Native applications.
npx @tessl/cli install tessl/npm-expo-localization@17.0.0Expo Localization provides an interface for native user localization information in React Native applications. It offers both function-based APIs and reactive React hooks to access locale-specific data including language tags, currency codes, measurement systems, calendar preferences, and formatting settings.
npx expo install expo-localization or npm install expo-localizationimport {
getLocales,
getCalendars,
useLocales,
useCalendars,
addLocaleListener,
addCalendarListener,
removeSubscription
} from "expo-localization";
import type {
Locale,
Calendar,
CalendarIdentifier,
Weekday
} from "expo-localization";For CommonJS:
const {
getLocales,
getCalendars,
useLocales,
useCalendars,
addLocaleListener,
addCalendarListener,
removeSubscription
} = require("expo-localization");import { getLocales, getCalendars, useLocales, useCalendars } from "expo-localization";
// Get current locales (functional API)
const locales = getLocales();
console.log(locales[0].languageTag); // e.g., "en-US"
console.log(locales[0].currencyCode); // e.g., "USD"
// Get current calendars (functional API)
const calendars = getCalendars();
console.log(calendars[0].calendar); // e.g., "gregory"
console.log(calendars[0].uses24hourClock); // e.g., false
// React hooks for reactive updates
function MyComponent() {
const locales = useLocales(); // Updates when OS settings change
const calendars = useCalendars(); // Updates when OS settings change
return (
<div>
<p>Language: {locales[0].languageCode}</p>
<p>Currency: {locales[0].currencyCode}</p>
<p>Time format: {calendars[0].uses24hourClock ? '24h' : '12h'}</p>
</div>
);
}Expo Localization is built around several key components:
getLocales, getCalendars) for one-time locale accessuseLocales and useCalendars hooks that automatically update when device settings changeaddLocaleListener, addCalendarListener) for custom reactive updatesManual subscription system for listening to locale and calendar changes outside of React components.
/**
* Adds a listener that is called whenever the user changes their device's locale settings.
* Returns a subscription object that can be used to remove the listener.
*/
function addLocaleListener(listener: (event?: unknown) => void): EventSubscription;
/**
* Adds a listener that is called whenever the user changes their device's calendar settings.
* Returns a subscription object that can be used to remove the listener.
*/
function addCalendarListener(listener: (event?: unknown) => void): EventSubscription;
/**
* Removes a subscription created by addLocaleListener or addCalendarListener.
*/
function removeSubscription(subscription: EventSubscription): void;
interface EventSubscription {
remove(): void;
}Usage Example:
import {
addLocaleListener,
addCalendarListener,
removeSubscription,
getLocales,
getCalendars
} from "expo-localization";
// Listen for locale changes
const localeSubscription = addLocaleListener(() => {
const newLocales = getLocales();
console.log('Locale changed to:', newLocales[0].languageTag);
});
// Listen for calendar changes
const calendarSubscription = addCalendarListener(() => {
const newCalendars = getCalendars();
console.log('Calendar changed to:', newCalendars[0].calendar);
});
// Clean up subscriptions when no longer needed
removeSubscription(localeSubscription);
removeSubscription(calendarSubscription);
// Alternative cleanup using the subscription object directly
localeSubscription.remove();
calendarSubscription.remove();Access comprehensive user locale information including language, region, currency, and formatting preferences.
/**
* List of user's locales, returned as an array of objects of type Locale.
* Guaranteed to contain at least 1 element.
* These are returned in the order the user defines in their device settings.
* On the web currency and measurements systems are not provided, instead returned as null.
*/
function getLocales(): Locale[];
/**
* A hook providing a list of user's locales, returned as an array of objects of type Locale.
* Guaranteed to contain at least 1 element.
* If the OS settings change, the hook will rerender with a new list of locales.
*/
function useLocales(): Locale[];
interface Locale {
/** IETF BCP 47 language tag with region code (e.g., 'en-US', 'es-419', 'pl-PL') */
languageTag: string;
/** IETF BCP 47 language tag without region code (e.g., 'en', 'es', 'pl') */
languageCode: string | null;
/** ISO 15924 4-letter script code (e.g., 'Latn', 'Hans', 'Hebr') */
languageScriptCode: string | null;
/** Region code from device settings (e.g., 'US') */
regionCode: string | null;
/** Region code for preferred language (e.g., 'US') */
languageRegionCode: string | null;
/** Currency code for locale (e.g., 'USD', 'EUR', 'PLN') - null on Web */
currencyCode: string | null;
/** Currency symbol (e.g., '$', '€', 'zł') */
currencySymbol: string | null;
/** Currency code for current locale (platform-specific) - null on Web */
languageCurrencyCode: string | null;
/** Currency symbol for language currency */
languageCurrencySymbol: string | null;
/** Decimal separator for numbers (e.g., '.', ',') */
decimalSeparator: string | null;
/** Digit grouping separator for large numbers (e.g., '.', ',') */
digitGroupingSeparator: string | null;
/** Text direction for locale */
textDirection: 'ltr' | 'rtl' | null;
/** Measurement system used in locale - null on Web */
measurementSystem: 'metric' | 'us' | 'uk' | null;
/** Temperature unit based on region */
temperatureUnit: 'celsius' | 'fahrenheit' | null;
}Usage Example:
import { getLocales, useLocales } from "expo-localization";
// Functional approach
const currentLocale = getLocales()[0];
console.log(`Language: ${currentLocale.languageCode}`);
console.log(`Region: ${currentLocale.regionCode}`);
console.log(`Currency: ${currentLocale.currencyCode} (${currentLocale.currencySymbol})`);
console.log(`Decimal separator: ${currentLocale.decimalSeparator}`);
// React hook approach (updates automatically)
function LocaleDisplay() {
const locales = useLocales();
const primary = locales[0];
return (
<div>
<h3>Current Locale: {primary.languageTag}</h3>
<p>Direction: {primary.textDirection}</p>
<p>Temperature: {primary.temperatureUnit}</p>
<p>Measurement: {primary.measurementSystem}</p>
</div>
);
}Access user's calendar and time formatting preferences including calendar system, time zone, and week settings.
/**
* List of user's preferred calendars, returned as an array of objects of type Calendar.
* Guaranteed to contain at least 1 element.
* For now always returns a single element, but may return preference list on some platforms in future.
*/
function getCalendars(): Calendar[];
/**
* A hook providing a list of user's preferred calendars, returned as an array of objects of type Calendar.
* Guaranteed to contain at least 1 element.
* If the OS settings change, the hook will rerender with a new list of calendars.
*/
function useCalendars(): Calendar[];
interface Calendar {
/** Calendar identifier (Unicode calendar type) */
calendar: CalendarIdentifier | null;
/** True when device uses 24-hour time format */
uses24hourClock: boolean | null;
/** First day of week (1=Sunday, 7=Saturday) */
firstWeekday: Weekday | null;
/** Time zone identifier (e.g., 'America/Los_Angeles', 'Europe/Warsaw') */
timeZone: string | null;
}Usage Example:
import { getCalendars, useCalendars } from "expo-localization";
// Functional approach
const currentCalendar = getCalendars()[0];
console.log(`Calendar type: ${currentCalendar.calendar}`);
console.log(`24-hour clock: ${currentCalendar.uses24hourClock}`);
console.log(`First weekday: ${currentCalendar.firstWeekday}`);
console.log(`Time zone: ${currentCalendar.timeZone}`);
// React hook approach (updates automatically)
function CalendarDisplay() {
const calendars = useCalendars();
const primary = calendars[0];
return (
<div>
<h3>Calendar Settings</h3>
<p>System: {primary.calendar}</p>
<p>Time Format: {primary.uses24hourClock ? '24-hour' : '12-hour'}</p>
<p>Week starts: {primary.firstWeekday === 1 ? 'Sunday' : 'Monday'}</p>
<p>Time Zone: {primary.timeZone}</p>
</div>
);
}interface EventSubscription {
/** Removes the listener subscription */
remove(): void;
}enum CalendarIdentifier {
/** Thai Buddhist calendar */
BUDDHIST = 'buddhist',
/** Traditional Chinese calendar */
CHINESE = 'chinese',
/** Coptic calendar */
COPTIC = 'coptic',
/** Traditional Korean calendar */
DANGI = 'dangi',
/** Ethiopic calendar, Amete Alem (epoch approx. 5493 B.C.E) */
ETHIOAA = 'ethioaa',
/** Ethiopic calendar, Amete Mihret (epoch approx, 8 C.E.) */
ETHIOPIC = 'ethiopic',
/** Gregorian calendar */
GREGORY = 'gregory',
/** Gregorian calendar (alias) */
GREGORIAN = 'gregory',
/** Traditional Hebrew calendar */
HEBREW = 'hebrew',
/** Indian calendar */
INDIAN = 'indian',
/** Islamic calendar */
ISLAMIC = 'islamic',
/** Islamic calendar, tabular (intercalary years [2,5,7,10,13,16,18,21,24,26,29] - civil epoch) */
ISLAMIC_CIVIL = 'islamic-civil',
/** Islamic calendar, Saudi Arabia sighting */
ISLAMIC_RGSA = 'islamic-rgsa',
/** Islamic calendar, tabular (intercalary years [2,5,7,10,13,16,18,21,24,26,29] - astronomical epoch) */
ISLAMIC_TBLA = 'islamic-tbla',
/** Islamic calendar, Umm al-Qura */
ISLAMIC_UMALQURA = 'islamic-umalqura',
/** ISO calendar (Gregorian calendar using the ISO 8601 calendar week rules) */
ISO8601 = 'iso8601',
/** Japanese imperial calendar */
JAPANESE = 'japanese',
/** Persian calendar */
PERSIAN = 'persian',
/** Civil (algorithmic) Arabic calendar */
ROC = 'roc',
}/**
* An enum mapping days of the week in Gregorian calendar to their index
* as returned by the firstWeekday property.
*/
enum Weekday {
SUNDAY = 1,
MONDAY = 2,
TUESDAY = 3,
WEDNESDAY = 4,
THURSDAY = 5,
FRIDAY = 6,
SATURDAY = 7,
}nullnull on browsers without textInfo API supportnull on browsers without weekInfo API supportnavigator.languages and Intl APIs for locale detectionExpo Localization works seamlessly with internationalization libraries:
import i18n from 'i18n-js';
import { getLocales } from 'expo-localization';
// Configure i18n-js with device locale
i18n.locale = getLocales()[0].languageCode || 'en';
i18n.translations = {
en: { welcome: 'Welcome' },
es: { welcome: 'Bienvenido' },
fr: { welcome: 'Bienvenue' },
};
// Use in your app
const greeting = i18n.t('welcome');