preface

For detailed information about internationalization of FLUTTER, you can go to the Internationalization of Flutter App

This article focuses on how Flutter is multilingual and how to use multiple languages ($T) and implement language switches just like the Web uses I18N, which is more user-friendly for front-end developers.

The project address

Flutter – UI, an open source project containing an introduction to flutter components, welcomes Star

Flutter_intl This tutorial project source, welcome star

The effect

How to use

Add the dependent

  • Introduce dependencies in pubspec.yaml
dependencies:
  flutter_localizations:
    sdk: flutter
Copy the code
  • perform
flutter packages get
Copy the code

New file Locale

locale
    |-en.json
    |-zh.json
Copy the code

Multilingual files

  • en.json
{
    "title_page": "i18n"."title_appbar": "i18n"."content": {
        "currentLanguage": "The current language is English"."zh": "zh"."en": "en"}}Copy the code
  • zh.json
{
    "title_page": "Internationalization examples"."title_appbar": "Internationalization examples"."content": {
        "currentLanguage": "Current language is Chinese"."zh": "Chinese"."en": "English"}}Copy the code

Create a new lang in lib

lang
  |- config.dart
  |- index.dart
Copy the code
  • config.dart
import 'package:flutter/material.dart';

class ConfigLanguage {
  static List<Locale> supportedLocales = [
    Locale('zh'.'CH'),
    Locale('en'.'US')];static Map<String.dynamic> supportLanguage = {
    "zh": {"code": "zh"."country_code": "CH"},
    "en": {"code": "en"."country_code": "US"}};static dynamic defaultLanguage = {
    "code": "zh"."country_code": "CH"
  };
}
Copy the code

The config.dart function consolidates configuration information into a file

  • index.dart
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:flutter/services.dart' show rootBundle;
import 'package:flutter/foundation.dart' show SynchronousFuture;
import 'package:flutter_intl/lang/config.dart' as I18NConfig;
class AppLocalizations {
  Locale _locale;
  static Map<String.dynamic> jsonLanguage; / / language pack
  static AppLocalizations _inst; // inst

  AppLocalizations(this._locale);

  // Initialize localizations
  static Future<AppLocalizations> init(Locale locale) async {
    _inst = AppLocalizations(locale);
    await getLanguageJson();
    return _inst;
  }

  // Get the language package
  static Future getLanguageJson() async {
    Locale _tmpLocale = _inst._locale;
    print('Get the language pack's language;${_tmpLocale.languageCode}');
    String jsonLang;
    try {
      jsonLang = await rootBundle.loadString('locale/${_tmpLocale.languageCode}.json');
    } catch (e) {
      print('Wrong');
      _inst._locale = Locale(I18NConfig.ConfigLanguage.defaultLanguage['code']);
      jsonLang = await rootBundle.loadString('locale/${I18NConfig.ConfigLanguage.defaultLanguage['code']}.json');
    }
    jsonLanguage = json.decode(jsonLang);
    print("Current language:${_inst._locale}");
    print(Data: $jsonLanguage);
  }

// $t package, the purpose is to use $t to get multilingual data
  static String $t(String key) {
    var _array = key.split('. ');
    var _dict = jsonLanguage;
    var retValue = ' ';
    try {
      _array.forEach((item) {
        if(_dict[item].runtimeType == Null) {
          retValue = key;
          return;
        }
        if(_dict[item].runtimeType ! =String) {
          _dict = _dict[item];
        } else{ retValue = _dict[item]; }}); retValue = retValue.isEmpty ? _dict : retValue; }catch (e) {
      print('i18n exception');
      print(e);
      retValue = key;
    }

    return retValue ?? ' '; }}// Implement the LocalizationsDelegate protocol to initialize the Localizations class
class AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
  final Locale locale;
  AppLocalizationsDelegate([this.locale]);

  @override
  bool isSupported(Locale locale) {
    return I18NConfig.ConfigLanguage.supportLanguage.keys
      .toList()
      .contains(locale.languageCode);
  }

// Initialize Localizations class here
  @override
  Future<AppLocalizations> load(Locale _locale) async {
    print('Language to load: $_locale');
    return await AppLocalizations.init(_locale);
    // return SynchronousFuture<AppLocalizations>(
    // AppLocalizations(_locale)
    // );
  }

  @override
  bool shouldReload(LocalizationsDelegate<AppLocalizations> old) {
    // Flase does not execute the above rewrite function
    return false; }}Copy the code

See the code comment ~~~~~~~~~ for details

Just to give you an overview

Implement a LocalizationsDelegate protocol and implement a Localizations class and import it into the MaterialApp in Main. dart

Process the main.dart file

import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_intl/lang/index.dart'
  show AppLocalizations, AppLocalizationsDelegate;
import 'package:flutter_intl/lang/config.dart' show ConfigLanguage;


void main () => runApp(MainApp());
GlobalKey<_ChangeLocalizationsState> changeLocalizationsStateKey = new GlobalKey<_ChangeLocalizationsState>();
class MainApp extends StatefulWidget {
  @override
  _MainAppState createState() => _MainAppState();
}

class _MainAppState extends State<MainApp> {
  // Define the global language proxy
  AppLocalizationsDelegate _delegate;

  @override
  void initState() {
    // TODO: implement initState
    _delegate = AppLocalizationsDelegate();
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // locale: Locale('zh', 'CH'),
      localeResolutionCallback: (deviceLocale, supportedLocal) {
        print('deviceLocale: $deviceLocale, supportedLocale: $supportedLocal}');
        // Determine whether the incoming language supports it
        Locale _locale = supportedLocal.contains(deviceLocale) ? deviceLocale : Locale('zh'.'CN');
        return _locale;
      },
      onGenerateTitle: (context) {
        // Set up the multilingual proxy
        // AppLocalizations.setProxy(setState, _delegate);
        return AppLocalizations.$t('title_page');
      },
      // localizationsDelegates the element in the list is the factory that generates the localized collection
      localizationsDelegates: [
        GlobalMaterialLocalizations.delegate,   // Provide localized strings and other values for the Material Components library
        GlobalWidgetsLocalizations.delegate,    // Define the default text orientation for the widget, from left to right or right to left
        _delegate
      ],
      supportedLocales: ConfigLanguage.supportedLocales,
      initialRoute: '/',
      routes: {
        '/': (context) => 
        // Home()
        Builder(builder: (context) {
          returnChangeLocalizations( key: changeLocalizationsStateKey, child: Home() ); })}); }}class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    Locale locale = Localizations.localeOf(context);
    return Scaffold(
      appBar: AppBar(title: Text('${AppLocalizations.$t('title_appbar')}'),),
      body: ListView(
        children: <Widget>[
          Container(
            margin: EdgeInsets.only(top: 60),
            alignment: Alignment.center,
            child: Text('${locale.languageCode} ${locale.toString()}'),
          ),
          Container(
            alignment: Alignment.center,
            child: Text('${AppLocalizations.$t('content.currentLanguage')}'),
          ),
          Wrap(
            spacing: 8.0,
            alignment: WrapAlignment.center,
            children: <Widget>[
              ActionChip(
                backgroundColor: Theme.of(context).primaryColor,
                onPressed: () {
                  changeLocalizationsStateKey.currentState.changeLocale(Locale('en'.'US'));
                },
                label: Text('${AppLocalizations.$t('content.en')}'),
              ),
              ActionChip(
                backgroundColor: Theme.of(context).primaryColor,
                onPressed: () {
                  changeLocalizationsStateKey.currentState.changeLocale(Locale('zh'.'CH'));
                },
                label: Text('${AppLocalizations.$t('content.zh')}'() [() [() [() }}class ChangeLocalizations extends StatefulWidget {
  final Widget child;
  ChangeLocalizations({Key key, this.child}):super(key: key);
  @override
  _ChangeLocalizationsState createState() => _ChangeLocalizationsState();
}

class _ChangeLocalizationsState extends State<ChangeLocalizations> {
  Locale _locale;
  @override
  void initState() {
    super.initState();
  }
  @override
  void didChangeDependencies() async {
    super.didChangeDependencies();
    // Get the language of the current device
    _locale = Localizations.localeOf(context);
    print('Device language: $_locale');
  }
  changeLocale(Locale locale) {
    setState(() {
      _locale = locale;
    });
  }
  @override
  Widget build(BuildContext context) {
    returnLocalizations.override( context: context, locale: _locale, child: widget.child, ); }}Copy the code
  • Specify the localizationsDelegate and supportedLocales in the MaterialApp
    • LocaleResolutionCallback: This callback is used when the application retrieves the Locale set by the user. You can return the Locale as required
    • OnGenerateTitle: Returns the corresponding title of the multilingual application
    • LocalizationsDelegates: The factory where localization sets are generated when the elements in the localizationsDelegates list
    • SupportedLocales: language supported by the APP
  • The Home class is the display class
    • Localizations. LocaleOf (context). LanguageCode obtains the language type of the current app
    • AppLocalizations.$t(‘content.currentLanguage’) play with multilingual content like the Web

At this point, you can happily play with multiple languages, and different language packs will be loaded when the user sets different languages

The following implementation in the APP language switch

  • The ChangeLocalizations class uses the Override method of Localizations, as shown above
    • Internal method of calling ChangeLocalizations using GlobalKey, GlobalKey<_ChangeLocalizationsState> changeLocalizationsStateKey = new GlobalKey<_ChangeLocalizationsState>(); We can also be GlobalKey into dojo.provide, so that you can implement multiple pages for changeLocalizationsStateKey visit
    • Modify language call changeLocale method, changeLocalizationsStateKey. CurrentState. ChangeLocale (Locale (‘ en ‘, ‘US’));

The last

Welcome more friends learning about flutter to join QQ group Flutter UI: 798874340

Stay tuned for what we’re working on: efoxTeam/ Futter-UI

The author