Flutter Multi Language Applications with Easy Localization

Murat Gun
5 min readAug 22, 2021

A mobile application becomes accessible to the whole world as soon as the application enters the markets. So, what is the first rule of making an application that can be accessed by users all over the world? The answer is simple, language. In this article, I will talk about how to easily develop multilingual applications with Flutter.

Today I will talk about how you can make your mobile applications multilingual with clean architecture.

Easy Localization Package

The basic operating principle of the easy_localization package is simple and effective. String values in the application are collected under a .json file. Then .json files of other languages are created with the same key values. However, values should be written as translated into the desired language. After the .json files are prepared, dynamic management is provided with the easy_localization package. How to do this management will be in the rest of the article.

es-ES.json

{
"welcome": "¡Hola Mundo!"
}

tr-TR.json

{    
"welcome": "Hoş geldiniz!"
}

en-US.json

{
"welcome": "Welcome!"
}

*The important point here is that the name of the .json file must be a language code.*

You can find all the language codes from here.

Architecture

In the architecture I use, simply the LocalizationManager class provides all localization management thanks to the easy_localization package. Instant localization information is stored and rested in the enum structure.

The contents of the json file of instant localization information are kept in the LocaleKeys class. In case of instant localization information changes, the content of this file is automatically reproduced. This reproduction happens thanks to the CodegenLoader class. This class stores the content of all .json files in the map structure.

LocalizationManager

This class is basically responsible for all localization management. It keeps 3 values. The first of these is instant localization data. This data is in enum structure. The 2nd data it stores is a list of languages the app supports. This list is kept under supportedLocales. Finally, the path of the .json files where the string data of the application is stored.

LocalizationExtension

As you know, enum values are meaningless on their own. In Flutter, extensions are a great tool for adding functions to enums. Thanks to this function, we provide the .translate function to an enum value. So what does this function do? We keep our instant localization data as enum. Thanks to this extension, our enum values can now be returned as Locale data.

extension LocalizationExtension on LocalizationEnum {  Locale? get translate {    switch (this) {      case LocalizationEnum.TURKCE:        return LocalizationManager.instance.trTRLocale;      case LocalizationEnum.ENGLISH:        return LocalizationManager.instance.enUSLocale;      default:        return LocalizationManager.instance.enUSLocale;  } }}

EasyLocalization Widget

  • To use the Easy Localization package, we should wrap MyApp() widget in runApp with EasyLocalization widget.*
runApp(  EasyLocalization(    path: LocalizationManager.instance.localePath!,    supportedLocales: LocalizationManager.instance.supportedLocales,    startLocale: LocalizationEnum.ENGLISH.translate,    assetLoader: CodegenLoader(),    child: MyApp(),  ),);

This Widget has 4 basic Property to take.
1- path: The location of .Json files that contain string values of the application. (We’ve identified in the LocalizationManager class.)

2- supportedLocales: Languages that the application supports. List <Locale> data type. (We’ve identified in the LocalizationManager class.)

3- startLocale: The language to be used when the application is started.

4- assetLoader: This is a class to generate by the easy_localization package. We will write the necessary script to generate this.

CodegenLoader() Generation

flutter pub run easy_localization:generate --source-dir 'your-source-directory-of-json-files' -O 'your-output-folder'

LocaleKeys() Generation

flutter pub run easy_localization:generate -f keys --source-dir 'your-source-directory-of-json-files' -O 'your-output-folder' -o locale_keys.g.dart

The LocaleKeys class statically hosts the string data of the application according to the instant localization information.

*If you add a new data in any json file, you need to regenerate CodegenLoader() and LocaleKeys() classes.*

MaterialApp Configurations

MaterialApp(
localizationsDelegates: context.localizationDelegates,
supportedLocales: context.supportedLocales,
locale: context.locale,
title: 'Material App',
home: HomeScreen(),
);

The easy_localization package includes the Buildcontext extension in itself. Thanks to this extension, we can call the required values in MaterialApp via the context value.

Localization Keys Using

Almost done. What we need to do now is to place the values in the LocaleKeys class in their places in the application.

Text(LocaleKeys.welcome).tr(); 
or
print(LocaleKeys.welcome.tr());

Localization Changing

Yes everything is working now. Our application started to work with the language we specified in the startLocale properties. So what do we do when we want to change localization?

The easy_localization package has an extension that runs on Buildcontext. Thanks to this extension, we have many functions on context information. Changing the localization information is one of them.

await context.setLocale(LocalizationEnum.ENGLISH.translate!);

Since this function is of Future data type, it is used with await. We place the Locale() widget of the language you target in it. We can easily get this data type with LocalizationExtension that we build on LocalizationEnum.

The great thing about this extension is that you don’t need to listen for changes on the UI. The extension in the easy_localization package also provides this.

Thanks to the data we give to the locale property in MaterialApp with context.locale, we can easily make UI changes without the need for any listening.

MaterialApp{  locale: context.locale}

--

--