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
| Option | Description | Default |
|---|---|---|
arb-dir | Directory containing ARB files | lib/l10n |
template-arb-file | The template ARB file | app_en.arb |
output-localization-file | Generated Dart file name | app_localizations.dart |
output-class | Name of the generated class | AppLocalizations |
nullable-localization | Whether of() can return null | true |
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
- Always create a template ARB file — it’s the source of truth for all translations
- Provide descriptions — translators need context to translate accurately
- Use placeholders with examples — helps translators understand format expectations
- Keep ARB files versioned — they’re part of your source code
- Run
flutter gen-l10nafter 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.