← Back to list

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…

Adwaith S · 2026-04-28 14:50 · 116 claps · 3.4 min read
#localization #l10n #flutter #mobile-app-development
Open on Medium ↗
Wiki topics: 📱 · Mobile Development

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:

  • intl package 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:

  • AppLocalizations class
  • 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.arb complete
  • 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