Flutter 国际化(i18n)实战 ------ 基于 Flutter Intl 插件
本文介绍如何使用 Flutter Intl 插件 实现多语言支持。
特点:
- 使用
S.of(context)
获取文案- 通过 IDE 菜单 Tools > Flutter Intl 自动生成文件
1. 环境依赖
在 pubspec.yaml
中:
yaml
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
intl: ^0.19.0
flutter_intl:
enabled: true
说明:
flutter_localizations
→ Flutter 官方的多语言支持包(Material、Cupertino、Widgets)。intl
→ 提供日期/数字/货币格式化,以及 ICU plural/gender/select 支持。flutter_intl
段落 → 插件自动生成,不需要你加intl_utils
。
2. 使用 Flutter Intl 插件菜单
在 IDE(Android Studio / IntelliJ)菜单:
Tools > Flutter Intl
-
Initialize for the Project
初始化工程,自动生成:
lib/l10n/intl_en.arb
(英文模板)lib/generated/l10n.dart
(包含S
类、delegate、supportedLocales`)- 在
pubspec.yaml
添加flutter_intl: enabled: true
-
Add Locale
新增语言(例如
intl_zh.arb
) -
Remove Locale
删除语言
-
Integrate with Localizely
对接在线翻译平台(可选)
保存 ARB 文件后,插件会自动调用 intl_utils
,刷新生成的 Dart 文件。
3. ARB 文件示例
lib/l10n/intl_en.arb
:
json
{
"appTitle": "My Application",
"greeting": "Hello",
"welcomeUser": "Welcome, {name}!",
"@welcomeUser": {
"description": "Welcome message with user name",
"placeholders": {"name": {"type": "String"}}
}
}
lib/l10n/intl_zh.arb
:
json
{
"appTitle": "我的应用",
"greeting": "你好",
"welcomeUser": "欢迎你,{name}!"
}
4. 自动生成的文件
插件会在 lib/generated/
下生成:
l10n.dart
:包含S
类(本地化入口)messages_*.dart
:各语言的实现
示例:
dart
class S {
static S of(BuildContext context) { ... }
String get appTitle => "My Application";
String greeting() => "Hello";
String welcomeUser(String name) => "Welcome, $name!";
}
5. 在 MaterialApp 中启用
dart
import 'package:flutter_localizations/flutter_localizations.dart';
import 'generated/l10n.dart';
MaterialApp(
onGenerateTitle: (ctx) => S.of(ctx).appTitle,
localizationsDelegates: const [
S.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: S.delegate.supportedLocales,
home: const HomePage(),
);
6. 在代码中取文案
dart
final s = S.of(context);
Text(s.greeting);
Text(s.welcomeUser('Alice'));
无
context
场景可用S.current.xxx
,但 UI 不会随语言切换自动刷新。
7. 应用内切换语言
dart
class LangController extends ChangeNotifier {
Locale? _locale;
Locale? get locale => _locale;
void setLocale(Locale? l) { _locale = l; notifyListeners(); }
}
final lang = LangController();
MaterialApp(
locale: lang.locale,
supportedLocales: S.delegate.supportedLocales,
localizationsDelegates: const [
S.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
);
UI 示例:
dart
DropdownButton<Locale>(
value: lang.locale ?? const Locale('en'),
items: const [
DropdownMenuItem(value: Locale('en'), child: Text('English')),
DropdownMenuItem(value: Locale('zh'), child: Text('简体中文')),
],
onChanged: (l) => lang.setLocale(l),
);
8. 日期/数字/货币本地化
借助 intl
:
dart
import 'package:intl/intl.dart';
final localeTag = Localizations.localeOf(context).toLanguageTag();
final dateStr = DateFormat.yMMMd(localeTag).format(DateTime.now());
final money = NumberFormat.currency(locale: localeTag, symbol: '¥').format(12345.67);
9. 最佳实践
- ARB key 用
snake_case
,例如:home_title
,device_status_ok
- 每个条目加
@description
,便于翻译理解 - 避免字符串拼接,统一用
{变量}
占位符 - 使用 ICU plural/gender/select 处理复数和条件文案
- CI/代码审查时检查 ARB 文件同步(英文模板 vs 翻译文件)
- 新增语言:通过插件菜单 Add Locale,保证生成流程一致
10. 常见问题
-
S.of(context)
返回 null→ 确认
MaterialApp
配置了S.delegate
和supportedLocales
,且调用时上下文在MaterialApp
之下。 -
翻译不生效
→ 检查设备系统语言 /
locale
设置。若应用内强制设置语言,需要在MaterialApp.locale
指定。 -
生成文件没更新
→ 保存 ARB 文件时插件会自动生成。如果没有触发,可尝试 Tools > Flutter Intl > Rebuild 或重启 IDE。
11. 总结
Flutter Intl
插件简化了多语言开发:ARB → 自动生成 →S.of(context)
- 完全 IDE 集成,无需命令行操作
- 推荐用于中小型团队快速实现国际化,配合 CI 可以保持翻译完整性