Flutter Localization (l10n) — A Production-Ready Guide
If you’re building a serious Flutter app, supporting multiple languages is not optional it’s essential. Flutter provides a robust and…
Flutter Localization (l10n) — A Production-Ready Guide

If you’re building a serious Flutter app, supporting multiple languages is not optional it’s essential. Flutter provides a robust and scalable localization system that integrates directly into your app with minimal runtime overhead.
This guide goes beyond basics and focuses on how localization actually works under the hood, best practices, and production-level implementation.
What is Localization (l10n)?
Localization (often written as l10n) is the process of adapting your app to different languages and regions.
It includes:
- Translated text
- Date & number formats
- Currency formats
- RTL (Right-to-Left) layout support
Flutter Localization Architecture
Flutter uses a combination of:
intlpackage which can use to translate currency , genders, plurals .etc- ARB files : A json like file which stores the translated text
- Generated Dart code → type-safe access
Flow:
ARB Files → Code Generation → AppLocalizations → UI
Step 1: Add Dependencies
In pubspec.yaml:
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
intl: ^0.20.2
Step 2: Enable Localization
import 'package:flutter_localizations/flutter_localizations.dart';
MaterialApp(
localizationsDelegates: const [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: const [
Locale('en'),
Locale('ml'), // Malayalam
Locale('hi'), // Hindi
],
)
Step 3: Create ARB Files
Inside lib/l10n/
app_en.arb
{
"hello": "Hello",
"@hello": {
"description": "Greeting message"
}
}
app_ml.arb
{
"hello": "ഹലോ"
}
Step 4: Configure l10n.yaml
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
Step 5: Generate Localization Code
Run:
flutter gen-l10n
This generates:
AppLocalizationsclass- Strongly typed getters
Step 6: Use in UI
final l10n = AppLocalizations.of(context)!;
Text(l10n.hello);
Advanced Localization Techniques
Once your app supports multiple languages, the next step is handling dynamic content values that change at runtime like usernames, counts, gender, dates, and currency. This is where ICU MessageFormat (via the intl package) really shines.
1. Parameters (Dynamic Values)
Localization isn’t just static text — you often need to inject user-specific data.
**.arb file:**
{
"welcomeUser": "Welcome, {name}"
}
Usage in Flutter:
Text(l10n.welcomeUser("Halid"));
Output:
Welcome, Halid
Here, {name} acts as a placeholder that gets replaced at runtime. This keeps your translations reusable and clean.
2. Pluralization
Different languages have different plural rules, so hardcoding strings like “items” doesn’t scale. ICU handles this elegantly:
{
"itemCount": "{count, plural, =0{No items} one{1 item} other{{count} items}}"
}
Usage:
l10n.itemCount(0); // No items
l10n.itemCount(1); // 1 item
l10n.itemCount(5); // 5 items
This ensures the correct grammatical form is used automatically based on the value and locale.
3. Gender Support
Some languages require gender-specific phrasing. ICU provides a select format for this:
{
"userGender": "{gender, select, male{He} female{She} other{They}} liked this"
}
Usage:
l10n.userGender("male"); // He liked this
l10n.userGender("female"); // She liked this
l10n.userGender("other"); // They liked this
4. Date & Number Formatting
Localization also includes formatting values according to regional conventions — dates, currencies, and numbers vary widely across locales.
Using the intl package:
final date = DateFormat.yMMMMd().format(DateTime.now());
final price = NumberFormat.currency(locale: 'en_IN').format(12345);
print(date); // April 28, 2026 (depends on locale)
print(price); // ₹12,345.00Dates follow local formats (e.g., “April 28, 2026” vs “28 April 2026”)
- Dates follow local formats (e.g., “April 28, 2026” vs “28 April 2026”)
- Numbers and currencies respect local separators and symbols (₹12,345 in India)
5. RTL Support
Flutter automatically handles RTL layouts for languages like Arabic.
Just include:
Locale('ar')
Flutter flips:
- Text direction
- Layout alignment
6. Locale Switching (Runtime)
// You can replace this with your preferred state management solution.
class LocaleProvider extends ChangeNotifier {
Locale _locale = const Locale('en');
Locale get locale => _locale;
void setLocale(Locale locale) {
_locale = locale;
notifyListeners();
}
}
MaterialApp(
locale: provider.locale,
) Locale get locale => _locale;
7. Fallback Strategy
If translation is missing:
- Falls back to default locale (usually
en)
Best practice:
- Keep
app_en.arbcomplete - Validate missing keys in CI
8. Folder Structure (Recommended)
lib/
├── l10n/
│ ├── app_en.arb
│ ├── app_ml.arb
│
├── core/
│ └── localization/
│ └── locale_provider.dart
9. Performance Considerations
- Localization is compile-time generated → very fast
- No runtime JSON parsing
- Minimal memory overhead
10. Common Mistakes
❌ Hardcoding strings Text(“Hello”)
❌ Missing keys across ARB files
❌ Not handling pluralization
❌ Ignoring RTL testing
What are @ (meta) tags in ARB?
In ARB files, keys starting with @ are metadata for a translation. They don’t show in the UI — they just give extra info about the main key.
Example
{
"hello": "Hello",
"@hello": {
"description": "Greeting message shown on home screen"
}
}
Why use them?
- Help translators understand the context
- Add notes for developers
- Define placeholders (for dynamic values)
Common Usage
1. Description
"@greeting": {
"description": "Greeting message shown in home screen"
}
2. Placeholders (for dynamic values)
{
"welcomeUser": "Welcome, {name}",
"@welcomeUser": {
"placeholders": {
"name": {
"type": "String",
"example": "Halid"
}
}
}
}
"key" → actual text
"@key" → information about that text
Final Thoughts
Flutter’s localization system is:
- Type-safe
- Performant
- Scalable
But the real power comes from:
- Proper ARB structure
- Consistent key naming
- Automated validation
Using @ metadata is not mandatory, but it’s very useful in real projects, especially when working with translators or large teams.
Once set up correctly, adding a new language becomes almost effortless.
메타데이터
- post_id
- d5e0593079ce
- slug
- flutter-localization-l10n-a-production-ready-guide-d5e0593079ce
- url
- https://medium.com/@adwaithnow/flutter-localization-l10n-a-production-ready-guide-d5e0593079ce
- canonical_url
- https://medium.com/@adwaithnow/flutter-localization-l10n-a-production-ready-guide-d5e0593079ce
- author_url
- https://medium.com/@adwaithnow
- status
- ok
- fetched_at
- 2026-06-18 07:02:39