What is internationalization
Internationalization is the process of decoupling software from a specific language and locale when it is designed. When the software is ported to a different language region, no internal engineering changes or modifications are made to the software itself.
Localization refers to the process of adding information about specific locales and translating files when porting software. The distinction between internationalization and localization is subtle but important. Internationalization means that products have the potential to be used everywhere; Localization is a feature added to make it more suitable for use in a particular place. For a product, internationalization only needs to be done once, but localization needs to be done once for different regions. The two are complementary, and the combination of the two makes a system that works everywhere.
Difficulties in internationalization implementation
Internationalization and localization can be a challenging task for developers when developing software, especially if the software was not designed with this in mind. It is common practice to separate text and other environment-related resources from program code. In an ideal world, you don’t have to change your code to respond to a changing environment, just your resources, which makes your job significantly easier.
Internationalization of Flutter
Internationalization in Flutter includes both internationalization of Flutter components and internationalization of other texts;
Internationalization of Flutter components
The widgets that Flutter provides us support internationalization by default, but they are displayed in English regardless of the environment until special Settings are made.
If you want to add other languages, your application must specify additional MaterialApp properties and add a separate package called Flutter_localizations.
As of November 2020, the package supports 78 languages.
Pubspec adds dependencies
To use flutter_localizations, we need to add it as a dependency in the pubspec.yaml file:
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
Copy the code
Set the MaterialApp
-
In localizationsDelegates specifies which widgets will be internationalized
- A factory used to produce localized sets of values
- We’ve specified that Material, Widgets, and Cupertino all use internationalization
-
SupportedLocales specifies which internationals to support
- We specify Chinese and English here (can also specify country code)
MaterialApp( localizationsDelegates: [GlobalMaterialLocalizations. Delegate, / / specified localized string GlobalCupertinoLocalizations. Delegate, Corresponding GlobalWidgetsLocalizations Cupertino style. / / the delegate / / specify the default text orientation, from left to right or from right to left, supportedLocales: [ Locale("en"), Locale("zh") ], )Copy the code
Note: If you want to specify a language code, a text code, and a country code, you can specify it as follows:
// Full Chinese support for CN, TW, and HK
supportedLocales: [
const Locale.fromSubtags(languageCode: 'zh'), // generic Chinese 'zh'
const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans'), // generic simplified Chinese 'zh_Hans'
const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant'), // generic traditional Chinese 'zh_Hant'
const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans', countryCode: 'CN'), // 'zh_Hans_CN'
const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant', countryCode: 'TW'), // 'zh_Hant_TW'
const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant', countryCode: 'HK'), // 'zh_Hant_HK'
],
Copy the code
Internationalization of custom text in Flutter
Creating localization classes
This class defines the strings we need to localize and so on:
- 1. We need a constructor and pass in a Locale object
- 2. Define a Map to store the corresponding text in our different languages
- 3. Define getter methods that return different results depending on the locale
import 'package:flutter/material.dart'; class QWLocalizations { final Locale locale; QWLocalizations(this.locale); static Map<String, Map<String, String>> _localizedValues = { "fr": {"title": "Titre", "hello": "Bonjour"}, "zh": {"title": "home ", "hello": "hello"}}; String get title { return _localizedValues[locale.languageCode]? ["title"] ?? 'title'; } String get hello { return _localizedValues[locale.languageCode]? ["hello"] ?? 'hello'; } static QWLocalizations of(BuildContext context) { return Localizations.of(context, QWLocalizations); }}Copy the code
A custom Delegate
Once the above class is defined, where or how do we initialize it? We can initialize Flutter widgets in the same manner as internationalization; We will also define an object’s Delegate class, and pass it into localizationsDelegates; The Delegate function is to call the load method when the Locale changes and reload the new Locale resource;
HYLocalizationsDelegate need to inherit from LocalizationsDelegate, and there are three methods must be rewritten: isSupported, shouldReload, load
import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'QWLocalizations.dart'; Class QWLocalizationsDelegate extends LocalizationsDelegate<QWLocalizations> {class QWLocalizations extends LocalizationsDelegate<QWLocalizations> isSupported(Locale locale) { return ["fr", "zh"].contains(locale.languageCode); Locale resources should be loaded only once during Locale switching, and Locale resources should be loaded only once during Locale switching. You don't need to load Localizations every time you rebuild them. So in general, return false; * */ @override bool shouldReload(LocalizationsDelegate<QWLocalizations> old) { return false; } /* * Loading HYLocalizations resources when Locale changes returns a Future, as it might be loaded asynchronously; But here we have a Map defined directly, Override Future<QWLocalizations> Load (Locale Locale) {return SynchronousFuture(QWLocalizations(locale)); } static QWLocalizationsDelegate delegate = QWLocalizationsDelegate(); }Copy the code
Asynchronously loading data
What if our data is loaded asynchronously, such as from a Json file or server?
In the QWLocalizations class, assume the following:
static Map<String, Map<String, String>> _localizedValues = {}; Future<bool> loadJson() async { // 1. JsonString = await rootbundle. loadString("assets/json/i18n.json"); Final map <String, dynamic> map = json.decode(jsonString); // 3. Note: Map<String, dynamic> = Map<String, Map<String, String>> value) { return MapEntry(key, value.cast<String, String>()); }); return true; }Copy the code
Load asynchronously in QWLocalizationsDelegate:
@override
Future<QWLocalizations> load(Locale locale) async {
final localization = QWLocalizations(locale);
await localization.loadJson();
return localization;
}
Copy the code
Using localization classes
We can then use the HYLocalization class in our code.
- We can get through
QWLocalizations.of(context)
Get the QWLocalizations object
Text(
QWLocalizations.of(context).hello,
)
Copy the code
Tool for internationalization –Intl
Understand arB files
We can now localize it by loading the corresponding JSON file.
However, there is another problem. In the process of internationalization, the following code still needs to be written manually from json files:
String get title { return _localizedValues[locale.languageCode]? ["title"] ?? 'title'; } String get hello { return _localizedValues[locale.languageCode]? ["hello"] ?? 'hello'; }Copy the code
Is there a better way that we can quickly convert directly in the localization file -dart code file? The answer is arB files
- The full name of the arB file is Application Resource Bundle, which stands for Application Resource Bundle.
- It is essentially a JSON file, but it can be converted to the appropriate locale;
- Arb documentation: github.com/google/app-…
Use the IDE plug-in to convert between ARB and DART files
-
Initialize the intl
Select tools-flutter intl-Initialize for the Project from the toolbar
After completing the above operations, the following directories are automatically generated:
- Generated is the automatically generated Dart code
- I10n is the corresponding arB file directory
Use the intl
Configured in localized localization: the generated class, known as S
- 1. Add a delegate
- 2. Use spyware doctor elegate supportedLocales. SupportedLocales
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
S.delegate
],
supportedLocales: S.delegate.supportedLocales,
Copy the code
Since we don’t have a localized string yet, we need to write it in intl_en.arb:
- CTRL (Command) + S save after writing
{
"title": "home",
"hello": "hello"
}
Copy the code
Use it in code
- The format is s.f (context).title
Add Chinese
If you want to add Chinese support: add local
- In the dialog box that is displayed, enter zh
As you can see, the corresponding intl_zh.arb and Messages_zh. dart files are generated
Arb Other syntax
If we want to pass some parameters while using localization:
- Like Hello Kobe or Hello James
- Such as Hello ah, Li Yinhe or hello ah, Wang Xiaobo
Modify the corresponding ARB file:
- {name} : indicates the parameter passed
{
"title": "home",
"hello": "hello",
"sayHello": "hello {name}"
}
Copy the code
To use, pass in the corresponding parameter:
Text(s.f (context).sayhello (" Li Yinhe ")),Copy the code
conclusion
The essence of text internationalization is to obtain the corresponding text and perform corresponding operations on the UI (left-to-right or right-to-left display) according to the locale information provided by the system. Locale information refers to the country code and region code, etc. Usually, what we need to do locally is to put the text according to {country code: {common text: The format of localized text}} is organized. The country code here is en for China, en for the United States. Common texts are generally in English. Finally, the process of retrieving localized text values from dictionaries based on locale information and generic text.
Reference: Internationalization of Flutter