How to translate your Flutter app (using intl 0.13.1)

Andreas Löw, Joachim Grill
GitHub
How to translate your Flutter app (using intl 0.13.1)

This is the older version of the Flutter tutorial. It covers the intl package up to version 0.13.1. The newer versions if the intl package use a completely different way of handling the translation files.

Read this tutorial if you want to support the newest version of Flutter and intl:
How to translate your Flutter app and edit your .arb file

In this tutorial we explain how to quickly set up translations for your Flutter app. The first two sections explain how to set up a simple demo application — feel free to skip it ;-)

We've created this tutorial on a Mac with XCode already installed. The Flutter app runs in the iOS simulator. We assume that it should be easy enough for you to adapt the steps to run on Windows or Linux and/or run the app on an Android device.

Prepare a simple demo project

Install Flutter

git clone https://github.com/flutter/flutter.git
export PATH=$PATH:$(pwd)/flutter/bin
flutter precache

Alternatively Flutter can be downloaded as zip archive from flutter.dev

Create and launch the demo app in the simulator

Start iPhone simulator:

open -a Simulator

Create and run demo app:

flutter create myapp
cd myapp
flutter run

Setup internationalization

Add the required dependencies to your project

Add these lines to dependencies: in pubspec.yaml

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^0.1.2
  flutter_localizations:
      sdk: flutter
  flutter_cupertino_localizations: ^1.0.1
  intl:
  intl_translation:

Import Flutter localizations and add pass them to MaterialApp constructor in lib/main.dart. Some lines are commented out for now — you need them later but starting the app would fail with them.

import 'package:flutter_localizations/flutter_localizations.dart';
// import 'MyLocalizations.dart';

...


class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(

      ...

      localizationsDelegates: [
          // const MyLocalizationsDelegate(),
          GlobalMaterialLocalizations.delegate,
          GlobalWidgetsLocalizations.delegate,
          GlobalCupertinoLocalizations.delegate
      ],
      supportedLocales: [
          const Locale('en', ''), // English
          const Locale('de', ''), // German
      ],
      
      ...

Open ios/Runner.xcodeproj with Xcode and add "German" to the Localizations of the Runner project:

How to translate your Flutter application How to translate your Flutter application

flutter run should still compile and run the app successfully. Flutter texts are now localized, but localization of our own texts is still missing.

Add localization class

Create a new file lib/MyLocalizations.dart with your own Localization and the delegate class:

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

class MyLocalizations {
  MyLocalizations(this.localeName);

  static Future<MyLocalizations> load(Locale locale) {
    final String name = locale.countryCode.isEmpty ? locale.languageCode : locale.toString();
    final String localeName = Intl.canonicalizedLocale(name);
    return initializeMessages(localeName).then((_) {
      return MyLocalizations(localeName);
    });
  }

  static MyLocalizations of(BuildContext context) {
    return Localizations.of<MyLocalizations>(context, MyLocalizations);
  }

  final String localeName;

  String get pushCounterText {
    return Intl.message(
      'You have pushed the button this many times:',
      name: 'pushCounterText',
      desc: 'A description for the push counter',
      locale: localeName,
    );
  }
}

class MyLocalizationsDelegate extends LocalizationsDelegate<MyLocalizations> {
  const MyLocalizationsDelegate();

  @override
  bool isSupported(Locale locale) => ['en', 'de'].contains(locale.languageCode);

  @override
  Future<MyLocalizations> load(Locale locale) => MyLocalizations.load(locale);

  @override
  bool shouldReload(MyLocalizationsDelegate old) => false;
}

This file does not compile as long as messages_all.dart has not yet been generated (see below).

Replace your strings to localize with calls to the localization class

Import MyLocalizations.dart in main.dart, pass MyLocalizationsDelegate() to the MaterialApp constructor. You can do this by removing the comments from the lines in the previous section.

You now have to replace all your string literals you want to translate with method calls that retrieve the translated texts.

Replace string literals 'You have pushed the button this many times:' with MyLocalizations.of(context).pushCounterText:

  children: <Widget>[
    Text(
      MyLocalizations.of(context).pushCounterText,
    ),

Manage your translations

Extract the message IDs and primary language string literals from MyLocalizations.dart:

mkdir lib/l10n
flutter pub pub run intl_translation:extract_to_arb --output-dir=lib/l10n lib/MyLocalizations.dart

This command line extracts the strings from your application and creates an .arb file. These files are so-called Application Resource Bundle files, a file format invented by Google. See Application Resource Bundle Specification for more details.

The file format is based on JSON and uses keys starting with @ to add metadata to the values in the JSON file.

Copy the intl_messages.arb to intl_de.arb and intl_en.arb and translate the German arb file.

intl_en.arb:

{
  "@@last_modified": "2020-01-08T11:39:22.562134",
  "pushCounterText": "You have pushed the button this many times:",
  "@pushCounterText": {
    "description": "A description for the push counter",
    "type": "text",
    "placeholders": {}
  }
}

intl_de.arb:

{
    "@@last_modified": "2020-01-08T11:39:22.562134",
    "pushCounterText": "Du hast den Button so oft gedrückt:",
    "@pushCounterText": {
        "description": "A description for the push counter",
        "type": "text",
        "placeholders": {}
    }
}

Finally, you have to create the .dart files from the .arb files:

flutter pub pub run intl_translation:generate_from_arb --output-dir=lib/l10n --no-use-deferred-loading lib/MyLocalizations.dart lib/l10n/intl_*.arb

Run localized app

flutter run

Important on iOS:
You have to change the Language and Region in the settings to see the translations in the other languages.

Flutter application with English localizations
Flutter application with German localizations

How to add more translations

To add more translations add new methods to lib/MyLocalizations.dart similar to the existing one:

 String get helloWorldText {
    return Intl.message(
      'Hello World!',
      name: 'helloWorldText',
      desc: 'The famous words',
      locale: localeName,
    );
  }

And use the strings in your application:

MyLocalizations.of(context).helloWorldText

Simplify your translation workflow

Editing the .arb translation files might get a bit cumbersome over the time:

  • You have to escape the strings to write proper .json files
  • You have to update all language files from the newly extracted intl_messages.arb
  • The .arb files are bad to read because of all the metadata

A much simpler workflow is possible if you use BabelEdit:

  • After extracting the intl_messages.arb you simply have to copy it to your main language — e.g. intl_en.arb
  • BabelEdit automatically inserts the new translations in all other files and keeps them in sync
  • The nice user interface only displays relevant information
  • Use features like pre-translate to automatically create translations for other languages
  • Export and import into other formats (e.g. Excel) to send to translators
  • Spellchecker

You can download BabelEdit for Windows, macOS and Linux from here:

Start BabelEdit after the installation and simply drag & drop your project directory into the main window. Click on the Flutter ARB project:

Translate your Flutter application with BabelEdit

BabelEdit now searches the project folder for .arb files and presents them with a guess for the languages contained in the files. Confirm de and en, ignore the intl_messages.arb:

Select the language for your flutter translation files

Select your primary language — that is the language that you use in your main translations. It's used as the source language for features like pre-translate. Select en-US by clicking on the configure button:

Select english as source language

BabelEdit now automatically displays suggestions for your translations:

How to pre-translate your .arb files

Finally, save the files using the save button from the toolbar. BabelEdit asks you for the name and location of a .babel file — BabelEdit's project file that contains all project relevant settings.

It also updates your .arb files with the translations.