This tutorial will guide you through the process of adding multi-language support (internationalization and localization) to your Flutter application, using the flutter_localizations
and intl
packages for Material Design widgets.
1. Introduction
Internationalization (i18n) is the process of designing and developing an application so that it can be adapted to different languages and regions without engineering changes. Localization (l10n) is the process of adapting an application for a specific locale or market by adding locale-specific components and translating text.
In Flutter, the flutter_localizations
package provides localizations for standard Material Design widgets, while the intl
package is the Dart library that handles message formatting, date and number formatting, and bidirectional text.
2. Prerequisites
Flutter SDK installed and configured.
An existing Flutter project.
Basic knowledge of Flutter and Dart development.
3. Step-by-Step
Step 1: Install Dependencies
Instead of manually editing pubspec.yaml
, we will use the flutter pub add
command to add the packages. Open your terminal at the root of your Flutter project and run the following commands:
flutter pub add flutter_localizations --sdk=flutter
flutter pub add intl
The
flutter pub add flutter_localizations --sdk=flutter
command addsflutter_localizations
, specifying that it is part of the Flutter SDK; it is not a third-party library.The
flutter pub add intl
command adds theintl
package as a normal dependency.
After running these commands, your pubspec.yaml
file will be automatically updated, and the packages will be downloaded. You should see something like:
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
intl: ^0.20.2 # The version may vary
Step 2: Enable Localization Code Generation
Still in pubspec.yaml
, add the generate: true
flag in the flutter
section. This instructs Flutter to automatically generate localization files from your ARB (Application Resource Bundle) files.
flutter:
uses-material-design: true
generate: true # Add this line to enable localization code generation
# ... other Flutter configurations
Run flutter pub get
in your terminal after this change to ensure the configurations are applied.
Step 3: Create the l10n.yaml
Configuration File
Create a new file named l10n.yaml
in the root of your project (at the same level as pubspec.yaml
). This file configures how Flutter should generate the localization files.
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
arb-dir
: The directory where your.arb
files (with translations) will be stored. We will create it inlib/l10n
.template-arb-file
: The name of your base ARB file (usually the default language, like English).output-localization-file
: The name of the Dart file that will be generated with the localization classes.
Step 4: Create the ARB (Application Resource Bundle) Files
Create the directory specified in arb-dir
, which is lib/l10n
. Inside it, create your ARB files for each language you want to support.
lib/l10n/app_en.arb
(English - base file):
{
"@@locale": "en",
"helloWorld": "Hello World!",
"@helloWorld": {
"description": "A conventional greeting"
},
"welcomeMessage": "Welcome, {name}!",
"@welcomeMessage": {
"description": "A welcome message with a name parameter",
"placeholders": {
"name": {
"type": "String"
}
}
}
}
lib/l10n/app_pt.arb
(Portuguese):
{
"@@locale": "pt",
"helloWorld": "Olá Mundo!",
"welcomeMessage": "Bem-vindo(a), {name}!"
}
Explanation of ARB files:
"@@locale": "en"
: Defines the locale for this file."helloWorld": "Hello World!"
: The key for your string and its translation."@helloWorld"
: Optional metadata for the key, such as a description for translators."welcomeMessage": "Welcome, {name}!"
: Example of a string with a placeholder ({name}
). The@welcomeMessage
defines the type of the placeholder (these are mandatory when the string contains parameters so that the Flutter code generator knows how to create the corresponding Dart function).
Step 5: Generate Localization Files
After creating or modifying your ARB files, you need to generate the corresponding Dart code. Run the following command in the terminal at the root of your project:
flutter gen-l10n
This command will read your .arb
files and l10n.yaml
and generate the app_localizations.dart
file (and other necessary files) in the configured location. If the file already exists, it will be updated.
Step 6: Configure MaterialApp
In your main.dart
file (or where you define your MaterialApp
), import the generated localization files and configure the localizationsDelegates
and supportedLocales
properties.
lib/main.dart
(example):
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
// ATTENTION: The import below assumes 'app_localizations.dart' is generated directly in 'lib/l10n/'.
// Although the default Flutter approach (the one previously used) is
// 'package:flutter_gen/gen_l10n/app_localizations.dart;',
// if your environment generates the file in this location, use this line.
import 'l10n/app_localizations.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Localization Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
// Localization properties
localizationsDelegates: const [
AppLocalizations.delegate, // Delegate generated from your ARB files
GlobalMaterialLocalizations.delegate, // Localizations for Material widgets
GlobalWidgetsLocalizations.delegate, // Localizations for basic widgets
],
supportedLocales: const [
Locale('en'), // English
Locale('pt'), // Portuguese
// Add other languages you support
],
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
// Accessing localized strings
final appLocalizations = AppLocalizations.of(context)!;
return Scaffold(
appBar: AppBar(
title: Text(appLocalizations.helloWorld),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
appLocalizations.welcomeMessage('User'), // Using the string with a placeholder
style: Theme.of(context).textTheme.headlineMedium,
),
const SizedBox(height: 20),
Text(
'Current Language: ${Localizations.localeOf(context).languageCode}',
style: Theme.of(context).textTheme.bodyLarge,
),
],
),
),
);
}
}
Explanation:
import 'l10n/app_localizations.dart';
: This is the import path you requested, assumingapp_localizations.dart
is generated directly in thelib/l10n/
folder. Note that the default Flutter approach (especially in newer versions) for generated files ispackage:flutter_gen/gen_l10n/app_localizations.dart;
. Choose the path that works for your environment.AppLocalizations.delegate
: This is the delegate specific to your application that knows how to load translations from your ARB files.
In Flutter, a LocalizationsDelegate
is a class that knows how to load specific resources for a Locale
(language and region) for your application. It’s like a “manager” that knows where to find the translations and how to make them available to your widgets.
GlobalMaterialLocalizations.delegate
,GlobalWidgetsLocalizations.delegate
: These are the delegates provided byflutter_localizations
(i.e., native to the Flutter SDK itself) that provide translations for standard Material Design widgets (such asDatePicker
,TimePicker
, navigation buttons, etc.), ensuring that month names, “OK” and “CANCEL” buttons, “back” buttons, etc., are translated.supportedLocales
: A list of allLocale
s that your application supports. Flutter will attempt to match the user’s device language with one of the languages in this list.
Step 7: Use Localized Strings in Your Code
To access your translated strings, you will use the AppLocalizations
class (the class name is derived from output-localization-file
in l10n.yaml
).
// Inside a widget that has access to a BuildContext
final appLocalizations = AppLocalizations.of(context)!;
// For a simple string:
Text(appLocalizations.helloWorld)
// For a string with a placeholder:
Text(appLocalizations.welcomeMessage('UserName'))
When you run your app, Flutter will detect the device language and load the corresponding translations. If the device language is not supported, it will use the default language (defined in template-arb-file
in l10n.yaml
, which is en
in this example).
Step 8: Run the Application
Save all files and run your Flutter application:
flutter run
Your app should now display “Hello World!” or “Olá Mundo!” and the welcome message according to your device’s language (if it’s Portuguese or English).
Additional Tips:
Change Device Language: To test localization, you can change the language of your emulator or physical device in the system settings.
Correct Import: Always verify the exact path of the
app_localizations.dart
file that Flutter generates in your project. The path can beimport 'l10n/app_localizations.dart';
(if generated directly inlib/l10n/
) orimport 'package:flutter_gen/gen_l10n/app_localizations.dart';
(the more common default). Make sure to use the path your Flutter environment is using.Add New Languages: To add a new language, simply create a new
.arb
file (e.g.,app_es.arb
for Spanish) in thelib/l10n
directory and add theLocale('es')
to thesupportedLocales
list in yourMaterialApp
. Remember to runflutter gen-l10n
again so that the new language and its translations are included in the generated code.