How to localize Flutter app with Localazy
Tags: localization, howto, flutter
Published: 2022-04-29 09:40:11

<!--kg-card-begin: html-->

## How to localize Flutter app with Localazy

**[Localization](https://localazy.com/dictionary/localization)** is the process of rendering the content of your app into other languages and customizing your app for each target market that you want to support.

## Benefits Of Localazy

### Save money on translations

Save up to 50% of translation costs thanks to **[shared translations](https://localazy.com/docs/general/what-is-localazy-sharetm)**. Localize your app to 80+ languages for free.

#### What is Localazy ShareTM

[ShareTM](https://localazy.com/dictionary/sharetm) is [what makes Localazy unique](https://localazy.com/docs/general/what-is-localazy-sharetm) and different from other translation platforms. We are developers; we share our code on Github, Gitlab, or in another place. We cooperate, share our knowledge and libraries. We have this in our DNA. It saves us time and money; it helps us to move forward faster and produce better software.

Why don’t we share translations to make our apps better for the worldwide audience? Why we pay for translating the same words again and again? Does it make sense? It does not, and ShareTM is here to fix this issue.

Upload your app to Localazy and instantly share your translations with other apps on the platform, and as a reward, get your app translated to more languages for free.

### Stay assured about high quality

Verify translations with the **[pro-active review](https://localazy.com/docs/general/unique-review-process-and-self-managed-translations)** and use all tools for providing context to your translators for free.

### Keep track of changes

While the review is a way to ensure translation quality in other translation platforms, Localazy is organized around it. But our review process is entirely different. It’s not just a set of filtering options to find strings that may be inaccurately translated.

Our review process is a pro-active tool that helps you to verify translations and keep track of all changes that happened on Localazy while you spend your precious time developing your app and making it better. No matter if you visit Localazy every day or once per month, you never get lost! The best recipe for a peaceful mind.

## Sign Up and Create an App

Firstly, you need to **[sign up](https://localazy.com/register)** and create an app in Localazy. In this article, we’ll create a basic [Flutter](https://localazy.com/flutter) app which is using multi-language support.

![Register page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wupt632x3ywf5ot69v3f.png) 

After you create a new account in Localazy, you will see a new page which name is **Create a New App**. We are giving a name as “flutter-localazy”.

**App Type** means, if you do it public, people can help to improve translation and if you choose private, only invited people can improve the translation.

And we are choosing English as the source language.

Also, we are using **[ShareTM](https://localazy.com/docs/general/what-is-localazy-sharetm)** feature. ShareTM is what makes Localazy unique and different from other translation platforms. Briefly, **ShareTM** is highly accurate translation memory. It allows using of community translations.

![Create a New App](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bpfdtrr3e8ipm335zpgi.png) 

After all these things we can create a new project. Then you will see a “**Select Your Integration**” page. You can integrate Localazy to all these platforms, we will choose **Flutter** for now.

![Select your Integration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4ebr2u4c7quwaxrny2ep.png) 

Now, we need to install **[Localazy CLI](https://localazy.com/docs/cli/installation)** tool to manage the upload and download of phrases.

**Installation** Localazy CLI is available as a native app for all major platforms (Windows, Linux and macOS), Java’s JAR and Docker…

**Localazy CLI** is a command-line interface, and we can use it to upload files to the Localazy platform and download translations back to our app.

Also, [Localazy CLI](https://localazy.com/blog/localazy-cli-sofware-localization-tool-kotlin-github) is available as a **native app for all major platforms** (Windows, Linux and macOS), Java’s JAR and Docker image.

> You need to install Localazy CLI inside project folder or update your path

## Set Up Flutter Project

After **[install Flutter](https://flutter.dev/docs/get-started/install)**, we create a new Flutter project.

Use the `flutter create` the command to create a new project:

    $ flutter create flutter_localazy
    $ cd flutter_localazy

The command creates a Flutter project directory called `flutter_localazy` that contains a simple demo app that uses **[Material Components](https://material.io/guidelines)**.

![Demo App](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oi2c8i52cxxtx8ln6r5k.png) 

First step is to include required packages in `pubspec.yaml` file. For that just add the two packages name under the dependencies. It would look something like this.

    dependencies:
      flutter:
        sdk: flutter
      flutter_localizations:     //add this line
        sdk: flutter             //add this line
        
      intl_translation: ^0.17.1  //add this line

After you save this file, [Flutter](https://localazy.com/dictionary/flutter) will automatically download and it will include the packages. You can now use it in your app anywhere simply by importing it. We’ll import it in the `main.dart` file first. Go to, your `main.dart` file and add import the package.

    import 'package:flutter_localizations/flutter_localizations.dart';
    import 'package:intl/intl.dart';
    void main() => runApp(MyApp());

The next step is to set up the Localization delegates in your `main.dart` file. For that, you need to specify the two delegates first.

    Widget build(BuildContext context) {
        return MaterialApp(
          localizationsDelegates: [
            GlobalMaterialLocalizations.delegate,
            GlobalWidgetsLocalizations.delegate
          ],
          supportedLocales: [
            const Locale('en', 'US'),
            const Locale('de', 'DE')
          ],
          ...

`GlobalMaterialLocalizations.delegate` provides localized strings and other values for the Material Components library. `GlobalWidgetsLocalizations.delegate` defines the default text direction, either left to right or right to left, for the widgets library. As you can see here, we added two lists to our Material app `localizationsDelegates` & `supportedLocales`. The `supportedLocales` parameter holds the list of languages that our app will support.

Next step is to create an `AppLocalization` & `AppLocalizationDelegate`. Classes in which we’ll be defining our keywords and their translations. We’ll also use it throughout the app and for manually switching the Locale if required. Therefore I suggest you create this class in a separate folder in your lib directory. Mine looks like `/lib/locale/app_localization.dart` The AppLocalization class will only have two static methods for now. The `load()` & `of()` method.

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

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

      static AppLocalization of(BuildContext context) {
        return Localizations.of<AppLocalization>(context, AppLocalization);
      }
      
      // list of locales
    String get heyWorld {
      return Intl.*message*(
        'You have pushed the button this many times:',
        name: 'heyWorld',
        desc: 'Simple word for greeting ',
      );
    }
    }

*PS: Note that your `load()` might be returning an error on the line: `return initializeMessages()` ignore this for now, we’ll remove it in a while.*

`load()` : It will load/set all the Localized values. You can also call this method if you wish to switch the locale of app manually.

`of()` : This method will return the instance of current Localization of the app. Somewhat like a factory method.

`get heyWorld`: This getter returns the value of the heyWorld. This property is what will be using to get its translations based on locale of the app. For demo purpose I have only set 1 String as for now but you can as many as you can.

Now create an `AppLocalizationDelegate` for the `AppLocalization` class.

    class AppLocalizationDelegate extends LocalizationsDelegate<AppLocalization>{
      final Locale overriddenLocale;

      const AppLocalizationDelegate(this.overriddenLocale);

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

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

      @override
      bool shouldReload(LocalizationsDelegate<AppLocalization> old) => false; 
    }

As you can see this Delegate class is extended from main LocalizationsDelegate and we have pointed it to AppLocalization via add the above required methods and take a look at the isSupported() method:

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

This method will be called to check if the language is supported or not, based on the Locale instance provided. Make sure to you have your supported languages inserted in this list here such as: `[‘en’, ‘de’ ….]`

Now create a [l10n](https://localazy.com/dictionary/l10n) directory in your lib folder. This directory will hold all the translated values as per your Locale. Your final directory structure will look somewhat like this:

![Directory structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m7dj5lg89cdfh8xhr3gg.png) 

In your Terminal and run the following command to create the arb files:

    $ flutter pub run intl_translation:extract_to_arb --output-dir=lib/l10n lib/locale/app_localization.dart

NOTE: The Dart intl package only creates one template file of .arb from your Localization class and names it `intl_messages.arb`. From here, you now have to manually create other resource files with convention `intl_[LANGUAGE_CODE].arb` and copy the content of `intl_messages.arb` directly with updated the values.

Eg: For English format you will create file `intl_en.arb` and the content copied from `intl_messages.arb` :

    {
      "@@last_modified": "2020-11-07T23:41:23.983052",
      "heyWorld": "You have pushed the button this many times:",
      "@heyWorld": {
        "description": "Simple word for greeting ",
        "type": "text",
        "placeholders": {}
      }
    }

Now let’s create one in the German language. So this will be:

    {
      "@@last_modified": "2019-06-27T23:38:38.868199",
      "heyWorld": "Hey Welt",
      "@heyWorld": {
        "description": "Einfaches Wort zur Begrüßung",
        "type": "text",
        "placeholders": {}
      }
    }

Once you created these files in your l10n folder. Now you need to run another command to create the corresponding `.dart` files that will be used to manage these resource files. For that run the following command:

    $ flutter pub run intl_translation:generate_from_arb --output-dir=lib/l10n --no-use-deferred-loading lib/l10n/intl_messages.arb lib/l10n/intl_de.arb lib/l10n/intl_en.arb lib/locale/app_localization.dart

NOTE that i have only 2 files `intl_en.arb` & `intl_de.arb` therefore I am only passing those in command. But if you have more or less, you need to pass them all.

![Files](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/13nmtqyqvbo9xcghn0z0.png) 

Now import the `messages_all.dart` file in your `AppLocalization` Class and here’s a final look at your AppLocalization Class:

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

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

      String get heyWorld {
        return Intl.message(
          'Hey World',
          name: 'heyWorld',
          desc: 'Simpel word for greeting ',
        );
      }
    }

    class AppLocalizationDelegate extends LocalizationsDelegate<AppLocalization> {
      final Locale overriddenLocale;

      const AppLocalizationDelegate(this.overriddenLocale);

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

      @override
      Future<AppLocalization> load(Locale locale) => AppLocalization.load(locale);
      
      @override
      bool shouldReload(LocalizationsDelegate<AppLocalization> old) => false;
    }

*The error is gone! right.* 😉 Now you’re just one step from using the language values based on your current localization settings. To use language specific text in your app, you’ll simply need to follow the two steps:

*   import `AppLocalization` class where you want to use the text
*   Call localized value of text via: `AppLocalizations.of(context).heyWorld`

Now what is happening here is that if you call the above method, it calls the getter of the `AppLocalization` class and returns its value based on the Locale of the context.

If the context is `en` (i.e. english) it will return the value from `intl_en.arb` and when the Locale changes to de ( i.e. german) it will return the value from `intl_de.arb`. And since we’re using the same class getter for both languages ie `(heyWorld)` therefore we don’t need to worry about that either. Flutter will take care of that. But wait, here comes the best part.

## Integrate Localazy for strings management

Now it’s time to add the integration with Localazy. Create localazy.json in the **root folder** and paste the following configuration. Use the **write** and **read** keys from the step 2 of the **integration guide page**.

In your `main.dart` file will be like this:

    void main() => runApp(MyApp());

    class MyApp extends StatefulWidget {
      @override
      State<StatefulWidget> createState() => _MyAppState();
    }

    class _MyAppState extends State<MyApp> {
      // This widget is the root of your application.
      AppLocalizationDelegate _localeOverrideDelegate =
      AppLocalizationDelegate(Locale('en', 'US'));

      @override
      Widget build(BuildContext context) {
        return new MaterialApp(localizationsDelegates: [
          GlobalMaterialLocalizations.*delegate*,
          GlobalWidgetsLocalizations.*delegate*,
          _localeOverrideDelegate
        ], supportedLocales: [
          const Locale('en', 'US'),
          const Locale('de', 'DE')
        ],
            home: MyHomePage());
      }
    }

    class MyHomePage extends StatefulWidget {
      @override
      State<StatefulWidget> createState() => _MyHomePageState();
    }

    class _MyHomePageState extends State<MyHomePage> {

      int _counter = 0;

      void _incrementCounter() {
        setState(() {
          _counter++;
        });
      }

      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
             title: Text("Flutter Demo Localazy"),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text(
                  AppLocalization.*of*(context).heyWorld,
                ),
                Text(
                  '$_counter',
                  style: Theme.*of*(context).textTheme.headline4,
                ),
              ],
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: _incrementCounter,
            tooltip: 'Increment',
            child: Icon(Icons.*add*),
          ),
        );
      }
    }

## Implement Localization to Flutter App

We created our localization files easily, now we will add localazy to our Flutter app according to documentation.

    {
        "writeKey": "your-write-key",
        "readKey": "your-read-key",

        "upload": {
          "type": "arb",
          "files": "lib/l10n/intl_en.arb"
        },

        "download": {
          "files": "lib/l10n/intl_${lang}.arb"
        }

    }

And the project structure will be like this.

![Project structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mxkzzkhehi20aptu5bc7.png) 

Since we’ve set English to be the source language, this file will contain the source phrases for our application. You can fill in any key-value pair you like.

> Flutter’s ARB format is fully supported including arrays, plurals and selected context information. No extra configuration is necessary, but you can enable certain features if you want so. [File Format - Flutter ARB](https://localazy.com/docs/cli/flutter-format) 
*Flutter’s ARB format is fully supported including arrays, plurals and selected context information.

    {
        "@@last_modified": "2019-06-28T17:50:47.781400",
        "heyWorld": "You have pushed the button this many times:",
        "@heyWorld": {
          "description": "Simple word for greeting ",
          "type": "text",
          "placeholders": {}
        }
      }

![Language files](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/032bndluy705uiqenej1.png) 

We created language files for our project. Now, the application is ready to have [localization managed by Localazy](https://localazy.com/tags/localization). We can upload our language to Localazy and add multi-language support with using Localazy features.

Let’s upload the English file to Localazy.

    localazy upload

And it’s done in 2 seconds.

    Localazy CLI, v1.1.9
    Advanced file uploader/downloader for the Localazy translation platform.

    Read more information at [https://localazy.com/docs/cli](https://localazy.com/docs/cli)

    Uploading...
      - deprecate missing: false
      - import as new: false
      - app version: 0
      - groups: (default only)
      - folder: .

    Processing files...

    ./lib/l10n/intl_en.arb
      (file=intl.arb, lang=inherited, type=arb)

    Verifying...

    Validating...

    Uploading 432 B...

    Your data has been uploaded to Localazy. It's scheduled for processing and will be imported soon.
    You will be notified about the progress on the Localazy platform (through notifications).

    Your app on Localazy: [https://connect.localazy.com/p/flutter-localazy](https://connect.localazy.com/p/flutter-localazy)

    Done.

![Upload your strings](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/87t0u3942v137so71e1k.png) 

After refreshing this page, it shows our translations. Now we can add multiple languages.

![Translations](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2rdaksaqnkhevy3a6hta.png) 

Open the *Add languages* tab and there you find a couple of languages with info about the percentage of automated translations. Also you will see the suggestions for every key. You can just click and translate every key according to suggestions. It’s really easy to implement multiple languages.

![German](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jz0ah8ab8e61ai4o574t.png) 

Whenever you want, you can improve your translation, add new keys, or remove old keys. When we go back to project we need to do just download with CLI.

    localazy download

With this command, you’ll download all the newly accepted phrases and newly added languages. In the *locales* folder, we can see there is newly *intl\_de.arb*.

We created our localization files easily, now we will add localization to our [Flutter](https://localazy.com/tags/flutter) app according to documentation.

![Flutter Demo Localazy](https://directus.localazy.com/_/assets/13_o18GIwiMSpWVu5L-0nf64w.gif)

I hope you’ve enjoyed this short intro into Localazy with Flutter. If you’d like to get closer to us, join [Discord](https://discord.gg/CAVhHrh).

You can get all code from the link in below:

<https://github.com/durannumit/flutter-localazy>

<!--kg-card-end: html-->