Convenient internationalization of Flutter apps
Tags: flutter, i18n, l10n, arb
Published: 2020-02-25 08:36:08

---
title: Convenient internationalization of Flutter apps
published: true
date: 2020-02-25 8:30:00 UTC
tags: flutter, i18n, l10n, arb
canonical_url: 
---

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:

{% youtube 3IRGTTjVHug %}

There's also [original post on my blog](https://roszkowski.dev/2020/i18n-in-flutter/) 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](https://flutter.dev/docs/development/accessibility-and-localization/internationalization)
- [Using json files and custom localization delegate](https://medium.com/flutter-community/flutter-internationalization-the-easy-way-using-provider-and-json-c47caa4212b2)
- Recent semi-automatic proposal of [downloading arb files with some custom scripts](https://blog.codemagic.io/localising-flutter-applications-and-automating-the-localisation-process/)
- [Generating constant resources with r\_flutter package](https://pub.dev/packages/r_flutter)
- Some other fairly popular localization techniques:    
  - [flutter\_translate](https://pub.dev/packages/flutter_translate)
  - [easy\_localization](https://pub.dev/packages/easy_localization)
  - [ez\_localization](https://pub.dev/packages/ez_localization)
  - dynamic [auto\_localization](https://pub.dev/packages/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:

1. 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](https://github.com/bmw-tech/arb-converter-cli)[^2]
2. Fetch translation files from API directly in VS Code (and convert them to arb if necessary)
3. Automatically generate translation classes with [Flutter Intl](https://marketplace.visualstudio.com/items?itemName=localizely.flutter-intl) extension
4. 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](https://jamesblasco.github.io/arb_editor/master/#/) (without plurals support) and [BabelEdit](https://www.codeandweb.com/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](https://marketplace.visualstudio.com/items?itemName=localizely.flutter-intl) extension (also available for [Android Studio](https://plugins.jetbrains.com/plugin/13666-flutter-intl)). 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](https://github.com/orestesgaolin/i18n_example_flutter/blob/master/scripts/localizely.sh).

{% gist https://gist.github.com/orestesgaolin/e2c1716e49bb7ccfdeb67ce9cde15305.js %}
## 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](https://github.com/flutter/flutter/issues/41437) 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](https://github.com/orestesgaolin/i18n_example_flutter).

* * *


[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.