internationalization (i18n) and localization (l10n) are essential when building Flutter apps for global users. In my experience, I always approach this systematically — starting with setting up the Flutter localization framework, organizing translation resources properly, and ensuring the app dynamically responds to locale changes.
In Flutter, I typically use the Flutter’s built-in localization support provided by the flutter_localizations package, along with the intl package for message formatting.
Here’s how I usually set it up:
First, I enable localization in pubspec.yaml:
flutter:
generate: true
uses-material-design: true
generate_localized_resources: true
assets:
- assets/l10n/
dependencies:
flutter_localizations:
sdk: flutter
intl: ^0.18.0
Then, in my MaterialApp, I specify the supported locales and the generated localization delegates:
return MaterialApp(
title: 'My App',
localizationsDelegates: const [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: const [
Locale('en'), // English
Locale('ta'), // Tamil
Locale('fr'), // French
],
localeResolutionCallback: (locale, supportedLocales) {
for (var supportedLocale in supportedLocales) {
if (supportedLocale.languageCode == locale?.languageCode) {
return supportedLocale;
}
}
return supportedLocales.first;
},
home: const HomePage(),
);
After that, I create my localization resource files — arb (Application Resource Bundle) files — typically under lib/l10n/:
// lib/l10n/app_en.arb
{
"welcomeMessage": "Welcome, {username}!",
"@welcomeMessage": {
"description": "A welcome message for the user"
}
}
// lib/l10n/app_ta.arb
{
"welcomeMessage": "வரவேற்கிறோம், {username}!"
}
Once I run:
flutter gen-l10n
Flutter generates a AppLocalizations class that gives me type-safe access to localized strings:
Text(AppLocalizations.of(context)!.welcomeMessage(username))
I applied this in a Flutter e-commerce project that supported both English and Tamil. We needed to show not just text but also localized date, currency, and number formats. The intl package was really handy for this:
final price = NumberFormat.currency(locale: 'ta_IN', symbol: '₹').format(1299);
This automatically handled locale-specific formatting, including currency symbols and decimal separators.
A key challenge I faced was ensuring dynamic locale switching without restarting the app. I solved it using a ChangeNotifier or a state management approach (like Provider or Riverpod) to rebuild the MaterialApp whenever the user selected a new language.
Another challenge was with text direction for RTL (Right-to-Left) languages like Arabic. Flutter handles this automatically if the locale supports it, but I had to test UI layouts carefully to ensure widgets like icons and paddings mirrored correctly.
One limitation of using ARB files directly is that non-technical translators may find them difficult to edit. In a larger project, we integrated a translation management tool like Lokalise to sync translations automatically with ARB files — making collaboration easier.
As alternatives, I’ve also used community packages like easy_localization for smaller apps — it simplifies setup and allows hot reloads for language changes, though for enterprise apps I prefer Flutter’s official gen-l10n tool for better maintainability and type safety.
In summary, my approach to Flutter localization involves:
- Using
flutter_localizations+intlfor robust, official support - Managing translations with ARB files for scalability
- Handling locale changes dynamically through state management
- Testing UI for RTL layouts and cultural formatting differences
- Automating translation workflows in larger projects
This ensures a clean, scalable internationalization setup where adding new languages or updating translations is seamless — without touching the app’s logic or rebuilding from scratch.
