Skip to content
Skip to Content

Docs / Guides

Add a language

Add a new target locale to an existing verbatra project with a one-line config change and one translate run, while your existing locales stay untouched.

Use this when a project already translates into some languages and you want one more. It takes a one-line config change and one run. verbatra sees the new locale as missing every key and fills it; your existing locales cost nothing, because the lock file still has them on record as current.

You need a working project: a config, a source locale file, and a provider key. If you do not have one yet, start with the quickstart.

Add the locale to your config

Add the code to targetLocales in verbatra.config.ts:

verbatra.config.ts
import { defineConfig } from "@verbatra/cli";

export default defineConfig({
  sourceLocale: "en",
  targetLocales: ["de", "fr"], 
  format: "i18next-json",
  files: { pattern: "locales/{locale}.json" },
  provider: { id: "gemini", options: { model: "gemini-2.5-flash", maxOutputTokens: 4096 } },
});

Locale code rules

Write the code in BCP 47 form, with a hyphen: pt-BR, not pt_BR. If your files use underscores, keep writing pt-BR and set files.localeStyle to posix; verbatra keeps the pt_BR.json file name. The config load rejects an invalid code, the source locale, and two codes that differ only in case. See Locale codes for the full rules, and run verbatra doctor to see whether a provider supports the new language.

Preview the work

See what a run would do before you spend anything:

verbatra diff --locales fr

The new locale has no file yet, so every source key is listed as missing. Leave out --locales to confirm your other locales list nothing. diff calls no provider and writes nothing. For a cost figure, run verbatra translate --estimate; see Estimate cost before a run.

Translate

verbatra translate

The run translates every source key into the new locale and writes the file at your files.pattern, here locales/fr.json. Only the new locale triggers provider calls: the other locales have no missing or changed keys against their lock baseline, so nothing is sent for them.

If the run keeps nothing for the new locale, because every key failed a check, its provider requests failed, or a token budget withheld them, no file is created. The keys stay missing and the next run retries them.

Afterwards, verbatra check exits 0 when every locale, the new one included, is in sync.

Languages with more plural categories

Some languages need more plural forms than your source has. English has one and other; Polish needs four, Arabic six, and French adds many. By default verbatra translates the forms your source has and does not invent the others: the run succeeds and reports a PLURAL_CATEGORIES_INCOMPLETE notice naming what is missing.

Generate the missing forms

If you use i18next JSON with an LLM provider, you can let verbatra write the missing forms:

verbatra.config.ts
export default defineConfig({
  // ...
  generatePlurals: true,
});

Generated forms pass the same integrity checks as any translation.

Forms from CLDR

Which forms a language needs comes from the CLDR plural rules built into Node.js, for every language, ordinals included. The ICU formats (next-intl and ARB) keep a whole plural in one value, so they need no generation: the provider is asked for exactly the arms the target language uses. See generatePlurals for what falls back to the notice, and Plurals for how verbatra decides which forms a language needs.

Keep maintaining the source only

You edit only the source locale from now on. Add a string there and run translate again: verbatra fills it into every target, including the one you just added.

Edit on GitHub

On this page