Skip to content
Blog

The intl Package for Localization in Flutter: A Deep Dive

Master the intl package for Dart and Flutter localization. Learn date formatting, number parsing, pluralization, and message extraction for global apps.

Published on • September 19, 2026

AI Assistant

The intl Package for Localization in Flutter: A Deep Dive

The intl package is the backbone of localization in Dart and Flutter. It provides internationalization and localization utilities including message formatting, date/number parsing, pluralization, and bidirectional text support.

What is the intl Package?

The intl package (part of the Dart project) implements:

  • Date formatting and parsing with locale-aware patterns
  • Number formatting and parsing for currencies, percentages, and plain numbers
  • Message formatting with ICU message syntax for plurals and selects
  • Bidirectional text support for mixed RTL/LTR content
  • Character boundary analysis for proper text iteration

Installation

dependencies:
  intl: ^0.20.0

Date Formatting

The intl package provides DateFormat for locale-aware date formatting:

import 'package:intl/intl.dart';

// Full date format
final fullFormat = DateFormat.yMMMMd('en_US');
print(fullFormat.format(DateTime(2026, 9, 19)));
// Output: September 19, 2026

// Short date format
final shortFormat = DateFormat.yMMMd('ja_JP');
print(shortFormat.format(DateTime(2026, 9, 19)));
// Output: 2026/09/19

// Custom patterns
final customFormat = DateFormat('EEEE, MMMM d, yyyy', 'de_DE');
print(customFormat.format(DateTime(2026, 9, 19)));
// Output: Samstag, September 19, 2026

// Time formatting
final timeFormat = DateFormat.Hms('fr_FR');
print(timeFormat.format(DateTime(2026, 9, 19, 14, 30, 45)));
// Output: 14:30:45

// Relative time
final relativeFormat = DateFormat.EEEE('ar');
print(relativeFormat.format(DateTime(2026, 9, 19)));
// Output: السبت

Number Formatting

NumberFormat handles locale-aware number, currency, and percentage formatting:

import 'package:intl/intl.dart';

// Currency formatting
final usdFormat = NumberFormat.currency(locale: 'en_US', symbol: '\$');
print(usdFormat.format(1234567.89));
// Output: $1,234,567.89

final eurFormat = NumberFormat.currency(locale: 'de_DE', symbol: '€');
print(eurFormat.format(1234567.89));
// Output: 1.234.567,89 €

// Percentage formatting
final percentFormat = NumberFormat.percentPattern('en_US');
print(percentFormat.format(0.856));
// Output: 86%

// Compact notation (e.g., "1.2M")
final compactFormat = NumberFormat.compact(locale: 'en_US');
print(compactFormat.format(1234567));
// Output: 1.2M

// Decimal patterns
final decimalFormat = NumberFormat.decimalPattern('hi_IN');
print(decimalFormat.format(1234567.89));
// Output: 12,34,567.89

Pluralization with ICU Messages

The intl package supports ICU message syntax for complex pluralization:

import 'package:intl/intl.dart';

// Using Intl.message with plurals
String itemCount(int count) => Intl.plural(
  count,
  zero: 'No items',
  one: '1 item',
  other: '$count items',
  name: 'itemCount',
  args: [count],
  desc: 'Number of items in the cart',
  examples: const {'count': 5},
);

print(itemCount(0)); // No items
print(itemCount(1)); // 1 item
print(itemCount(5)); // 5 items

Message Extraction

The intl package includes tools for extracting translatable messages from your Dart code:

# Extract messages to ARB files
dart run intl_utils:generate

# This scans your code for Intl.message() calls
# and creates ARB files in your l10n directory

Bidirectional Text

For apps that mix RTL and LTR text (common in Arabic, Hebrew, etc.):

import 'package:intl/bidi.dart';

// Force text direction
final rtlText = Bidi.stripHtmlIfNeeded('مرحبا Hello World');
print(Bidi.textDirection(rtlText)); // TextDirection.RTL

// Embed LTR in RTL context
final mixed = Bidi.embedControls('مرحبا Hello World');

Integration with Flutter

The intl package integrates seamlessly with Flutter’s localization system:

import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:intl/intl.dart';

class FormattedDateWidget extends StatelessWidget {
  final DateTime date;
  
  const FormattedDateWidget({super.key, required this.date});

  @override
  Widget build(BuildContext context) {
    final l10n = AppLocalizations.of(context)!;
    final locale = l10n.localeName;
    
    return Text(
      DateFormat.yMMMMd(locale).format(date),
      style: Theme.of(context).textTheme.headlineSmall,
    );
  }
}

Best Practices

  1. Use named parameters in Intl.message for clarity
  2. Always provide descriptions — translators need context
  3. Use examples to help translators understand format expectations
  4. Run the extractor regularly to keep ARB files in sync
  5. Test with plural edge cases — 0, 1, 2, and large numbers

The intl package is an indispensable tool for any Flutter developer building global applications. Its robust formatting, pluralization, and message extraction capabilities make internationalization straightforward and maintainable.