Skip to content

mariokreitz/verbatra

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

542 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

verbatra: automated i18n translation for modern applications

verbatra

Automate i18n translation and keep your locale files in sync across languages with AI and machine-translation providers.

@verbatra/cli npm version @verbatra/sdk npm version CI Coverage Monthly npm downloads License: MIT

Description

verbatra translates your application's locale files for you. You maintain the source locale by hand, and as strings are added or change, verbatra fills in every target locale through the AI or machine-translation provider you choose. It records what it has already translated, so each run touches only what actually changed.

It ships in two packages. @verbatra/cli gives you a verbatra command for the terminal and CI, and @verbatra/sdk is the same engine as a programmatic API. verbatra is built SDK-first: the CLI is a thin wrapper over the SDK, so anything the command line does, you can also do in code.

Features

  • Many locale formats. JSON for i18next, vue-i18n, next-intl, and ngx-translate, plus XLIFF, YAML, and ARB.
  • Five providers behind one interface: Anthropic, OpenAI, Gemini, and openai-compatible (a local or self-hosted server such as LM Studio, Ollama, or vLLM) as LLMs, plus DeepL (machine translation).
  • Incremental by default. A lock file records what has been translated, so each run sends only new or changed strings to the provider.
  • Project scaffolding. verbatra init writes a config and a .env.example for your project.
  • Dry runs. --dry-run previews what would change without calling a provider or writing files.
  • Read-only status and diff. verbatra check reports per-locale missing, stale, and up-to-date counts, and verbatra diff lists the exact keys that would be added, re-translated, or are orphaned. Both write nothing and exit non-zero when locales are out of sync, so they slot into CI.
  • Watch mode. verbatra watch re-translates automatically on every source change.
  • Manual translation. verbatra export writes the strings that need translating to a styled Excel workbook for a human translator, and verbatra import reads the filled file back with the same safety checks as an automated run.
  • Placeholder integrity. Every translation is checked after the fact; a result that drops or alters a placeholder is withheld and reported rather than written.
  • Lossless key round-trip. Literal dotted leaf keys (such as "foo.bar" used as a single leaf) and real nested paths each keep their on-disk shape. A genuine collision, where one file expresses the same effective path both as a literal dotted leaf and as a real nested path, errors with INVALID_STRUCTURE rather than guessing or corrupting data. See the Formats page for the full behavior.
  • Opt-in cleanup and plural generation. Orphan pruning (--prune / prune) and CLDR plural-category generation (generatePlurals) are off by default and documented on the Configuration page.
  • Keys stay in your environment. API keys are read only from environment variables, never from the config.

Requirements

Node.js >=22.14.0.

Installation

verbatra is a development dependency:

pnpm add -D @verbatra/cli
# npm
npm install -D @verbatra/cli
# yarn
yarn add -D @verbatra/cli

Quick start

# 1. Install as a dev dependency
pnpm add -D @verbatra/cli

# 2. Scaffold verbatra.config.ts and .env.example (choose your provider)
verbatra init --provider anthropic

# 3. Provide the provider's API key. init created .env.example and gitignored
#    .env, so you can set it in .env, or export it (Anthropic shown):
export ANTHROPIC_API_KEY=your-key-here

# 4. Translate every target locale once
verbatra translate

Invoke the binary through your package manager: pnpm verbatra ..., npx verbatra ..., or yarn verbatra ....

Configuration

verbatra looks for its configuration upward from the working directory: a verbatra.config.ts, a .verbatrarc.json (and the other .verbatrarc.* variants), or a "verbatra" key in package.json. The quickest way to get a valid one is verbatra init. A minimal verbatra.config.ts:

import { defineConfig } from "@verbatra/sdk";

export default defineConfig({
  sourceLocale: "en",
  targetLocales: ["de", "fr"],
  format: "i18next-json",
  files: {
    pattern: "locales/{locale}.json",
  },
  provider: {
    id: "anthropic",
    options: {
      model: "claude-sonnet-4-6", // replace with your provider's model id
      maxTokens: 4096,
    },
  },
});

files.pattern must contain the {locale} token, and targetLocales must not include sourceLocale. The supported format values are i18next-json, vue-i18n-json, next-intl-json, ngx-translate-json, xliff, yaml, and arb. The optional glossary (a term map) and tone ("formal", "informal", or "neutral") refine the output.

The provider block is selected by id. The LLM providers take a model and a token limit; DeepL needs no model:

// OpenAI / Gemini
provider: { id: "openai", options: { model: "gpt-5.4-mini", maxOutputTokens: 4096 } }

// DeepL (machine translation)
provider: { id: "deepl", options: {} }

Each provider reads its API key from one environment variable:

Provider id Environment variable
anthropic ANTHROPIC_API_KEY
openai OPENAI_API_KEY
gemini GEMINI_API_KEY
deepl DEEPL_API_KEY

openai-compatible is not in this table: most local servers need no key at all, and when one is required you name your own environment variable for it. See the Providers page for its key resolution.

Commands

Command What it does Common flags
verbatra init Create a verbatra config and .env example for this project --provider <id>, --source, --targets, --path, --yes, --force
verbatra translate Translate every target locale once, then exit --cwd, --config, --dry-run, --prune, --json
verbatra watch Re-translate on every source change until interrupted --cwd, --config, --debounce <ms>, --json
verbatra check Report per-locale missing, stale, and up-to-date counts without writing (read-only) --cwd, --config, --locales, --json
verbatra diff List the keys per locale that would be added, re-translated, or are orphaned, without writing (read-only) --cwd, --config, --locales, --json
verbatra export Export untranslated strings into a styled Excel workbook for a human translator --out, --locales, --include-unchanged, --cwd, --config, --json
verbatra import <workbook> Import a filled workbook back into the locale files, with the same safety checks --dry-run, --cwd, --config, --json

Run verbatra <command> --help for the full option list. The complete command reference - every flag, examples, and the exit-code contract - lives on the documentation site.

Verbatra Studio

verbatra studio starts Verbatra Studio, a local, read-only web dashboard over your project: translation status, the diff explorer, your resolved config and glossary, lock-file drift, and locale-file history, all read from the same computations as check and diff. It binds to 127.0.0.1 only, gates every request behind a per-session token, and never calls a provider or writes a file.

verbatra studio

Verbatra Studio is currently available only as a prerelease. @verbatra/cli needs the next tag explicitly; @verbatra/studio has not had a stable release yet, so its own latest tag already carries the current prerelease build:

pnpm add -D @verbatra/cli@next @verbatra/studio

A plain pnpm add -D @verbatra/cli (no tag) resolves to the current stable release, which does not include the studio command.

See the Verbatra Studio docs for the full command reference and security model.

Programmatic use

Everything the CLI does is available from @verbatra/sdk:

import { loadConfig, translate } from "@verbatra/sdk";

// Discovers and validates verbatra.config.ts (or .verbatrarc.json, or a package.json "verbatra" key).
const config = await loadConfig();

// The provider reads its API key from the environment (e.g. ANTHROPIC_API_KEY). No key is passed.
const summary = await translate({ config });

console.log(`${summary.succeeded.length} locale(s) translated, ${summary.failed.length} failed`);

The manual-translation workflow is available too, with exportWorkbook and importWorkbook:

import { exportWorkbook, importWorkbook, loadConfig } from "@verbatra/sdk";

const config = await loadConfig();

// Export the strings that need translating to an Excel workbook.
const { path } = await exportWorkbook({ config });

// ...a human fills the Translation column, then import the file back.
const summary = await importWorkbook({ config, workbook: path });

See the @verbatra/sdk README for the full API.

Packages

Package Description
@verbatra/cli The verbatra command-line tool.
@verbatra/sdk The programmatic API.

Security

API keys are read only from environment variables, never from the config file. The config schema rejects unknown keys, so a key cannot hide there by accident, and verbatra init adds .env and .env.local to your .gitignore. To report a vulnerability, see SECURITY.md.

Documentation

The hosted documentation site at verbatra.kreitz-webdev.de is the canonical reference, including the full CLI command reference. The @verbatra/sdk README documents the programmatic API. At the terminal, verbatra <command> --help prints the same command reference.

Contributing

Contributions are welcome. Please read CONTRIBUTING.md and our Code of Conduct first.

License

MIT (c) Mario Kreitz

About

CLI and SDK to automate i18n translation across i18next, vue-i18n, next-intl, ngx-translate, XLIFF, YAML, and Flutter ARB, using OpenAI, Anthropic, Gemini, and DeepL.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Contributors