Flutter: i18n Made Easy

Tien Do Nam
Jul 27, 2020 · 2 min read

At the time of writing, the “basic” i18n approach in Flutter is complicated and heavyweight. That’s why I decided to start my own library: fast_i18n

Step 1: Add dependencies

Please don’t forget to include the build_runner. You will need that because the JSON files will be translated at compile-time!

It is recommended to add to .

# pubspec.yaml

build_runner: any
fast_i18n: ^4.6.2

Step 2: Write JSON files

Now lets add some strings. Just make sure that they are inside the lib directory and all in one common package like lib/i18n/strings.i18n.json

Default Locale

File: strings.i18n.json{
"hello": "Hello $name",
"save": "Save",
"login": {
"success": "Logged in successfully",
"fail": "Logged in failed"

German Locale

File: strings_de.i18n.json{
"hello": "Hallo $name",
"save": "Speichern",
"login": {
"success": "Login erfolgreich",
"fail": "Login fehlgeschlagen"

Step 3: Generate the dart code

This will translate the .json files into .dart files.

flutter pub run fast_i18n


flutter pub run build_runner build --delete-conflicting-outputs

Step 4: Initialize the right language

Users expect that your app shows the right language at the start of the app.

There are 2 methods to set the locale: and . It is up to you how you implement it.

a) use device locale

void main() {

b) use specific locale

void initState() {
String storedLocale = loadFromStorage(); // your logic here

Step 4b: iOS-only

There is one small change needed for iOS users:

File: ios/Runner/Info.plist<key>CFBundleLocalizations</key>

Step 5: Finally use your translations!

That’s all! In the generated dart file you will see the famous variable.

While most libraries goes for the solution with a plain string, the approach of fast_i18n is 100% safe, and it has nice autocompletion. Let’s try this out:

import 'package:my_app/i18n/strings.g.dart'; // import

String a = t.login.success; // plain
String b = t.hello(name: 'Tom'); // with argument
String c = t.step[3]; // with index (for arrays)
String d = t.type['WARNING']; // with key (for maps)

// advanced
TranslationProvider(child: MyApp()); // wrap your app with TranslationProvider
// [...]
final t = Translations.of(context); // forces a rebuild on locale change
String translateAdvanced = t.hello(name: 'Tom');

Supported Features

  • String Interpolation, e.g.
  • Pluralization, e.g.
  • Arrays, e.g.
  • Maps, e.g.
  • Fully Dynamic, e.g.

More info at


The Startup

Get smarter at building your thing. Join The Startup’s +737K followers.