Flutter intl Package: Complete Setup and Usage Guide 2025
The intl package is the foundation of Flutter internationalization. Whether you're building a simple app or a complex multilingual platform, understanding how to use flutter_intl and the intl package is essential for every Flutter developer.
What is the Flutter intl Package?
The intl package provides internationalization and localization support for Dart applications. It includes:
- Message formatting with placeholders
- Date and time formatting
- Number and currency formatting
- Plural and gender support
- Bidirectional text handling
Quick Setup Guide
Step 1: Add Dependencies
# pubspec.yaml
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
intl: ^0.19.0
flutter:
generate: true
Step 2: Configure l10n.yaml
Create l10n.yaml in your project root:
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
output-class: AppLocalizations
Step 3: Create Your First ARB File
Create lib/l10n/app_en.arb:
{
"@@locale": "en",
"appTitle": "My App",
"@appTitle": {
"description": "The application title"
},
"welcomeMessage": "Welcome, {username}!",
"@welcomeMessage": {
"description": "Welcome message with user name",
"placeholders": {
"username": {
"type": "String",
"example": "John"
}
}
}
}
Step 4: Configure MaterialApp
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Intl Demo',
localizationsDelegates: const [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: const [
Locale('en'),
Locale('es'),
Locale('fr'),
Locale('ar'),
],
home: const HomePage(),
);
}
}
Step 5: Use Translations in Widgets
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
return Scaffold(
appBar: AppBar(
title: Text(l10n.appTitle),
),
body: Center(
child: Text(l10n.welcomeMessage('John')),
),
);
}
}
Date and Time Formatting with intl
The intl package excels at locale-aware date formatting:
import 'package:intl/intl.dart';
class DateFormattingExample {
void formatDates() {
final now = DateTime.now();
// Short date format
final shortDate = DateFormat.yMd('en_US').format(now);
// Output: 12/4/2025
// Long date format
final longDate = DateFormat.yMMMMd('en_US').format(now);
// Output: December 4, 2025
// Time format
final time = DateFormat.jm('en_US').format(now);
// Output: 3:30 PM
// Custom pattern
final custom = DateFormat('EEEE, MMMM d, y').format(now);
// Output: Thursday, December 4, 2025
// Different locale
final frenchDate = DateFormat.yMMMMd('fr_FR').format(now);
// Output: 4 décembre 2025
}
}
Number and Currency Formatting
import 'package:intl/intl.dart';
class NumberFormattingExample {
void formatNumbers() {
// Number formatting
final number = NumberFormat('#,##0.00', 'en_US').format(1234567.89);
// Output: 1,234,567.89
// Currency formatting
final usd = NumberFormat.currency(locale: 'en_US', symbol: '\$').format(99.99);
// Output: $99.99
final euro = NumberFormat.currency(locale: 'de_DE', symbol: '€').format(99.99);
// Output: 99,99 €
// Compact numbers
final compact = NumberFormat.compact(locale: 'en_US').format(1500000);
// Output: 1.5M
// Percentage
final percent = NumberFormat.percentPattern('en_US').format(0.75);
// Output: 75%
}
}
Message Formatting with Placeholders
Simple Placeholders
{
"greeting": "Hello, {name}!",
"@greeting": {
"placeholders": {
"name": {"type": "String"}
}
}
}
Numeric Placeholders
{
"itemsInCart": "You have {count} items in your cart",
"@itemsInCart": {
"placeholders": {
"count": {"type": "int"}
}
}
}
Date Placeholders
{
"lastLogin": "Last login: {date}",
"@lastLogin": {
"placeholders": {
"date": {
"type": "DateTime",
"format": "yMMMd"
}
}
}
}
Plural Support with intl
Handle complex plural rules correctly:
{
"messageCount": "{count, plural, =0{No messages} =1{One message} other{{count} messages}}",
"@messageCount": {
"placeholders": {
"count": {"type": "int"}
}
}
}
For languages with complex plural rules like Arabic:
{
"messageCount": "{count, plural, =0{لا رسائل} =1{رسالة واحدة} =2{رسالتان} few{{count} رسائل} many{{count} رسالة} other{{count} رسالة}}",
"@messageCount": {
"placeholders": {
"count": {"type": "int"}
}
}
}
Gender Support
{
"userWelcome": "{gender, select, male{Welcome, Mr. {name}} female{Welcome, Ms. {name}} other{Welcome, {name}}}",
"@userWelcome": {
"placeholders": {
"gender": {"type": "String"},
"name": {"type": "String"}
}
}
}
intl_utils vs flutter_intl: Which to Choose?
| Feature | intl_utils | flutter_intl (IDE Plugin) |
|---|---|---|
| CLI support | Yes | No |
| IDE integration | No | Yes (VS Code, Android Studio) |
| Watch mode | Yes | Yes |
| ARB generation | Yes | Yes |
| Best for | CI/CD, Teams | Individual developers |
Common intl Package Errors and Fixes
Error: "Getter not found: 'of'"
Solution: Run flutter gen-l10n to generate localization files.
flutter gen-l10n
Error: "The argument type 'String' can't be assigned"
Solution: Check your placeholder types match the ARB definition.
Error: "LocalizationsDelegate not found"
Solution: Ensure you've added the delegate to MaterialApp:
localizationsDelegates: [
AppLocalizations.delegate,
// ... other delegates
],
Performance Best Practices
1. Lazy Load Locales
supportedLocales: AppLocalizations.supportedLocales,
localeResolutionCallback: (locale, supportedLocales) {
return supportedLocales.firstWhere(
(supported) => supported.languageCode == locale?.languageCode,
orElse: () => supportedLocales.first,
);
},
2. Cache DateFormat Instances
class DateFormatters {
static final Map<String, DateFormat> _cache = {};
static DateFormat getFormatter(String pattern, String locale) {
final key = '$pattern-$locale';
return _cache.putIfAbsent(key, () => DateFormat(pattern, locale));
}
}
3. Use const Constructors
const Locale('en'); // Good - creates compile-time constant
Locale('en'); // Works but creates new instance each time
FlutterLocalisation: The Better Way
While the intl package is powerful, managing ARB files manually across multiple languages becomes tedious. FlutterLocalisation automates the entire workflow:
- Visual editor for translations (no JSON editing)
- AI-powered translations across 50+ languages
- Automatic ARB file generation
- Git integration for seamless syncing
- Real-time collaboration for teams
Conclusion
The intl package is essential for Flutter internationalization, providing robust support for message formatting, dates, numbers, plurals, and more. While it's powerful, the complexity grows with each language you add.
For professional apps targeting multiple markets, consider using FlutterLocalisation to automate translation management while still leveraging the intl package under the hood.
Ready to simplify your Flutter internationalization? Try FlutterLocalisation free and automate your intl workflow with AI-powered translations and visual editing.