Skip to main content

File Mode

File mode uses a static JSON translation file — no server connection at runtime. Perfect for static sites, CDNs, and offline-first apps.

Setup

<script src="/path/to/loco.js"></script>
<script>
// Single file
Loco.init({ file: '/translations.json' });

// Multiple files (merged)
Loco.init({ files: ['/translations-core.json', '/translations-extra.json'] });

// Multiple files with a high-priority override file
Loco.init({
files: [
'/translations-core.json',
{ url: '/client-overrides.json', priority: 100 }
]
});

Loco.apply('zh-CN');

// Optional floating language picker
Loco.widget({ position: 'bottom-right' });
</script>

Merge order and file priority

When multiple files are passed, they merge in order — a later file's entries win any key conflicts. Each entry in files can be a URL string or an object:

Loco.init({
files: [
'/translations-core.json', // priority 0 (default)
{ url: '/client-overrides.json', priority: 100 } // merges last, wins conflicts
]
});

Files merge in ascending priority order, so the highest-priority file always wins key conflicts regardless of its position in the array. Files with equal priority keep their array order (later still wins).

Backward compatibility

URLs containing clientSpecificTranslationsJson automatically get priority 100 unless an explicit priority is set. New integrations should use the explicit { url, priority } form instead.

Getting the JSON file

Export from the dashboard: Translations → Approved tab → Export JSON.

Or download a single language: GET /api/export/:lang from the REST API.

Translation JSON format

{
"languages": ["fr", "zh-CN"],
"languageNames": {
"fr": "Français",
"zh-CN": "Simplified Chinese"
},
"translations": {
"fr": [
{ "key": "Hello", "context": "", "value": "Bonjour" },
{ "key": "Delete", "context": "button", "value": "Supprimer" },
{ "key": "Welcome back, {{text:0}}", "context": "", "value": "Bon retour, {{text:0}}" },
{ "key": "{{number:0}} items in cart", "context": "", "value": "{{number:0}} articles dans le panier" }
],
"zh-CN": [
{ "key": "Hello", "context": "", "value": "你好" },
{ "key": "Delete", "context": "button", "value": "删除" }
]
},
"timestamp": 1715000000000
}
note

Each translation is an object with key, context, and value. The context field disambiguates the same phrase appearing in multiple UI locations. Translations within each language are an array, not a map.

Variable slots in translations

Slot tokens ({{text:0}}, {{number:0}}, {{date:0}}) must be preserved in the translated value. See Variable Slots for details.

Caching (IndexedDB)

Loco caches translation files in IndexedDB for offline use and faster load times. To force a refresh:

await Loco.pullLatest(); // re-fetches if server timestamp is newer
await Loco.clearCache(); // clear all cached files + saved language preference

Differences from Server Mode

Server ModeFile Mode
Server required at runtime✅ Yes❌ No
Auto phrase discovery✅ Yes❌ No (manual export)
Real-time translation updates✅ Yes❌ No (redeploy required)
AI translate✅ Yes✅ (export after)
Language switcher widget✅ Yes✅ Yes
IndexedDB offline cache❌ No✅ Yes
Works on static hosting❌ No✅ Yes