Flutter Localization Delegates: The Complete Configuration Guide
Master Flutter localization delegates including AppLocalizations, GlobalMaterialLocalizations, and GlobalCupertinoLocalizations for proper locale support.
Published on • September 19, 2026
AI Assistant

Flutter Localization Delegates: The Complete Configuration Guide
Localization delegates are the glue that connects Flutter’s localization system to your app. They tell Flutter how to load localized data, format dates and numbers, and provide locale-specific widget behavior. Understanding delegates is essential for proper multi-language support.
What Are Localization Delegates?
A localization delegate is a class that provides localized values for a specific aspect of your app. Flutter uses them to:
- Load translation data — your ARB file content
- Format locale-specific data — dates, numbers, currencies
- Provide widget localization — Material and Cupertino widgets
The Four Essential Delegates
1. AppLocalizations.delegate (Your Translations)
This delegate is generated from your ARB files and provides access to all your translated strings:
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: const [
AppLocalizations.delegate, // Your translations
// ...
],
);
}
}
2. GlobalMaterialLocalizations (Material Widgets)
Provides localized names for Material Design widgets (OK, Cancel, January, etc.):
import 'package:flutter_localizations/flutter_localizations.dart';
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: const [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate, // Material widget names
// ...
],
);
}
}
3. GlobalWidgetsLocalizations (Text Direction)
Handles text direction and text rendering:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: const [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate, // Text direction
// ...
],
);
}
}
4. GlobalCupertinoLocalizations (Cupertino Widgets)
Provides localized names for iOS-style widgets:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: const [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate, // iOS widget names
],
);
}
}
Complete Configuration
Minimal Setup
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My App',
localizationsDelegates: const [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: AppLocalizations.supportedLocales,
home: const HomeScreen(),
);
}
}
With Custom Locale Resolution
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My App',
localizationsDelegates: const [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: AppLocalizations.supportedLocales,
localeResolutionCallback: (locale, supportedLocales) {
// Custom resolution logic
for (final supportedLocale in supportedLocales) {
if (supportedLocale.languageCode == locale?.languageCode) {
return supportedLocale;
}
}
return supportedLocales.first; // Default to English
},
home: const HomeScreen(),
);
}
}
Using Delegates in Widgets
Accessing Translations
class MyWidget extends StatelessWidget {
const MyWidget({super.key});
@override
Widget build(BuildContext context) {
// Access your translations
final l10n = AppLocalizations.of(context)!;
return Column(
children: [
Text(l10n.appTitle),
Text(l10n.welcomeMessage),
ElevatedButton(
onPressed: () {},
child: Text(l10n.loginButton),
),
],
);
}
}
Accessing Material Localizations
class DatePickerWidget extends StatelessWidget {
const DatePickerWidget({super.key});
@override
Widget build(BuildContext context) {
// Access Material localizations
final materialLocalizations = MaterialLocalizations.of(context);
return TextButton(
onPressed: () {
showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2020),
lastDate: DateTime(2030),
);
},
child: const Text('Select Date'),
);
}
}
Advanced: Custom Localization Delegates
Creating a Custom Delegate
class CustomLocalizations {
final Locale locale;
CustomLocalizations(this.locale);
static CustomLocalizations of(BuildContext context) {
return Localizations.of<CustomLocalizations>(
context,
CustomLocalizations,
)!;
}
static const LocalizationsDelegate<CustomLocalizations> delegate =
_CustomLocalizationsDelegate();
// Custom localized data
String get appName => locale.languageCode == 'es' ? 'Mi App' : 'My App';
}
class _CustomLocalizationsDelegate
extends LocalizationsDelegate<CustomLocalizations> {
const _CustomLocalizationsDelegate();
@override
bool isSupported(Locale locale) {
return ['en', 'es'].contains(locale.languageCode);
}
@override
Future<CustomLocalizations> load(Locale locale) async {
return CustomLocalizations(locale);
}
@override
bool shouldReload(_CustomLocalizationsDelegate old) => false;
}
Using Custom Delegates
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: const [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
CustomLocalizations.delegate, // Your custom delegate
],
supportedLocales: const [
Locale('en', ''),
Locale('es', ''),
],
);
}
}
Debugging Delegates
Checking Loaded Locales
class DebugLocaleWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final locale = Localizations.localeOf(context);
final l10n = AppLocalizations.of(context);
return Text(
'Current locale: ${locale.languageCode}\n'
'Translations loaded: ${l10n != null}',
);
}
}
Handling Missing Translations
// In l10n.yaml, set:
nullable-localization: false
// Then use:
final l10n = AppLocalizations.of(context)!; // Throws if null
// Or provide fallback:
final l10n = AppLocalizations.of(context) ?? AppLocalizations.defaultLocalization;
Common Pitfalls
Missing Delegates
// Bad: Missing GlobalWidgetsLocalizations breaks RTL support
localizationsDelegates: const [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
]
// Good: Include all four delegates
localizationsDelegates: const [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
]
Wrong Order
// Bad: AppLocalizations.delegate should come first
localizationsDelegates: const [
GlobalMaterialLocalizations.delegate,
AppLocalizations.delegate,
]
// Good: AppLocalizations.delegate first
localizationsDelegates: const [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
]
Resources
Localization delegates are the foundation of Flutter’s multi-language support. By properly configuring them, you ensure your app works correctly across all supported locales.