持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情
Intl 是官方出品的,包含用于处理国际化/本地化消息,日期和数字格式和解析,双向文本以及其他国际话问题。
pub地址:pub.dev/packages/in…
Github地址:github.com/dart-lang/i…
Intl插件最主要的是就是Intl类,他为我们提供了国际化的大量方法,同时该插件还封装了DateFormat、NumberFormat和BidiFormatter几个常用的格式化的工具类。
我经常使用到的就是国际化以及日期格式化功能。使用起来也非常的简单,我们先看看如何实现国际化。
安装Intl插件
Flutter为我们提供了Intl的插件,同时支持as和vs,使用插件可以快速的创建国际化需要的文件,比手动写要舒服多了。
VS code
插件地址:marketplace.visualstudio.com/items?itemN…
插件市场搜索能够更快的找到并安装它。
安装好以后,在命令窗口输入 Flutter Intl能够看到方法就表示已经安装成功了。
Android Studio
插件地址:plugins.jetbrains.com/plugin/1366…
当然,也可以在插件市场搜搜安装。
安装后在Tool里如果能看到Flutter Intl菜单就表示安装好了。
后边我我只用vs来演示了,as的方法大概相同,在tool中选择flutter intl菜单选中响应的功能就行了。
配置项目
创建一个测试的项目
flutter create intl_test
启动国际化支持
编辑pubspec.yaml文件,启动国际化的支持,引入Intl插件。
dependencies:
# 国际化
flutter_localizations:
sdk: flutter
intl: ^0.17.0
初始化Intl
执行命令Flutter Intl initialize
这个时候插件会帮我们创建一个基本的国际化结构,包括pubspec.yaml的调整
# 文件结尾会增加
flutter_intl:
enabled: true
在lib目录下会生成以下文件,在I10n文件夹下边有一个默认的intl_en.arb语言包,arb文件全称Application Resource Bundle(abbr. ARB)是一种本地化资源格式,使用arb文件作为资源配置文件(类似xml)可以提供给翻译人员翻译,他的编辑也是很简单,就像一个json文件,使用key-value格式来录入我们的语言内容。而intl文件夹内的文件,还有I10n.dart都不需要手动编辑,而且不建议大家手动编辑,他们是会根据我们配置的语言包内容自动更新。
新增语言
在命令行输入Flutter intl: Add locale,来新增我们需要的语言。比如ko,ja,如果有地区的需要使用下划线来连接地区,比如简体中文zh_CN,繁体中文有zh_HK、zh_TW,英语美国en_US,英语英国en_GB等,这里根据应用的目标地区自行调整。
在输入语言后,插件会帮我们自动的创建message_,intl_.arb两个文件。同时在I10n中注册我们的语言。
我们可以直接编辑intl_**.arb的文件,来设置我们的语言包,比如我们新建的这个简体中文,然后来设置一些简单的测试数据。编辑语言包很简单,就是一个json格式的文件,要注意的arb文件不支持嵌套,只能有一层。
{
"name": "姓名",
"age": "年龄",
}
{
"name": "Name",
"age": "Age"
}
设置应用
在MaterialApp中增加
// 国际化配置
localizationsDelegates: const [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
S.delegate
],
// 将en设置为第一项,没有适配语言时,英语为首选项
supportedLocales: [
const Locale('en', ''),
...S.delegate.supportedLocales
],
使用就很简单了,在需要国际化的地址,使用S.of(context)来获取一个国际化的实例,属性就是我们在arb中配置的key。
Text(S.of(context).name),
Text(S.of(context).age),
我们还可以增加两个按钮来切换语言。
\
分析一下实现
当我们配置arb文件后,Intl会在generated/I10n.dart文件中使用message方法生成get方法。比如刚才的姓名和年龄代码:
/// `Name`
String get name {
return Intl.message(
'Name',
name: 'name',
desc: '',
args: [],
);
}
/// `Age`
String get age {
return Intl.message(
'Age',
name: 'age',
desc: '',
args: [],
);
}
- 第一个参数就是我们默认的国家化输出内容。
- name:Intl函数的名称,对应arb文件中的key,这个参数必须是全局唯一的。
- desc:文本的描述信息,方便我们了解这个词条的含义,方便翻译人员进行翻译。
- args:插值
最后一个参数这里没用上,我们来看看如何使用插值这个参数。重新编辑一下我们的arb文件
{
"name": "Name",
"age": "Age",
"input": "place input {label}",
"todo": "Do what you {todo},{todo} what you do",
"getMessageTips": "{howMany, plural, zero{You have no message} one{You have 1 message} other{You have {howMany} messages}}",
"gender": "{gender, select, male{Mr {lastName}} female{Ms {lastName} } other{VIP {lastName}}}",
"select": "{select, select, option1{{lastName},select} option2{{lastName},select} other{{lastName} default select}}"
}
{
"name": "姓名",
"age": "年龄",
"input": "请输入 {label}",
"todo": "做你{todo}到的,{todo}你做到的",
"getMessageTips": "{howMany, plural, zero{没有消息} one{有1条消息} other{有{howMany}条消息}}",
"gender": "{gender, select, male{{lastName}先生} female{{lastName}女士} other{{lastName} 贵宾}}",
"select": "{select, select, option1{{lastName}被选择} option2{{lastName},被选择} other{{lastName} 默认选中}}"
}
在界面上增加一些输出
Text(S.of(context).getMessageTips(0)),
Text(S.of(context).getMessageTips(1)),
Text(S.of(context).getMessageTips(4)),
Text(S.of(context).input("country")),
Text(S.of(context).todo("say")),
Text(S.of(context).gender("male", "Jones")),
Text(S.of(context).gender("female", "Jones")),
Text(S.of(context).gender("other", "Jones")),
Text(S.of(context).select("option1", "Germany")),
Text(S.of(context).select("option2", "U.S.A")),
Text(S.of(context).select("", "china")),
\
使用占位符输出
/// `place input {label}`
String input(Object label) {
return Intl.message(
'place input $label',
name: 'input',
desc: '',
args: [label],
);
}
和message不一样的地方是,这里不再是一个get方法了,是一个普通的方法,多了一个Object的输入参数,第一个参数中也多了占位符,在args的值就是我们传入给方法的值。
占位符可以多次使用
/// `Do what you {todo},{todo} what you do`
String todo(Object todo) {
return Intl.message(
'Do what you $todo,$todo what you do',
name: 'todo',
desc: '',
args: [todo],
);
}
和input方法一样,只是占位符可以多次使用。
数字国际化
/// `{howMany, plural, zero{You have no message} one{You have 1 message} other{You have {howMany} messages}}`
String getMessageTips(num howMany) {
return Intl.plural(
howMany,
zero: 'You have no message',
one: 'You have 1 message',
other: 'You have $howMany messages',
name: 'getMessageTips',
desc: '',
args: [howMany],
);
}
这里使用了Intl.plural方法,这是一个数字国际化的方法,根据不同的数量,进行不同内容的输出。
性别国际化
/// `{gender, select, male{Mr {lastName}} female{Ms {lastName} } other{VIP {lastName}}}`
String gender(String gender, Object lastName) {
return Intl.gender(
gender,
male: 'Mr $lastName',
female: 'Ms $lastName ',
other: 'VIP $lastName',
name: 'gender',
desc: '',
args: [gender, lastName],
);
}
这个是性别国际化
多种选项
/// `{select, select, option1{{lastName},select} option2{{lastName},select} other{{lastName} default select}}`
String select(Object select, Object lastName) {
return Intl.select(
select,
{
'option1': '$lastName,select',
'option2': '$lastName,select',
'other': '$lastName default select',
},
name: 'select',
desc: '',
args: [select, lastName],
);
}
}
明天再来说说日期和数字的格式化。
演示代码地址:gitee.com/radium/flut… 视频地址:查看视频