news 2026/5/12 8:16:43

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Flutter 国际化与本地化完全指南

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

引言

国际化(Internationalization)和本地化(Localization)是构建全球化应用的关键。Flutter 提供了强大的国际化支持,让应用能够轻松支持多种语言和地区。本文将深入探讨 Flutter 国际化的各种技巧和最佳实践。

基础配置

添加依赖

dependencies: flutter_localizations: sdk: flutter intl: ^0.18.0

配置 MaterialApp

import 'package:flutter_localizations/flutter_localizations.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Internationalization', localizationsDelegates: [ GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, GlobalCupertinoLocalizations.delegate, ], supportedLocales: [ const Locale('en', 'US'), const Locale('zh', 'CN'), const Locale('ja', 'JP'), ], home: HomePage(), ); } }

高级技巧一:创建本地化资源

使用 intl 包

// l10n/messages_all.dart import 'dart:async'; import 'package:intl/intl.dart'; import 'package:intl/message_lookup_by_library.dart'; final MessageLookup messages = MessageLookup(); class MessageLookup extends MessageLookupByLibrary { @override String? lookupMessage( String? messageText, String? locale, String? name, List<Object>? args, String? meaning, Map<String, String>? examples, ) { return messageText; } }

创建本地化文件

// l10n/intl_en.arb { "helloWorld": "Hello World!", "welcome": "Welcome to Flutter", "greeting": "Hello {name}!", "count": "{count, plural, zero{No items} one{1 item} other{{count} items}}" } // l10n/intl_zh.arb { "helloWorld": "你好世界!", "welcome": "欢迎来到 Flutter", "greeting": "你好 {name}!", "count": "{count, plural, zero{没有项目} one{1个项目} other{{count}个项目}}" }

高级技巧二:使用 flutter_localizations

创建自定义 LocalizationsDelegate

class AppLocalizations { final Locale locale; AppLocalizations(this.locale); static AppLocalizations? of(BuildContext context) { return Localizations.of<AppLocalizations>(context, AppLocalizations); } static const LocalizationsDelegate<AppLocalizations> delegate = _AppLocalizationsDelegate(); 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; } } 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: [ AppLocalizations.delegate, GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, ], supportedLocales: [ const Locale('en', 'US'), const Locale('zh', 'CN'), const Locale('ja', 'JP'), ], )

高级技巧三:动态切换语言

创建语言切换服务

class LanguageService extends ChangeNotifier { Locale _currentLocale = const Locale('en', 'US'); Locale get currentLocale => _currentLocale; void setLocale(Locale locale) { _currentLocale = locale; notifyListeners(); } }

使用 GetX 切换语言

// 在 GetX 中配置 GetMaterialApp( locale: Get.deviceLocale, fallbackLocale: const Locale('en', 'US'), translations: MyTranslations(), ) // 切换语言 Get.updateLocale(const Locale('zh', 'CN'));

高级技巧四:格式化日期和数字

日期格式化

// 使用 intl 包 final date = DateTime.now(); final formatter = DateFormat('yyyy-MM-dd HH:mm:ss', 'zh_CN'); print(formatter.format(date)); // 2024-01-15 14:30:00

数字格式化

final number = 1234567.89; final formatter = NumberFormat('#,##0.00', 'zh_CN'); print(formatter.format(number)); // 1,234,567.89

货币格式化

final amount = 1234.56; final formatter = NumberFormat.currency( locale: 'zh_CN', symbol: '¥', ); print(formatter.format(amount)); // ¥1,234.56

高级技巧五:RTL 支持

配置 RTL

MaterialApp( locale: const Locale('ar'), supportedLocales: [ const Locale('ar'), ], localizationsDelegates: [ GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, ], )

检测文本方向

final direction = Directionality.of(context); if (direction == TextDirection.rtl) { // RTL 布局 } else { // LTR 布局 }

实战案例:多语言应用

class HomePage extends StatelessWidget { @override Widget build(BuildContext context) { final localizations = AppLocalizations.of(context); return Scaffold( appBar: AppBar( title: Text(localizations?.translate('welcome') ?? 'Welcome'), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(localizations?.translate('helloWorld') ?? 'Hello World'), SizedBox(height: 20), ElevatedButton( onPressed: () { // 切换语言 final locale = Localizations.localeOf(context); if (locale.languageCode == 'en') { Get.updateLocale(const Locale('zh', 'CN')); } else { Get.updateLocale(const Locale('en', 'US')); } }, child: Text(localizations?.translate('changeLanguage') ?? 'Change Language'), ), ], ), ), ); } }

实战案例:动态语言切换

class LanguageSelector extends StatelessWidget { final List<Map<String, String>> languages = [ {'code': 'en', 'name': 'English'}, {'code': 'zh', 'name': '中文'}, {'code': 'ja', 'name': '日本語'}, ]; @override Widget build(BuildContext context) { return DropdownButton<String>( value: Get.locale?.languageCode, items: languages.map((lang) { return DropdownMenuItem( value: lang['code'], child: Text(lang['name']!), ); }).toList(), onChanged: (value) { if (value != null) { Get.updateLocale(Locale(value)); } }, ); } }

常见问题与解决方案

Q1:如何支持地区变体?

A:使用完整的 locale 代码:

supportedLocales: [ const Locale('en', 'US'), const Locale('en', 'GB'), const Locale('zh', 'CN'), const Locale('zh', 'TW'), ],

Q2:如何处理复数形式?

A:使用 ICU 消息格式:

{ "items": "{count, plural, zero{No items} one{1 item} other{{count} items}}" }

Q3:如何获取设备语言?

A:使用WidgetsBinding.instance.window.locale

final deviceLocale = WidgetsBinding.instance.window.locale;

最佳实践

1. 集中管理翻译资源

// 错误:硬编码字符串 Text('Hello World') // 正确:使用本地化 Text(AppLocalizations.of(context)?.translate('helloWorld') ?? 'Hello World')

2. 使用 ARB 文件

{ "helloWorld": "Hello World!", "@helloWorld": { "description": "The classic hello world message" } }

3. 支持 RTL 语言

Directionality( textDirection: TextDirection.rtl, child: Text('مرحبا بالعالم'), )

总结

国际化是构建全球化应用的重要环节。通过本文的学习,你应该能够:

  1. 配置基本的国际化支持
  2. 创建多语言资源文件
  3. 实现动态语言切换
  4. 格式化日期、数字和货币
  5. 支持 RTL 语言

掌握这些技巧,能够帮助你构建更加友好的全球化应用。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/12 8:12:22

Asset Factory MCP:AI驱动的42步SOP工具箱,为独立创业者构建商业流水线

1. 项目概述&#xff1a;一个为独立创业者打造的AI驱动商业流水线如果你是一名独立开发者、自由职业者或者小团队的创始人&#xff0c;你一定经历过这样的时刻&#xff1a;脑子里冒出一个绝妙的商业点子&#xff0c;兴奋地打开电脑&#xff0c;然后……对着空白的屏幕陷入迷茫。…

作者头像 李华
网站建设 2026/5/12 8:11:11

18.地下室的服务器

六月第一个周末的深夜&#xff0c;暴雨如注。陈远坐在书桌前&#xff0c;屏幕上是花花绿绿的监控图表&#xff0c;代表着他那台二手服务器资源使用率的曲线&#xff0c;正像垂死病人的心电图一样剧烈地上下跳动。CPU占用率长时间维持在90%以上&#xff0c;内存也逼近红线。这已…

作者头像 李华