Skip to content
better-i18n.com
On this page

Overview #

@better-i18n/expo is an i18next integration that pre-loads translations from the better-i18n CDN. It plugs into your existing i18next + react-i18next setup with zero native modules — meaning it works in Expo Go out of the box.

  • Pre-loaded translations — CDN fetch, caching, and namespace discovery handled automatically
  • Offline-first — Persistent caching via MMKV or AsyncStorage with network-first strategy
  • Expo Go compatible — Pure JavaScript, no native modules required
  • Device locale detection — Auto-detect via expo-localization

Features #

  • Works in Expo Go — Pure JS implementation — no native modules, no dev client required.
  • Offline Support — Persistent caching ensures translations are always available, even without network.
  • Pluggable Storage — Uses MMKV by default, falls back to AsyncStorage, or any custom key-value store.
  • Device Locale — Auto-detect the user's language via expo-localization.
  • Instant Language Switching — Translations are pre-loaded before the switch happens — no English flash or loading spinners.

Quick Start #

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

i18n.use(initReactI18next);

export const { languages } = await initBetterI18n({
  projectId: 'your-org/your-project',
  i18n,
  defaultLocale: 'en',
  debug: __DEV__,
});
App.tsx
import './i18n';
import { useTranslation } from 'react-i18next';
import { Text } from 'react-native';

function HomeScreen() {
  const { t } = useTranslation();
  return <Text>{t('welcome')}</Text>;
}

Production-Ready Setup #

The Quick Start above works for development, but production mobile apps need offline fallback. Your app's translations come from the CDN at runtime — if the CDN is unreachable (airplane mode, slow network, or App Store Review), you need a safety net.

Add two things: persistent storage (caches translations on device) and bundled translations (last-resort fallback shipped in your app binary).

i18n.ts
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import { MMKV } from 'react-native-mmkv';
import { initBetterI18n, storageAdapter } from '@better-i18n/expo';

// Generated by: npx @better-i18n/cli pull
import en from './locales/en.json';
import tr from './locales/tr.json';

const mmkv = new MMKV({ id: 'i18n' });
i18n.use(initReactI18next);

export const i18nReady = initBetterI18n({
  projectId: 'your-org/your-project',
  i18n,
  defaultLocale: 'en',
  useDeviceLocale: true,
  storage: storageAdapter(mmkv, { localeKey: '@app:locale' }),
  staticData: { en, tr },
});

How it works:

  1. CDN available — Your app uses the freshest translations
  2. CDN unavailable, has cache — Falls back to previously cached translations (MMKV)
  3. First launch, no network — Falls back to bundled staticData from your locale files

Keep your bundled translations in sync by running pull before each build:

Bash
npx @better-i18n/cli pull -o ./locales

Add this to your CI/CD (e.g., eas-build-pre-install.sh) so it runs automatically. Learn more about offline caching →

Guide #

Comparison #

FeatureExpoViteTanStack StartNext.js
RenderingClientClientClient + SSRClient + SSR
i18n libraryi18nextuse-intluse-intlnext-intl
Offline supportBuilt-inManualManualManual
Expo GoYesN/AN/AN/A
Persistent cacheMMKV / AsyncStorageN/AN/AN/A

Choose Expo for React Native / Expo apps. For web apps, see Vite, TanStack Start, or Next.js.

AI Tooling #

Now that you've integrated the SDK, your AI agent can check coverage, translate keys, and publish — all without leaving your editor.

  • MCP Server — Translate keys, check coverage, and publish — all from your editor via Cursor, Claude Code, or Windsurf.
  • Agent Skill — Permanent better-i18n knowledge for your AI agent — SDK patterns, CDN behavior, key conventions. No prompts needed each session.