New and easy internationalization of Flutter apps
Flutter provides a set of useful APIs that enable you to support multiple languages out of the box. In this post you’ll learn how to use new simplified approach to i18n and see ways to conveniently manage the ARB files.
After 1 year since previous i18n tutorial here comes the updated and simplified version!
See the short video version:
Foreword
When building a mobile app, especially if it’s a side project, it’s common to skip the translation process until the very last moment before release. I often hear from other developers and clients that it’s difficult to manage multiple languages and there’s no common way to manage translations in Flutter apps. In this post I want to debunk this statement and show you how easy internationalization can be in Flutter.
With Flutter 1.22 a new approach to localization is available. You no longer need to run Flutter commands to generate Dart localization classes. The setup is described in the official guide, but here I want to lay out the basics that you need to get started.
Check out my video linked above for more visual guide.
General overview
The new approach to i18n introduced to Flutter in 2020 requires from you a basic setup in pubspec.yaml
, l10n.yaml
and a template ARB file. After that the code generation will run automatically during flutter packages get
or before building your app.
Steps to follow
-
Add
flutter_localizations
andintl
packagesflutter_localizations
gives you out of the box support for almost 80 languages supported by Flutter in its built-in widgets -
Add
generate: true
flag topubspec.yaml
influtter
sectiondependencies: flutter: sdk: flutter flutter_localizations: # Add this package sdk: flutter intl: ^0.16.1 # Add this package flutter: generate: true # Add this flag
-
Add
l10n.yaml
file with default configuration in the root of your app (next topubspec.yaml
)arb-dir: lib/l10n template-arb-file: app_en.arb output-localization-file: app_localizations.dart
-
Add template ARB file (and optionally desired language file) in
lib/l10n
directory asapp_en.arb
:{ "helloWorld": "Hello Flutter Engage!", "@helloWorld": { "description": "The greeting shown to the Flutter Engage attendees" } }
-
To add a new language just add another ARB file e.g.
app_pl.arb
. The Flutter translation tool will pick it up automatically and assume its locale based on the file name. -
Run
flutter packages get
to trigger the localization classes generation. Flutter transaltion tool will create localization delegate in the.dart-tool
directory (i.e. it will be hidden and should not be committed to the repository). -
Use newly generated class in your
MaterialApp
by adding built-in localization delegates andAppLocalizations.delegate
import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; // important import 'package:flutter_gen/gen_l10n/app_localizations.dart'; // important class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( localizationsDelegates: AppLocalizations.localizationsDelegates, // important supportedLocales: AppLocalizations.supportedLocales, // important home: MyHomePage(), ); } }
-
That’s all! 🎉 Now you can use your translated term
helloWorld
in your widget tree:Text(AppLocalizations.of(context).helloWorld),
Thanks to this new approach the only thing you need to do in order to add a new term is to edit the template ARB file (and potentially other languages). After each flutter packages get
the term should be automatically added to the generated localization delegate.
Automate adding terms to ARB file
I came up with a setup to use Flutter Intl
extension to add terms automatically to template ARB file, but it’s a bit tricky (see the end of the post). I’m working on the extension that will support vanilla Flutter setup so that it will look more or less like this:
What would you say about something like this? And imagine term being added automatically to all your arb files, and in result regenerating dart classes. pic.twitter.com/rNqkJsGfkW
— Dominik Roszkowski ⚡️ (@OrestesGaolin) February 18, 2021
Translation services and ARB files
Only few translation services support ARB files out of the box. This is the list I came up with:
- Arbify - self hosted, ARB as first class citizen ✔️
- Localizely - ARB as first class citizen ✔️
- Crowdin - ARB supported ✔️ but a bit tricky (e.g. names not changed automatically and source file has to be ARB too)
- POEditor - not supported, but json can be converted to ARB without plural support ✔️
- Loco - ARB supported, but without placeholders and genders ✔️
- Lingohub - not supported
- Weblate - not supported
- Transifex - not supported
- Pootle - not supported
There are also some standalone editors like this web-based (without plurals support) and BabelEdit which is a desktop editor.
In my case the most convenient to use was Localizely even though it’s paid for closed source projects. It has a free plan and is available for open source projects as well. I’m not paid to promote them :)
ARB files
A typical ARB file can look like this:
{
"@@locale" : "en",
"page_home_counter" : "{count, plural, one{You have pushed the button once} other{You have pushed the button {count} times}}",
"@page_home_counter" : {
"type" : "text",
"description" : ""
},
"helloWorldOn": "Hello World on {date}",
"@helloWorldOn": {
"description": "A message with a date parameter",
"placeholders": {
"date": {
"type": "DateTime",
"format": "yMd"
}
}
}
}
The syntax used in case of the plural form in the page_home_counter
is called ICU message and allows for pretty complex terms (e.g. number formatting or currencies). There’s a great overview available in the official Flutter guide.
VS Code/Android Studio extension - Flutter Intl
One of the best tools to streamline internationalization of Flutter apps is Flutter Intl extension (also available for Android Studio). I described this in detail in previous post, but unfortunately right now it’s not compatible with new official i18n approach i.e. it will generate its own localization delegate. It’s completely fine to use it, though, so check out my previous video and post to see how it can be used.
I found a way to force it to be compatible with the approach described above. In the pubspec.yaml
set following configuration of Flutter Intl:
flutter_intl:
arb_dir: lib/l10n_new
class_name: Translations
enabled: true
And in l10n.yaml
use following configuration:
arb-dir: lib/l10n_new
template-arb-file: intl_en.arb
output-localization-file: app_localizations.dart
output-class: Translations
This will cause Flutter Intl extension to add new terms to intl_en.arb
. However, it will still generate its own delegate inside lib/generated
directory. What you can do is just to ignore them and user the Translations
class from .dart-tool
as described above.
Wrap up
I hope this short tutorial helped you to understand the new Flutter internationalization approach. The ARB files are very powerful, but at the same time almost no translation services support it. Because of the multitude of i18n tutorials on the Internet, it feels like the official guide somehow got lost. Please check it out and feel free to reach out to me with any questions.
The example app code script are available in the project repository.