多语言(国际化)
国际化(internationalization 简称 i18n)
终端(手机)系统语言切换时,flutter 应用跟随切换
内容
组件(Widget)国际化
例如:日历、弹窗等常用组件的国际化
文本国际化(包括文本的顺序)
自定义文本的国际化
1、组件国际化
使用步骤:
(1)、在 pubspec.yaml 中引入 flutter_localizations
(2)、设置 MaterialApp
①、import 'package:flutter_localizations/flutter_localizations.dart';
②、 localizationsDelegates(指定哪些组件需要进行国际化)
③、supportedLocales(指定要支持哪些语言)
例如:在 main.dart 中添加以上设置内容
import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import '09_form/form_05_datepicker.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return const MaterialApp( title: "Flutter Demo", home: Home(), debugShowCheckedModeBanner: false, // 国际化 localizationsDelegates: [ // 本地化代理 GlobalMaterialLocalizations.delegate, // Material 国际化 GlobalCupertinoLocalizations.delegate, // Cupertino 国际化 GlobalWidgetsLocalizations.delegate, // 组件国际化 ], supportedLocales: [ Locale('en', 'US'), // 美国英语 Locale('zh', 'CN'), // 简体中文 ], ); } }
(3)、查看组件效果
在模拟器上,切换语言,然后,查看组件效果(例如:日历)
2、文本国际化
使用步骤:
(1)、创建本地化类 CustomLocalizations
(2)、创建本地化类的代理
CustomLocalizationsDelegate extends LocalizationsDelegate<CustomLocalizations>
isSupported(当前本地化,是否在有效的语言范围内)
shouldReload(本地化重新构建时,是否调用 load 方法,加载本地化资源)
load(语言发生变更时,加载对应的本地化资源)
// CustomLocalizations.dart import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; class CustomLocalizations { final Locale locale; CustomLocalizations(this.locale); static final Map<String, Map<String, String>> _localizedValues = { 'en': { 'title': 'Home', 'greet': 'Hello', }, 'zh': { 'title': '首页', 'greet': '你好', } }; String? t(String key) { return _localizedValues[locale.languageCode]![key]; } static CustomLocalizations of(BuildContext context) { return Localizations.of(context, CustomLocalizations); } static CustomLocalizationsDelegate delegate = CustomLocalizationsDelegate(); } class CustomLocalizationsDelegate extends LocalizationsDelegate<CustomLocalizations> { // 当前本地化,是否在有效的语言范围内 @override bool isSupported(Locale locale) { return ['en', 'zh'].contains(locale.languageCode); } // 语言发生变更时,加载对应的本地化资源 @override Future<CustomLocalizations> load(Locale locale) { return SynchronousFuture(CustomLocalizations(locale)); } // 本地化重新构建时,是否调用 load 方法,加载本地化资源 @override bool shouldReload(covariant LocalizationsDelegate<CustomLocalizations> old) { return false; } }
(3)、使用本地化类 CustomLocalizations.delegate
// main.dart import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import '11_theme/theme_01_i18n.dart'; import '11_theme/CustomLocalizations.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: "Flutter Demo", home: const Home(), debugShowCheckedModeBanner: false, // 国际化 localizationsDelegates: [ // 本地化代理 CustomLocalizations.delegate, GlobalMaterialLocalizations.delegate, // Material 国际化 GlobalCupertinoLocalizations.delegate, // Cupertino 国际化 GlobalWidgetsLocalizations.delegate, // 组件国际化 ], supportedLocales: const [ Locale('en', 'US'), // 美国英语 Locale('zh', 'CN'), // 简体中文 ], ); } }
(4)、新建一个 theme_01_i18n.dart 文件,使用文本国际化,查看效果
import 'package:flutter/material.dart'; import 'CustomLocalizations.dart'; class Home extends StatelessWidget { const Home({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( // 文本国际化 title: Text( Localizations.of(context, CustomLocalizations).t('title'), ), ), body: const HomePage(), ); } } class HomePage extends StatelessWidget { const HomePage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Center( // 文本国际化 child: Text( Localizations.of(context, CustomLocalizations).t('greet'), style: const TextStyle(fontSize: 60), ), ); } }
3、加载语言包
使用步骤:
(1)、检测当前语言
loadResolutionCallback
locale.languageCode (语言代码,例如:en、zh)
locale.countryCode (国家代码,例如:US、CN)
// main.dart import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import '11_theme/theme_01_i18n.dart'; import '11_theme/CustomLocalizations.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: "Flutter Demo", home: const Home(), debugShowCheckedModeBanner: false, // 国际化 localizationsDelegates: [ // 本地化代理 CustomLocalizations.delegate, GlobalMaterialLocalizations.delegate, // Material 国际化 GlobalCupertinoLocalizations.delegate, // Cupertino 国际化 GlobalWidgetsLocalizations.delegate, // 组件国际化 ], supportedLocales: const [ Locale('en', 'US'), // 美国英语 Locale('zh', 'CN'), // 简体中文 ], // 检测当前语言 localeResolutionCallback: (locale, supportedLocales) { print('device locale: $locale'); // device locale: zh_Hans_CN print('supportedLocales: $supportedLocales'); // [en_US, zh_CN] for (var supportedLocale in supportedLocales) { print('supportedLocale: $supportedLocale'); // supportedLocale: en_US // supportedLocale: zh_CN if (supportedLocale.languageCode == locale?.languageCode && supportedLocale.countryCode == locale?.countryCode) { return supportedLocale; } } return supportedLocales.first; }, ); } }
(2)、设置语言包
①、创建语言文件
②、在 pubspec.yaml 中配置语言资源
(3)、异步加载语言包
①、在 CustomLocalizations 中,添加 loadJson() 方法
②、在 CustomLocalizationsDelegate 中,调用 CustomLocalizations 的 loadJson() 方法
// CustomLocalizations.dart import 'dart:convert'; // import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; class CustomLocalizations { final Locale locale; CustomLocalizations(this.locale); // static final Map<String, Map<String, String>> _localizedValues = { // 'en': { // 'title': 'Home', // 'greet': 'Hello', // }, // 'zh': { // 'title': '首页', // 'greet': '你好', // } // }; // String? t(String key) { // return _localizedValues[locale.languageCode]![key]; // } // 加载本地语言包 late Map<String, String> _localizedValues; Future<bool> loadJson() async { String jsonString = await rootBundle.loadString('lang/${locale.languageCode}.json'); Map<String, dynamic> jsonMap = jsonDecode(jsonString); _localizedValues = jsonMap.map((key, value) => MapEntry(key, value.toString())); print('_localizedValues, $_localizedValues'); // _localizedValues, {title: 主页, greet: 你好 Flutter} return true; } String? t(String key) { return _localizedValues[key]; } static CustomLocalizations of(BuildContext context) { return Localizations.of(context, CustomLocalizations); } static CustomLocalizationsDelegate delegate = CustomLocalizationsDelegate(); } class CustomLocalizationsDelegate extends LocalizationsDelegate<CustomLocalizations> { // 当前本地化,是否在有效的语言范围内 @override bool isSupported(Locale locale) { return ['en', 'zh'].contains(locale.languageCode); } // 语言发生变更时,加载对应的本地化资源 @override // Future<CustomLocalizations> load(Locale locale) { // return SynchronousFuture(CustomLocalizations(locale)); // } Future<CustomLocalizations> load(Locale locale) async { CustomLocalizations localizations = CustomLocalizations(locale); await localizations.loadJson(); return localizations; } // 本地化重新构建时,是否调用 load 方法,加载本地化资源 @override bool shouldReload(covariant LocalizationsDelegate<CustomLocalizations> old) { return false; } }
(4)、重新启动应用,切换语言,查看效果