---
title: Flutter Localization: ARB, intl & gen-l10n | Smartcat
description: Set up Flutter localization with ARB files and gen-l10n: placeholders, plurals, intl vs easy_localization, RTL testing and a translation workflow check.
canonical: https://www.smartcat.com/flutter-localization/
language: en
updated: 2026-11-03
---

# Flutter Localization: ARB, intl & gen-l10n | Smartcat

## Flutter Localization: ARB Files, intl and gen-l10n Explained

Flutter localization adapts an application’s messages and interface for different locales. In the built-in workflow, flutter_localizations supports localized framework widgets, while ARB resources and gen-l10n produce the application’s AppLocalizations API, with intl supporting language-sensitive messages and formatting.

- [Book a demo](https://www.smartcat.com/book-a-demo/?main-cta2-flutter-localization)

- [Start free trial](https://smartcat.com/sign-up?main-cta3-flutter-localization)

## Set up flutter_localizations and gen-l10n

This guide sets up a small English and Spanish example, explains message metadata and compares common package approaches. It also shows what to validate before connecting a translation platform to a Flutter project.

Use one localization generator and make its input and output locations explicit. The example below assumes an existing Flutter application with its own SDK constraints and normal project configuration.

Merge the relevant entries into pubspec.yaml ; do not duplicate the dependencies or flutter sections:

dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
intl: any

flutter:
generate: true Resolve dependencies with flutter pub get . The intl: any entry follows the official setup pattern, allowing dependency resolution to select the version compatible with the Flutter SDK; keep the application’s lockfile and normal dependency-review process.

Create l10n.yaml at the project root:

arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart Use the current [Flutter internationalization guide](https://docs.flutter.dev/ui/internationalization) for SDK-specific setup. Generated localization files belong in the application’s source tree in the modern workflow. The example imports from lib/l10n ; avoid copying an old synthetic package:flutter_gen import into a new setup. See the [generated-source migration note](https://docs.flutter.dev/release/breaking-changes/flutter-generate-i10n-source).

## Write ARB files with context and typed placeholders

An ARB file is a JSON-based resource bundle containing messages and optional metadata. Keep message keys stable, write complete messages and use metadata to explain how the text is used.

Create lib/l10n/app_en.arb :

{
"@@locale": "en",
"appTitle": "Reading room",
"@appTitle": {
"description": "Title of the sample reading application"
},
"welcomeName": "Welcome, {name}",
"@welcomeName": {
"description": "Greeting on the home screen",
"placeholders": {
"name": {"type": "String", "example": "Sam"}
}
},
"savedBooks": "{count, plural, =0{No saved books} one{1 saved book} other{{count} saved books}}",
"@savedBooks": {
"description": "Number of books saved to the user's library",
"placeholders": {
"count": {"type": "int"}
}
},
"readingState": "{state, select, active{Reading now} paused{Reading paused} other{Ready to read}}",
"@readingState": {
"description": "Reading status; state is active, paused or another value",
"placeholders": {
"state": {"type": "String"}
}
}
} Create lib/l10n/app_es.arb :

{
"@@locale": "es",
"appTitle": "Sala de lectura",
"welcomeName": "Te damos la bienvenida, {name}",
"savedBooks": "{count, plural, =0{No hay libros guardados} one{1 libro guardado} other{{count} libros guardados}}",
"readingState": "{state, select, active{Leyendo ahora} paused{Lectura en pausa} other{Todo listo para leer}}"
} The template contains the placeholder metadata used by the generator. The localized file preserves message keys, placeholder names and select identifiers while changing the user-facing wording. These Spanish examples illustrate the mechanics; production language should receive native review in its actual product context.

Run flutter gen-l10n after adding or changing resources. Treat generator errors as actionable resource problems and resolve them before integrating the files into a release.

## Connect the generated messages to MaterialApp

Register the generated delegates and supported locales, then read localized messages from a context below the application widget.

The following example belongs in lib/main.dart after generation:

import 'package:flutter/material.dart';
import 'l10n/app_localizations.dart';

void main() => runApp(const ReadingApp());

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

@override
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: const ReadingHome(),
);
}
}

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

@override
Widget build(BuildContext context) {
final messages = AppLocalizations.of(context)!;
return Scaffold(
appBar: AppBar(title: Text(messages.appTitle)),
body: Padding(
padding: const EdgeInsetsDirectional.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(messages.welcomeName('Sam')),
Text(messages.savedBooks(3)),
Text(messages.readingState('active')),
],
),
),
);
}
} ReadingHome has access to the localizations supplied by MaterialApp . Asking for AppLocalizations from the outer widget’s context would look above the provider created by that widget. The [Localizations API documentation](https://api.flutter.dev/flutter/widgets/Localizations-class.html) explains how localized resources are made available to descendants. The generated API makes the distinction between a plain message and a message with arguments visible in code. appTitle is accessed as a value; welcomeName , savedBooks and readingState receive the values needed to build their messages.

## Handle plurals and select messages deliberately

Plural messages choose wording according to a quantity and the target locale’s grammar. Select messages choose a branch from an application-supplied identifier. Preserve the syntax and identifiers while translating the text each branch displays.

Plurals

In the example, =0 provides an explicit empty-state sentence. The one and other branches cover the forms used by the sample languages; they are not a universal template for every target locale. Give the reviewer enough context to provide the forms required by the language and the values your app can produce.

Select messages

Values such as active and paused are program identifiers. Translating those identifiers would disconnect the resource from the code that supplies them. The other branch gives the message a fallback for a value that does not match a named branch.

Complete messages

Avoid concatenating fragments such as a translated verb, a count and a translated noun. A complete message gives the target language control over word order. Explain the values, expected ranges and screen context in the brief so reviewers can evaluate the sentence as users will see it.

## Compare Flutter localization packages

Choose a package by resource format, application architecture and maintenance needs. The packages below provide different conventions; adopting more than one generator for the same messages creates unnecessary ambiguity.

| | Approach | Typical resources | Code generation | Plural approach | Useful when

| Built-in gen-l10n | ARB | Generates typed Dart accessors | ICU-style message syntax | You want the official Flutter resource workflow

| easy_localization | JSON by default, with additional loaders available | Optional generation tooling | Package plural APIs and locale-aware rules | You prefer its asset-loading and locale-management conventions

| GetX translations | Locale-keyed maps in its documented basic workflow | Not required for the basic map API | trPlural uses singular/plural keys; assess richer grammar separately | Your application already uses GetX and its translation model fits the requirements

Review the current [easy_localization documentation](https://pub.dev/packages/easy_localization) and [GetX documentation](https://pub.dev/packages/get) before choosing. Test fallback behavior, parameters, plural categories and extraction workflows with your real messages. A convenient API for English strings does not prove coverage for every language you plan to ship.

intl is not a competing translation-management platform. It supplies internationalization utilities used by localization workflows. gen-l10n generates application accessors from ARB resources. The separate [intl_utils package](https://pub.dev/packages/intl_utils) also generates localization code, but its package page was marked discontinued when checked on 30 October 2026. Check maintenance status before adopting it for a new project.

## Test locale switching, RTL and text expansion

Test both resource correctness and the way translated text behaves in the interface. A successful JSON parse or code-generation step cannot establish that a screen is understandable and usable.

Locale switching

For a focused development check, set MaterialApp.locale to a supported value such as const Locale('es') . For a production language selector, keep the chosen locale in application state, persist the preference according to your product requirements and offer a way to follow the system language. Validate a stored preference against the locales the current app version actually supports.

Right-to-left layouts

Use directional layout APIs for elements that should follow reading direction. Check padding, alignment, navigation affordances and mixed-direction content in a real right-to-left locale. Do not assume every icon should mirror: a directional navigation arrow and a brand symbol have different semantics.

Text expansion

Test long translations and larger text sizes. Inspect buttons, tabs, dialogs, empty states, errors and narrow layouts. Include dynamic values such as long names and counts so the layout is checked with the message users will actually receive.

Use a practical test matrix:

| | Check | Example

| Resource coverage | Every required template key has an intentional localized value or fallback

| Message arguments | Placeholder names and types remain compatible with generated methods

| Quantity behavior | Zero, one and values exercising the target language’s additional forms

| Select behavior | Known states plus an unexpected value that reaches other

| Locale behavior | System language, explicit selection, restart and unsupported preference

| Layout | Expanded text, large font settings and right-to-left content

| Meaning | Native review of important user journeys

For the language side of the process, use the [localization testing workflow](https://www.smartcat.com/software-localization/testing/). Keep linguistic approval and functional test results visible as separate pieces of release evidence.

## Plan Flutter web localization and discoverability separately

Flutter web can use localized application resources, but localizing the interface does not automatically create an SEO-ready multilingual website. Language selection, routing, metadata and the discoverability of content remain architectural decisions.

Flutter’s [web FAQ](https://docs.flutter.dev/platform-integration/web/faq) describes its focus on application experiences and recommends a document-oriented approach for static, text-rich web content. Consider separate HTML-based marketing, help and editorial pages when those pages need to perform in organic search.

Keep terminology aligned between the app and those public pages. A search visitor should recognize the feature name after moving from the localized landing page into the application, even when the two surfaces use different rendering systems.

## Validate an ARB translation workflow before scaling it

Treat ARB as a structured application resource, not merely a file of text values. A translation handoff must preserve keys, metadata, placeholders and message syntax, then return files that pass generation and app tests.

Smartcat’s documented software-project formats include JSON, YAML, Android XML, iOS .strings and LocJSON imports. The documentation reviewed for this guide does not establish native ARB support or a tested ARB-to-JSON conversion workflow. Do not assume that changing a file extension proves compatibility. See the [software-project documentation](https://help.smartcat.com/create-a-software-localization-project/).

Use the following as a proposed validation procedure with your implementation team, not as an already-tested connector recipe:

- Choose a representative sample

Select a small ARB sample containing plain strings, metadata, typed placeholders, plurals and selects.

- Confirm import and export

Confirm the supported import/export method with the product team, including treatment of @ metadata and ICU messages.

- Provide language assets and context

Supply a glossary, translation memory where appropriate and clear context for each message.

- Translate and protect structure

Translate and review the user-facing text while protecting program identifiers and structure.

- Compare and restore

Compare the returned resources with the source contract and restore them to the expected project paths.

- Generate and test

Run flutter gen-l10n , static analysis and relevant tests in the project’s pinned SDK environment.

- Review and record

Review the localized interface and record the approved source version.

Automate repository synchronization only after that round trip succeeds. Define who handles source changes, how review status is invalidated and how generated artifacts are managed. Keep ARB resources under version control as the source of truth for the application workflow.

Review your Flutter translation workflow

- [Book a demo](https://www.smartcat.com/book-a-demo/?main-cta1-flutter-localization)

## Common failures and what to check first

| | Symptom | First check

| Generated import cannot be found | Generation ran successfully and the import matches the configured source output path

| AppLocalizations.of(context) is unavailable | The context is below the application’s localization provider

| A message method has unexpected arguments | Template placeholder metadata and the generated API

| A select always shows the fallback | Application identifier matches the resource branch exactly

| A locale is missing | Resource files, supported locales and locale-resolution configuration

| Translation breaks after export | Keys, JSON validity, metadata and ICU syntax survived the round trip

Fix the earliest broken contract rather than editing generated Dart by hand. Generated code can be regenerated; a manual repair there is likely to disappear the next time resources change.

## Frequently asked questions

### What is an ARB file in Flutter?

An Application Resource Bundle is a JSON-based file containing localized messages and optional metadata. Flutter’s gen-l10n workflow uses ARB resources to generate a Dart localization API. Metadata can describe the message and its placeholders, giving developers and translators a clearer contract for each key.

### What is the difference between gen-l10n and intl_utils?

Both generate localization code from ARB resources, but they are separate tools with different configuration and output conventions. gen-l10n is part of Flutter’s built-in workflow. The intl_utils package page was marked discontinued when checked for this guide, so verify maintenance status before choosing it for a new implementation.

### How should I translate ARB files?

Translate the user-facing messages while preserving stable keys, placeholder identifiers, metadata and the required message structure. Use a workflow that supports those requirements, then run generation and application tests on the returned files. Native review should assess meaning and context in addition to structural validity.

### Does Smartcat support ARB placeholders and plurals?

The software-project documentation reviewed here does not establish native ARB support or a tested conversion path preserving all ARB features. Confirm the import/export method with the product team and validate a representative round trip before adoption. Generic JSON support alone does not prove ARB compatibility.

### Does Flutter localization work on the web?

Flutter web applications can use localized resources and locale selection. Search discoverability is a separate concern: public marketing and help content may benefit from an HTML-based architecture. Test routing, language selection and metadata for your specific web experience rather than assuming the mobile localization setup completes web SEO.

Didn’t find your answer? [Talk to a localization specialist](https://www.smartcat.com/book-a-demo/?main-cta4-flutter-localization)

Make your translation handoff as reliable as your resource contract

Bring a small ARB sample and the checks your build requires. Review the workflow before scaling to every language and release.

- [Book a demo](https://www.smartcat.com/book-a-demo/?main-cta5-flutter-localization)

- [Explore mobile app localization](https://www.smartcat.com/software-localization/mobile-apps/)
