Skip to content
better-i18n.com
Bu sayfada

Complete API reference for the Expo/React Native SDK.

initBetterI18n #

The primary API. Fetches translations from the better-i18n CDN, initializes i18next with all namespaces pre-loaded, and overrides changeLanguage() to pre-load translations before switching.

TypeScript
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import { initBetterI18n } from '@better-i18n/expo';

i18n.use(initReactI18next);

const { languages, core } = await initBetterI18n({
  projectId: 'acme/my-app',
  i18n,
  defaultLocale: 'en',
  useDeviceLocale: true,
  debug: __DEV__,
});

What it does #

  1. Fetches the project manifest and initial translations from CDN in parallel
  2. Auto-discovers all namespaces and picks "common" as the default (or first available)
  3. Initializes i18next with translations pre-loaded into the resource store
  4. Overrides changeLanguage() to pre-load translations before switching (no English flash)
  5. Registers a languageChanged listener as a safety net for lazy loading

Options #

TypeScript
interface InitBetterI18nOptions {
  projectId: string;
  i18n?: i18n;
  defaultLocale?: string;
  storage?: TranslationStorage;
  staticData?: Record<string, Messages> | (() => Promise<Record<string, Messages>>);
  fetchTimeout?: number;
  retryCount?: number;
  useDeviceLocale?: boolean;
  debug?: boolean;
  i18nextOptions?: Partial<InitOptions>;
}
OptionTypeDefaultDescription
projectIdstringRequiredProject ID — org/project slug or canonical UUID
i18ni18nGlobal singletoni18next instance (call .use(initReactI18next) before passing). Defaults to the global import i18next from 'i18next' singleton — safe to omit in React Native.
defaultLocalestring"en"Fallback locale
storageTranslationStorageIn-memoryPersistent storage adapter — use storageAdapter(mmkv) or storageAdapter(AsyncStorage)
staticDataRecord<string, Messages>Bundled translations for airplane mode first launch
fetchTimeoutnumber10000CDN fetch timeout in milliseconds
retryCountnumber1Retry attempts on CDN failure
useDeviceLocalebooleanfalseAuto-detect device locale via expo-localization
debugbooleanfalseEnable debug logging to console
i18nextOptionsPartial<InitOptions>{}Additional i18next init options (e.g., defaultNS, ns, react). Merged with SDK defaults.

Return Value #

TypeScript
interface BetterI18nResult {
  /** Core instance for accessing manifest, languages, etc. */
  core: I18nCore;
  /** Available languages from the CDN manifest */
  languages: LanguageOption[];
}

core — The @better-i18n/core instance. Use it to access the raw manifest, fetch messages for specific locales, or interact with the CDN directly.

languages — Array of available languages from the CDN manifest. Use this to build a dynamic language picker.


Locale Detection #

Returns the device's primary locale using expo-localization. Falls back to the provided default if expo-localization is not installed.

TypeScript
import { getDeviceLocale } from '@better-i18n/expo';

const locale = getDeviceLocale({ fallback: 'en' });
// "tr" on a Turkish device, "en" if detection fails
OptionTypeDefaultDescription
fallbackstring"en"Locale to return if detection fails

Returns: string — language code (e.g., "en", "tr", "de")

Returns all device locales as language codes. Returns an empty array if expo-localization is not installed.

TypeScript
import { getDeviceLocales } from '@better-i18n/expo';

const locales = getDeviceLocales();
// ["tr", "en", "de"]

Returns: string[] — array of language codes


Storage #

Wraps an MMKV or AsyncStorage instance and normalizes it to the TranslationStorage interface. When localeKey is provided, returns a LocaleAwareTranslationStorage that also persists the active locale.

TypeScript
storageAdapter(
  storage: MMKVLike | AsyncStorageLike,
  options?: StorageAdapterOptions
): TranslationStorage | LocaleAwareTranslationStorage
import { MMKV } from 'react-native-mmkv';
import { storageAdapter } from '@better-i18n/expo';

const mmkv = new MMKV({ id: 'app' });

// Without localeKey — TranslationStorage (no locale persistence)
storage: storageAdapter(mmkv)

// With localeKey — LocaleAwareTranslationStorage (locale persisted)
storage: storageAdapter(mmkv, { localeKey: '@app:locale' })

```ts tab="StorageAdapterOptions" interface StorageAdapterOptions { /** Key used to persist the user's locale selection in storage. */ localeKey?: string; }

Code

When `localeKey` is set, the returned adapter gains `readLocale()` / `writeLocale()` methods. `initBetterI18n` detects these via duck-type check and automatically reads the saved locale on startup.

Extends `TranslationStorage` with locale persistence. Returned by `storageAdapter()` when `localeKey` is provided.

```ts
interface LocaleAwareTranslationStorage extends TranslationStorage {
  /** Returns the previously saved locale, or null if none. */
  readLocale(): Promise<string | null>;
  /** Persists the given locale to storage. Called on every changeLanguage(). */
  writeLocale(lng: string): Promise<void>;
}

initBetterI18n uses duck-type detection at runtime: if the storage object has readLocale and writeLocale methods, it automatically calls readLocale() during startup to restore the user's last-selected language — before device locale detection and defaultLocale fallback.

Interface for pluggable storage adapters. Any key-value store that implements these three methods works.

TypeScript
interface TranslationStorage {
  getItem(key: string): Promise<string | null>;
  setItem(key: string, value: string): Promise<void>;
  removeItem(key: string): Promise<void>;
}

Compatible with: MMKV, AsyncStorage, SecureStore, or any custom implementation. Use storageAdapter() to wrap MMKV or AsyncStorage instances.

Creates an in-memory storage adapter backed by a Map. Useful for testing or when persistence is not needed.

TypeScript
import { createMemoryStorage } from '@better-i18n/expo';

const storage = createMemoryStorage();

await initBetterI18n({
  projectId: 'acme/app',
  i18n,
  storage,
});

Returns: TranslationStorage


Types #

Represents an available language from the CDN manifest. Returned in the languages array from initBetterI18n.

TypeScript
interface LanguageOption {
  /** Language code — "en", "tr", "az" */
  code: string;
  /** English name — "English", "Turkish" */
  name?: string;
  /** Native name — "English", "Türkçe" */
  nativeName?: string;
  /** URL to flag image (configured in dashboard) */
  flagUrl?: string;
  /** true for the source language */
  isDefault?: boolean;
}

The core instance returned in BetterI18nResult. Provides low-level access to the CDN manifest and translation fetching.

TypeScript
interface I18nCore {
  getLanguages(): Promise<LanguageOption[]>;
  getMessages(locale: string): Promise<Messages>;
  getManifest(): Promise<ManifestResponse>;
}
TypeScript
import type {
  // Primary API
  InitBetterI18nOptions,
  BetterI18nResult,

  // Storage
  TranslationStorage,
  LocaleAwareTranslationStorage,
  StorageAdapterOptions,

  // Core types
  LanguageOption,
  ManifestResponse,
  I18nCore,
} from '@better-i18n/expo';