intl

repository·master·Indexed 19 days ago

https://github.com/dart-archive/intl

A Dart package providing internationalization and localization facilities, including message translation, plurals, genders, and date/number formatting. It features the Intl class for locale management and message formatting, NumberFormat and DateFormat for locale-aware data parsing, and BidiFormatter for bidirectional text. The package supports extracting messages to .arb files and generating translated libraries via the intl_translation package.

Tokens
10.1K
Snippets
36
Records
42
Agent score
67%

What's inside intl

  1. Understand how date formatting data is structured

    master

    The intl package uses two primary data directories to handle locale-specific date formatting when reading data from JSON files or over a network:

    1. patterns: Contains mappings from skeleton strings (e.g., yMd) to locale-specific format patterns. This data is equivalent to date_time_patterns.dart.
    2. symbols: Contains locale-specific symbols used during formatting, such as the names of weekdays and months. This data is equivalent to date_symbol_data_locale.dart.

    A localeList.dart file is used to maintain a comprehensive list of all available locales supported by these directories.

  2. Manage the current locale in intl

    master

    The intl package uses a single global locale called defaultLocale. Most operations use this locale unless explicitly overridden. You can manage locales in three ways:

    1. Set the global locale: Use Intl.defaultLocale to change the locale for the entire application.
    2. Override for a specific operation: Use Intl.withLocale(locale, () => ...) to run a specific block of code with a different locale. This is preferred if your application uses multiple locales simultaneously, as it also covers async tasks spawned within that block.
    3. Specify locale per object/method: Create format objects (like DateFormat) with a specific locale, or pass a locale parameter directly to methods.
    // Set global locale
    Intl.defaultLocale = 'pt_BR';
    
    // Override for a specific operation
    Intl.withLocale('fr', () => print(myLocalizedMessage()));
    
    // Specify locale in a format object
    var format = DateFormat.yMd('ar');
    var dateString = format.format(DateTime.now());
    
    // Specify locale in a method call
    print(myMessage(dateString, locale: 'ar'));
  3. Extract and generate translated messages

    master

    To move from hardcoded messages to a translated application, follow these steps using the intl_translation package:

    1. Extract messages: Run extract_to_arb.dart to create an .arb file containing all your messages.
      pub run intl_translation:extract_to_arb --output-dir=target/directory my_program.dart
    2. Generate libraries: Use generate_from_arb.dart to create Dart libraries for each locale based on your translated .arb files.
      pub run intl_translation:generate_from_arb --generated_file_prefix=<prefix> <my_dart_files> <translated_ARB_files>
    3. Initialize: Import the generated messages_all.dart file and call the initialization function for your target locale.
    import 'my_prefix_messages_all.dart';
    
    // After initialization, Intl.message calls will return translations
    initializeMessages('dk').then(printSomeMessages);
  4. Initialize locale data for dates, numbers, and messages

    master

    To reduce application size, intl uses an asynchronous initialization step for different types of locale data. You must initialize the specific area of internationalization you intend to use before performing operations.

    • Messages: Requires importing generated files and calling an initialization function (e.g., initializeMessages).
    • Dates: Requires calling initializeDateFormatting from package:intl/date_symbol_data_local.dart.
    • Numbers: Requires separate initialization (details in subsequent sections).
  5. Use the Intl class for internationalization

    master

    The Intl class is the primary entry point for internationalization tasks in Dart. It provides methods for message formatting (including plurals, gender, and selection), date/number formatting, and locale management.

    Key capabilities:

    • Message Formatting: Use Intl.message, Intl.plural, Intl.gender, and Intl.select to create translatable strings.
    • Locale Management: Set a defaultLocale or use Intl.withLocale to run specific code blocks with a different locale.
    • Formatting: Create locale-aware formatters via anIntl.date(pattern).
    import 'package:intl/intl.dart';
    
    // Example: Message formatting
    String hello(String name) => Intl.message(
      'Hello, $name',
      name: 'hello',
      args: [name],
      desc: 'Say hello',
    );
    
    // Example: Setting default locale
    Intl.defaultLocale = 'pt_BR';
    
    // Example: Using a specific locale for a block of code
    Intl.withLocale('fr', () {
      print(NumberFormat.format(123456));
    });
  6. Use BidiFormatter to handle bidirectional text

    master

    The BidiFormatter class is used to format text that contains both Left-to-Right (LTR) and Right-to-Left (RTL) characters. This prevents layout issues when mixing languages (e.g., embedding English in Hebrew) by either wrapping text in HTML <span> tags or using Unicode BiDi control characters.

    Key Capabilities

    1. BiDi Wrapping: Automatically wraps text in <span> tags with dir attributes or Unicode markers (LRE/RLE/PDF) to isolate directionality.
    2. Directionality Estimation: Automatically detects if a string is LTR or RTL based on its content.
    3. HTML Escaping: When generating HTML output, the formatter can automatically escape plain text to prevent XSS.
    4. Direction Resetting: Can append Unicode marks (LRM/RLM) to ensure the text following the inserted string returns to the correct context directionality.
    // Example: Wrapping text for HTML output in an LTR context
    var formatter = BidiFormatter.LTR();
    String safeHtml = formatter.wrapWithSpan("Hello (Hebrew: שלום)", isHtml: false);
    // Result might look like: <span dir="rtl">שלום</span>
  7. Understand the DateSymbols class

    master
    The DateSymbols class holds localization data for date formatting. It contains strings for months, weekdays, eras, and quarters in various lengths (narrow, short, full), as well as standalone versions of these names. It also stores locale-specific configuration like the first day of the week, weekend ranges, and supported date/time/datetime formats. This data is typically used in conjunction with date_time_patterns to define named formats for a specific locale.
  8. Handle plurals and genders in messages

    master

    For complex expressions like plurals and genders, you can use Intl.plural and Intl.gender. These can be nested.

    Using Intl.plural: You can wrap the plural logic inside an Intl.message call, or if the plural is the top-level requirement of the function, you can call Intl.plural directly and provide the name, args, desc, and examples to it.

    Using Intl.gender: Use Intl.gender to provide different message variations based on a gender string (e.g., 'male', 'female', 'other').

    // Plural example
    remainingEmailsMessage(int howMany, String userName) =>
      Intl.plural(
        howMany,
        zero: 'There are no emails left for $userName.',
        one: 'There is $howMany email left for $userName.',
        other: 'There are $howMany emails left for $userName.',
        name: 'remainingEmailsMessage',
        args: [howMany, userName],
        desc: 'How many emails remain after archiving.',
        examples: const {'howMany': 42, 'userName': 'Fred'});
    
    // Gender example
    notOnlineMessage(String userName, String userGender) =>
      Intl.gender(
        userGender,
        male: '$userName is unavailable because he is not online.',
        female: '$userName is unavailable because she is not online.',
        other: '$userName is unavailable because they are not online',
        name: 'notOnlineMessage',
        args: [userName, userGender],
        desc: 'The user is not available to hangout.',
        examples: const {'userGender': 'male', 'userName': 'Fred'});
  9. Format and parse numbers with NumberFormat

    master

    Use the NumberFormat class to format numbers according to specific patterns and locales. If no locale is provided, it defaults to Intl.defaultLocale.

    You can also access f.symbols to retrieve locale-specific separator characters and patterns.

    var f = NumberFormat('###.0#', 'en_US');
    print(f.format(12.345)); // Output: 12.35
  10. Create localized messages with Intl.message

    master

    Localized messages are defined as functions that return an Intl.message call. This allows you to provide metadata for translators, such as a name, description, and examples.

    Rules for message strings:

    • Use a restricted form of Dart string interpolation: only the function's parameters can be used in simple expressions.
    • Local variables and expressions with curly braces {} are not allowed inside the message string.
    • If you need to format numbers or dates within a message, format them outside the function and pass the resulting string into the message.

    Parameters:

    • name: Must match the function name (or ClassName_methodName).
    • args: Must match the function's argument list.
    • desc: A description for translators.
    • examples: A map of example inputs and outputs.
    greetingMessage(name) => Intl.message(
        'Hello $name!',
        name: 'greetingMessage',
        args: [name],
        desc: 'Greet the user as they first open the application',
        examples: const {'name': 'Emily'});
    
    print(greetingMessage('Dan'));
  11. Handle Bidirectional Text with BidiFormatter

    master

    The BidiFormatter class provides utilities for managing Bidirectional (BiDi) text, which is essential when mixing Left-to-Right (LTR) and Right-to-Left (RTL) scripts. You can wrap strings with Unicode directional indicator characters or with an HTML <span> to explicitly set the text direction.

    Direction can be specified using:

    • BidiFormatter.RTL(): For Right-to-Left text.
    • BidiFormatter.LTR(): For Left-to-Right text.
    • Automatic detection from the text content.

    Available wrapping methods:

    • wrapWithUnicode(String text): Wraps the string with Unicode directional indicator characters.
    • wrapWithSpan(String text): Wraps the string in an HTML <span> tag to indicate direction.
    BidiFormatter.RTL().wrapWithUnicode('xyz');
    BidiFormatter.RTL().wrapWithSpan('xyz');
  12. Format and parse dates with DateFormat

    master

    Use DateFormat to format or parse DateTime objects. You can use ICU/CLDR skeletons (like yMd) or explicit patterns (like EEEEE).

    Important: Before formatting dates for a specific locale, you must initialize the date symbol data.

    Limitations: Time zones are not currently supported (only local or UTC). Formatting/parsing Duration is not yet implemented.

    import 'package:intl/date_symbol_data_local.dart';
    
    // 1. Initialize data
    await initializeDateFormatting('de_DE', null);
    
    // 2. Format
    var format = DateFormat.yMMMMEEEEd();
    print(format.format(DateTime.now()));
    
    // 3. Parse
    var date = DateFormat.yMd('en_US').parse('1/10/2012');