Flutter进阶(2):国际化开发
在全球化趋势下,应用支持多语言是非常重要的。Flutter 提供了强大的国际化(i18n)支持,可以通过 flutter_localizations 与 gen-l10n 工具生成的本地化类来实现不同区域和语言的适配。本篇博客将介绍如何在 Flutter 项目中使用 flutter_localizations,并实现多语言支持与动态切换。
先看下效果图:
一. 什么是国际化(i18n)和本地化(l10n)?
国际化(i18n) 是指编写软件,使其能够在不同的语言和文化环境中运行。它包含了将软件中的文本、日期、时间等元素抽象出来,以便根据用户的区域设置进行翻译和显示。
本地化(l10n) 是国际化的具体应用步骤,它包括将应用程序的语言、日期格式、货币符号等内容适配到特定地区。
二、部署环境&初始化
(1)这边用到vscode
进行开发,需要下载 Flutter Intl
插件。
(2)下载完成后,在项目中的pubspec.yaml
添加依赖库:
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
(3)在vscode
中按command\ctrl+shift+p
,然后会弹出一个输入vscode
内置命令的输入框和下拉结果。在 flutter 项目中,首次需要搜索Flutter Intl: Initialize
命令,回车即可初始化和生成国际化相关文件代码。
就在项目中lib
中默认生成了以下文件:
|-- generated 自动生成的文件,不需要手动编辑
|-- intl
| |-- messages_all.dart 桥接多个语言文件 下面en zh等文件。
| |-- messages_en.dart 转译文件 自动从l10n/intl_en.arb 提取key/value 自动生成代码
|-- l10n.dart 入口文件代码,不需要手动编辑
|-- l10n 存放国际化json文件位置 arb=json
|-- intl_en.arb
三、修改 MaterialApp 以支持国际化
在 MaterialApp 中配置 localizationsDelegates 和 supportedLocales 以支持本地化。具体代码如下:
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Locale _locale = Locale('en'); // 默认语言
void setLocale(Locale locale) {
setState(() {
_locale = locale;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
locale: _locale,// 设置当前的 Locale
localizationsDelegates: const [
S.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: const [
Locale('en', 'US'), // 英文
Locale('zh', 'CN'), // 简体中文
Locale('zh', 'TW') // 繁体中文
],
home: MyHomePage(
onLocaleChange: (Locale locale) {
setLocale(locale);
},
),
);
}
}
四、添加和生成语言文件(新增国际化)
intl
使用.arb
文件来存储不同语言的翻译资源。
(1)添加新的国际化文件可以搜索Flutter Intl: Add Locale
命令,回车会切换到输入国际化编码。
(2)然后在编辑框会提示输入国际化编码,例如要添加简体中文就输入:zh,添加繁体中文就添加:zh_TW。
(3)然后就会在l10n
文件夹,自动添加 intl_zh.arb
和intl_zh_TW.arb
文件,以及在generated/l10n
文件夹中生成转译文件。
语言文件示例
lib/l10n/intl_en.arb:
{
"content": "china"
}
lib/l10n/intl_zh.arb:
{
"content": "中国"
}
lib/l10n/intl_zh_TW.arb:
{
"content": "中國"
}
五、动态切换语言
代码如下:
class MyHomePage extends StatelessWidget {
final Function(Locale) onLocaleChange;
const MyHomePage({super.key, required this.onLocaleChange});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter 国际化 Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
//此处国际化文字
Text(
S.current.content,
style: const TextStyle(
color: Colors.red, fontSize: 50, fontWeight: FontWeight.w700),
),
changeButton(const Locale('zh', 'CN'), '简体'),
changeButton(const Locale('zh', 'TW'), '繁体'),
changeButton(const Locale('en', 'US'), '英文'),
],
),
),
);
}
// 动态切换语言
Widget changeButton(Locale newLocale, String text) {
return ElevatedButton(
onPressed: () {
onLocaleChange(newLocale); // 调用 MyAppState 的 setLocale 方法
},
child: Text(text),
);
}
}
六、通过手机系统语言来显示对应语言的话
代码如下:
class _MyAppState extends State<MyApp> {
Locale _locale = const Locale('en', 'US'); // 默认语言
void setLocale(Locale locale) {
setState(() {
_locale = locale;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
//locale: _locale, // 【(1)localec参数不用设置】
// 设置当前的 Locale
localizationsDelegates: const [
S.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: const [
Locale('en', 'US'), //英文
Locale('zh', 'CN'), //简体中文
Locale('zh', 'TW') //繁体中文
],
//如果使用系统语言,使用下面的:【(2)判断是什么系统语言,就返回下面的语言值】
localeResolutionCallback: (locale, supportedLocales) {
if (locale?.countryCode == 'CN') {// 如果语言是简体
return const Locale('zh', 'CN');
} else if (locale?.countryCode == 'TW') {// 如果语言繁体
return const Locale('zh', 'TW');
} else {
return const Locale('en', 'US');
}
},
home: MyHomePage(
onLocaleChange: (Locale locale) {
setLocale(locale);
},
),
);
}
}
七、完整示例代码
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'generated/l10n.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Locale _locale = const Locale('en', 'US'); // 默认语言
void setLocale(Locale locale) {
setState(() {
_locale = locale;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
locale: _locale,
// 设置当前的 Locale
localizationsDelegates: const [
S.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: const [
Locale('en', 'US'), //英文
Locale('zh', 'CN'), //简体中文
Locale('zh', 'TW') //繁体中文
],
//如果使用系统语言,使用下面的:
/*localeResolutionCallback: (locale, supportedLocales) {
if (locale?.countryCode == 'CN') {// 如果语言是简体
return const Locale('zh', 'CN');
} else if (locale?.countryCode == 'TW') {// 如果语言繁体
return const Locale('zh', 'TW');
} else {
return const Locale('en', 'US');
}
},*/
home: MyHomePage(
onLocaleChange: (Locale locale) {
setLocale(locale);
},
),
);
}
}
class MyHomePage extends StatelessWidget {
final Function(Locale) onLocaleChange;
const MyHomePage({super.key, required this.onLocaleChange});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter 国际化 Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
//此处国际化文字
Text(
S.current.content,
style: const TextStyle(
color: Colors.red, fontSize: 50, fontWeight: FontWeight.w700),
),
changeButton(const Locale('zh', 'CN'), '简体'),
changeButton(const Locale('zh', 'TW'), '繁体'),
changeButton(const Locale('en', 'US'), '英文'),
],
),
),
);
}
Widget changeButton(Locale newLocale, String text) {
return ElevatedButton(
onPressed: () {
onLocaleChange(newLocale); // 调用 MyAppState 的 setLocale 方法
},
child: Text(text),
);
}
}