移动端出海,搞APP的就不得不提前预备应对方案,Flutter 实现国际化的方案有许多,例如:
flutter_localizations
Intl
getx
参考众多开源库,这里推荐一种较简单且容易理解的实现方案,通过flutter_localizations
+ getx
组合实现多语言适配、切换刷新。具体实现方案如下:
通过Flutter的gen-l10n
命令,基于arb资源文件生成对应的国际化语言文件及相关调用类
1. 准备
l10n.yaml
- 在项目工程根目录新建一个
l10n.yaml
文件 - 是
flutter gen-l10n
命令的默认配置文件 gen-l10n
命令的参数可以跟在命令行后面,同时也可以在项目中的l10n.yaml文件定义l10n.yaml
大致内容
- 在项目工程根目录新建一个
arb-dir: lib/language/l10n #指定arb多国语文件目录
template-arb-file: app_zh.arb #指定arb多国语文件
output-dir: lib/language/l10n/gen
output-class: AppLocalizations
output-localization-file: app_localizations.dart #指定多国语配置生成的代码文件,代码中自动生成类文件AppLocalizations.dart
synthetic-package: false
untranslated-messages-file: lib/language/l10n/gen/app_localizations_untranslated.json
format: true
arb(Application Resource Bundle)
文件- 准备要支持的国际化语言集合,如下:
#app_en.arb
{
"@@locale": "en",
"appVersion": "Version: {version}",
"@appVersion": {
"placeholders": {
"version": {
"type": "String"
}
}
},
"helloWorld": "helloWorld"
}
#app_zh.arb
{
"@@locale": "zh",
"appVersion": "版本号: {version}",
"@appVersion": {
"placeholders": {
"version": {
"type": "String"
}
}
},
"helloWorld": "你好,世界"
}
2. 生成
在l10n.yaml
同级目录下,运行命令flutter gen-l10n
生成的代码如下:
//app_localizations_en.dart
//略
//app_localizations_zh.dart
class AppLocalizationsZh extends AppLocalizations {
AppLocalizationsZh([String locale = 'zh']) : super(locale);
String appVersion(String version) {
return '版本号: $version';
}
String get helloWorld => '你好,世界';
}
//app_localizations.dart
abstract class AppLocalizations {
AppLocalizations(String locale)
: localeName = intl.Intl.canonicalizedLocale(locale.toString());
final String localeName;
static AppLocalizations? of(BuildContext context) {
return Localizations.of<AppLocalizations>(context, AppLocalizations);
}
static const LocalizationsDelegate<AppLocalizations> delegate =
_AppLocalizationsDelegate();
/// A list of this localizations delegate's supported locales.
static const List<Locale> supportedLocales = <Locale>[
Locale('en'),
Locale('zh')
];
/// No description provided for @appVersion.
///
/// In zh, this message translates to:
/// **'版本号: {version}'**
String appVersion(String version);
/// No description provided for @helloWorld.
///
/// In zh, this message translates to:
/// **'你好,世界'**
String get helloWorld;
}
class _AppLocalizationsDelegate
extends LocalizationsDelegate<AppLocalizations> {
const _AppLocalizationsDelegate();
Future<AppLocalizations> load(Locale locale) {
return SynchronousFuture<AppLocalizations>(lookupAppLocalizations(locale));
}
bool isSupported(Locale locale) =>
<String>['en', 'zh'].contains(locale.languageCode);
bool shouldReload(_AppLocalizationsDelegate old) => false;
}
AppLocalizations lookupAppLocalizations(Locale locale) {
// Lookup logic when only language code is specified.
switch (locale.languageCode) {
case 'en':
return AppLocalizationsEn();
case 'zh':
return AppLocalizationsZh();
}
throw FlutterError(
'AppLocalizations.delegate failed to load unsupported locale "$locale". This is likely '
'an issue with the localizations generation tool. Please file an issue '
'on GitHub with a reproducible sample app and the gen-l10n configuration '
'that was used.');
}
3. 配置
- 配置
MaterialApp
或GetMaterialApp
国际化字段supportedLocales
,支持切换的语言localizationsDelegates
,委托定义locale
,默认语言fallbackLocale
,出错时配置语言
4. 调用
- 方法1:直接使用
AppLocalizations.of(context).helloWorld
//使用
Text(AppLocalizations.of(context).helloWorld)
- 方法2:扩展使用
- 将方法1的
AppLocalizations.of(context)
定义为BuildContext
的扩展l10n
,则可以在使用文本的地方调用context.l10n.helloWorld
- 将方法1的
//扩展BuildContext
extension BuildContextExtension on BuildContext {
AppLocalizations get l10n => AppLocalizations.of(this)!;
}
//使用
Text(context.l10n.helloWorld)
5. 与getx
结合
方案中提到getx
,目的是利用它单实例的优点,可直接获取当前设备使用的语言,同时与main.dart
的GetMaterialApp
相结合,在切换的时候,可以实现全局刷新。
Get.updateLocale(Locale('zh')); //切换语言
略...
Enjoy it~~