Localizing Dates, Numbers, Currencies, and Other Data Based on Locale in Flutter

Flutter provides robust support for internationalization (i18n) and localization (l10n), enabling developers to create applications that adapt to different languages, regions, and cultural preferences. Localizing data such as dates, numbers, and currencies is crucial for providing a seamless user experience. In this blog post, we will explore how to localize dates, numbers, currencies, and other data based on the locale in Flutter.

What is Localization?

Localization involves adapting an application to a specific locale, including translating text, adjusting date and time formats, currency symbols, number formats, and other locale-specific elements. It ensures that the application is culturally appropriate and user-friendly for a specific region or language.

Setting up Internationalization in Flutter

Before localizing dates, numbers, or currencies, we need to set up internationalization in the Flutter project.

Step 1: Add Dependencies

Add the necessary dependencies to your pubspec.yaml file:


dependencies:
  flutter:
    sdk: flutter
  intl: ^0.17.0  # or a newer version
  flutter_localizations:
    sdk: flutter

Then, run flutter pub get to install the dependencies.

Step 2: Configure flutter_localizations

Configure the flutter_localizations in your MaterialApp:


import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      localizationsDelegates: [
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      supportedLocales: [
        const Locale('en', 'US'), // English, United States
        const Locale('es', 'ES'), // Spanish, Spain
        const Locale('fr', 'FR'), // French, France
      ],
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Localization Demo'),
      ),
      body: Center(
        child: Text('Hello, World!'), // This will be localized later
      ),
    );
  }
}

Localizing Dates in Flutter

Dates can be formatted differently based on the locale. The intl package provides the DateFormat class for localizing dates.

Basic Date Formatting

Here’s how to format a date according to the current locale:


import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

class DateLocalizationExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final now = DateTime.now();
    final locale = Localizations.localeOf(context);
    final formatter = DateFormat.yMMMd(locale.toString());
    final formattedDate = formatter.format(now);

    return Scaffold(
      appBar: AppBar(
        title: Text('Date Localization'),
      ),
      body: Center(
        child: Text('Formatted Date: $formattedDate'),
      ),
    );
  }
}

In this example, DateFormat.yMMMd(locale.toString()) creates a formatter that displays the year, month, and day in the format specific to the current locale.

Custom Date Formatting

You can also use custom patterns to format dates:


import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

class CustomDateFormatting extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final now = DateTime.now();
    final locale = Localizations.localeOf(context);
    final formatter = DateFormat('EEEE, MMMM d, y', locale.toString()); // Example: Friday, July 9, 2024
    final formattedDate = formatter.format(now);

    return Scaffold(
      appBar: AppBar(
        title: Text('Custom Date Formatting'),
      ),
      body: Center(
        child: Text('Formatted Date: $formattedDate'),
      ),
    );
  }
}

Common date formatting patterns:

  • y: Year
  • M: Month
  • d: Day
  • E: Day of the week
  • H: Hour (24-hour format)
  • m: Minute
  • s: Second

Localizing Numbers in Flutter

Numbers also vary in formatting based on the locale, including decimal separators, thousands separators, and more. The NumberFormat class from the intl package is used to format numbers according to the locale.

Basic Number Formatting

Here’s how to format a number:


import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

class NumberLocalizationExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final number = 12345.678;
    final locale = Localizations.localeOf(context);
    final formatter = NumberFormat.decimalPattern(locale.toString());
    final formattedNumber = formatter.format(number);

    return Scaffold(
      appBar: AppBar(
        title: Text('Number Localization'),
      ),
      body: Center(
        child: Text('Formatted Number: $formattedNumber'),
      ),
    );
  }
}

In this example, NumberFormat.decimalPattern(locale.toString()) creates a formatter that formats numbers with the appropriate decimal and thousands separators for the given locale.

Custom Number Formatting

You can also format numbers to a specific number of decimal places:


import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

class CustomNumberFormatting extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final number = 12345.678;
    final locale = Localizations.localeOf(context);
    final formatter = NumberFormat('###,###.00', locale.toString());
    final formattedNumber = formatter.format(number);

    return Scaffold(
      appBar: AppBar(
        title: Text('Custom Number Formatting'),
      ),
      body: Center(
        child: Text('Formatted Number: $formattedNumber'),
      ),
    );
  }
}

Localizing Currencies in Flutter

Currency formatting varies widely based on locale, including the currency symbol, placement of the symbol, and the decimal format.

Basic Currency Formatting

Here’s how to format a currency amount:


import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

class CurrencyLocalizationExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final amount = 1234.56;
    final locale = Localizations.localeOf(context);
    final formatter = NumberFormat.currency(locale: locale.toString());
    final formattedCurrency = formatter.format(amount);

    return Scaffold(
      appBar: AppBar(
        title: Text('Currency Localization'),
      ),
      body: Center(
        child: Text('Formatted Currency: $formattedCurrency'),
      ),
    );
  }
}

In this example, NumberFormat.currency(locale: locale.toString()) creates a formatter that formats the amount as currency, using the symbol and format appropriate for the given locale.

Specifying Currency Symbol

If you need to specify a specific currency symbol, you can do so like this:


import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

class SpecificCurrencyFormatting extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final amount = 1234.56;
    final locale = Localizations.localeOf(context);
    final formatter = NumberFormat.currency(locale: locale.toString(), symbol: 'EUR');
    final formattedCurrency = formatter.format(amount);

    return Scaffold(
      appBar: AppBar(
        title: Text('Specific Currency Formatting'),
      ),
      body: Center(
        child: Text('Formatted Currency: $formattedCurrency'),
      ),
    );
  }
}

Localizing Other Data

Besides dates, numbers, and currencies, you can localize other types of data as well. For example, you can localize pluralization rules or units of measurement.

Pluralization

The intl package can also help with handling pluralization. However, for more complex text, consider using more sophisticated localization techniques, such as .arb files and code generation (which is outside the scope of this post).


import 'package:flutter/material.dart';

class PluralizationExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final count = 5;
    final message = Intl.plural(
      count,
      zero: 'No items',
      one: 'One item',
      other: '$count items',
      locale: Localizations.localeOf(context).toString(),
    );

    return Scaffold(
      appBar: AppBar(
        title: Text('Pluralization Example'),
      ),
      body: Center(
        child: Text(message),
      ),
    );
  }
}

Conclusion

Localizing dates, numbers, and currencies in Flutter involves using the intl package along with Flutter’s localization features. By formatting these types of data according to the locale, you can provide a more natural and intuitive user experience for users around the world. Ensure that your app is set up for internationalization properly, and use DateFormat, NumberFormat, and other tools to adapt your app’s display to cultural preferences.