Flutter_Localizations Package: Complete Setup Guide 2025
The flutter_localizations package is Flutter's official solution for internationalizing your app. It provides localized strings for Flutter widgets and integrates seamlessly with the framework's localization system.
What is flutter_localizations?
flutter_localizations is a Flutter SDK package that provides:
- Material Design localizations - Translated strings for Material widgets
- Cupertino localizations - Translated strings for iOS-style widgets
- Widget localizations - Basic Flutter widget translations
- RTL support - Right-to-left text direction for Arabic, Hebrew, etc.
Quick Start Setup
Step 1: Add Dependencies
# pubspec.yaml
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
intl: any
flutter:
generate: true
Run flutter pub get to install.
Step 2: Create l10n.yaml Configuration
Create l10n.yaml in your project root:
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
output-class: AppLocalizations
synthetic-package: true
nullable-getter: false
Step 3: Create Your First ARB File
Create the directory and template file:
mkdir -p lib/l10n
Create lib/l10n/app_en.arb:
{
"@@locale": "en",
"appTitle": "My Flutter App",
"@appTitle": {
"description": "The title of the application"
},
"hello": "Hello!",
"@hello": {
"description": "A greeting"
},
"welcomeUser": "Welcome, {username}!",
"@welcomeUser": {
"description": "Welcome message with username",
"placeholders": {
"username": {
"type": "String",
"example": "John"
}
}
},
"itemCount": "{count, plural, =0{No items} =1{One item} other{{count} items}}",
"@itemCount": {
"description": "Number of items",
"placeholders": {
"count": {
"type": "int"
}
}
}
}
Step 4: Add More Languages
Create lib/l10n/app_es.arb for Spanish:
{
"@@locale": "es",
"appTitle": "Mi Aplicación Flutter",
"hello": "¡Hola!",
"welcomeUser": "¡Bienvenido, {username}!",
"itemCount": "{count, plural, =0{Sin elementos} =1{Un elemento} other{{count} elementos}}"
}
Create lib/l10n/app_fr.arb for French:
{
"@@locale": "fr",
"appTitle": "Mon Application Flutter",
"hello": "Bonjour!",
"welcomeUser": "Bienvenue, {username}!",
"itemCount": "{count, plural, =0{Aucun élément} =1{Un élément} other{{count} éléments}}"
}
Step 5: Generate Localization Code
Run the generator:
flutter gen-l10n
Or simply build your app—Flutter auto-generates on build:
flutter run
Step 6: Configure MaterialApp
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Localization Demo',
// Localization configuration
localizationsDelegates: [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: AppLocalizations.supportedLocales,
// Optional: Set default locale
// locale: Locale('es'),
home: HomePage(),
);
}
}
Simpler syntax (using generated delegates):
MaterialApp(
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: HomePage(),
)
Step 7: Use Translations in Widgets
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Get the localization instance
final l10n = AppLocalizations.of(context)!;
return Scaffold(
appBar: AppBar(
title: Text(l10n.appTitle),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(l10n.hello),
Text(l10n.welcomeUser('John')),
Text(l10n.itemCount(5)),
],
),
),
);
}
}
Understanding the Delegates
GlobalMaterialLocalizations.delegate
Provides translations for Material Design widgets:
- DatePicker (month names, weekdays)
- TimePicker (AM/PM, hour labels)
- Dialog buttons (OK, Cancel)
- Form validation messages
- Pagination controls
GlobalWidgetsLocalizations.delegate
Provides basic widget localizations:
- Text direction (LTR/RTL)
- Text selection controls
GlobalCupertinoLocalizations.delegate
Provides iOS-style (Cupertino) widget translations:
- CupertinoDatePicker
- CupertinoAlertDialog
- CupertinoActionSheet
AppLocalizations.delegate
Your custom translations generated from ARB files.
Supported Locales
Flutter's built-in localizations support 80+ locales including:
| Language | Code | RTL |
|---|---|---|
| English | en | No |
| Spanish | es | No |
| French | fr | No |
| German | de | No |
| Chinese (Simplified) | zh | No |
| Chinese (Traditional) | zh_TW | No |
| Japanese | ja | No |
| Korean | ko | No |
| Arabic | ar | Yes |
| Hebrew | he | Yes |
| Persian | fa | Yes |
| Hindi | hi | No |
| Russian | ru | No |
| Portuguese | pt | No |
Check the full list:
import 'package:flutter_localizations/flutter_localizations.dart';
void printSupportedLocales() {
print(GlobalMaterialLocalizations.delegate.supportedLocales);
}
Advanced Configuration
l10n.yaml Options Explained
# Required: Directory containing ARB files
arb-dir: lib/l10n
# Required: Template file (source language)
template-arb-file: app_en.arb
# Output file name
output-localization-file: app_localizations.dart
# Generated class name
output-class: AppLocalizations
# Generate as synthetic package (recommended)
synthetic-package: true
# Make getters non-nullable
nullable-getter: false
# Output directory (if not using synthetic package)
# output-dir: lib/generated
# Generate a header in output files
# header: "// Generated file - do not edit"
# Use deferred loading (for web, reduces initial bundle)
# use-deferred-loading: true
# Require descriptions for all messages
# require-description: true
# Require placeholders in messages
# require-placeholders: true
Custom Locale Resolution
MaterialApp(
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
// Custom resolution logic
localeResolutionCallback: (deviceLocale, supportedLocales) {
// Check for exact match
for (var locale in supportedLocales) {
if (locale.languageCode == deviceLocale?.languageCode &&
locale.countryCode == deviceLocale?.countryCode) {
return locale;
}
}
// Check for language match
for (var locale in supportedLocales) {
if (locale.languageCode == deviceLocale?.languageCode) {
return locale;
}
}
// Default to first supported locale
return supportedLocales.first;
},
)
Dynamic Locale Switching
class MyApp extends StatefulWidget {
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Locale _locale = Locale('en');
void setLocale(Locale locale) {
setState(() {
_locale = locale;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
locale: _locale,
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: HomePage(onLocaleChange: setLocale),
);
}
}
ARB File Format Deep Dive
Basic Message
{
"greeting": "Hello",
"@greeting": {
"description": "A simple greeting"
}
}
Message with Placeholder
{
"greeting": "Hello, {name}!",
"@greeting": {
"description": "Greeting with name",
"placeholders": {
"name": {
"type": "String",
"example": "World"
}
}
}
}
Plural Message
{
"emails": "{count, plural, =0{No emails} =1{1 email} other{{count} emails}}",
"@emails": {
"description": "Email count",
"placeholders": {
"count": {
"type": "int"
}
}
}
}
Select Message (Gender)
{
"userWelcome": "{gender, select, male{Welcome, Mr. {name}} female{Welcome, Ms. {name}} other{Welcome, {name}}}",
"@userWelcome": {
"description": "Gender-specific welcome",
"placeholders": {
"gender": {
"type": "String"
},
"name": {
"type": "String"
}
}
}
}
Date/Time Placeholder
{
"lastLogin": "Last login: {date}",
"@lastLogin": {
"description": "Shows last login date",
"placeholders": {
"date": {
"type": "DateTime",
"format": "yMMMd"
}
}
}
}
Number Placeholder
{
"price": "Price: {amount}",
"@price": {
"description": "Product price",
"placeholders": {
"amount": {
"type": "double",
"format": "currency",
"optionalParameters": {
"symbol": "$",
"decimalDigits": 2
}
}
}
}
}
Common Issues and Solutions
"Cannot find generated localization file"
Run the generator manually:
flutter gen-l10n
Or ensure flutter: generate: true is in pubspec.yaml.
"Locale not supported"
Add the locale to your ARB files:
# Create app_de.arb for German
touch lib/l10n/app_de.arb
"Null check operator used on null value"
The locale isn't available yet. Ensure MaterialApp has the delegates:
// Wrong - accessing before localization is ready
final l10n = AppLocalizations.of(context)!; // May crash
// Right - check for null or use in widget tree
final l10n = AppLocalizations.of(context);
if (l10n != null) {
return Text(l10n.hello);
}
RTL Not Working
Ensure you include the widgets delegate:
localizationsDelegates: [
GlobalWidgetsLocalizations.delegate, // Required for RTL
GlobalMaterialLocalizations.delegate,
AppLocalizations.delegate,
],
FlutterLocalisation: Visual ARB Management
Editing ARB files manually is error-prone. FlutterLocalisation provides:
- ✅ Visual ARB editor - No JSON syntax errors
- ✅ Side-by-side translations - Compare all languages
- ✅ Placeholder validation - Catch missing placeholders
- ✅ AI translation - Instant translations for new languages
- ✅ Export to ARB - Download ready-to-use files
Ready to streamline your Flutter localization? Try FlutterLocalisation free — the visual way to manage ARB files for flutter_localizations.