大家好,我是 17。
春节期间为大家精心准备了这篇实现国际化的文章,和大家一起,用最简单快速的方式实现 Flutter 国际化。
Flutter 国际化要解决的是两个问题
- flutter 框架本身的国际化,flutter 已经为我们实现,只要启用即可。
- 工程国际化,就是我们自己写的代码,需要自己做国际化。
flutter 框架的国际化
实现框架国际化只要 2 步
添加依赖
打开项目根目录下的 pubspec.yaml 文件,找到 dependencies,添加
flutter_localizations:
sdk: flutter
添加后的配置
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
添加好配置后,执行
flutter pub get
添加代码
MaterialApp(
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: [
const Locale('en', 'US'), // 美国英语
const Locale('zh', 'CN'), // 中文简体
//其他Locales
],
// ...
)
这样就大功告成了。
测试
代码加上了,但是怎么测试国际化有没有生效呢?很简单,加一个 TextField Widget,随便输入点内容,然后长按输入框,就会有提示文本 ”全选“ 出现。国际化成功后显示的是中文。把国际化的代码删除再看下,显示的是英文 ”Select all"。
const MaterialApp(
supportedLocales: [
Locale('en', 'US'), // 美国英语
Locale('zh', 'CN'), // 中文简体
],
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate
],
home: Scaffold(
body: Center(
child: TextField(),
)),
);
代码解释
supportedLocales 指定支持的语言和地区。Locale 的第一个参数是语言标签,第二个参数是地区标签。一般情况下,支持中文和英文就够了,如果要支持更多语言和地区,可以到 语言和地区的标签列表 中查阅。
GlobalMaterialLocalizations.delegate
为 Material 组件库提供本地化的字符串和其他值。
GlobalCupertinoLocalizations.delegate
为 Cupertino 组件库提供本地化的字符串和其他值。
GlobalWidgetsLocalizations.delegate
定义了默认的文本排列方向,由左到右或者由右到左。
到这里 Flutter 框架的国际化就完成了,下面看下如何为自己写的代码做国际化。
工程国际化
自己写的代码做国际化需要 IDE 和插件的配合,这样才能事半功倍。
初始化环境
- IDE 选择 vscode(visual studio code)
- IDE 插件用 Flutter Intl
- 打开 vscode,新建一个 application
- 配置 pubspec.yaml 文件,增加 flutter_localizations。这是必须的,必须得先支持 Flutter 框架的国际化。
flutter_localizations:
sdk: flutter
执行 pub get
fluter pub get
- 同时按 cmd 键(windows 是 ctrl 键) + shift 键 + p 键,打开命令面板,单独按 F1,也能打开命令面板,选择 Flutter Intl:Initialize
执行完命令后在pubspec.yaml 中多了一个配置
flutter_intl:
enabled: true
lib 文件夹中多了两个文件夹 generated 和 i10n。generated 我们不用管,vscode 的插件 Flutter Intl 负责维护。我们需要关注的是 l10n。l10n 是 localization 的缩写,10 代表中间省略了 10 个字母。
编辑内容
目录只有一个文件 intl_en.arb。
arb 文件扩展名为:Application Resource Bundle 缩写,意为应用程序资源包,并得到Google的支持,每个 .arb 文件都包含一个JSON表,该表从资源ID映射到本地化值。
arb 文件很简单,无关代码,交给翻译,翻译好了再放回来。
打开 intl_en.arb 发现只有一个 {}
我们增加一个 title。
{
"title":"IAM17"
}
为了支持中文,我们通过命令面板执行 Flutter Intl:Add locale。
然后让我们输入语言和地区。我们输入 zh_CN,在 l10n 文件夹下面会多出一个文件 intl_zh_CN.arb。
打开 intl_zh_CN.arb,输入以下内容
{
"title":"我是 17"
}
通过文件命名我们可以看出,默认的 intl_en.arb 不区分地区,只要语言是英语就行。
应用国际化
我们准备好了一个 title 现在把它展示出来 。
需要 4 步
- 引用
import generated/l10n.dart
- 添加
S.delegate
- 添加
supportedLocales: S.delegate.supportedLocales
-
S.of(context).title
获得 title
完整代码,贴到 main.dart 就能运行。
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
// 1
import 'generated/l10n.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: const [
// 2
S.delegate,
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalWidgetsLocalizations.delegate
],
// 3
supportedLocales: S.delegate.supportedLocales,
home: Scaffold(body: Builder(
builder: (context) {
return Center(
// 4
child: Text(S.of(context).title),
);
},
)));
}
}
说英语的地区有很多,总不能每个地区都配置一套吧
一般情况下,只提供美国英语就够了,其它地区都使用美国英语。
MaterialApp(
localeResolutionCallback: (locale, supportedLocales) {
// 如果语言是英语
if (locale?.languageCode == 'en') {
//注意大小写,返回美国英语
return const Locale('en', 'US');
} else {
return locale;
}
},
// 省略...
参数 locale 是设备系统报告的设备支持的首选语言环境。当环境为英语时,不论是哪个地区,都返回美国英语。
localeResolutionCallback 负责在 App 启动和用户改变设备语言的时候确定语言环境。
实际上,设备系统报告的支持的语言环境可能不止一个,如果要对所有支持的语言环境做判断,可以用 LocaleListResolutionCallback 回调,并不常用,了解即可。
占位符
打开 intl_zh_CN.arb 和 intl_en.arb,把 17 用变量替换,变量用 {} 括起来就行。
{
"title":"我是{name}"
}
{
"title":"IAM{name}"
}
修改完后,保存文件,插件会为我自动生成代码,更新 generated 文件夹中的文件。用的时候这样用。
Text(S.of(context).title(17))
17 写成字符串也是可以的,因为参数的类型是 Object。
Text(S.of(context).title(”17“))
App 标题实现国际化
不能直接设置 title,需要在 onGenerateTitle 中设置。
MaterialApp(
title:'不能在这里设置'
onGenerateTitle: (context){
return S.of(context).title;
},
// 省略...
如果直接设置在 title 处,S.of(context).title
是会报错的,原因是S.of
会从当前的 context 沿着widget 树向顶部查找S
,但是 MaterialApp 已经是顶层了,往上不可能找到 S
,所以S.of(context)
会返回 null,报错。
子树应用不同语言
可能某些特殊需求,我们需要对一部分子树应用不同语言,了解一下即可。
Scaffold(body: Builder(
builder: (context) {
return Column(
children: [
Text(S.of(context).title),
Localizations.override(
context: context,
locale: const Locale('en'),
child: Builder(
builder: (context) {
return Text(S.of(context).title);
},
))
],
);
},
))
显示两段文本,上面显示 ”我是 17“,下面显示 IAM17。
删除多余的语言
如果加多了,可以删除。直接删除对应的 arb 文件即可,插件会自动为我们重新生成 generated 中的代码。
获取当前 locale
var locale = Localizations.localeOf(context);
手动改变 Locale
比如当按一个按钮的时候需要切换为美国英语,执行下面的代码就行。
S.load(Locale('en', 'US'));
拿不到 context 怎么办
用 current
可以替代 S.of(context)
S.current.title
如果 App 只有中文如何设置
在一些非大陆行货渠道买的一些 Android 和 iOS 设备,会出现默认的 Locale 不是中文简体的情况。为了能让 App 确定显示中文,我们设置一下 locale 锁定中文。
MaterialApp(
locale: Locale('zh', 'CN'),
supportedLocales: [
Locale('zh','CN')
],
localizationsDelegates: const [
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalWidgetsLocalizations.delegate
],
// 省略...
如果不设置 locale,flutter 会采用系统的首选语言。
最后赠送两个插件配置的小知识
在 pubspec.yaml 文件的最后有两行配置,除了 enabled,还有另外两个选项可以配置
- class_name 前面我们用了很多的 S ,是类名,如果你不喜欢这个名字,可以修改。
- main_locale 设置默认的 locale。
flutter_intl:
enabled: true
class_name: S # 可选。 Default: S
main_locale: en # 可选。可以改成 zh_CN 中文简体,这关系到默认生成的arb文件的名字。Default: en
没骗你吧,说快速实现,就是快速实现。只要按步骤一步一步做下来,轻松就能实现国际化了。
本文到这就结束了,谢谢观看!