Skip to main content

Agent Guide: Using champollion

champollion is a CLI tool that translates your app's locale files with one command. This guide is for AI agents (or developers working with AI agents) who want to go from zero to translated locale files quickly.

:::tip Already familiar? If you just need commands, jump to the CLI Reference. If you want to build and benchmark a translation method, see the Arena Agent Guide. :::


Environment Setup

# No global install needed — npx runs it directly
npx champollion sync

Requirements:

  • Node.js 18+
  • An API key for your translation provider

API key setup — champollion needs at least one key depending on which methods you use:

# Option 1: export (session only)
export OPENROUTER_API_KEY="sk-or-..." # for llm / llm-coached methods
export GOOGLE_TRANSLATE_API_KEY="AIza..." # for google-translate method

# Option 2: .env file in your project root (persistent, gitignored)
echo 'OPENROUTER_API_KEY=sk-or-...' > .env

Champollion reads .env automatically. Get an OpenRouter key at openrouter.ai/keys.


First Sync

Champollion auto-detects your locale files, their format (JSON, TOML, YAML, PO), and your target languages:

npx champollion sync

What happens:

  1. Loads champollion.config.json (or auto-detects settings)
  2. Scans your source locale file, flattens nested keys
  3. Compares against .champollion.lock (SHA-256 hashes of previously translated values)
  4. Checks .champollion/tm.json for cached translations (Translation Memory)
  5. Translates only changed, missing, or stale keys via the configured method
  6. Runs the quality gate (5 checks) on every translation
  7. Writes passing translations to the target locale file
  8. Updates the lock file and TM cache

On a typical re-run after changing one key, step 4 serves 142 keys from cache and step 5 translates 1 key. This is why subsequent syncs are fast and cheap.


Configuration

Create champollion.config.json in your project root:

{
"inputLocale": "en",
"pairs": {
"en-fr": { "method": "llm-coached" },
"en-ja": { "method": "google-translate" },
"en-crk": { "method": "api", "endpoint": "http://localhost:3000/translate" }
}
}

Key fields:

FieldPurposeDefault
inputLocaleSource languageen
pairsMap of source→target with method config(required)
localesDirWhere locale files live(auto-detected)
modelLLM model for llm/llm-coached methodsgoogle/gemini-2.5-flash
batchSizeKeys per API call80 (LLM), 128 (Google)
jsonConcurrencyParallel locale translations for JSON keys200
contentConcurrencyParallel API calls for content translation48

Full reference: Configuration


Translation Methods

MethodWhen to useCostAPI key needed
llmGeneral-purpose, good for well-resourced languagesPer-token (model-dependent)OPENROUTER_API_KEY
llm-coachedWhen you have grammar rules/dictionary for the target languagePer-token + coaching contextOPENROUTER_API_KEY
google-translateHigh-resource languages where GT works well$20/million charsGOOGLE_TRANSLATE_API_KEY
apiCustom pipeline hosted behind an HTTP endpointServer-determinedNone (endpoint handles auth)
pluginPre-packaged method installed locallyVariesVaries

Details: Translation Methods


Coaching Data

For llm-coached pairs, coaching data steers the LLM with explicit linguistic knowledge. Create a coaching file:

coaching/fr.json
{
"grammar_rules": [
"Use formal register (vous) for all UI text",
"Adjectives agree in gender and number with the noun"
],
"dictionary": {
"dashboard": "tableau de bord",
"settings": "paramètres"
},
"style_notes": "Prefer active voice. Avoid anglicisms."
}

Reference it in your pair config:

"en-fr": { "method": "llm-coached", "coachingFile": "coaching/fr.json" }

The quality gate verifies that dictionary terms actually appear in the output — violations are logged as [TERM] warnings.

Details: Coaching Data


Quality Gate

Every translation passes through five automated checks before it's written to disk:

CheckWhat it catchesExample
Empty/blankModel returned nothing""
Source echoModel returned the English input unchanged"Welcome" for Japanese
Hallucination loopRepeated trigrams"Qo' Qo' Qo' Qo'"
Length inflationOutput is 4×+ longer than source10-char source → 50-char output
Script complianceWrong script for the localeLatin text for Arabic locale

Failures are logged with [GATE] prefix. No silent fallbacks — if a translation fails, it's reported, not quietly accepted.

Details: Quality Gate


Translation Memory

Champollion caches translations in .champollion/tm.json, keyed by source text + locale + method. On subsequent syncs, unchanged keys are served from cache — no API call, no cost.

[TM] 142 key(s) served from cache
Translating 3 key(s) to French (llm)... [OK]

To bypass the cache for one run: npx champollion sync --no-tm

Details: Translation Memory


Generated Files

Champollion creates several files in your project. Know what they are so you don't accidentally delete or commit the wrong ones:

FilePurposeGit?
.champollion.lockSHA-256 hashes of translated source values (change detection)Yes — commit this
.champollion-content.lockSame, but for Markdown/MDX content filesYes — commit this
.champollion/tm.jsonTranslation Memory cacheYes — commit this (saves API costs for the team)
.champollion/coaching/Coaching data directoryYes — this is your linguistic knowledge
champollion.config.jsonProject configurationYes — commit this

Common Patterns

Translate one language pair:

npx champollion sync --pair en-fr

Translate all configured pairs:

npx champollion sync

Champollion translates all locales in parallel. With TM caching, only changed keys hit the API.

Content mode (Markdown/MDX for Docusaurus, Hugo, etc.):

npx champollion sync --content

Translates docs, blog posts, and content files alongside locale JSON. Uses parallel concurrency (default: 48 simultaneous API calls). Tune with --content-concurrency.

Dry run (preview without writing):

npx champollion sync --dry-run

Force re-translate specific keys:

npx champollion sync --force-keys "hero.title,nav.about"

Force re-translate all content files:

npx champollion sync --force-content

Check translation status:

npx champollion status

Shows coverage, quality tiers, and plugin info for each pair.

Audit for untranslated fallbacks:

npx champollion audit

Lists all [EN] fallback values that need translation.


Troubleshooting

ProblemFix
OPENROUTER_API_KEY not setExport the key or add it to .env in your project root
No locale files foundSet localesDir in config, or ensure your locale files match standard naming (en.json, fr.json)
[GATE] Script compliance failedYour target locale got Latin text instead of the expected script — try a different model or add coaching data
[GATE] Source echoThe model returned English unchanged — coaching data or a different model usually fixes this
All translations cachedRun with --no-tm to bypass the cache, or --force-keys for specific keys
Lock file conflicts.champollion.lock uses SHA-256 hashes — merge conflicts are safe to resolve by keeping either version, then re-running sync

What's Next