foreword

Brother Cat also has this confusion in the project, how to manage multiple languages, if the constant definition method is still a bit inelegant.

The author of this article put forward a good suggestion, server-side editing, local file cache synchronization.

It's just reading the database, and maintaining an interface on the backend to maintain the data seems to be a good solution.

original

https://medium.com/flutter-community/make-localization-by-custom-services-in-flutter-apps-519b5de32aae

code

https://github.com/VB10/custom_localization

refer to

text

Many applications are localized on the client side. This means that if there is any problem with your key, you have to update both the string and the application. Let's learn a custom solution, when the user will change the language, our app will directly update each screen with the new language.

As I said, usually we use localization of JSON files etc. I've written many Flutter projects, so I've made localizations for our clients in the past, and generally I've made a Turkish and English version of the product written by me.

Usually we define these keys like this, and then the application reads the value with the key.

Flutter has many localization options, in particular I have used easy_localizaiton many times in production projects. This works for all my requirements, but one day the client needs a special solution. I have asked directly,

  • You know we have a location, what else do you expect?
  • Yes Veli we know this, but we want to manage localization files in our web service and the client can change the language to our localization list in response.

Actually, this request is not a big deal, as we can have custom backend solutions using remote config, Firebase realtime config, or simple localization, but none of these requirements can be met. Time to make donuts!

If we want better coding time, we have to make a plan. First, what are the API endpoints for both apps to get the list of languages we support, the app will bring the translation value by looking at the language key. When the application user changes the language in the application, we have to change the whole string value, not the old value.

Our steps:

  • The backend endpoint for the application and the application to change the language can be the display language
  • We will implement the initial language
  • We can change one point of the entire text based on the new language information automatically received.
  • The user can find the current language value.

I created simple backend resources with Firebase like:

Usually I have a custom backend like node.js, Java, etc, or I can choose Firebase Cloud Functions, but I just wanted to show how to use flutter features to customize localization, so we didn't use this method.

Let's start coding!

We know how to load language resources with backend endpoints. After that I want to cache it's backend response since the client needs the full data for each restart. Therefore, we need caching mechanism to keep the backend responsive without the user changing the language.

I have chosen Hive solution to use cached applications, so Hive is very fast, secure, and useful solution for us. I choose Hive for many of our enterprise projects. I will use this library in this project:

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

Now, I'll implement a service layer to get list language results and associated key values. I always tend to provide interfaces for each business operation called by the instance service 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 and it is correct, so I want to validate this response for our business.

When you call this test service test file, you will see that every action is correct.

  • Test function results

Time to implement the backend part. After including the to title and body widgets, I'll call en's resource list. When done, we completed the first objective

  • initial resource

Now that we are connected to the backend service, if we change to the language parameter, we can automatically display the new resource. Now, what do we need? If we have too many pages, we want to change the whole key dynamically. Let's take this building.

Finally, I implemented this gadget. It is populated by the language list response. If you want to add a new language, you just need to add a resource key to the database when you are done using it.

language management

I will create a manager class for managing operations. It needs to be notified of every change in an application. Other requirements for keys. I plan to have language extension classes for key strings. This extension will be able to listen for language changes.

It changes our localized resources and then informs the whole module via provider management. I updated the initial resource key for every language change request.

This is ready to use, but how do I use my keys. Yes, we talked about requiring a string change extension. First, we need to learn how to implement this manager based on the current view.

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

That is, you get a string response for every change, but I don't use this because it's too long and out of control. Of course, how can we write a better solution for this?

I will replace the text widget in the home view like:

ListTile(title: Text(LocaleKeys.ageQuestion.tr(context))),
You may choose other methods of state management that do not use context-param. That's your choice, and I'll suggest you should use this.

Runtime changes from backend responses

Now, we're ready to use, but we need a final improvement cache, so we'll get performance and power from caching. We have asked enough. Hive It is both a fast and secure key-value database.

Once hive is done, I'll add backend responses to the database to use offline or application start. Usually we should get the language response until the user can manually change the language or get the data to the app with any data.

I created IHive abstract class to manage my hive classes. I made a two box, the first manages my keys and the other holds the list of languages.

After I updated my language manager. I've added two new parameters IHive <map> and IHive <list> to hold locale data.

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

I'm starting to control applications that have cached data. If the application has any cached data, it will update the manager resource on first launch. When the user updates the locale, I'll go in to respond in Hive for reuse again.

I keep the selected language in the map array, but usually if you want to keep other languages you can open a new box for the new key. It will offer to no longer download other languages because your old box remains in the app while you delete Hive.

One more thing, when the application starts, I will initialize first after checking the data in the cache.

We're almost ready! Let's see how it turns out.

Other tip, you can use the stream builder to listen for configuration changes, but I don't use the stream to create the screen, maybe you can create a base class and listen for configuration changes without any state management.

Thank you for reading 🍀
Have a good hacking, both in real life and coding life

Thanks for reading 🍀

《Have a good hacking, both in real life and coding life》

GitHub code

https://github.com/VB10/custom_localization

end


© Cat Brother


独立开发者_猫哥
666 声望126 粉丝