# What Is an ARB File? Flutter''s Localization Format

> ARB is the JSON-based translation format Flutter uses for app localization. How the format works (keys, placeholders and @ metadata) and how to edit it.

Source: https://stringlane.app/docs/what-is-an-arb-file
Last updated: 2026-08-19

ARB stands for **Application Resource Bundle**. It is a JSON-based file format for storing localized strings, and it is the format Flutter's `flutter_localizations` and `gen-l10n` toolchain reads when you translate an app. One ARB file holds all the strings for a single locale: `app_en.arb` for English, `app_es.arb` for Spanish, and so on.

## What an ARB file looks like

An ARB file is plain JSON. Each translation is a key/value pair, and Flutter generates a typed Dart getter for every key:

```json
{
  "@@locale": "en",
  "helloWorld": "Hello, World!",
  "greeting": "Hello, {name}!",
  "@greeting": {
    "description": "Greeting shown on the home screen",
    "placeholders": {
      "name": { "type": "String" }
    }
  }
}
```

Three things are happening here:

- **`@@locale`**: a reserved key that declares which language this file holds.
- **Translation keys**: `helloWorld` and `greeting` are the strings your app renders.
- **`@` metadata**: `@greeting` is an annotation object describing the `greeting` key. It carries a `description` (context for translators and AI) and `placeholders` (the typed variables in the string).

## Placeholders and ICU

ARB values can contain placeholders like `{name}` and full [ICU MessageFormat](/docs/icu-messageformat-explained) plurals and select forms:

```json
"itemCount": "{count, plural, one {# item} other {# items}}"
```

The `placeholders` block in the `@` annotation tells Flutter the type of each variable so it generates a correctly-typed Dart method. If a placeholder appears in your English source but goes missing in a translation, the generated code breaks at runtime, which is exactly the kind of error a [side-by-side editor catches before it ships](/docs/fix-placeholder-mismatches).

## Why ARB is awkward to edit by hand

The format is simple, but managing it across many locales is not. Each language is a separate file, so confirming that every locale has every key means opening five, ten, or twenty JSON files and reading them in parallel. A missing key, a stray comma, or a placeholder typo is easy to introduce and hard to spot.

## How StringLane works with ARB

StringLane is a desktop editor built for exactly this. It opens your `lib/l10n/` folder, loads every `app_*.arb` file, and shows all locales side-by-side for each key, so gaps and mismatches are visible at a glance instead of buried in JSON. It reads and preserves your [`@` metadata](/docs/arb-metadata-fields), validates ICU and placeholders in real time, and writes changes straight back to the source files. Nothing is imported or exported.

## Next steps

- **[ARB editor](/arb-editor)**: what StringLane validates in a Flutter project, and how it sits alongside `gen_l10n`.
- **[Localize Your Flutter App End to End](/docs/localize-flutter-app)**: the full ARB workflow, from setup to `flutter gen-l10n`.
- **[How to Work with ARB Metadata Annotations](/docs/arb-metadata-fields)**: what `@description`, `x-max-length`, and `x-guarded` do.
- **[Getting Started with StringLane](/docs/getting-started)**: install and make your first edit.

## Frequently asked questions

### Can I edit an ARB file by hand?

Yes — it is plain JSON, so any text editor works. The friction is that one locale per file means comparing translations requires opening every file side by side, and a trailing comma or an unescaped brace breaks the build with an error that points at JSON, not at the string you got wrong.

### What is the difference between ARB and JSON?

ARB is JSON with conventions layered on top. Keys starting with @@ are file-level attributes such as @@locale; a key starting with a single @ is metadata describing the translation key of the same name. Any ARB file is valid JSON, but not every JSON file is valid ARB.

### Do I need @ metadata for every key?

No. Metadata is optional and StringLane works without it. It earns its place on keys with placeholders — declaring a placeholder's type is what lets gen-l10n generate a correctly typed Dart parameter instead of a String — and on keys where a description meaningfully improves translation quality.

### What file name does Flutter expect?

By default gen-l10n looks for app_<locale>.arb in lib/l10n — app_en.arb, app_pt_BR.arb. Both the directory and the prefix are configurable in l10n.yaml via arb-dir and template-arb-file.
