Flutter 国际化与本地化完全指南
·
Flutter 国际化与本地化完全指南
引言
国际化与本地化是构建面向全球用户的应用程序的关键。Flutter 提供了强大的国际化支持,允许开发者轻松实现多语言支持。本文将深入探讨 Flutter 国际化的各种用法和高级技巧。
基础概念回顾
国际化 vs 本地化
- 国际化(Internationalization):设计和开发应用程序,使其能够轻松适应不同语言和地区。
- 本地化(Localization):为特定语言和地区定制应用程序。
基本配置
在 pubspec.yaml 中添加依赖:
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
intl: ^0.18.1
flutter:
generate: true
高级技巧一:配置本地化代理
创建 LocalizationsDelegate
class AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
const AppLocalizationsDelegate();
@override
bool isSupported(Locale locale) {
return ['en', 'zh', 'ja'].contains(locale.languageCode);
}
@override
Future<AppLocalizations> load(Locale locale) async {
AppLocalizations localizations = AppLocalizations(locale);
await localizations.load();
return localizations;
}
@override
bool shouldReload(AppLocalizationsDelegate old) => false;
}
在 MaterialApp 中配置
MaterialApp(
localizationsDelegates: [
AppLocalizationsDelegate(),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: [
Locale('en', 'US'),
Locale('zh', 'CN'),
Locale('ja', 'JP'),
],
home: MyHomePage(),
)
高级技巧二:创建本地化类
基本本地化类
class AppLocalizations {
final Locale locale;
AppLocalizations(this.locale);
static AppLocalizations of(BuildContext context) {
return Localizations.of<AppLocalizations>(context, AppLocalizations)!;
}
Map<String, String> _localizedStrings = {};
Future<void> load() async {
String jsonString = await rootBundle.loadString(
'i18n/${locale.languageCode}.json',
);
Map<String, dynamic> jsonMap = json.decode(jsonString);
_localizedStrings = jsonMap.map((key, value) => MapEntry(key, value.toString()));
}
String translate(String key) {
return _localizedStrings[key] ?? key;
}
}
JSON 本地化文件
// i18n/en.json
{
"welcome": "Welcome",
"hello": "Hello",
"message": "This is a message"
}
// i18n/zh.json
{
"welcome": "欢迎",
"hello": "你好",
"message": "这是一条消息"
}
高级技巧三:使用 Intl 包
添加依赖
dependencies:
intl: ^0.18.1
创建 ARB 文件
// app_en.arb
{
"@welcome": {
"description": "Welcome message"
},
"welcome": "Welcome",
"@hello": {
"description": "Hello message",
"placeholders": {
"name": {}
}
},
"hello": "Hello {name}"
}
生成代码
运行命令生成本地化类:
flutter pub run intl_translation:generate_from_arb \
--output-dir=lib/i18n \
--no-use-deferred-loading \
lib/localizations.dart \
lib/i18n/intl_*.arb
高级技巧四:复数和性别
处理复数
String getPluralMessage(int count) {
return Intl.plural(
count,
zero: 'No items',
one: 'One item',
two: 'Two items',
few: '$count items',
many: '$count items',
other: '$count items',
locale: locale.toString(),
);
}
处理性别
String getGenderMessage(String gender) {
return Intl.gender(
gender,
male: 'He is a developer',
female: 'She is a developer',
other: 'They are a developer',
locale: locale.toString(),
);
}
高级技巧五:日期和时间格式化
格式化日期
String formatDate(DateTime date) {
return DateFormat.yMMMd(locale.toString()).format(date);
}
String formatFullDate(DateTime date) {
return DateFormat.yMMMEd(locale.toString()).format(date);
}
格式化时间
String formatTime(DateTime time) {
return DateFormat.jm(locale.toString()).format(time);
}
String formatFullTime(DateTime time) {
return DateFormat.Hms(locale.toString()).format(time);
}
高级技巧六:数字格式化
格式化数字
String formatNumber(num number) {
return NumberFormat.decimalPattern(locale.toString()).format(number);
}
格式化货币
String formatCurrency(double amount, String currencyCode) {
return NumberFormat.currency(
locale: locale.toString(),
symbol: currencyCode,
).format(amount);
}
实战案例:切换语言
class LanguageSwitcher extends StatefulWidget {
@override
_LanguageSwitcherState createState() => _LanguageSwitcherState();
}
class _LanguageSwitcherState extends State<LanguageSwitcher> {
Locale? _selectedLocale;
void _changeLanguage(Locale locale) {
setState(() {
_selectedLocale = locale;
});
// 使用全局状态管理更新语言
MyAppState.of(context).setLocale(locale);
}
@override
Widget build(BuildContext context) {
return DropdownButton<Locale>(
value: _selectedLocale,
onChanged: (Locale? locale) {
if (locale != null) {
_changeLanguage(locale);
}
},
items: [
DropdownMenuItem(
value: Locale('en', 'US'),
child: Text('English'),
),
DropdownMenuItem(
value: Locale('zh', 'CN'),
child: Text('中文'),
),
DropdownMenuItem(
value: Locale('ja', 'JP'),
child: Text('日本語'),
),
],
);
}
}
实战案例:动态语言切换
class MyApp extends StatefulWidget {
static _MyAppState? of(BuildContext context) =>
context.findAncestorStateOfType<_MyAppState>();
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Locale? _locale;
void setLocale(Locale locale) {
setState(() {
_locale = locale;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
locale: _locale,
localizationsDelegates: [
AppLocalizationsDelegate(),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: [
Locale('en', 'US'),
Locale('zh', 'CN'),
Locale('ja', 'JP'),
],
home: HomePage(),
);
}
}
实战案例:使用生成的本地化类
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final localizations = AppLocalizations.of(context);
return Scaffold(
appBar: AppBar(
title: Text(localizations.translate('welcome')),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(localizations.translate('hello')),
Text(localizations.translate('message')),
],
),
),
);
}
}
常见问题与解决方案
Q1:如何处理 RTL 语言?
A:Flutter 自动支持 RTL:
MaterialApp(
locale: Locale('ar', 'SA'), // 阿拉伯语
...
)
Q2:如何检测设备语言?
A:使用 WidgetsBinding.instance.platformDispatcher.locale:
Locale? deviceLocale = WidgetsBinding.instance.platformDispatcher.locale;
Q3:如何支持地区变体?
A:在 supportedLocales 中指定:
supportedLocales: [
Locale('zh', 'CN'), // 简体中文
Locale('zh', 'TW'), // 繁体中文
],
最佳实践
1. 使用 ARB 文件管理翻译
# 推荐
lib/
├── i18n/
│ ├── app_en.arb
│ ├── app_zh.arb
│ └── app_ja.arb
2. 集中管理翻译键
// 推荐
class TranslationKeys {
static const welcome = 'welcome';
static const hello = 'hello';
static const message = 'message';
}
// 使用
Text(AppLocalizations.of(context).translate(TranslationKeys.welcome));
3. 提供默认值
// 推荐
String translate(String key) {
return _localizedStrings[key] ?? key; // 返回键名作为默认值
}
总结
Flutter 的国际化与本地化支持非常完善。通过本文的学习,你应该能够:
- 配置本地化代理
- 创建和管理翻译文件
- 使用 Intl 包处理复数和性别
- 格式化日期、时间和数字
- 实现动态语言切换
掌握这些技巧,能够帮助你创建面向全球用户的应用程序。
更多推荐
所有评论(0)