Skip to content
Blog

ARB Files for Translations in Flutter: The Complete Guide

Learn how ARB (Application Resource Bundle) files work in Flutter localization. Master message formatting, placeholders, plurals, and code generation.

Published on • September 19, 2026

AI Assistant

ARB Files for Translations in Flutter: The Complete Guide

ARB (Application Resource Bundle) files are the standard format for defining translatable strings in Flutter. They’re JSON-based, human-readable, and integrate directly with Flutter’s code generation tooling to produce type-safe localization classes.

What is an ARB File?

ARB files are JSON files with a specific structure that defines translatable messages, their descriptions, and metadata. Flutter’s code generator reads these files and produces Dart classes with strongly-typed accessor methods for each message.

Basic ARB Structure

{
  "@@locale": "en",
  "appTitle": "My Application",
  "@appTitle": {
    "description": "The title displayed in the app bar",
    "placeholders": {}
  },
  "greeting": "Hello, {name}!",
  "@greeting": {
    "description": "A greeting message with a user's name",
    "placeholders": {
      "name": {
        "type": "String",
        "example": "World",
        "description": "The user's display name"
      }
    }
  }
}

ARB File Naming Convention

Flutter expects ARB files to follow this pattern:

lib/l10n/
  app_en.arb      # English (template)
  app_es.arb      # Spanish
  app_fr.arb      # French
  app_ja.arb      # Japanese
  app_ar.arb      # Arabic

The app_ prefix is configurable in l10n.yaml, and the locale code must match the supported locale in your app.

Message Types and Formatting

Simple Strings

{
  "loginButton": "Log In",
  "logoutButton": "Log Out",
  "settingsTitle": "Settings"
}

Placeholder-Based Messages

{
  "welcomeUser": "Welcome back, {username}!",
  "@welcomeUser": {
    "description": "Greeting shown when user logs in",
    "placeholders": {
      "username": {
        "type": "String",
        "example": "john_doe"
      }
    }
  }
}

Pluralization

{
  "unreadCount": "{count, plural, =0{No unread messages} =1{1 unread message} other{{count} unread messages}}",
  "@unreadCount": {
    "description": "Number of unread messages",
    "placeholders": {
      "count": {
        "type": "int",
        "example": "5"
      }
    }
  }
}

Gender Select

{
  "userGreeting": "{gender, select, male{Hello, sir!} female{Hello, ma'am!} other{Hello there!}}",
  "@userGreeting": {
    "description": "Gender-aware greeting",
    "placeholders": {
      "gender": {
        "type": "String",
        "example": "male"
      }
    }
  }
}

Number Formatting

{
  "priceMessage": "Total: {amount, number, currency}",
  "@priceMessage": {
    "description": "Displays a formatted price",
    "placeholders": {
      "amount": {
        "type": "double",
        "example": "1234.56"
      }
    }
  }
}

Configuring l10n.yaml

The l10n.yaml file controls how Flutter generates localization code:

arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
output-class: AppLocalizations
preferred-supported-locales: ["en"]
nullable-localization: false
synthetic-package: false
output-dir: lib/generated/l10n

Key Configuration Options

OptionDescriptionDefault
arb-dirDirectory containing ARB fileslib/l10n
template-arb-fileThe template ARB fileapp_en.arb
output-localization-fileGenerated Dart file nameapp_localizations.dart
output-className of the generated classAppLocalizations
nullable-localizationWhether of() can return nulltrue

Using Generated Code

After running code generation, you get type-safe access to all messages:

import 'package:flutter_gen/gen_l10n/app_localizations.dart';

class MyWidget extends StatelessWidget {
  const MyWidget({super.key});

  @override
  Widget build(BuildContext context) {
    final l10n = AppLocalizations.of(context)!;

    return Column(
      children: [
        Text(l10n.appTitle),
        Text(l10n.welcomeUser('john_doe')),
        Text(l10n.unreadCount(5)),
        Text(l10n.userGreeting('male')),
        Text(l10n.priceMessage(1234.56)),
      ],
    );
  }
}

Running Code Generation

# Generate localization code
flutter gen-l10n

# Or run pub get (automatically triggers generation)
flutter pub get

Testing ARB Files

Verify Completeness

Ensure all locales have all keys from the template:

// In a test file
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

void main() {
  test('all locales have all keys', () {
    for (final locale in AppLocalizations.supportedLocales) {
      // Verify no missing translations
      expect(() => AppLocalizations.delegate.load(locale),
          isA<Future<AppLocalizations>>());
    }
  });
}

Best Practices

  1. Always create a template ARB file — it’s the source of truth for all translations
  2. Provide descriptions — translators need context to translate accurately
  3. Use placeholders with examples — helps translators understand format expectations
  4. Keep ARB files versioned — they’re part of your source code
  5. Run flutter gen-l10n after changes — keeps generated code in sync

ARB files are the backbone of Flutter’s localization system. By mastering their structure and capabilities, you can create maintainable, type-safe, and fully localized applications.