eloqnt/studiov0.5
Navigation

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:

  1. {locale}: Resolves to a given locale (e.g. en)
  2. {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:

  1. 'po' (recommended)
  2. '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 SDK
model: 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.