Flutter国际化与本地化完全指南

Flutter国际化与本地化完全指南 Flutter国际化与本地化完全指南引言国际化是构建全球化应用的关键环节Flutter提供了完善的国际化支持。本文将深入探讨Flutter中的国际化和本地化技术。一、基础配置1.1 添加依赖dependencies: flutter_localizations: sdk: flutter intl: ^0.18.11.2 更新main.dartimport package:flutter_localizations/flutter_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, localizationsDelegates: const [ GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, GlobalCupertinoLocalizations.delegate, ], supportedLocales: const [ Locale(en, ), Locale(zh, CN), Locale(ja, ), ], home: const HomePage(), ); } }二、创建本地化资源2.1 创建arb文件lib/l10n/app_en.arb{ locale: en, title: Hello World, welcome: Welcome to our app!, greeting: Hello {name}!, count: {count, plural, zero{No items} one{One item} other{{count} items}}, gender: {gender, select, male{He} female{She} other{They}} likes this. }lib/l10n/app_zh.arb{ locale: zh, title: 你好世界, welcome: 欢迎来到我们的应用, greeting: 你好 {name}, count: {count, plural, zero{没有项目} one{一个项目} other{{count}个项目}}, gender: {gender, select, male{他} female{她} other{他们}}喜欢这个。 }lib/l10n/app_ja.arb{ locale: ja, title: こんにちは世界, welcome: アプリへようこそ, greeting: こんにちは {name}, count: {count, plural, zero{アイテムがありません} one{アイテム1つ} other{アイテム{count}個}}, gender: {gender, select, male{彼は} female{彼女は} other{彼らは}}これが好きです。 }2.2 配置pubspec.yamlflutter: generate: true assets: - lib/l10n/2.3 生成代码flutter pub get三、使用本地化字符串3.1 基础使用import package:flutter_gen/gen_l10n/app_localizations.dart; 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.title)), body: Center( child: Column( children: [ Text(loc.welcome), Text(loc.greeting(John)), ], ), ), ); } }3.2 复数处理Text(loc.count(0)); // No items / 没有项目 / アイテムがありません Text(loc.count(1)); // One item / 一个项目 / アイテム1つ Text(loc.count(5)); // 5 items / 5个项目 / アイテム5個3.3 性别选择Text(loc.gender(male)); // He likes this. / 他喜欢这个。 / 彼はこれが好きです。 Text(loc.gender(female)); // She likes this. / 她喜欢这个。 / 彼女はこれが好きです。 Text(loc.gender(other)); // They like this. / 他们喜欢这个。 / 彼らはこれが好きです。四、动态切换语言4.1 创建语言提供器class LocaleProvider extends ChangeNotifier { Locale _locale const Locale(en); Locale get locale _locale; void setLocale(Locale locale) { _locale locale; notifyListeners(); } }4.2 使用Provider包装void main() { runApp( ChangeNotifierProvider( create: (_) LocaleProvider(), child: const MyApp(), ), ); } class MyApp extends StatelessWidget { const MyApp({super.key}); override Widget build(BuildContext context) { final localeProvider Provider.ofLocaleProvider(context); return MaterialApp( locale: localeProvider.locale, localizationsDelegates: const [ GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, GlobalCupertinoLocalizations.delegate, ], supportedLocales: const [ Locale(en, ), Locale(zh, CN), Locale(ja, ), ], home: const HomePage(), ); } }4.3 创建语言选择器class LanguageSelector extends StatelessWidget { const LanguageSelector({super.key}); override Widget build(BuildContext context) { final localeProvider Provider.ofLocaleProvider(context); return DropdownButtonLocale( value: localeProvider.locale, items: const [ DropdownMenuItem(value: Locale(en), child: Text(English)), DropdownMenuItem(value: Locale(zh, CN), child: Text(中文)), DropdownMenuItem(value: Locale(ja), child: Text(日本語)), ], onChanged: (locale) { if (locale ! null) { localeProvider.setLocale(locale); } }, ); } }五、日期和数字本地化5.1 日期格式化import package:intl/intl.dart; void formatDate() { final date DateTime.now(); // 默认格式 print(DateFormat.yMMMd().format(date)); // 中文格式 print(DateFormat.yMMMd(zh_CN).format(date)); // 日文格式 print(DateFormat.yMMMd(ja).format(date)); // 自定义格式 print(DateFormat(yyyy-MM-dd HH:mm:ss).format(date)); }5.2 数字格式化void formatNumber() { final number 1234567.89; // 默认格式 print(NumberFormat().format(number)); // 中文格式 print(NumberFormat.currency(locale: zh_CN).format(number)); // 百分比 print(NumberFormat.percentPattern().format(0.75)); }六、RTL支持6.1 配置RTLMaterialApp( locale: const Locale(ar), supportedLocales: const [ Locale(ar), ], localizationsDelegates: const [ GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, ], home: const HomePage(), );6.2 处理RTL布局class RtlAwareWidget extends StatelessWidget { const RtlAwareWidget({super.key}); override Widget build(BuildContext context) { final textDirection Directionality.of(context); return Row( textDirection: textDirection, children: [ const Text(First), const Text(Second), ], ); } }七、最佳实践7.1 提取本地化键// 不好 Text(AppLocalizations.of(context)!.title); // 好 extension AppLocalizationsExtension on BuildContext { AppLocalizations get loc AppLocalizations.of(this)!; } // 使用 Text(context.loc.title);7.2 处理缺失翻译// 在arb文件中添加默认值 { title: Hello World, title: { description: The title of the app, type: text, placeholders: {} } }7.3 测试多语言void main() { testWidgets(English locale, (tester) async { await tester.pumpWidget( MaterialApp( locale: const Locale(en), localizationsDelegates: const [ GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, ], home: const HomePage(), ), ); expect(find.text(Hello World), findsOneWidget); }); testWidgets(Chinese locale, (tester) async { await tester.pumpWidget( MaterialApp( locale: const Locale(zh, CN), localizationsDelegates: const [ GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, ], home: const HomePage(), ), ); expect(find.text(你好世界), findsOneWidget); }); }总结国际化是构建全球化应用的重要环节通过合理使用Flutter的国际化支持你可以支持多种语言轻松添加新语言支持格式化日期和数字根据区域设置自动格式化支持RTL语言正确处理阿拉伯语、希伯来语等动态切换语言提供良好的用户体验掌握国际化技术让你的应用走向全球