Flutter国际化与本地化完全指南:打造多语言应用
·
引言
在全球化时代,开发支持多语言的应用已成为必备技能。Flutter提供了强大的国际化(Internationalization, i18n)和本地化(Localization)支持,使开发者能够轻松创建支持多种语言和地区的应用。
一、国际化基础概念
1.1 核心术语
| 术语 | 含义 |
|---|---|
| 国际化(i18n) | 设计应用使其能够适应不同语言和地区的过程 |
| 本地化(l10n) | 为特定语言和地区定制应用的过程 |
| Locale | 语言和地区标识符,如zh_CN、en_US |
| ICU | Unicode国际化组件,提供日期、数字等格式化 |
1.2 Flutter国际化支持
Flutter通过以下包提供国际化支持:
flutter_localizations- 官方本地化支持intl- 国际化工具库intl_translation- 翻译文件生成工具
二、配置流程
2.1 添加依赖
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
intl: ^0.19.0
dev_dependencies:
intl_translation: ^0.19.0
2.2 配置MaterialApp
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:intl/intl.dart';
import 'l10n/app_localizations.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(primarySwatch: Colors.blue),
supportedLocales: const [
Locale('en', 'US'),
Locale('zh', 'CN'),
Locale('ja', 'JP'),
Locale('ko', 'KR'),
],
localizationsDelegates: const [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
localeResolutionCallback: (locale, supportedLocales) {
for (var supportedLocale in supportedLocales) {
if (supportedLocale.languageCode == locale?.languageCode &&
supportedLocale.countryCode == locale?.countryCode) {
return supportedLocale;
}
}
return supportedLocales.first;
},
home: const HomePage(),
);
}
}
三、创建翻译文件
3.1 创建ARB文件
ARB (Application Resource Bundle)是Flutter推荐的翻译文件格式:
// l10n/app_en.arb
{
"@@locale": "en",
"hello": "Hello",
"welcome": "Welcome to our app",
"greeting": "Hello {name}!",
"itemsCount": "{count, plural, zero{No items} one{1 item} other{{count} items}}",
"welcomeMessage": "{gender, select, male{Welcome Mr. {name}} female{Welcome Ms. {name}} other{Welcome {name}}}"
}
// l10n/app_zh.arb
{
"@@locale": "zh",
"hello": "你好",
"welcome": "欢迎使用我们的应用",
"greeting": "你好 {name}!",
"itemsCount": "{count, plural, zero{没有项目} one{1个项目} other{{count}个项目}}",
"welcomeMessage": "{gender, select, male{欢迎 {name} 先生} female{欢迎 {name} 女士} other{欢迎 {name}}}"
}
3.2 生成翻译代码
创建l10n.yaml配置文件:
arb-dir: l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
output-class: AppLocalizations
preferred-supported-locales:
- en
- zh
运行生成命令:
flutter pub run intl_translation:generate_from_arb \
--output-dir=lib/l10n \
--no-use-deferred-loading \
lib/l10n/app_localizations.dart \
l10n/app_en.arb \
l10n/app_zh.arb
四、使用翻译
4.1 基本用法
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
final loc = AppLocalizations.of(context)!;
return Scaffold(
appBar: AppBar(title: Text(loc.welcome)),
body: Center(
child: Column(
children: [
Text(loc.hello),
Text(loc.greeting('Flutter')),
Text(loc.itemsCount(5)),
Text(loc.welcomeMessage('male', 'John')),
],
),
),
);
}
}
4.2 使用BuildContext扩展
extension AppLocalizationsX on BuildContext {
AppLocalizations get loc => AppLocalizations.of(this)!;
}
// 使用
Text(context.loc.hello)
五、复数和选择器
5.1 复数处理
// app_en.arb
{
"itemsCount": "{count, plural, zero{No items} one{1 item} other{{count} items}}"
}
// 使用
Text(loc.itemsCount(0)) // No items
Text(loc.itemsCount(1)) // 1 item
Text(loc.itemsCount(5)) // 5 items
5.2 选择器
// app_en.arb
{
"welcomeMessage": "{gender, select, male{Welcome Mr. {name}} female{Welcome Ms. {name}} other{Welcome {name}}}"
}
Text(loc.welcomeMessage('male', 'John')) // Welcome Mr. John
Text(loc.welcomeMessage('female', 'Jane')) // Welcome Ms. Jane
Text(loc.welcomeMessage('other', 'Alex')) // Welcome Alex
5.3 组合使用
{
"notification": "{unreadCount, plural, zero{No new notifications} one{1 new notification from {sender}} other{{unreadCount} new notifications from {sender}}}"
}
六、日期和数字格式化
6.1 日期格式化
import 'package:intl/intl.dart';
void formatDates() {
final now = DateTime.now();
// 中文格式
print(DateFormat.yMMMd('zh_CN').format(now)); // 2025年5月20日
print(DateFormat.yMMMEd('zh_CN').format(now)); // 2025年5月20日 星期二
print(DateFormat.Hm('zh_CN').format(now)); // 14:30
// 英文格式
print(DateFormat.yMMMd('en_US').format(now)); // May 20, 2025
print(DateFormat.yMMMEd('en_US').format(now)); // Tue, May 20, 2025
}
6.2 数字格式化
void formatNumbers() {
final number = 1234567.89;
// 中文格式
print(NumberFormat.decimalPattern('zh_CN').format(number)); // 1,234,567.89
print(NumberFormat.currency(locale: 'zh_CN', symbol: '¥').format(number)); // ¥1,234,567.89
// 英文格式
print(NumberFormat.decimalPattern('en_US').format(number)); // 1,234,567.89
print(NumberFormat.currency(locale: 'en_US', symbol: '\$').format(number)); // \$1,234,567.89
}
6.3 百分比格式化
void formatPercentages() {
final percentage = 0.75;
print(NumberFormat.percentPattern('zh_CN').format(percentage)); // 75%
print(NumberFormat.percentPattern('en_US').format(percentage)); // 75%
}
七、动态切换语言
7.1 使用状态管理
class LocaleProvider extends ChangeNotifier {
Locale _locale = const Locale('en', 'US');
Locale get locale => _locale;
void setLocale(Locale locale) {
_locale = locale;
notifyListeners();
}
}
7.2 更新MaterialApp
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return Consumer<LocaleProvider>(
builder: (context, provider, child) {
return MaterialApp(
locale: provider.locale,
// ...其他配置
);
},
);
}
}
7.3 创建语言选择器
class LanguageSelector extends StatelessWidget {
const LanguageSelector({super.key});
@override
Widget build(BuildContext context) {
final provider = Provider.of<LocaleProvider>(context);
return DropdownButton<Locale>(
value: provider.locale,
items: const [
DropdownMenuItem(value: Locale('en', 'US'), child: Text('English')),
DropdownMenuItem(value: Locale('zh', 'CN'), child: Text('中文')),
DropdownMenuItem(value: Locale('ja', 'JP'), child: Text('日本語')),
],
onChanged: (locale) {
if (locale != null) {
provider.setLocale(locale);
}
},
);
}
}
八、RTL支持
8.1 启用RTL
MaterialApp(
// ...
supportedLocales: const [
Locale('ar', 'SA'), // 阿拉伯语
],
// ...
)
8.2 RTL布局适配
Widget build(BuildContext context) {
return Directionality(
textDirection: TextDirection.rtl,
child: const Text('مرحبا'), // 阿拉伯语"你好"
);
}
8.3 动态方向检测
bool isRTL = Directionality.of(context) == TextDirection.rtl;
九、最佳实践
9.1 翻译文件管理
lib/
└── l10n/
├── app_localizations.dart # 自动生成
├── app_localizations_delegate.dart
└── arb/
├── app_en.arb
├── app_zh.arb
├── app_ja.arb
└── app_ko.arb
9.2 使用专业翻译工具
推荐使用专业翻译管理平台:
- Crowdin
- Lokalise
- Transifex
9.3 测试多语言环境
void main() {
testWidgets('Chinese localization', (tester) async {
await tester.pumpWidget(
MaterialApp(
locale: const Locale('zh', 'CN'),
localizationsDelegates: const [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
home: const HomePage(),
),
);
expect(find.text('你好'), findsOneWidget);
});
}
9.4 性能优化
// 使用const避免重复创建
const supportedLocales = [
Locale('en', 'US'),
Locale('zh', 'CN'),
];
十、常见问题
10.1 翻译字符串未更新
解决方案:确保运行了翻译生成命令:
flutter pub run intl_translation:generate_from_arb ...
10.2 Locale未生效
解决方案:检查localeResolutionCallback配置:
localeResolutionCallback: (locale, supportedLocales) {
return locale ?? supportedLocales.first;
}
10.3 日期格式不正确
解决方案:确保导入了intl包并使用正确的Locale:
import 'package:intl/intl.dart';
DateFormat.yMMMd(Localizations.localeOf(context).toString())
十一、总结
Flutter的国际化支持非常强大,通过合理配置可以轻松创建多语言应用。关键要点:
- 使用ARB文件管理翻译内容
- 利用intl包进行日期、数字格式化
- 支持复数、选择器等复杂场景
- 实现动态语言切换
- 考虑RTL语言支持
掌握Flutter国际化开发,将使你的应用能够服务全球用户,提升用户体验和产品竞争力。
更多推荐

所有评论(0)