or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

index.mddocs/

Expo Localization

Expo 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.

Package Information

  • Package Name: expo-localization
  • Package Type: npm
  • Language: TypeScript
  • Installation: npx expo install expo-localization or npm install expo-localization

Core Imports

import { 
  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");

Basic Usage

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>
  );
}

Architecture

Expo Localization is built around several key components:

  • Functional API: Direct function calls (getLocales, getCalendars) for one-time locale access
  • React Hooks: useLocales and useCalendars hooks that automatically update when device settings change
  • Event System: Manual subscription functions (addLocaleListener, addCalendarListener) for custom reactive updates
  • Platform Abstraction: Unified API across iOS, Android, and Web with platform-specific implementations
  • Type Safety: Comprehensive TypeScript definitions for all locale and calendar properties

Capabilities

Event System

Manual 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();

Locale Information

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>
  );
}

Calendar Information

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>
  );
}

Types

Event Subscription Interface

interface EventSubscription {
  /** Removes the listener subscription */
  remove(): void;
}

Calendar Identifier Enum

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',
}

Weekday Enum

/**
 * 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,
}

Platform-Specific Behavior

Web Platform

  • Currency and measurement system properties return null
  • Text direction may be null on browsers without textInfo API support
  • Clock format and first weekday may be null on browsers without weekInfo API support
  • Uses browser navigator.languages and Intl APIs for locale detection

Native Platform (iOS/Android)

  • Provides full locale data including currency and measurement systems
  • iOS: Currency from Region setting, not current locale
  • Android: Currency specific to locale in list
  • Native module integration via expo-modules-core

Integration with i18n Libraries

Expo 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');