Dominik Roszkowski
Posted on February 25, 2020
There are many ways to have multiple languages in your app in Flutter. Some folks use canonical Flutter arb files. Other use some json equivalents or statically typed constant resources like r_flutter. In this post I’m going to show you the way I find the most convenient to setup and use.
See the short video version:
There's also original post on my blog if you prefer.
Foreword
While researching the i18n[^1] topic I found several different ways of adding multiple languages support in Flutter:
- Canonical Flutter way with manual configuration
- Using json files and custom localization delegate
- Recent semi-automatic proposal of downloading arb files with some custom scripts
- Generating constant resources with r_flutter package
- Some other fairly popular localization techniques:
- flutter_translate
- easy_localization
- ez_localization
- dynamic auto_localization
- and perhaps several others
As you can see there’s no single best way to handle this right now. All of them share some common steps, though. Together with our colleagues we also have been using a custom localization solution with some bash scripts to fetch and convert localization json files. Unfortunately this causes delays when onboarding new people and starting new projects.
My goal was to find a solution that:
- is relatively quick to setup in new project (either is single time manual setup or fully automatic),
- supports {placeholders} and preferably plural forms,
- would be nice to rely on arb files which are native to Flutter.
After few days of hacking I think I found something that I can share with you.
General overview
Simply speaking my solution is as follows:
- Use some tool to translate your app (POEditor, Localizely, Loco, CrowdIn…).
- Not all of them support exporting arb files. In that case export json and convert it to arb with arb-converter-cli[^2]
- Fetch translation files from API directly in VS Code (and convert them to arb if necessary)
- Automatically generate translation classes with Flutter Intl extension
- Be happy with statically typed translations with plurals and placeholder support
This approach requires some configuration steps once but later is mostly automatic due to VS Code extension and tasks in VS Code.
Translation services and arb files
Only few translation services support arb files out of the box. This is the list I came up with:
- Localizely - arb supported ✔️
- 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 POEditor, but the json file couldn’t be easily converted to arb[^1]. Thus, I stayed with Localizely for now. Both have free plans that should be enough for smaller apps.
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). It generates the boilerplate getters for translation keys. It will also generate special methods if translation term has placeholder or plural version. Unfortunately, it’s closed source.
The setup is pretty straightforward and I recommend you to read the README.
In short, if you have enabled Flutter Intl extension, then you just put your arb files in l10n directory and the extension generates Dart files for you. The extension automatically updates available locales and generates localization delegate. Then you can reference translation terms in you widgets via:
Text(
S.of(context).page_home_counter(_counter),
// 'You have pushed the button {count} times',
),
And if you take a look at the source of the generated method you’ll see typical Flutter intl
package handling:
String page_home_counter(dynamic count) {
return Intl.plural(
count,
one: 'You have pushed the button once',
other: 'You have pushed the button $count times',
name: 'page_home_counter',
desc: '',
args: [count],
);
}
Fetching translation updates with VS Code
VS Code allows to set custom tasks which are arbitrary shell commands. That’s what I wanted to utilize to semi-automatically fetch translation files from Localizaly or POEditor API. I prepared simple bash script to download arb files from Localizely and json files from POEditor. You can take a look at the tasks.json file in this gist if you want to use them from VS Code. The script is available here.
Wrap up
I hope this short tutorial helped you to improve your internationalization workflow. The arb files are very powerful, but at the same time almost no translation services support it. There is one issue in the Flutter GitHub project that holds the discussion about the simplified i18n process. I really recommend you to read it.
The app code and download script are available in the project repository.
[1^]: i18n stands for internationalization which is just adding multiple languages to the app, whereas l12n stands for localization which is adapting your app to given locale/culture/region (e.g. different layout or navigation).
[2^]: Unfortunately json conversion works for very simple terms without plural version but works OK with placeholders.
Posted on February 25, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.