Internationalization in Flutter: solved exercise with flutter_localizations and ARB files
Internationalization in Flutter: solved exercise with flutter_localizations and ARB files
Internationalization (i18n) in Flutter is built on flutter_localizations + the gen-l10n code generator. ARB (Application Resource Bundle) files are the standard translation format: annotated JSON that the generator converts into typed Dart classes.
Problem statement
Build a multilingual app that:
- Supports English and Spanish via ARB files.
- Uses
AppLocalizationsauto-generated withflutter gen-l10n. - Shows translations with variable arguments (username).
- Uses correct pluralization (
itemCount). - Shows the date formatted according to the active locale.
Dependencies and configuration
pubspec.yaml
l10n.yaml (in the project root)
lib/l10n/app_en.arb
lib/l10n/app_es.arb
After creating the ARB files, run:
This generates lib/gen/app_localizations.dart (or inside .dart_tool/flutter_gen/).
Full solution
ARB file structure
| Field | Usage |
|---|---|
@@locale | Declares the file language ("en", "es") |
"key": "value" | Simple translation |
"@key" | Key metadata (description, placeholders) |
{param} | Positional String argument |
{count, plural, ...} | Pluralization via ICU MessageFormat |
{date} with "type": "DateTime" | Date formatted with intl per locale |
Common mistakes
- Forgetting
flutter: generate: trueinpubspec.yaml: without this line,flutter gen-l10ndoes not generate Dart files and theAppLocalizationsimport does not exist. - Using
AppLocalizations.of(context)without!: in a correctly configuredMaterialAppit never returns null inside the widget tree. Use!or check for null only for screens outside the localization tree. - Not adding
GlobalMaterialLocalizations.delegate: without this delegate, native Material strings (OK button, Cancel, date picker) won’t be translated even if your content is. - ARB with incorrect plural syntax: the ICU format is
{count, plural, =0{...} =1{...} other{...}}. Theothercase is mandatory β if you omit it,gen-l10nfails with a cryptic error.
Practical use
Any app published in multiple markets needs i18n: productivity apps, e-commerce, and SaaS tools. The key is implementing it from the start β retrofitting i18n into a large app is expensive.
Recommended next exercise
Guided practice and next step
FAQ
Should I use gen-l10n or the intl_utils package?
gen-l10n is the official Flutter team solution and requires no extra dependencies. intl_utils is a popular alternative with VS Code and Android Studio integration, but adds an extra dev dependency. For new projects, use gen-l10n.
How does pluralization work in languages with more than two forms?
ICU MessageFormat supports the categories zero, one, two, few, many, other. The locale determines how many forms a language uses: English uses only one/other, Polish uses one/few/many/other. The intl library automatically handles selection by locale.
Can ARB files be shared with other platforms?
Yes. ARB is also the standard format for Flutter Web, macOS, and Desktop. Some teams reuse the same ARB files on Android (with android-arb-plugin) and in iOS/macOS projects semi-automatically.