Documentation

Keep every locale file in step with your source.

verbatra translates your i18n locale files incrementally: it sends only the new and changed strings to the provider you configure, checks every result, and writes the files back in place.

pnpm add -D @verbatra/cli
~/acme-shop

An example verbatra command-line session.

  1. verbatra init
    • ✓ created verbatra.config.ts
    • source en · targets de, es, fr
    • provider gemini · key from GEMINI_API_KEY
  2. verbatra translate
    • diff en.json · 12 new · 0 changed · 108 unchanged
    • de 12 translated · 108 unchanged · 0 withheld
    • es 12 translated · 108 unchanged · 0 withheld
    • fr 12 translated · 108 unchanged · 0 withheld
    • ✓ 36 keys translated in 5.4s · 0 skipped · lock updated
  3. verbatra diff
    • en.json · 120 keys · source of truth
    • de 2 new · 1 changed · 117 up to date
    • es 0 new · 0 changed · 120 up to date
    • fr 5 new · 0 changed · 115 up to date
    • 8 keys would be sent · run verbatra translate to apply
  4. verbatra watch
    • watching en.json for changes
    • en.json changed · 1 new key
    • de 1 translated · 0 withheld
    • ✓ 3 keys translated · waiting for changes

The problem

You hand-maintain one source locale. Every other locale file drifts as that source evolves: new keys are missing from the targets, edited source strings leave stale translations behind, and deleted keys linger as orphans. Catching up by hand does not scale, and retranslating everything on every change is slow, costs provider tokens for strings that were already fine, and churns text your team has reviewed.

How verbatra solves it

A committed lock file, verbatra.lock.json, records for every translated key the hash of the source string its translation came from. Each run reads the source locale, diffs every target against it and against that baseline, and sends only the missing and changed keys to the provider. Keys that are still current are left alone: run translate twice in a row and the second run makes no provider call at all.

Every string the provider returns is checked before it is written: placeholder integrity and ICU integrity are enforced, and a translation that breaks either is withheld instead of shipped, then retried on the next run. The read-only check and diff commands report drift without writing anything, so CI can gate on their exit codes.

verbatra reads and writes eight formats (i18next, vue-i18n, next-intl, and ngx-translate JSON, XLIFF, YAML, Flutter ARB, and Java/Spring properties) and translates through five providers (Anthropic, OpenAI, Gemini, DeepL, and any OpenAI-compatible server, including local ones) behind one interface. See Formats and Providers.

The packages

verbatra ships as three npm packages:

  • @verbatra/cli provides the verbatra binary with eight commands: init, translate, watch, check, diff, export, import, and studio. It is a thin wrapper over the SDK, so everything it does is available programmatically too. Start here.
  • @verbatra/sdk is the engine underneath: one-shot translate(), long-running watch(), read-only check() and diff(), the Excel workbook round-trip for human translators, and config loading. Use it directly from scripts, build tools, or CI. See the SDK.
  • @verbatra/studio is Verbatra Studio, a local dashboard over your project with built-in editing and a review queue. The CLI starts it with verbatra studio; provider spend from Studio stays off unless you pass --allow-spend. See Review in Studio.

Where to go next