欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Flutter 中的国际化之多语言环境

程序员文章站 2022-05-29 10:54:12
...

更多文章请查看 flutter从入门 到精通

本文章将综述:

  • flutter 应用通过 MaterialApp 设置言本地化
  • flutter 应用通过 MaterialApp 配制多语言国际化支持

本文章的终极效果:
Flutter 中的国际化之多语言环境


通常我们新建的 Flutter 应用是默认不支持多语言的,即使用户在中文环境下,显示的文字仍然是英文,接下来我们将一步步将系统的这些组件国际化。

1 添加依赖

dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter

然后 运行

flutter packages get

以获取依赖

2 在 main.dart 中 import


import 'package:flutter_localizations/flutter_localizations.dart';
3 配置

在 MaterialApp 中配制

import 'package:flutter/material.dart';
import 'package:flutter_mo_study_ui/select_language_page.dart';
import 'package:flutter/foundation.dart';
import 'localizations_delegates.dart';
import 'package:flutter_localizations/flutter_localizations.dart';

void main() => runApp(MyAppThem2());

///创建key值,就是为了调用外部方法
///ChangeLocalizationsState 用来应用内切换语言环境的类
GlobalKey<ChangeLocalizationsState> changeLocalizationStateKey = new GlobalKey<ChangeLocalizationsState>();

class MyAppThem2 extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      ///android 应用任务栏显示的标题
//      title: 'Flutter MU KE DEMO',
      home: new Builder(builder: (context) {
        ///通过 Localizations.override 包裹一层。---这里
        ///将 ChangeLocalizations 使用到 MaterialApp 中
        return new ChangeLocalizations(
          key: changeLocalizationStateKey,
          child: new SelectLanguagePage(),
        );
      }),
      /// 此处 配制多语言环境
      ///配置 android 应用任务栏显示的标题 的国际化
      ///因为 DemoLocalizations 使用到了context 所以这里不使用title 属性
      onGenerateTitle: (context) {
        ///根据语言环境来获取 taskTitle
        ///DemoLocalizations 为自定义的语言文字适配中心
        return DemoLocalizations.of(context).taskTitle;
      },
      ///本地化委托,用于更改Flutter Widget默认的提示语,按钮text等
      ///通常我们新建的 Flutter 应用是默认不支持多语言的,即使用户在中文环境下,显示的文字仍然是英文
      localizationsDelegates: [
        ///初始化默认的 Material 组件本地化
        GlobalMaterialLocalizations.delegate,
        ///初始化默认的 通用 Widget 组件本地化
        GlobalWidgetsLocalizations.delegate,
        ///初始化自定义多语言环境运行
        MyLocalizationsDelegates.delegate,
      ],

      ///当前区域,如果为null则使用系统区域一般用于语言切换
      ///传入两个参数,语言代码,国家代码
      ///这里配制为中国
      locale: Locale('zh', 'CN'),

      ///传入支持的语种数组
      supportedLocales: [
        const Locale('en', 'US'), // English 英文
        const Locale('he', 'IL'), // Hebrew 西班牙
        const Locale('zh', 'CN'), // 中文,后面的countryCode暂时不指定
      ],

      ///当传入的是不支持的语种,可以根据这个回调,返回相近,并且支持的语种
      localeResolutionCallback: (local, support) {
        ///当前软件支行的语言 也就是[supportedLocales] 中配制的语种
        if (support.contains(local)) {
          print('support  $local');
          return local;
        }
        ///如果当前软件运行的手机环境不在 [supportedLocales] 中配制的语种范围内
        ///返回一种默认的语言环境,这里使用的是中文
        print('no_support local is $local and support is $support');
        return const Locale('zh', 'CN');
      },
    );
  }
}

//自定义类 用来应用内切换
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 = const Locale('zh', 'CH');

  changeLocale(Locale locale) {
    setState(() {
      _locale = locale;
    });
  }

  //通过Localizations.override 包裹我们需要构建的页面
  @override
  Widget build(BuildContext context) {
    //通过Localizations 实现实时多语言切换
    //通过 Localizations.override 包裹一层。---这里
    return new Localizations.override(
      context: context,
      locale: _locale,
      child: widget.child,
    );
  }
}

对于类 MyLocalizationsDelegates

import 'dart:ui';

import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';


///自定义多语言处理代理
class MyLocalizationsDelegates
    extends LocalizationsDelegate<DemoLocalizations> {
  ///构造
  const MyLocalizationsDelegates();
  ///静态构造
  static MyLocalizationsDelegates delegate = const MyLocalizationsDelegates();

  @override
  bool isSupported(Locale locale) {
    return ['en', 'zh', 'he'].contains(locale.languageCode);
  }

  @override //是否需要重载
  bool shouldReload(LocalizationsDelegate old) => false;

  ///MyLocalizations就是在此方法内被初始化的
  ///通过方法的 locale 参数,判断需要加载的语言,然后返回自定义好多语言实现类MyLocalizations
  ///最后通过静态 delegate 对外提供 LocalizationsDelegate。
  @override
  Future<DemoLocalizations> load(Locale locale) {
    //加载本地化
    return new SynchronousFuture(new DemoLocalizations(locale));
  }
}

对于 DemoLocalizations 是配置 具体的文字内容


///Localizations类 用于语言资源整合
class DemoLocalizations {
  ///该Locale类是用来识别用户的语言环境
  /// 在MyLocalizationsDelegates 的load方法中初始化的
  final Locale locale;

  DemoLocalizations(this.locale);


  ///此处通过静态方式来初始化
  static DemoLocalizations of(BuildContext context) {
    ///Localizations 是多国语言资源的汇总
    return Localizations.of(context, DemoLocalizations);
  }

  //根据不同locale.languageCode 加载不同语言对应
  static Map<String, Map<String, String>> _localizedValues = {
    'en': {
      'task title': 'Flutter Demo',
      'titlebar title': 'Flutter Demo Home Page',
      'click tip': 'You have pushed the button this many times:',
      'inc': 'Increment',
      'click button': 'click select language',
      'welcomes': 'China welcomes you'
    },
    'zh': {
      'task title': 'Flutter 示例',
      'titlebar title': 'Flutter 示例主页面',
      'click tip': '你一共点击了这么多次按钮:',
      'inc': '增加',
      'click button': '点击切换',
      'welcomes': '中国欢迎你'
    },
    'he': {
      'task title': 'Ejemplo de Flutter',
      'titlebar title': 'Flutter 示例主页面',
      'click tip': 'Has hecho clic en los botones tantas veces en total:',
      'inc': '增加',
      'click button': 'Haga clic en cambiar',
      'welcomes': 'Bienvenido a China'
    }
  };

  get taskTitle {
    Map<String, String> map = _localizedValues[locale.languageCode];
    return map['task title'];
  }

  get titleBarTitle {
    return _localizedValues[locale.languageCode]['titlebar title'];
  }

  get clickButtonTitle {
    return _localizedValues[locale.languageCode]['click button'];
  }

  get clickTop {
    return _localizedValues[locale.languageCode]['click tip'];
  }

  get inc {
    return _localizedValues[locale.languageCode]['inc'];
  }
  get welcomes {
    return _localizedValues[locale.languageCode]['welcomes'];
  }

}

SelectLanguagePage 页面中 点击按钮实现应用内切换当前语言环境

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mo_study_ui/localizations_delegates.dart';
import 'package:flutter_mo_study_ui/second_page.dart';

import 'main_language.dart';

/**
 * 多语言切换
 */
class SelectLanguagePage extends StatefulWidget {
  SelectLanguagePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<SelectLanguagePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        ///多种语言支持的导航栏标题
        title: Text(DemoLocalizations.of(context).titleBarTitle),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ///多种语言支持的显示文本
            Text(DemoLocalizations.of(context).welcomes,style: TextStyle(color: Colors.red,fontSize: 22),),
            Padding(
              padding: EdgeInsets.all(30),
            ),
            ///点击按钮显示语言选择框
            FlatButton(
              child: Text(DemoLocalizations.of(context).clickButtonTitle),
              onPressed: () {
                changeLocale();
              },
            )
          ],
        ),
      ),
    );
  }


  ///语言切换
  ///这里则是弹框内容了
  void changeLocale(){
    showDialog(
      context: context,
      barrierDismissible: false,//// user must tap button!
      builder: (BuildContext context) {
        return new SimpleDialog(
          title: new Text("请选择语言"),
          children: <Widget>[
            SimpleDialogOption(
              onPressed: () {
                switchLanguage(0);
                Navigator.of(context).pop();
              },
              child: const Text("中文"),
            ),
            SimpleDialogOption(
              onPressed: () {
                switchLanguage(1);
                Navigator.of(context).pop();
              },
              child: const Text("英语"),
            ),
            SimpleDialogOption(
              onPressed: () {
                switchLanguage(2);
                Navigator.of(context).pop();
              },
              child: const Text("西班牙语"),
            )
          ],
        );
      },
    );
  }

  ///切换语言
  ///通过 changeLocalizationStateKey 来修改本应用内的 Locale
  void switchLanguage(int index) {
    switch(index){
      case 0:
        changeLocalizationStateKey.currentState.changeLocale(const Locale('zh','CH'));
        break;
      case 1:
        changeLocalizationStateKey.currentState.changeLocale(const Locale('en','US'));
        break;
      case 2:
        changeLocalizationStateKey.currentState.changeLocale(const Locale('he', 'IL'));
        break;
    }
  }
}