官方文档:docs.flutter.dev/ui/accessib...
第一步:引入库
- 设置
generate: true
,项目启动时会自动生成对应的语言库,需要开启generate
pubspec.yaml
yml
dependencies:
# 本地化
flutter_localizations:
sdk: flutter
# 国际化
intl: ^0.18.1
# ...
flutter:
generate: true
第二步:编辑配置文件
- 项目根目录下创建语言配置文件,固定命名为:l10n.yaml
l10n.yaml
yaml
# 其他配置参考官网:https://docs.flutter.dev/ui/accessibility-and-internationalization/internationalization
# arb-dir: lib/l10n # arb文件文件路径,默认 lib/l10n
template-arb-file: intl_en.arb # arb文件名的格式,默认是app_en.arb
nullable-getter: false # Localizations.of(context)的返回值不可以为空
output-localization-file: planx_localizations.dart # 生成的文件名,默认是app_localizations.dart.
output-class: PlanxLocalizations # 类名,默认是AppLocalizations.
第三步:新建对应的arb文件
- 在lib/l10n文件中新建需要翻译的对应的arb文件
- 英文,葡萄牙语,中文
- arb内容文件格式(也是json格式)
- 如果需要接收参数使用大括号,然后在@相同字段名 内设置格式等信息,只用en里面配置就可以了
intl_en.arb
json
{
"home": "Home",
"dayFormat": "{date}",
// 注释请删掉,@dayFormat设置接收参数的类型,DateTime可以设置模版格式
"@dayFormat": {
"placeholders": {
"date": {
"type": "DateTime",
"format": "yMd"
}
}
}
}
intl_zh.arb
json
{
"home": "首页",
"dayFormat": "{date}"
}
第四步:执行flutter run
- 运行项目后,此时我们可以看到,根目录下自动生成了对应的语言类
第五步:在MaterialApp中配置语言
main.dart
dart
// 引入生成的国际化文件
import 'package:flutter_gen/gen_l10n/planx_localizations.dart';
// ....
MaterialApp(
// ...
// 配置语言,可以直接使用生成的PlanxLocalizations类支持的语言
localizationsDelegates: PlanxLocalizations.localizationsDelegates,
supportedLocales: PlanxLocalizations.supportedLocales,
home: const IndexPage(),
);
使用
dart
// 引入国际化文件
import 'package:flutter_gen/gen_l10n/planx_localizations.dart';
// .....
// 获取locale
PlanxLocalizations locale = PlanxLocalizations.of(context);
// 获取对应的翻译文案
print(locale.home);
print(locale.dayFormat(DateTime.now()));
如何设置同一语种的不同区域,以中文简体和繁体为例
- 由于中文简体和繁体同属于中文,因此需要自定设置中文简体和繁体
- 在
MaterialApp
中设置支持的语言
dart
// 引入国际化文件
import 'package:flutter_gen/gen_l10n/planx_localizations.dart';
// ....
MaterialApp(
// ...
// 配置语言
localizationsDelegates: PlanxLocalizations.localizationsDelegates,
// 自行配置支持的语言
supportedLocales: const <Locale>[
Locale('en'),
Locale('pt'),
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans'),
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant'),
],
home: const IndexPage(),
);
- 新建中文繁体的arb文件,注意文件名按照intl_zh_Hant.arb的格式
intl_zh_Hant.arb
json
{
"home": "首頁",
"dayFormat": "{date}"
}
- 重新运行项目,切换系统语言进行测试即可
修改语言
- 我们通过以上的配置,可以通过手机的系统语言,自动适配app的语言
- 如果我们需要手动设置app的语言,需要给
MaterialApp
中的locale
参数传入需要设定的语言,null
就表示取系统语言
dart
MaterialApp(
// ...
// 这里配置app的语言,默认为null也就是系统语言
locale: Locale('zh', 'CN'),
localizationsDelegates: PlanxLocalizations.localizationsDelegates,
supportedLocales: const <Locale>[
Locale('en'),
Locale('pt'),
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans'),
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant'),
],
home: const IndexPage(),
);
配合provide状态管理和本地存储,设置语言
效果:
- 安装相应的依赖:
pubspec.yaml
yml
dependencies:
# 状态管理
provider: ^6.0.5
# 本地存储
shared_preferences: ^2.2.2
- 简单封装本地存储,本地存储,用户下次进入时还是之前选择的语言
lib/utils/storage_util.dart
dart
import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
class StorageUtil {
static late SharedPreferences _preferences;
static init() async {
_preferences = await SharedPreferences.getInstance();
}
// 设置本地缓存
static Future<bool> set<T>(String key, T value) {
String type = value.runtimeType.toString();
switch (type) {
case "String":
return _preferences.setString(key, value as String);
case "int":
return _preferences.setInt(key, value as int);
case "bool":
return _preferences.setBool(key, value as bool);
case "double":
return _preferences.setDouble(key, value as double);
case "List<String>":
return _preferences.setStringList(key, value as List<String>);
case "_InternalLinkedHashMap<String, String>":
return _preferences.setString(key, json.encode(value));
default:
return Future.value(false);
}
}
// 取出缓存
static Object? get(String key) {
Object? value = _preferences.get(key);
if (value.runtimeType.toString() == "String") {
try {
return json.decode(value as String);
} catch (err) {
return value;
}
}
return value;
}
// 删除缓存
static Future<bool> remove(String key) {
return _preferences.remove(key);
}
}
- 新增一个
ChangeNotifier
,用于存储语言,后续在ChangeNotifierProvider
中可以监听
lib/provider/locale_provider.dart
dart
import 'package:flutter/material.dart';
import 'package:planx_app/utils/storage_util.dart';
/// 定义一个 ChangeNotifier,用于存储当前的语言。后续在ChangeNotifierProvider中可以监听
class LocaleProvider extends ChangeNotifier {
String? _locale;
Locale? get locale {
// 获取本地缓存
_locale = (StorageUtil.get('locale') as String?) ?? "system";
switch (_locale) {
case 'zh':
return const Locale('zh');
case 'zh_Hant':
return const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant');
case 'en':
return const Locale('en');
case 'pt':
return const Locale('pt');
default: // 选择系统设置语言
return null;
}
}
// 修改语言
changeLanguage(String val) async {
// 如果当前语言与新语言一致,则不做任何操作
if (val == _locale) return;
_locale = val;
// 本地保存语言
await StorageUtil.set('locale', val);
// 通知所有监听器
notifyListeners();
}
}
- 最外层使用
ChangeNotifierProvider
,用于监听状态的变化,如果发生变化就会执行Consumer
的builder
。 - 在
MaterialApp
外面包一层Consumer获取值。并且给locale
赋值,确定当前app的语言 - provider的更多使用,请参考:Flutter状态管理之 Provider 使用详解 - 掘金
- 注意:在
main
中初始化本地缓存实例
lib/main.dart
dart
import 'package:provider/provider.dart';
import 'package:planx_app/utils/storage_util.dart';
void main() async {
// main函数中有await时,需要先调用此方法
WidgetsFlutterBinding.ensureInitialized();
// 初始化本地缓存实例
await StorageUtil.init();
runApp(const MyApp());
}
//...
///...
ChangeNotifierProvider(
// 监听LocaleProvider的变化
create: (_) => LocaleProvider(),
child: Consumer(
// LocaleProvider变化就会执行Consumer的builder,并接收最新的LocaleProvider
builder: (context,LocaleProvider localeProvider,Widget? child) {
// 包裹MaterialApp
return MaterialApp(
// ...
// 使用语言
locale: localeProvider.locale,
// ...
home: const IndexPage(),
);
}
),
);
- 使用
context.read<LocaleProvider>()
获取LocaleProvider
实例,通过实例更改语言
dart
import 'package:provider/provider.dart';
import 'package:planx_app/provider/locale_provider.dart';
// ....
ElevatedButton(
onPressed: () {
context.read<LocaleProvider>().changeLanguage('en');
},
child: const Text("英语"),
),