实现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。