← Back to Blog

Flutter l10n.yaml Configuration: Every Option Explained

flutterlocalizationconfigurationl10nyaml

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:

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.