Skip to content

Docs / Get started / Quickstart

Flutter quickstart

Translate the ARB locale files of your Flutter app with verbatra, from install to the first German string on screen.

By the end of this page your Flutter app shows a German string that verbatra translated from lib/l10n/app_en.arb, and a lock file makes every later run translate only what changed. You need Node.js ^22.18.0 || >=24, a Flutter project, and about ten minutes. The first four steps need no account and no API key.

Already have locale files and a coding agent? Hand it the prompt on Set up with an AI agent instead: it works around the files your project has and stops before it spends anything.

Steps

Install the CLI

npm install --save-dev @verbatra/cli

verbatra is a development tool and never ships in your app. The commands below use npx; with pnpm, yarn, or bun, run pnpm verbatra, yarn verbatra, or bun run verbatra instead.

A Flutter app has no package.json

Your package manager creates one on the first install. Add node_modules/ to your .gitignore.

Add a source locale file

Skip this step if lib/l10n/app_en.arb already exists. Otherwise create it with two strings, one of them with a placeholder:

lib/l10n/app_en.arb
{
  "@@locale": "en",
  "greeting": "Hello, {name}!",
  "@greeting": {
    "placeholders": { "name": { "type": "String" } }
  },
  "cartEmpty": "Your cart is empty."
}

Scaffold a config

npx @verbatra/cli init --format arb --provider gemini --yes

--format arb is the file format of flutter_localizations. init finds your locale files, or writes the pattern lib/l10n/app_{locale}.arb when there are none yet. --yes takes what init detected instead of prompting. The new verbatra.config.ts translates from en into de; add codes to targetLocales for more languages.

Preview the run without a key

npx @verbatra/cli translate --dry-run
Output
verbatra: dry run over 1 locale, no provider call
verbatra: de done, 2 would translate
verbatra translate (dry run)
  de: 2 would translate, 0 unchanged
1 succeeded, 0 partial, 0 failed (dry run: nothing written)
[ok] dry run done in 0.0s, nothing written
next: verbatra translate (run it for real)

A dry run builds no provider, so it needs no key, spends nothing, and writes nothing.

Translate

cp .env.example .env

Open .env and paste your key after GEMINI_API_KEY=. No key yet? Gemini has a free tier: create one in Google AI Studio. Every other provider and its variable is on Providers.

npx @verbatra/cli translate

verbatra sends the two strings to Gemini, checks that every placeholder survived, and writes lib/l10n/app_de.arb. The wording depends on the model, for example:

lib/l10n/app_de.arb
{
  "@@locale": "de",
  "greeting": "Hallo, {name}!",
  "cartEmpty": "Dein Warenkorb ist leer."
}

Check that every locale is in sync

npx @verbatra/cli check
Output
[ok] checking the locales (0.0s)
verbatra check
  de: 0 missing, 0 stale, 2 up-to-date (in sync)
all locales in sync

check calls no provider and exits 1 once a locale falls out of sync, so it can gate a pull request.

Load the locales in your app

Add flutter_localizations:

flutter pub add flutter_localizations:"{sdk: flutter}" intl:any

Then load both files and render the greeting:

pubspec.yaml
flutter:
  generate: true
l10n.yaml
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
lib/main.dart
import 'package:flutter/material.dart';
import 'l10n/app_localizations.dart';

void main() => runApp(
  MaterialApp(
    locale: const Locale('de'),
    localizationsDelegates: AppLocalizations.localizationsDelegates,
    supportedLocales: AppLocalizations.supportedLocales,
    home: Builder(
      builder: (context) => Text(AppLocalizations.of(context)!.greeting('Ada')),
    ),
  ),
);

Start your app: the greeting reads Hallo, Ada!.

What just happened

  • verbatra.lock.json records a hash of each source string, so the next run sends only new and changed strings. See The lock file.
  • A result that drops a placeholder is withheld, never written. See Translation safety.

Commit the locale files, verbatra.lock.json, and verbatra.provenance.json together.

Optional: connect your coding agent Available from 0.12.0

npx @verbatra/cli init --agent

With the config in place, init --agent keeps it and adds only the agent files: the verbatra rules in AGENTS.md (or CLAUDE.md, when that is your only instruction file) and the verbatra MCP server, with spending off, in the project config of each coding agent it detects. Which files it writes for which agent, and --client to name the agents yourself, are in Set up coding agents. --dry-run shows the files without writing them.

Or, without the CLI, add only the MCP server to your VS Code user profile; use one route, never both:

Add to VS Code

Next

Edit on GitHub

On this page