0 purchases
dynamic intl
Description #
基于原intl和flutter_intl自动生成插件,使原先固定的arb变为可动态化更新的模式。也可以不用flutter_intl,默认的只要格式正确也是一样的。
支持通过版本变更来更新,以及arb增量更新。并且可以动态增加支持的语言并及时应用。
Installing #
dependencies:
dynamic_intl: ^0.1.0
copied to clipboard
Import it
import 'package:dynamic_intl/dynamic_intl.dart';
copied to clipboard
初始化以及配置 #
继承LanguageSetting来配置对应的设置。首要就是设置对应的资源远程链接,还可以配置缓存的目录、文件名等。
import 'package:dynamic_intl/dynamic_intl.dart';
class TestSetting extends LanguageSetting {
@override
Future<String> languageApi(String locale) async {
return 'https://jomin-web.web.app/language/intl_$locale.arb';
}
@override
String get defaultLocale => 'en';
@override
Map<String, LibraryLoader> get deferredLibraries => {
'zh': () => Future.value(null),
'en': () => Future.value(null),
};
}
copied to clipboard
defaultLocale为默认的语言,最好跟flutter_intl中设置的保持一致。会根据这个默认语言来决定各个文案的占位符,很重要。
deferredLibraries是支持的语言列表,格式跟官方intl中自动生成的一样,下边的checkAndDownload可以放在这里,那么在加载对应语言时就可以触发检查下载。
还可以设置在远程资源失效或没有正常获得的时候,备用的本地语言包,格式也是跟官方的一致。
import 'package:lib/generated/intl/messages_zh.dart' as messages_zh;
import 'package:lib/generated/intl/messages_en.dart' as messages_en;
@override
MessageLookupByLibrary? defaultLocaleMessages(String localeName) {
switch (localeName) {
case 'zh':
return messages_zh.messages;
case 'en':
return messages_en.messages;
default:
return null;
}
}
copied to clipboard
本地语言包示例 #
flutter_intl的配置:
flutter_intl:
enabled: true
copied to clipboard
按照官方的来即可,也可以自己配置路径什么的(example中的配置了language路径下)。
自动生成的文件(generated下的)不需要去手动修改,messages_all已经不会用到。messages_en等,可以作为本地备用资源,在远程资源失败时可做备用。l10n.dart需要记住其中的类,后续需要注册到delegate中,但不要用它自己里面的delegate。
l10n目录下的为语言包,即本地的,尽量跟远程同步,修改后及时更新到远程中或随版本更新。格式就简单的json,根据文件名区分语言。
{
"test": "test title"
}
copied to clipboard
Arb转译器 #
目前arb的转译仅支持普通的Intl.message,且最多十个占位符(各规则可参考ApplicationResourceBundleSpecification),如果有需要想支持plural、gender等,或者需要更多占位符,可以继承ArbTraslation,并重写parseFile。相应的写法可自行查看代码。然后设置到LanguageSetting中。
@override
ArbTranslation arbTranslation = NewArbTranslation();
copied to clipboard
开启arb增量更新 #
若是觉得语言包体积过于庞大,可以配合服务端做增量更新。即服务端把‘增量’返回,客户端会进行merge并更新(不会移除旧的)。
默认为false,需设置为true。
@override
bool get arbMergeEnable => true;
copied to clipboard
在runApp前初始化完成 #
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await LanguageUtil.instance.init(TestSetting());
runApp(const MyApp());
}
copied to clipboard
使用多语言,WidgetsFlutterBinding.ensureInitialized()也是需要的。
注册到MaterialApp #
locale可自行控制,需要配置的主要是localizationsDelegates和supportedLocales。可继承BaseLocalizationsDynamicDelegate<T>(T 即为flutter_intl自动生成的类,默认是S, 具体由你决定)来获取最简单的Delegate。有自己想法的也可以自行编写,并重写supportedLocales和在load中使用initializeDynamicMessages。
class AppLocalizationDynamicDelegate
extends BaseLocalizationsDynamicDelegate<S> {
const AppLocalizationDynamicDelegate();
static const AppLocalizationDynamicDelegate delegate =
AppLocalizationDynamicDelegate();
@override
Future<S> loadS() {
final instance = S();
return Future.value(instance);
}
}
copied to clipboard
按照上边的写法即可。然后设置到MaterialApp中
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
/// 当前语言
locale: MyApp.locale,
localizationsDelegates: const [
/// Delegate 注册
AppLocalizationDynamicDelegate.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
/// 支持的语言列表
supportedLocales:
AppLocalizationDynamicDelegate.delegate.supportedLocales,
home: MyHomePage(
title: 'Flutter Demo Home Page', updateLocale: updateLocale),
);
}
copied to clipboard
在自定支持语言列表时,这三个delegate也是需要的,系统功能的多语言支持,记得也加上。
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
copied to clipboard
它们需要flutter_localizations
flutter_localizations: # Add this line
sdk: flutter
copied to clipboard
触发检查下载 #
通过Future checkAndDownload(String locale, [String? newVersion])可下载指定语言指定版本的语言包(版本不同则会更新)。下载完成之后可刷新UI来展示最新文案。切换语言也应该调用该方法,已存在语言包则会跳过。
// 下载语言包,可以加版本, 无版本则每次都更新
LanguageUtil.instance
.checkAndDownload(MyApp.locale.languageCode, '1002')
.then((value) {
// 因为下载完成前会使用默认文案,下载完成后应刷新下UI
setState(() {});
});
copied to clipboard
若当前下载的不是默认语言,且默认语言包也没有下载保存过,那么会先下载默认语言包。
版本管理需要自行设计,这里仅根据传入的版本对比来更新。
增加支持的语言列表 #
可通过updateLanguageLibrary动态新增支持的语言列表。
updateLanguageLibrary([const Locale('it'), const Locale('de')]);
copied to clipboard
若Setting中没有,则可以先检查远程列表然后通过该方法新增,新增后才可以有效切换。
关闭远程仅使用本地 #
setLocalLanguage设置为true,则会无视远程语言包,直接使用本地的语言包,确认defaultLocaleMessages正常配置。
LanguageUtil.instance.setLocalLanguage(true);
copied to clipboard
使用文案 #
即普通的S.of(context).text,觉得需要context太麻烦,可以在MaterialApp下build的时候注册一个全局context(参考GetX的全局context),一样用。
Text(S.of(context).test)
/// 带占位符
S.of(context).textPlace(‘123’)
copied to clipboard
切换语言 #
修改MaterialApp的locale,然后检查语言包下载,最后刷新UI即可。需要刷新到MaterialApp这一层,可以看看example中的示例。
void _changeLocale() async {
var locale = MyApp.locale.languageCode == 'en'
? const Locale('zh')
: const Locale('en');
LanguageUtil.instance
.checkAndDownload(locale.languageCode, '1002')
.then((_) {
// 因为下载前会使用默认文案,下载完成后应刷新下UI
widget.updateLocale(locale);
});
}
copied to clipboard
最后 #
翻译的文件有@开头的注释消息,也没有问题,只不过默认的ArbTranslation不会处理。LanguageSetting可以在你的管理类里面继承,建议S也重新再套一层再使用,方便维护。检查下载和切换可以根据实际需求来,全部都一起下载也不是不可以,也可以配置在deferredLibraries中随系统切换时自动同步检查下载。
example中有个比较简单的可以直接运行的例子,可供参考。有什么问题的话可以直接提issue。
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.