Flutter多语言支持插件multiple_localization_plus的使用
Flutter多语言支持插件multiple_localization_plus的使用
问题
如果你想要有多个arb文件,并且为每个文件注册单独的委托(delegate),那么你将面临一个问题。Intl
包不允许多次调用initializeMessages
。只有第一次调用会被处理,并且只会使用首次调用的消息。之后的调用将被忽略。
为什么我们需要多个arb文件?
在一般情况下,我们并不需要。只需将所有本地化字符串放在一个文件中即可。但如果你希望将带有arb文件的国际化添加到一个独立的包中,然后在你的项目中使用该包及其自己的本地化文件时,就会遇到问题。
MultipleLocalizations
支持使用 Localizations.override(delegates: [SomeLocalizationsDelegate(), ...])
小部件。正是为了解决这种情况,开发了此包。
更多信息可以参见Medium上的文章:Dart包的本地化。
使用方法
要使用此包,请在 pubspec.yaml
文件中将其作为依赖项添加:
dependencies:
multiple_localization_plus: ^x.x.x
然后,在加载代理(delegate)时使用 MultipleLocalizations.load
方法,而不是显式调用 initializeMessages
。
示例
class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
const _AppLocalizationsDelegate();
[@override](/user/override)
bool isSupported(Locale locale) {
return ['en', 'ru'].contains(locale.languageCode);
}
[@override](/user/override)
Future<AppLocalizations> load(Locale locale) {
return MultipleLocalizations.load(
initializeMessages, locale, (l) => AppLocalizations(l),
setDefaultLocale: true);
}
[@override](/user/override)
bool shouldReload(LocalizationsDelegate<AppLocalizations> old) {
return false;
}
}
覆盖来自包中的字符串
如果你想要覆盖项目中包内的字符串(例如更改包小部件中的某些标签),则需要在应用程序本地化类中定义具有所需名称的字符串。
示例
如果包内有一个名为 messageFromPackageForOverride
的字符串:
class PackageLocalizations {
...
String get messageFromPackageForOverride =>
Intl.message('Package', name: 'messageFromPackageForOverride');
}
那么你需要在 AppLocalizations
中定义 messageFromPackageForOverride
:
class AppLocalizations {
...
String get messageFromPackageForOverride =>
Intl.message('App', name: 'messageFromPackageForOverride');
}
确保在添加包本地化代理之前先添加应用程序本地化代理:
const MaterialApp(
localizationsDelegates: [
AppLocalizations.delegate,
PackageLocalizations.delegate,
DefaultCupertinoLocalizations.delegate,
],
...
)
现在,每当包使用 messageFromPackageForOverride
时,你将会看到 App
,而不是 Package
。
设置回退语言环境
你还可以在加载应用程序本地化代理时指定一个回退语言环境。使用 [fallbackLocale]
参数设置一个在当前语言环境中找不到某些键时使用的语言环境。只有第一次调用 [load]
会设置回退语言环境,请确保应用程序的本地化代理作为委托列表的第一个元素添加。
注意,如果你提供了 [fallbackLocale]
,则会在应用程序启动时将所有消息加载到内存中,而不仅仅是当前语言环境。
完整示例代码
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:multiple_localization_plus/multiple_localization_plus.dart';
import './app/l10n/messages_all.dart';
import './package/l10n/messages_all.dart' as package;
void main() {
runApp(
const MaterialApp(
supportedLocales: [Locale('en')],
localizationsDelegates: [
AppLocalizations.delegate,
PackageLocalizations.delegate,
DefaultCupertinoLocalizations.delegate,
],
home: HomeScreen(),
),
);
}
class HomeScreen extends StatelessWidget {
const HomeScreen({Key? key}) : super(key: key);
[@override](/user/override)
Widget build(BuildContext context) {
final appLocalization = AppLocalizations.of(context);
final packageLocalization = PackageLocalizations.of(context);
return Scaffold(
appBar: AppBar(
title: Text(appLocalization.title),
),
body: Padding(
padding: const EdgeInsets.all(18.0),
child: Center(
child: Column(
children: [
Text(appLocalization.messageFromApp),
Text(packageLocalization.messageFromPackage),
Text(packageLocalization.messageFromPackageForOverride),
],
),
),
),
);
}
}
// 应用程序本地化
class _AppLocalizationsDelegate
extends LocalizationsDelegate<AppLocalizations> {
const _AppLocalizationsDelegate();
[@override](/user/override)
bool isSupported(Locale locale) => ['en'].contains(locale.languageCode);
[@override](/user/override)
Future<AppLocalizations> load(Locale locale) {
return MultipleLocalizations.load(
initializeMessages, locale, (l) => AppLocalizations(l),
setDefaultLocale: true);
}
[@override](/user/override)
bool shouldReload(LocalizationsDelegate<AppLocalizations> old) => false;
}
/// 应用程序本地化。
class AppLocalizations {
/// 委托。
static const LocalizationsDelegate<AppLocalizations> delegate =
_AppLocalizationsDelegate();
static AppLocalizations of(BuildContext context) =>
Localizations.of<AppLocalizations>(context, AppLocalizations)!;
final String locale;
AppLocalizations(this.locale);
String get title => Intl.message('Multiple localization', name: 'title');
String get messageFromApp =>
Intl.message('Default Message from App', name: 'messageFromApp');
String get messageFromPackageForOverride =>
Intl.message('Default overrided message from Package',
name: 'messageFromPackageForOverride');
}
// 其他本地化,例如来自包
class _PackageLocalizationsDelegate
extends LocalizationsDelegate<PackageLocalizations> {
const _PackageLocalizationsDelegate();
[@override](/user/override)
bool isSupported(Locale locale) => ['en'].contains(locale.languageCode);
[@override](/user/override)
Future<PackageLocalizations> load(Locale locale) {
return MultipleLocalizations.load(
package.initializeMessages, locale, (l) => PackageLocalizations(l));
}
[@override](/user/override)
bool shouldReload(LocalizationsDelegate<PackageLocalizations> old) => false;
}
/// 包本地化。
class PackageLocalizations {
/// 委托。
static const LocalizationsDelegate<PackageLocalizations> delegate =
_PackageLocalizationsDelegate();
static PackageLocalizations of(BuildContext context) =>
Localizations.of<PackageLocalizations>(context, PackageLocalizations)!;
final String locale;
PackageLocalizations(this.locale);
String get messageFromPackage =>
Intl.message('Default Message from Package', name: 'messageFromPackage');
String get messageFromPackageForOverride =>
Intl.message('Default Message from Package for override',
name: 'messageFromPackageForOverride');
}
更多关于Flutter多语言支持插件multiple_localization_plus的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html