Better I18NBetter I18N

pull

Download translations from CDN to local JSON files for offline fallback

Download translations from the Better i18n CDN to local JSON files. Essential for mobile apps where bundled translations serve as the offline safety net.

Why pull?

Mobile apps (Expo, React Native, Swift, Flutter) depend on CDN translations at runtime. If the CDN is unreachable — airplane mode, slow network, or App Store Review environment — the app needs a fallback. pull downloads translations so you can bundle them as staticData.

CDN available    → Fresh translations (best case)
CDN unavailable  → Persistent cache (MMKV/AsyncStorage)
First launch, no cache, no network → staticData from pull ✅

App Store Review risk: Apple reviewers may test your app in environments where external CDN calls timeout. Without bundled translations, your app shows raw keys like common.button.save — and gets rejected as "incomplete" under Guideline 2.1.

Usage

# Auto-detect project from i18n.config.ts or initBetterI18n() call
better-i18n pull

# Explicit project (no config file needed)
better-i18n pull -p acme/my-app

# Custom output directory
better-i18n pull -o ./src/locales

# Download specific locales only
better-i18n pull -l en,tr,de

Example output

✔ Project: acme/my-app
✔ Manifest: 3 languages (en, de, tr)
✔ Downloaded 3 locale(s) to locales/

  ✓ en      1867 keys  145.8 KB
  ✓ de      1742 keys  146.3 KB
  ✓ tr      1741 keys  131.0 KB

  Use as offline fallback in your app:
    staticData: { en: require('./locales/en.json'), de: require('./locales/de.json'), tr: require('./locales/tr.json') }

Options

FlagDescriptionDefault
-p, --project <org/name>Project identifierFrom i18n.config.ts
-o, --output <path>Output directory for JSON files./locales (or config pull.output)
-l, --locales <codes>Comma-separated locale codesAll languages from manifest
-d, --dir <path>Directory to scan for configCurrent directory
--verboseShow per-locale download detailsOff

Configuration

Add a pull section to your i18n.config.ts to set defaults:

i18n.config.ts
export const i18nConfig = {
  project: "acme/my-app",
  defaultLocale: "en",
  pull: { 
    output: "./locales", 
    locales: ["en", "tr", "de"], 
  }, 
};

CLI flags always override config values.

Mobile Workflow

Expo / React Native

After pulling, import the JSON files as staticData:

lib/i18n.ts
import en from './locales/en.json';
import tr from './locales/tr.json';

await initBetterI18n({
  project: 'acme/my-app',
  i18n,
  storage: storageAdapter(new MMKV()),
  staticData: { en, tr }, 
});

CI/CD Integration

Add pull to your build pipeline so bundled translations stay in sync:

eas-build-pre-install.sh or CI script
npx @better-i18n/cli pull

Run pull before every build to ensure your bundled translations match what's on CDN. This is especially important if your team updates translations frequently through the dashboard.

Project Detection

The pull command finds your project in this order:

  1. -p flag (highest priority)
  2. i18n.config.ts in the target directory
  3. Source file scan for initBetterI18n() or createI18n() calls

This means Expo projects work without a config file — the CLI finds project: 'acme/my-app' from your initBetterI18n() call automatically.

On this page