Flutter ARB Translation

Translate Flutter .arb localisation files using the flutter_localizations l10n format.

What is an ARB file?

ARB (Application Resource Bundle) is the format used by Flutter's official flutter_localizations package and the intl package. Each file is a JSON object containing translatable strings, a @@locale key identifying the language, and optional @key metadata blocks that hold descriptions and placeholder definitions used by the Flutter code generator.

Folder structure

Set arbPath in your config. PolyCLI expects a single source file named <arbPrefix>_<sourceLanguage>.arb inside that folder. Target files are created automatically.

text
lib/l10n/                           ← arbPath
├── app_en.arb                      ← source (you create this)
├── app_it.arb                      ← created by PolyCLI
├── app_es.arb                      ← created by PolyCLI
└── .polycli-arb-lock.json          ← commit this file

Configuration

buildtranslator.json
{
  "sourceLanguage": "en",
  "targetLanguages": ["it", "es", "fr"],
  "localesPath": "./locales",
  "arbPath": "./lib/l10n",
  "arbPrefix": "app",
  "translateArbDescriptions": false
}

arbPath — folder containing the .arb files.

arbPrefix — filename prefix; defaults to app. Produces app_en.arb, app_it.arb, etc.

translateArbDescriptions — when true, the description field inside @key blocks is also translated (uses additional credits).

What is translated vs. preserved

✓ Preserved exactly

  • @@locale — auto-updated to target language code
  • @key.type, @key.placeholders
  • All other metadata fields
  • Flutter placeholder syntax — {name}
  • @key.description when translateArbDescriptions is false

✎ Translated

  • All string values (non-@ keys)
  • @key.description when translateArbDescriptions: true

Before and after

lib/l10n/app_en.arb (source)
{
  "@@locale": "en",
  "appTitle": "My App",
  "@appTitle": {
    "description": "The application title shown in the app bar"
  },
  "welcomeMessage": "Welcome, {name}!",
  "@welcomeMessage": {
    "description": "Greeting shown on the home screen",
    "placeholders": {
      "name": { "type": "String" }
    }
  },
  "itemCount": "{count, plural, one{1 item} other{{count} items}}",
  "@itemCount": {
    "description": "Number of items in the list",
    "placeholders": {
      "count": { "type": "num", "format": "compact" }
    }
  }
}
lib/l10n/app_it.arb (output)
{
  "@@locale": "it",
  "appTitle": "La Mia App",
  "@appTitle": {
    "description": "The application title shown in the app bar"
  },
  "welcomeMessage": "Benvenuto, {name}!",
  "@welcomeMessage": {
    "description": "Greeting shown on the home screen",
    "placeholders": {
      "name": { "type": "String" }
    }
  },
  "itemCount": "{count, plural, one{1 elemento} other{{count} elementi}}",
  "@itemCount": {
    "description": "Number of items in the list",
    "placeholders": {
      "count": { "type": "num", "format": "compact" }
    }
  }
}

Placeholder tokens ({name}, {count}) and ICU plural syntax are preserved verbatim. Metadata fields other than description are copied unchanged.

Lock file

PolyCLI stores a snapshot of the last translated source strings in .polycli-arb-lock.json inside your arbPath. The snapshot contains only the translatable string values — no metadata. On each run, PolyCLI compares the current source against the snapshot to identify new or changed keys and translate only those.

By default, description fields inside @key blocks are not translated. Descriptions are developer notes consumed by the Flutter code generator — they are never shown to end users. Set translateArbDescriptions: true only if your descriptions contain user-facing content. This will use additional credits.
Commit .polycli-arb-lock.json to version control. Without it, every run re-translates all strings from scratch and credits are charged accordingly.