Flutter资源管理
在pubspec.yaml中指定资源所在目录:
assets:
- images/
- images/mic_status/
Asset 变体(variant)
在选择匹配当前设备分辨率的图片时,Flutter会使用到asset变体
…/graphics/background.png
…/graphics/dark/background.png
…/my_icon.png
…/2.0x/my_icon.png
…/3.0x/my_icon.png
// 只需包含:
flutter:
assets:
- graphics/background.png
- my_icon.png
加载assets
1 加载文本assets
// 建议使用 DefaultAssetBundle 来获取当前BuildContext的AssetBundle。 这种方法不是使用应用程序构建的默认asset bundle,而是使父级widget在运行时动态替换的不同的AssetBundle,这对于本地化或测试场景很有用
DefaultAssetBundle.of()
// 每个Flutter应用程序都有一个rootBundle对象, 通过它可以轻松访问主资源包,直接使用package:flutter/services.dart中全局静态的rootBundle对象来加载asset即可
rootBundle.loadString('assets/config.json');
2 加载图片
AssetImage('graphics/background.png'),
AssetImage('icons/heart.png', package: 'my_icons')
Flutter国际化
.arb( Application Resource Bundle) 基于json格式的资源文件,每个.arb文件都包含一个JSON表,该表从资源ID映射到本地化值,文件名包含已为其转换值的语言环境
使用
1 在pubspec.yaml中添加flutter_localizations依赖并执行flutter packages get
dependencies:
flutter:
sdk: flutter
# international
flutter_localizations:
sdk: flutter
2 通过插件Flutter Intl
纯手动方式参考下方的
补充标签
主要是将intl_xx.arb文件自动生成对应语言的message_xx.dart文件
(如要适用于ios和远端构建 ,则前面的步骤手动添加,然后执行一下intl_util.generate的命令,如android在gradle中执行,远端CI使用sh脚本直接执行)
2.1 初始化项目 Tools -> Flutter Intl -> Initialize for the Project
其实就是在pubspec.yaml下增加了
flutter_intl:
enabled: true
// 可以自定义一些内容
class_name: S (自定义语言库Delegate的默认类名) # Optional. Sets the name for the generated localization class. Default: S
main_locale: en (会根据这个对应的arb文件的字符串定义来生成相应的代码,即使别的arb文件没相关的字符串定义) # Optional. Sets the main locale used for generating localization files. Provided value should consist of language code and optional script and country codes separated with underscore (e.g. 'en', 'en_GB', 'zh_Hans', 'zh_Hans_CN'). Default: en
arb_dir: lib/l10n # Optional. Sets the directory of your ARB resource files. Provided value should be a valid path on your system. arb文件存放的路径
localizely: (Localizely platform可以帮你翻译你的主语言为其他语言) # Optional settings if you use Localizely platform. Read more: https://localizely.com/flutter-localization-workflow
project_id: # Get it from the https://app.localizely.com/projects page.
branch: # Get it from the “Branches” page on the Localizely platform, in case branching is enabled and you want to use a non-main branch.
upload_overwrite: # Set to true if you want to overwrite translations with upload. Default: false
upload_as_reviewed: # Set to true if you want to mark uploaded translations as reviewed. Default: false
download_empty_as: # Set to empty|main|skip, to configure how empty translations should be exported from the Localizely platform. Default: empty
ota_enabled: # Set to true if you want to use Localizely Over-the-air functionality. Default: false
并且在lib目录下生成了
generated
目录(存放如
messages_all.dart、message_en.dart
)和
l10n
目录(存放arb文件)
2.2 添加国家/地区语言 Tools -> Flutter Intl ->add locale
其实会在
generated
目录生成
message_xx.dart
和
I10n
目录生成
intl_xx.arb
手动方式则自己在
I10n
目录创建
intl_xx.arb
2.3 在arb文件中添加你要的字符串,ide中ctrl+s保存一下,即会自动执行intl_util.generate的命令,命令会将字符串的key添加到l10n.dart文件中,将相应的字符串内容添加到message_xx.dart文件中
手动方式则执行intl_util.generate的命令:
在pubspec.yaml所在的目录执行
flutter --no-color pub global run intl_utils:generate
参考:https://pub.dev/packages/intl_utils
3 初始化
import 'package:flutter_localizations/flutter_localizations.dart';
Widget build(BuildContext context) {
return MaterialApp(
// 1 添加语言库delegates
localizationsDelegates: [
// 插件自动生成
S.delegate,
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalWidgetsLocalizations.delegate
],
// 2 插件自动生成
supportedLocales: S.delegate.supportedLocales,
要设置支持同一个国家不同地区特色的语言:
默认仅提供美国英语本地化,要自己设置需要的国家、地区的语言
supportedLocales: [
const Locale('en', 'US'),
const Locale('zh', 'CN'),
// Full Chinese support for CN, TW, and HK
const Locale.fromSubtags(languageCode: 'zh'), // generic Chinese 'zh'
const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans'), // generic simplified Chinese 'zh_Hans'
const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant'), // generic traditional Chinese 'zh_Hant'
const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans', countryCode: 'CN'), // 'zh_Hans_CN'
const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant', countryCode: 'TW'), // 'zh_Hant_TW'
const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant', countryCode: 'HK'), // 'zh_Hant_HK'
],
4 资源使用
MaterialLocalizations.of(context).xxLable
补充:手动方式
2 添加自定义的语言库类,并绑定自定义的localizationsDelegate中
(1) 通过map的方式
创建一个语言库类,类中一个Map<String, Map<String, String>>,key为语言,第二个Map的key为字符串的id标识,value为具体字符串
并绑定自定义的localizationsDelegate中
class SimpleLocalizationsDelegate
extends LocalizationsDelegate<SimpleLocalizations> {
const SimpleLocalizationsDelegate();
@override
bool isSupported(Locale locale) => ['en', 'zh'].contains(locale.languageCode);
@override
Future<SimpleLocalizations> load(Locale locale) {
return SynchronousFuture<SimpleLocalizations>(SimpleLocalizations(locale));
}
@override
bool shouldReload(SimpleLocalizationsDelegate old) => false;
}
(2) 通过dart的intl
添加依赖:
dependencies:
intl: ^0.15.7
dev_dependencies:
intl_translation: ^0.17.3
创建一个语言库类,类中
class IntlLocalizations {
static IntlLocalizations of(BuildContext context) {
return Localizations.of<IntlLocalizations>(context, IntlLocalizations);
}
String get appName {
return Intl.message('App Name');
}
String get helloWorld {
return Intl.message('Hello world');
}
}
执行
flutter pub pub run intl_translation:extract_to_arb --output-dir=你想要的输出目录
。这一操作将会在指定目录里生成一个名为
intl_messages.arb
的文件
然后可以复制多份,如
intl_zh.arb
等不同国家、地区语言的字符串资源文件
执行
flutter pub pub run intl_translation:generate_from_arb --output-dir=输出目录 --no-use-deferred-loading IntlLocalizations所在文件 所有arb文件
。这样会生成几个 messages_ 开头的 dart 文件
其中名为 messages_all.dart 的文件里,在 IntlLocalizations 中添加如下的方法:
static Future<IntlLocalizations> load(Locale locale) {
final name =
locale.countryCode.isEmpty ? locale.languageCode : locale.toString();
final localeName = Intl.canonicalizedLocale(name);
return initializeMessages(localeName).then((_) {
Intl.defaultLocale = localeName;
return IntlLocalizations();
});
}
再绑定自定义的localizationsDelegate中:
@override
Future<IntlLocalizations> load(Locale locale) {
return IntlLocalizations.load(locale);
}
参考:https://segmentfault.com/a/1190000022579469
问题1 无法找到intl
解决:
flutter pub global activate 'packageName'
flutter pub global activate 'intl_utils'
当你想从命令行运行某个 Package 中的可执行对象时你需要先激活它
问题2 找不到l10.dart文件
gradle的这个任务要执行
exec {
println("###################execIntlTask########################")
commandLine "flutter", "--no-color", "pub", 'global', 'run', 'intl_utils:generate'
workingDir "../../flutter_module"
}