i18n.json is the configuration file that controls the Lingo.dev CLI and CI/CD integrations. It defines which languages to translate, where translatable content lives, and which translation backend to use.
Minimal example#
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.15",
"locale": {
"source": "en",
"targets": ["es", "fr", "ja"]
},
"buckets": {
"json": {
"include": ["locales/[locale].json"]
}
}
}The $schema field enables IDE autocompletion and validation. The version field tracks the schema version for automatic migration compatibility.
Locale#
The locale section defines the source and target languages:
{
"locale": {
"source": "en",
"targets": ["es", "fr", "de", "ja"]
}
}| Field | Description |
|---|---|
locale.source | The language your source content is written in. All translations flow from this locale. |
locale.targets | Array of target languages. Each target produces a separate file (or section) depending on the bucket format. |
Language codes follow the BCP 47 standard - en, en-US, es-ES, zh-Hans, and platform-specific formats like Android's en-rUS are all supported.
To list available locale codes:
npx lingo.dev@latest show locale sources # Available source languages
npx lingo.dev@latest show locale targets # Available target languagesBuckets#
Buckets define file discovery patterns and processing rules. Each bucket key specifies a file format, and its value configures which files to include or exclude:
{
"buckets": {
"json": {
"include": ["locales/[locale].json"],
"exclude": ["locales/[locale]/internal.json"]
},
"markdown": {
"include": ["docs/[locale]/*.md"]
}
}
}| Field | Description |
|---|---|
include | Array of file patterns with [locale] placeholder. Supports glob wildcards (*). |
exclude | Optional. Array of patterns to skip during processing. |
lockedKeys | Optional. Keys whose values are copied from source without translation. See Key Locking. |
ignoredKeys | Optional. Keys excluded from translation entirely - they don't appear in target files. See Key Ignoring. |
preservedKeys | Optional. Keys initialized once from source, then protected from automatic updates. See Key Preserving. |
injectLocale | Optional. Keys where the target locale code is injected automatically. |
Include patterns#
Include patterns use the [locale] placeholder, which resolves to your configured locale codes at runtime:
locales/[locale].jsonโlocales/en.json,locales/es.jsondocs/[locale]/*.mdโdocs/en/*.md,docs/es/*.md
Recursive glob patterns (**/*.json) are not supported. Use explicit directory paths instead.
Custom locale delimiters#
By default, locale codes in filenames use a dash (-) delimiter: en-US.json. To use underscores instead, pass an object with a delimiter field:
{
"include": [
"standard/[locale].json",
{ "path": "legacy/[locale].json", "delimiter": "_" }
]
}This produces legacy/en_US.json instead of legacy/en-US.json.
Key path notation#
The lockedKeys, ignoredKeys, and preservedKeys arrays use forward slash (/) notation for nested keys and asterisk (*) for wildcards:
{
"lockedKeys": ["brand/name", "config/*"]
}For the full list of supported bucket types, see Supported Formats.
Provider#
The provider section configures a raw LLM provider for translation. This section is optional - when omitted, the CLI uses a localization engine on Lingo.dev.
{
"provider": {
"id": "openai",
"model": "gpt-4o-mini",
"prompt": "Translate the provided text from {source} to {target}."
}
}| Field | Description |
|---|---|
provider.id | Provider identifier: openai, anthropic, google, mistral, openrouter, or ollama. |
provider.model | Model name from the provider (e.g., gpt-4o-mini, claude-3-haiku). |
provider.prompt | System prompt. {source} and {target} are replaced with locale codes at runtime. |
provider.baseUrl | Optional. Custom API endpoint (required for Ollama: http://localhost:11434). |
Engine connection#
To route translations through a specific localization engine, add the engineId field:
{
"engineId": "eng_SxjMwMsfOIsvV1wh"
}When engineId is set, every translation request applies your engine's brand voice, glossary, instructions, and model configuration automatically. If omitted and LINGO_API_KEY is set, the CLI uses the default engine in your organization.
For the full setup guide, see Connect Your Engine.
Environment variables#
| Variable | Required | Description |
|---|---|---|
LINGO_API_KEY | For Lingo.dev Engine | Your Lingo.dev API key. |
LINGO_API_URL | No | Custom API base URL (for self-hosted or staging). |
OPENAI_API_KEY | For OpenAI provider | OpenAI API key. |
ANTHROPIC_API_KEY | For Anthropic provider | Anthropic API key. |
GOOGLE_API_KEY | For Google provider | Google API key. |
MISTRAL_API_KEY | For Mistral provider | Mistral API key. |
OPENROUTER_API_KEY | For OpenRouter provider | OpenRouter API key. |
Full example#
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.15",
"locale": {
"source": "en",
"targets": ["es", "fr", "de", "ja"]
},
"buckets": {
"json": {
"include": ["locales/[locale].json"],
"lockedKeys": ["brand/name", "brand/tagline"],
"ignoredKeys": ["internal/*"]
},
"markdown": {
"include": ["docs/[locale]/*.md"]
}
},
"engineId": "eng_SxjMwMsfOIsvV1wh"
}Version migration#
The CLI automatically migrates older i18n.json configurations to the latest schema version. It creates a backup of your current file, updates the schema, and preserves all settings. No manual intervention is required.
