ARB

Flutter ARB files, from messages to metadata

ARB is Flutter’s official localization format: JSON plus conventions. Messages are ICU strings, every key can carry @key metadata holding a description and placeholder declarations, and gen-l10n compiles the files into Dart. One file set covers iOS, Android, web and desktop builds.

This page covers the metadata conventions, ICU plurals and their edge cases, and the l10n.yaml plumbing around the files.

lib/l10n/app_en.arb
{
  "@@locale": "en",
  "checkoutTitle": "Order summary",
  "@checkoutTitle": {
    "description": "Title of the checkout screen"
  },
  "cartItems": "{count, plural, one {{count} item} other {{count} items}}",
  "@cartItems": {
    "placeholders": { "count": {} }
  }
}
A message, its description metadata and an ICU plural with a placeholder.
Download a sample: app_de.arb

Cheatsheet

ARB syntax in five rows

You writeWhat it means
"@@locale": "de" Declares the file’s language; the app_de.arb filename works too.
"@cartItems": { "description": … } Metadata for the key of the same name. The description imports as the key’s note and returns on export.
"placeholders": { "count": {} } Declares the message’s variables. A plural that selects on an undeclared placeholder is left untouched rather than guessed at.
{count, plural, …} ICU plurals decompose into CLDR forms translators fill in separately, then reassemble on export.
select, offset:, =0 Messages using these should travel whole; splitting them into plural forms would drop meaning.

Untranslated keys, three spellings

Dropped keys let flutter gen-l10n fall back to the template language; empty strings render as empty in the app.

exported empty
"checkoutConfirm": ""
left out
(key and its @metadata not exported)
source fallback
"checkoutConfirm": "Confirm purchase"

Conventions

Where ARB files live

PurposePath
Template lib/l10n/app_en.arb
Translations lib/l10n/app_de.arb, one file per locale
Configuration l10n.yaml with arb-dir and template-arb-file

Typical flow: lib/l10n lives in the repo, GitHub or GitLab imports new messages on push, and translated ARB files come back as a pull request ready for flutter gen-l10n.

Beyond plurals: ICU select

ARB messages can branch on things other than numbers, like grammatical gender.

app_en.arb
"invited": "{gender, select,
  female {She is invited}
  male {He is invited}
  other {They are invited}}"

Select messages travel whole through a TMS: splitting them into forms would drop the branch conditions, so careful tools keep them as one message.

Plurals

Plurals in ARB

ARB plurals are ICU messages, and locamorph parses them into forms instead of passing the braces along as one opaque blob.

lib/l10n/app_fr.arb
"cartItems": "{count, plural, one {{count} article} other {{count} articles}}",
"@cartItems": {
  "placeholders": { "count": {} }
}
en · two forms
"cartItems": "{count, plural,
  one {{count} item}
  other {{count} items}}"
pl · four forms
"cartItems": "{count, plural,
  one {{count} artykuł} few {{count} artykuły}
  many {{count} artykułów} other {{count} artykułu}}"
ar · six forms
"cartItems": "{count, plural,
  zero {لا عناصر} one {عنصر واحد}
  two {عنصران} few {{count} عناصر}
  many {{count} عنصرًا} other {{count} عنصر}}"

The categories per language come from CLDR: Polish needs four branches, Arabic six, Japanese one.

See the same plural in every format locamorph exports.

In locamorph

How locamorph handles ARB

icu

Plurals read, not passed through

ICU plural messages are parsed into CLDR forms with one shared, strict reader. Each form is a separate field for translators, then reassembled on export.

metadata

Descriptions become notes

The @key description written for translators imports as the key’s note and returns to the file on export.

locale

Language from the file itself

@@locale and app_de.arb style filenames both identify the language, so bulk imports land in the right locales.

Convert

Convert ARB to and from other formats

Conversion is import plus export; descriptions and plurals map onto the shared model and back out.

ARB to JSON

Flutter strings shared with the web side of the product.

  1. Import app_*.arb; descriptions become notes.
  2. ICU plurals carry over as forms.
  3. Export as JSON for your JS i18n library.

strings.xml to ARB

An Android app migrating to Flutter.

  1. Import each values-* file into its locale.
  2. Comments become descriptions; plurals become ICU.
  3. Export ARB ready for gen-l10n.

ARB to XLIFF

Handing a Flutter app to a translation agency.

  1. Import the ARB files.
  2. Descriptions ride along as XLIFF notes.
  3. Export XLIFF 1.2 for any CAT tool.

Bring your app_en.arb

Import it on the free plan and see every ICU plural and description arrive as structured, translatable content instead of a wall of braces.