eloqnt/cli
eloqnt translate
Uses AIFill in missing translations across your target locales.
Before translating, it’s recommended to run eloqnt review and fix mistakes in your source strings so they don’t spread out.
By default, a run translates every string that doesn’t have a translation yet. To retranslate a given string, you can use the --id and --locale flags.
How it works
Each invocation passes through five steps:
Context enrichment
Your messages hold a set of strings, but they typically lack context on how they’re used:
messages/en.json
{"XPruqs": "Order",...}
Without additional information, it’s hard to tell:
- Where this string is used
- What kind of UI component it’s used for
- Whether "Order" is a noun or a verb
- How "Order" is translated elsewhere in your app
- Which voice and tone to use
If you have srcPath configured, the CLI will analyze your code and extract a simplified source outline that keeps the relevant parts around each string:
src/app/orders/[orderId]/page.tsx
⋮│ export default function OrderDetailPage({params}: Props) {│ const t = useExtracted();│ return (│ <main>█ <h1>{t('Order')}</h1>⋮
This provides clear answers to the first three questions raised above:
- It’s used on the order detail page
- It’s the heading of that page
- "Order" is the noun
Styleguides
Next, all applicable styleguides are attached to the request:
- Your global styleguide, defining the voice and terminology of your project
- The styleguide of your target locale, holding tone and a glossary specific to the language
.eloqnt/styleguide.md
# Styleguide## Voice and tone- Friendly and concise.- Address the user as "you", and prefer active voice....
.eloqnt/styleguide.es.md
# `es` styleguide## Tone- Use informal "tú", never formal "usted".## Glossary- "order" (a purchase): "pedido"...
With this, we can answer the remaining questions from above:
- "Pedido" is the expected translation
- Informal tone should be used
Translation
With all context now available, the following is passed to an LLM:
- Your source strings
- Source outlines
- Styleguides
- CLDR data for target locales
- General translation best practices
Depending on your plan, the actual translation work either happens on our hosted backend or is delegated to your own model.
Post-checks
Once the LLM returns, every translation has to pass various quality checks, like:
- Are there syntactical errors?
- Do arguments like
{name}match the source? - Are the right plural cases defined?
If a translation doesn’t meet the bar yet, then it’s fixed:
- Minor mechanical slips are repaired directly (e.g. removal of superfluous plural cases)
- If the issue requires more work, then the translation step is retried with the findings attached, and with increased reasoning effort
Persistence
Finally, the translations are written to the messages of your target locales:
messages/es.json
{+ "XPruqs": "Pedido",...}
Good to know
Usage with coding agents
If a coding agent should translate your source strings, then let it run eloqnt translate instead of attempting to translate on its own. Agents will attempt to translate from insufficient context, will introduce inconsistencies and will skip over important quality checks.
An instruction like this is typically enough:
AGENTS.md
## UI text- Write UI text in the source locale only, never edit other locales by hand.- After adding or changing UI text, run `npx eloqnt review` and then `npx eloqnt translate`.
Alternatively, you can systematically translate in a CI job (see GitHub Actions).
Values that aren’t text
Booleans and numbers in a messages file aren’t translatable, so they’re never sent for translation.
A target locale keeps its own value if it has one. If it doesn’t, the value is copied over from the source locale as-is.
Flags
| --id | string | (Re-)translate these message ids (comma-separated) |
| --locale | string | Restrict to these target locales (comma-separated) |
| --config | string | Path to the eloqnt config file (defaults to .eloqnt/config.{ts,mts,js,mjs}) |
| --json | boolean | Output the result as JSON |