Flutter-国际化之Localizations实现

219 阅读2分钟

实现Localizations类

Localizations类中主要实现提供了本地化值:

enum SSLLocaleType{
  cn("zh"),
  en("en"),
  fr("fr");

  final String value;
  const SSLLocaleType(this.value);
}

class SSLLocalizations {
  SSLLocalizations(this.type);
  SSLLocaleType type = SSLLocaleType.cn;

  static SSLLocalizations? of(BuildContext context){
    return Localizations.of<SSLLocalizations>(context, SSLLocalizations);
  }

  String get title{

    if (type == SSLLocaleType.cn){
      return "国际化";
    }else if (type == SSLLocaleType.fr){
      return "Localization";
    }else{
      return "Localization";
    }

  }
}

SSLLocalizations会根据语言返回不同的文本,可以将所有需要支持的多语言都定义在此类中。SSLLocalizations的实例将会在Delegate类的load方法中创建。

实现Delegate类

Delegate类的职责是在locale改变时加载新的locale资源,所以它有一个load方法,Delegate类需要继承自LocalizationDelegate类,实现相应的接口:

class SSLLocalizationsDelegate extends LocalizationsDelegate<SSLLocalizations>{
  const SSLLocalizationsDelegate();
  @override
  bool isSupported(Locale locale) =>['en', 'zh', 'fr'].contains(locale.languageCode);

  @override
  Future<SSLLocalizations> load(Locale locale){
    return SynchronousFuture<SSLLocalizations>(
      SSLLocalizations(locale.languageCode as SSLLocaleType)
    );
  }
  @override
  bool shouldReload(SSLLocalizationsDelegate old)=> false;
}

shouldReload的返回值决定当Localizations组件重新build时,是否调用load方法重新加载local资源。一般情况下,locale资源只会在切换locale时加载一次,所以返回false,如果启动后用户再改变疑凶语言时,load方法将不会再被调用,所以locale资源不会被加载。事实上,每当locale改变时,Flutter都会再调用load方法加载新的locale,无论shouleReload返回true还是false。

添加多语言支持

先注册SSLLocalizations类,然后再通过SSLLocalizations.of(context)来动态获取Locale文本。
只需要MaterialApp或WidgetsApp的localizationsDelegates列表中添加Delegate实例即可完成注册:

localizationsDelegates: [
 // 本地化的代理类
 GlobalMaterialLocalizations.delegate,
 GlobalWidgetsLocalizations.delegate,
 // 注册我们的Delegate
 DemoLocalizationsDelegate()
],

在 Widget中使用Locale值:

return Scaffold(
  appBar: AppBar(
    //使用Locale title  
    title: Text(DemoLocalizations.of(context).title),
  ),
  ... //省略无关代码

这样,当语言进行切换时,APP的标题将会分别为使用对应的语言。
上面比较麻烦的是,每种语言需要手动的判断当前语言的locale,然后返回适合的文本。当支持的语言太多的时候,文本会变得很繁琐。如果可以像i18n或l10n标准那样可以将翻译单独保存为arb文件交给翻译去翻译,翻译好了后,再通过工具将arb文件转化为代码,这样可以大大节省工作量。Flutter 中有插件Intl,安装这个插件后,国际化变的非常的便捷,只需要维护好翻译文本就行,其他的插件基本都已经处理好,每次改变翻译文本后,插件也会自动更新。下篇会介绍如何使用Intl。