Make localization by custom services in Flutter apps

Veli Bacık
Flutter Community
Published in
7 min readJan 30, 2022

Many applications make localizations on the client-side. It’s mean if you have any problem with your keys, you have to update both your strings and applications. Let’s learn to make custom solutions and when the user will change language, our apps going directly update the new language with every screen.

Pikachu Native Guard
Pikachu ready to speak

As I said, normally we’re using localization from JSON files, etc. I was writing many flutter projects so I used to make localization for our customers and in general, I made a Turkish and English version of the products by the written for me.

Normally we define like these keys then the application reads the value with the key.

Flutter has many options for localization, especially I used many times easy_localizaiton package at the production project. That’s works for my all requirements but one day, customers want special solutions. And I’ve asked to directly,

  • You know we have a location, what else do you expect?
  • Yep, Veli we knew that but we want to manage localization file’s in our web services and clients can be change language to our localization list response.

Actually, that request is not a big deal because we can use remote config, Firebase real-time, or easy localization has a custom backend solution but anyone does not meet requirements. Time to make the donuts!

Plans, If we want great coding times, we have to make a plans. Firstly, what is the API endpoint for both applications to get our supported language list and the application will bring translate values by looking at the language key. When app users change the language in the application, we must be changed whole string values instead of old values.

Our steps:

  • The backend endpoint for changing language by the application and app can be show language
  • We’re going to implement initial language
  • We can change the entire text by a single point according to the new language information received automatically.
  • Users can be found current language values.

And I created simple backend resources using Firebase. For instance:

Normally I have a custom backend like NodeJS, Java, etc. or I can select Firebase cloud functions, but I just want to show how to make custom localization with flutter features so no probs we used the method.

Let’s start coding!

We knew how can load the language resources with the backend endpoint. After I’d like to cache it backend response because the client needs the whole data for every re-launch. So we need to cache mechanism to keep backend response while the user doesn’t change the language.

I’ve selected Hive solution to use cache by the app so hive very fast, secure, and useful solution for us. I’ve selected hive for many of our enterprise projects. I will use this library in this project:

Firstly, we need to sample screen to show our key values for the initial language (right now I accept to en while app starting after I'll change to tr).

And I added language values for tr and en in the below image.

That’s time, I’m going to implement a service layer to fetch list language results and related key-value. I always prefer to interface for every business operation for an instance service call in the below.

abstract class ILangugaeService {final INetworkManager networkManager;ILangugaeService(this.networkManager);Future<List<String>?> fetchLangageList();Future<Map<String, dynamic>?> fetchSpesificResources(String key);
}

I wrote this interface after I tried to implement a feature test for the control backend response it is right so I want to validate the response for our business.

When you call this test service test file, you’ll see every operation is right.

Test functions results.

It’s time to implement the backend part. I’ll call the resources list for en after including to title and body widget. After it has done, we finished the first target

Initial resources

Right now, we’re connected to backend service, and if change to language params, we can show new resources automatically. Right now, what do we need? If we have too many pages, we want to change whole keys dynamically. Let’s make this architecture.

Lastly, I implemented this widget. It is filled by language list response. If you want to add a new language, you can just add a resource key in your database after ready use.

Language Manager

I’m going to create a manager class for managing operations. It needs to notify an application of every change. Other requirements for our keys. I’m planning to language extension class for key strings. This extension will be able to listen to language changes.

It has changed our localization resources then notify to the whole module with provider management. I updated to initial resource key to every language change request.

That’s ready to use but how can I use readily my keys. Yeah, we talked to need an extension for string changes. Firstly, we need to learn how to implement this manager to the current view.

Text(context.watch<LanguageManager>().resources?[LocaleKeys.hello.name] ?? '')

That’s usage can be getting string response for every change as well as I don’t use this because it’s too long and doesn't control. Sure, how can we write a better solution for this?

And I’m going to replace my text widget in the home view for instance this;

ListTile(title: Text(LocaleKeys.ageQuestion.tr(context))),

You can select other state management methods for use without context-param. That’s your choice, I give suggestion to should use this.

The run time change from backend response

Right now, We’re ready to use but we need to last improvements caching thus we’ll gain performance and power with the cache. Hive quite enough of our requirements. It’s both a fast and secure key-value database.

After the hive, I’ll add backend response into the database in order to use offline or application starting. Normally We should fetch language response until the user can change the language manually or fetch data to the application that has any data.

I created the IHive abstract class the manage my hive classes. I make a two-box, the first one manages to my keys other one keep the language list.

After I’ve updated my language manager. I added two new parameters IHive<Map> and IHive<List> for as I said keeping locale data.

LanguageManager(LanguageService(ProductNetworkManager()),LanguageHive(), LanguageListHive()),

And I started to control applications that have any cached data. If an app has any cached data, it will update manager resources on the first start. User while updating the locale language, I’m going into to response in the hive for re-use again.

I keep to selected language in the map array but normally if you want to keep other languages, you can open a new box for the new key. It will be provided doesn’t download again other languages because your old box keeps in the app while you remove the hive.

And other points while the app starts, I’m going to init firstly hive after checking the data in cache.

And We’re almost ready! Let’s check the result what we have.

Other hints, you can listen to hive changes with stream builder but I don’t create screens with streams maybe you can create a base class and listen to hive changes without any state management.

--

--

Veli Bacık
Flutter Community

We always change the world, so just want it. [OLD]Google Developer Expert Flutter & Dart, Gamer, Work More!