Project files
Configuration
Configuration for eloqnt/cli is defined locally in your project repository.
All configuration lives in .eloqnt/config.ts at your project root:
.eloqnt/config.ts
import {defineConfig} from '@eloqnt/cli';export default defineConfig({srcPath: './src',messages: {path: './messages',locales: 'infer',sourceLocale: 'en',format: 'json'}});
srcPath
string | Array<string> (optional)
Relative path(s) to the source code that uses your messages (next-intl only).
.eloqnt/config.ts
import {defineConfig} from '@eloqnt/cli';export default defineConfig({srcPath: './src'// ...});
When set, the CLI analyzes your source code: AST-level lint rules like orphan-message and undefined-key become available, and translation runs automatically pick up context from the call sites of your messages.
In a monorepo, you can pass an array of relative source roots, including sibling or installed packages (see the next-intl docs).
messages
object
Describes your message catalogs: where they live and how they're stored.
.eloqnt/config.ts
import {defineConfig} from '@eloqnt/cli';export default defineConfig({messages: {path: './messages',locales: 'infer',sourceLocale: 'en',format: 'json'}// ...});
messages.path
MessagesPathEntry | Array<MessagesPathEntry>
The relative path to the directory containing your messages, with one file per locale.
For example:
path: './messages';
… corresponds to:
./messages/en.json./messages/es.json- etc.
You can also pass an array of paths when your app messages are sourced from multiple places:
path: ['./messages', '../ui/messages'];
Note that all messages share the same root namespace in this case (contrary to when using a {namespace} placeholder—see below).
For more advanced setups, there are three placeholders available:
{locale}: Resolves to a given locale (e.g.'en'){namespace}: Splits messages per namespace (the first part of a message ID){code}: Custom mapping for locales to files viamessages.codes(defaults to{locale})
For example:
.eloqnt/config.ts
import {defineConfig} from '@eloqnt/cli';export default defineConfig({messages: {path: './locales/{locale}/{namespace}',locales: 'infer',sourceLocale: 'en',format: 'json'}});
… will match files like:
./locales/en/auth.json./locales/es/auth.json- etc.
Formats that keep all locales in one shared file can point path at the file itself (without an extension or placeholder)—see custom formats.
Additionally, if your source and target messages use a different path, you can split path into an object with separate properties for each:
.eloqnt/config.ts
import {defineConfig} from '@eloqnt/cli';export default defineConfig({messages: {path: {source: './i18n/Messages',targets: './i18n/Messages_{locale}'}// ...}});
The source path holds the source locale's file and uses no locale placeholder, while targets must contain {locale} or {code}.
messages.locales
'infer' | Array<string>
The locales to translate between.
Pass 'infer' to detect your target locales from the files in the messages directory. If you prefer to be explicit, e.g. when messages.path contains non-messages, you can list the locales with an explicit array.
messages.sourceLocale
string
The primary locale that serves as the source for translations.
messages.format
MessageFormat
Defines how your messages files are stored, the built-in formats are:
'po'(recommended)'json'
For advanced cases and libraries other than next-intl, see the docs on custom formats.
messages.codes
Record<string, string> (optional)
If your files don't match your locales, you can add a mapping:
.eloqnt/config.ts
import {defineConfig} from '@eloqnt/cli';export default defineConfig({messages: {codes: {'de-AT': 'de-rAT','es-419': 'b+es+419'}// ...}});
This establishes the {code} placeholder which can then be used in messages.path.
lint
object (optional)
Configures how eloqnt lint reports its rules.
lint.rules
LintRulesConfig (optional)
Sets the severity of individual rules:
'error': Fails the run'warn': Reports without failing'off': Disables the rule entirely
Rules you don't list keep their default severity (see the rules overview).
.eloqnt/config.ts
import {defineConfig} from '@eloqnt/cli';export default defineConfig({lint: {rules: {// Completeness is tracked in an external system'missing-translation': 'off'}}// ...});
Warnings still fail the run when you pass --strict to eloqnt lint.
lint.overrides
Array<LintOverride> (optional)
Applies rule settings only to matching message keys. Entries apply in order, with the last matching entry winning over lint.rules and earlier entries.
.eloqnt/config.ts
import {defineConfig} from '@eloqnt/cli';export default defineConfig({lint: {overrides: [{// Keys under `products.` are constructed dynamicallykeys: 'products.*',rules: {'orphan-message': 'off'}}]}// ...});
The keys field accepts one or more patterns matched against message keys, where a single * matches any sequence of characters.
model
LanguageModel (optional)
On the "Bring your own model" plan, translations run through a model you configure yourself, with any provider the AI SDK supports. All inference then runs through your model, and no messages or source code ever touch our backend.
.eloqnt/config.ts
import {anthropic} from '@ai-sdk/anthropic';import {defineConfig} from '@eloqnt/cli';export default defineConfig({// Pick any model supported by the AI SDKmodel: anthropic('claude-opus-5')// ...});
Note that you may need to set provider environment variables like ANTHROPIC_API_KEY.
Using a coding agent subscription (Claude Code, Codex, …)
If you already subscribe to a coding agent, 3rd-party providers let you use it as your model (examples: Claude Code, Codex). No separate API key needed.
.eloqnt/config.ts
import {claudeCode} from 'ai-sdk-provider-claude-code';import {defineConfig} from '@eloqnt/cli';export default defineConfig({model: claudeCode('opus')// ...});
Note: These providers are community-maintained, and whether your subscription allows this kind of use is up to the vendor. That can change at any time, so check that it's in line with the plan you're using.
styleguides
string (optional)
Relative path to the directory that holds your styleguides (defaults to .eloqnt).
Especially if you want to share styleguides among multiple consumers, it can be handy to centralize them:
.eloqnt/config.ts
import {defineConfig} from '@eloqnt/cli';export default defineConfig({styleguides: '../i18n/styleguides'// ...});