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.
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 fileConfiguration
{
"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.descriptionwhentranslateArbDescriptionsisfalse
✎ Translated
- All string values (non-
@keys) @key.descriptionwhentranslateArbDescriptions: true
Before and after
{
"@@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" }
}
}
}{
"@@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.
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..polycli-arb-lock.json to version control. Without it, every run re-translates all strings from scratch and credits are charged accordingly.