Flutter l10n.yaml Configuration: Every Option Explained
The l10n.yaml file controls how Flutter generates your localization code. While most tutorials show basic setups, understanding every option unlocks powerful customization for your workflow. This guide covers all configuration options with practical examples.
Basic l10n.yaml Setup
Here's the minimal configuration most projects start with:
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
This generates code in .dart_tool/flutter_gen/gen_l10n/. But there's much more you can configure.
Complete Configuration Reference
# === Required Settings ===
# Directory containing .arb files
arb-dir: lib/l10n
# The .arb file used as the template (source of truth)
template-arb-file: app_en.arb
# === Output Settings ===
# Name of the generated Dart file
output-localization-file: app_localizations.dart
# Name of the generated class
output-class: AppLocalizations
# Directory for generated files (if not using synthetic-package)
output-dir: lib/generated/l10n
# Generate as real package vs synthetic
synthetic-package: false
# === Behavior Settings ===
# Make all translations required (fail build on missing)
required-resource-attributes: false
# Make translations nullable when missing
nullable-getter: true
# Generate additional helper methods
use-deferred-loading: false
# === Advanced Settings ===
# Header added to generated files
header: |
/// Generated file. Do not edit.
/// Generated by flutter gen-l10n
# Add imports to generated file
preferred-supported-locales:
- en
- es
- de
# Untranslated messages file
untranslated-messages-file: lib/l10n/untranslated.txt
Configuration Options Deep Dive
arb-dir
Purpose: Specifies where your .arb files live.
# Standard location
arb-dir: lib/l10n
# Alternative: assets folder
arb-dir: assets/translations
# Nested structure
arb-dir: lib/src/localization/arb
Best practice: Use lib/l10n for consistency with Flutter conventions.
template-arb-file
Purpose: The source .arb file that defines all keys. Other locales are validated against this.
template-arb-file: app_en.arb
How it works:
- All keys must exist in this file
- Metadata (
@key) is read from here - Placeholders and plural rules defined here apply to all locales
Common patterns:
# English as template (most common)
template-arb-file: app_en.arb
# Using a "key" file (keys as values)
template-arb-file: app_keys.arb
# Regional variant
template-arb-file: app_en_US.arb
output-localization-file
Purpose: Name of the generated Dart file containing your localizations.
output-localization-file: app_localizations.dart
Custom naming:
# For multiple localization files in large apps
output-localization-file: my_app_strings.dart
# Match your app's naming convention
output-localization-file: localized_strings.dart
output-class
Purpose: The class name used to access translations in code.
output-class: AppLocalizations
Usage in code:
// With default name
Text(AppLocalizations.of(context)!.welcomeMessage)
// With custom name
output-class: S
// Usage becomes:
Text(S.of(context)!.welcomeMessage)
// Or more descriptive
output-class: Strings
Text(Strings.of(context)!.welcomeMessage)
Popular conventions:
| output-class | Usage | Why |
|---|---|---|
| AppLocalizations | Verbose but clear | Flutter default |
| S | Short, easy to type | Popular in Android |
| L10n | Balanced | Clear + short |
| Strings | Descriptive | Self-documenting |
synthetic-package
Purpose: Controls whether generated files live in .dart_tool or your project.
# Generated in .dart_tool (default)
synthetic-package: true
# Generated in your project (recommended)
synthetic-package: false
Why use false:
- Files visible in IDE
- Can commit to version control
- Easier debugging
- No surprises in CI/CD
Required with false:
synthetic-package: false
output-dir: lib/generated/l10n # Must specify output location
output-dir
Purpose: Where to generate files when synthetic-package: false.
synthetic-package: false
output-dir: lib/generated/l10n
Directory structure created:
lib/
├── generated/
│ └── l10n/
│ ├── app_localizations.dart
│ ├── app_localizations_en.dart
│ ├── app_localizations_es.dart
│ └── app_localizations_de.dart
└── l10n/
├── app_en.arb
├── app_es.arb
└── app_de.arb
nullable-getter
Purpose: Controls null safety behavior when translations are missing.
# Default: Returns null if translation missing for locale
nullable-getter: true
# Strict: Throws if translation missing
nullable-getter: false
With nullable-getter: true:
// May return null, requires null check
final text = AppLocalizations.of(context)?.welcomeMessage ?? 'Default';
With nullable-getter: false:
// Never null, but throws if locale not supported
final text = AppLocalizations.of(context)!.welcomeMessage;
Recommendation: Use true during development, consider false for production with complete translations.
required-resource-attributes
Purpose: Enforces that every key has metadata.
# Optional metadata (default)
required-resource-attributes: false
# Required metadata
required-resource-attributes: true
With true, every key needs this:
{
"welcomeMessage": "Welcome!",
"@welcomeMessage": {
"description": "Required description"
}
}
Benefits of requiring:
- Better translator context
- Self-documenting code
- Catches keys without descriptions
Build fails without metadata when enabled.
use-deferred-loading
Purpose: Enables lazy loading of locale data.
use-deferred-loading: true
What it does:
- Locale files loaded on demand
- Reduces initial bundle size
- Useful for apps with many languages
Generated code difference:
// Without deferred loading
import 'app_localizations_es.dart';
// With deferred loading
import 'app_localizations_es.dart' deferred as es;
Future<void> loadLocale(Locale locale) async {
if (locale.languageCode == 'es') {
await es.loadLibrary();
}
}
Use when:
- 10+ languages supported
- Large translation files
- Web app with bundle size concerns
preferred-supported-locales
Purpose: Orders locales for fallback behavior.
preferred-supported-locales:
- en
- es
- de
How it affects fallback:
User locale: es_MX (Mexican Spanish)
Lookup order:
1. es_MX (exact match) - not found
2. es (first in preferred list) - found!
Without this setting: Order is undefined (usually alphabetical).
untranslated-messages-file
Purpose: Outputs a file listing missing translations.
untranslated-messages-file: lib/l10n/untranslated.txt
Generated content:
The following messages are not translated in app_de.arb:
- newFeatureTitle
- newFeatureDescription
- settingsPrivacyPolicy
The following messages are not translated in app_ja.arb:
- newFeatureTitle
- newFeatureDescription
- settingsPrivacyPolicy
- settingsTermsOfService
Use cases:
- CI/CD translation coverage checks
- Tracking translation progress
- Handoff lists for translators
header
Purpose: Adds a comment header to generated files.
header: |
// GENERATED CODE - DO NOT MODIFY BY HAND
// Generated by: flutter gen-l10n
// Source: lib/l10n/*.arb
//
// To regenerate, run: flutter gen-l10n
Best practice headers:
# Simple
header: "// Generated file. Do not edit manually."
# With instructions
header: |
// This file is generated from .arb files in lib/l10n/
// To add or modify translations, edit the .arb files
// Then run: flutter gen-l10n
# With timestamp (useful but regenerates file constantly)
header: "// Generated on: ${DateTime.now()}" # Note: This won't work - just example
Complete Production Configuration
Here's a recommended configuration for production apps:
# l10n.yaml - Production Configuration
# Source files
arb-dir: lib/l10n
template-arb-file: app_en.arb
# Output configuration
output-localization-file: app_localizations.dart
output-class: L10n
synthetic-package: false
output-dir: lib/generated/l10n
# Locale ordering (affects fallback)
preferred-supported-locales:
- en
- es
- de
- fr
- ja
- zh
# Strict mode for production quality
required-resource-attributes: true
nullable-getter: false
# Track missing translations
untranslated-messages-file: lib/l10n/untranslated.txt
# Generated file header
header: |
// GENERATED CODE - DO NOT MODIFY
// Run "flutter gen-l10n" to regenerate
Configuration for Different Project Types
Small App (5 languages or fewer)
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
Medium App (5-15 languages)
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
output-class: S
synthetic-package: false
output-dir: lib/generated/l10n
required-resource-attributes: true
untranslated-messages-file: lib/l10n/untranslated.txt
Large App (15+ languages)
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
output-class: L10n
synthetic-package: false
output-dir: lib/generated/l10n
use-deferred-loading: true
required-resource-attributes: true
nullable-getter: false
preferred-supported-locales:
- en
- es
- zh
- hi
- ar
# ... more languages
untranslated-messages-file: lib/l10n/untranslated.txt
header: |
// Generated localization file
// Do not edit manually
Troubleshooting Common Issues
"Missing required resource attribute"
Error: Missing required resource attribute for "welcomeMessage"
Solution: Add metadata to your .arb file:
{
"welcomeMessage": "Welcome!",
"@welcomeMessage": {
"description": "Main greeting text"
}
}
"arb-dir does not exist"
Error: The specified arb-dir (lib/l10n) does not exist
Solution: Create the directory:
mkdir -p lib/l10n
"output-dir required when synthetic-package is false"
Error: output-dir must be specified when synthetic-package is false
Solution: Add output-dir:
synthetic-package: false
output-dir: lib/generated/l10n
Generated files not updating
# Clear the cache and regenerate
flutter clean
flutter pub get
flutter gen-l10n
Integration with Build Runner
You can integrate gen-l10n with build_runner:
# build.yaml
targets:
$default:
builders:
flutter_gen_l10n:
enabled: true
Then run with:
flutter pub run build_runner build
CI/CD Configuration
GitHub Actions Example
- name: Generate localizations
run: flutter gen-l10n
- name: Check for untranslated strings
run: |
if [ -s lib/l10n/untranslated.txt ]; then
echo "Missing translations found:"
cat lib/l10n/untranslated.txt
exit 1
fi
Quick Reference Card
| Option | Type | Default | Purpose |
|---|---|---|---|
| arb-dir | path | required | Location of .arb files |
| template-arb-file | string | required | Source .arb file |
| output-localization-file | string | auto | Generated file name |
| output-class | string | AppLocalizations | Generated class name |
| output-dir | path | - | Output location |
| synthetic-package | bool | true | Use .dart_tool |
| nullable-getter | bool | true | Allow null returns |
| required-resource-attributes | bool | false | Require metadata |
| use-deferred-loading | bool | false | Lazy load locales |
| preferred-supported-locales | list | - | Fallback order |
| untranslated-messages-file | path | - | Missing translations output |
| header | string | - | File header comment |
Related Resources:
- Complete Guide to Flutter .arb Files
- 5 Flutter Localization Tips
- Flutter Internationalization Documentation
Master your l10n.yaml configuration and your localization workflow becomes predictable and maintainable. Need help managing the .arb files that feed into this configuration? FlutterLocalisation streamlines the entire process.