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).
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.
messages.path
string | Array<string>
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.
If your messages live in a custom folder structure (typically with frameworks other than next-intl), two placeholders are available:
{locale}: Resolves to a given locale (e.g.en){namespace}: Splits messages per namespace (the first part of a message id)
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.
You can also pass an array of paths when messages live in more than one place.
messages.locales
'infer' | Array<string>
The locales to translate between. Pass an explicit array, or 'infer' to detect them from the files in your messages directory.
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'
Beyond the built-in formats, you can configure custom formats. These can handle special cases, like for example storing message descriptions in JSON files:
messages/en.json
{"HomePage.title": {"message": "Welcome, {name}!","description": ["Greeting for the user when the app starts."]}}
A custom format consists of a codec along with an extension. The codec can be created with defineCodec at an arbitrary place in your project:
.eloqnt/StructuredJSONCodec.ts
import {defineCodec} from '@eloqnt/cli';type Entry = {message: string; description?: Array<string>};export default defineCodec(() => ({decode(content) {const data = JSON.parse(content) as Record<string, Entry>;return Object.entries(data).map(([id, entry]) => ({id,message: entry.message,description: entry.description ?? [],references: []}));},encode(messages) {const data: Record<string, Entry> = {};for (const message of messages) {data[message.id] = {message: message.message,description: message.description};}return JSON.stringify(data, null, 2);}}));
Then, reference it in your configuration along with an extension:
.eloqnt/config.ts
import {defineConfig} from '@eloqnt/cli';export default defineConfig({messages: {format: {codec: './.eloqnt/StructuredJSONCodec.ts',extension: '.json'}// ...}});
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. Note that you may need to set provider environment variables like ANTHROPIC_API_KEY.
.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-4-8')// ...});
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.