Flutter-国际化总结

223 阅读2分钟

1、默认语言区域不对

在一些非大陆行货渠道购买的Android和iOS设备,会出现默认的Locale不是中文简体的情况,为了防止设备获取的Local与实际的区域不一致,APP可以提供一个手选语言的入口。

2、应用辩题进行国际化

MatterAPP有一个title属性,用于指定APP的标题,在Android系统中,APP的标题会出现在任务管理器中,所以需要对title进行国际化。但是很多国际化配置都是在MatterialApp上设置的,无法在构建MaterialAPP时通过Localizations.of来获取本地化资源:

MaterialApp(
  title: DemoLocalizations.of(context).title, //不能正常工作!
  localizationsDelegates: [
    // 本地化的代理类
    GlobalMaterialLocalizations.delegate,
    GlobalWidgetsLocalizations.delegate,
    DemoLocalizationsDelegate() // 设置Delegate
  ],
);

上面代码DemoLocalizations.of(context).title是会报错的,原因是Localizations.of会从当前的context沿着widget树向顶部查找DemoLocalizations,在Material APP中设置完DemoLocalizationsDelegate后,实际上DemoLocalizations是在当前context树中,所以DemoLocalizations.of(context)会返回null,报错,解决方式如下:

MaterialApp(
  onGenerateTitle: (context){
    // 此时context在Localizations的子树中
    return DemoLocalizations.of(context).title;
  },
  localizationsDelegates: [
    DemoLocalizationsDelegate(),
    ...
  ],
);

3、如何为英语系的国家指定同一个locale

英语系国家很多,比如美国、英国、澳大利亚,虽然都是英语,也会有一些区别,如果APP只想提供一种英语,供所有英语系国家使用,可以在localeListResolutionCallback中来做兼容:

localeListResolutionCallback:
    (List<Locale> locales, Iterable<Locale> supportedLocales) {
  // 判断当前locale是否为英语系国家,如果是直接返回Locale('en', 'US')     
}

在使用Intl时问题

记得如果使用了插件Flutter Intl时在pubspec.yaml中有这个标识

flutter_intl:
  enabled: true

在使用了插件时,不用在pubspec.yaml中再引入

intl: ^0.18.1

二者二选一就好,通常的推荐是选择插件。

在使用国际化的时候一定要规范命名,不然随着项目的增加,会出现很多重复的翻译。

下面提供自己维护APP内语言的方法:

class LocaleTool {
  // 获取本地存储的配置语言
  static List<String> languageConfig() {
    List<String> list = ["zh", 'CN'];
    String language = CommonSpUtil.getLanguageType();
    if (language.isNotEmpty) {
      List<String> languageList = language.split('_');
      if (languageList.length >= 2) {
        list = languageList;
      }
    }
    return list;
  }

  /// 切换语言
  changeLanguage({required languageStr}) async {
    List list = languageStr.split('_');
    String languageCode = 'zh';
    String countryCode = "CN";
    if (list.length == 2) {
      languageCode = list[0];
      countryCode = list[1];
    }
    var locale = Locale(languageCode, countryCode);

    /// 更新语言
    await Get.updateLocale(locale);

    /// 存储本地语言配置
    await CommonSpUtil.saveLanguageType(languageStr);
  }
  // 存语言配置
  static saveLanguageType(String languageType) {
    return SpUtil.putString(CommonSpUtil.languageType, languageType);
  }

  /// 获取语言配置 默认 中文
  static String getLanguageType() {
    return SpUtil.getString(CommonSpUtil.languageType) ?? "zh_CN";
  }
}

上面CommonSpUtil类,是基于插件sp_util封装的本地存储类。

用法:

/// 配置语言 根据需求 进行处理
  String configlanguage(String string) {
    String languagestr = "zh_CN";
    switch (string) {
      case "简体中文":
        languagestr = "zh_CN";
        break;
      case "English":
        languagestr = "en_US";
        break;
      default:
    }
    return languagestr;
  }
  LocaleTool().changeLanguage(
   languageStr: logic.configlanguage(
      logic.config[logic.datas[index].toString()]));