初始化一个项目 locale_demo
VSCode 安装 flutter Intl 插件
pubspec.yaml 添加如下依赖
dependencies:flutter:sdk: flutter# 添加如下flutter_localizations:sdk: flutter# ...
国际化初始化⌘ + ⇧ + P
> Flutter Intl: Initialize
项目 lib 目录会自动生成 generated 和 l10n 目录
默认语言文本 en 自动添加
本文额外添加一个语言两种版本,简体中文和繁体中文> Flutter Intl: Add locale
键入 zh_CN
重复上述操作 键入 zh_TW
l10n 目录生成 intl_zh_CN.arb , intl_zh_TW.arb 文件
|-lib |-generated |-intl -messages_all.dart -messages_en.dart -messages_zh_CN.dart -messages_zh_TW.dart -l10n.dart |-l10n -intl_en.arb -intl_zh_CN.arb -intl_zh_TW.arb
main 文件中
// 引入import 'package:flutter_localizations/flutter_localizations.dart';import 'generated/l10n.dart';// ...return MaterialApp(localizationsDelegates: [S.delegate,GlobalMaterialLocalizations.delegate,GlobalWidgetsLocalizations.delegate,GlobalCupertinoLocalizations.delegate,],supportedLocales: S.delegate.supportedLocales,// ...);
修改生成的 arb 文件intl_en.arb 文件中配置如下
{"general_appbar_title": "General","general_darkmode": "Dark Mode","general_language": "Language","general_textsize": "Text Size","general_background": "Background","general_sticker": "My Stickers","general_sourcenet": "Photos, Videos, Files & Calls","general_speaker": "Turn Off Speaker","general_discover": "Manage Discover","general_tool": "WeChat Tools","general_backup": "Backup & Migrate Chats","general_storage": "Storage","general_clear": "Clear Chat History"}
intl_zh_CN.arb
{"general_appbar_title": "通用","general_darkmode": "深色模式","general_language": "多语言","general_textsize": "字体大小","general_background": "聊天背景","general_sticker": "我的表情","general_sourcenet": "照片、视频、文件和通话","general_speaker": "听筒模式","general_discover": "发现页管理","general_tool": "辅助功能","general_backup": "聊天记录备份与迁移","general_storage": "存储空间","general_clear": "清空聊天记录"}
intl_zh_TW.arb
{"general_appbar_title": "一般","general_darkmode": "深色模式","general_language": "語言","general_textsize": "字型大小","general_background": "聊天背景","general_sticker": "我的貼圖","general_sourcenet": "相片、影片和檔案","general_speaker": "聽筒模式","general_discover": "發現頁管理","general_tool": "協助工具","general_backup": "聊天巨鹿備份與轉移","general_storage": "存儲空間","general_clear": "刪除對話記錄"}
lib目录下新建 pages 目录
新建两个文件 general.dart 和 language.dart
general.dart
import 'package:flutter/material.dart';import 'package:locale_demo/generated/l10n.dart';class _ListTile extends StatelessWidget {final Widget title;final onTap;_ListTile({Key key, this.title, this.onTap}) : super(key: key);@overrideWidget build(BuildContext context) {return Container(color: Colors.white,child: ListTile(title: title,onTap: onTap,),);}}class GeneralPage extends StatelessWidget {GeneralPage(BuildContext context);@overrideWidget build(BuildContext context) {return Scaffold(backgroundColor: Color(0xffedeced),appBar: AppBar(title: Text(S.of(context).general_appbar_title),),body: SingleChildScrollView(child: Column(children: <Widget>[_ListTile(title: Text(S.of(context).general_darkmode),),SizedBox(height: 10,),_ListTile(title: Text(S.of(context).general_language),onTap: () {Navigator.pushNamed(context, '/language');},),SizedBox(height: 10,),_ListTile(title: Text(S.of(context).general_textsize),onTap: () {},),_ListTile(title: Text(S.of(context).general_background),onTap: () {},),_ListTile(title: Text(S.of(context).general_sticker),onTap: () {},),_ListTile(title: Text(S.of(context).general_sourcenet),onTap: () {},),SizedBox(height: 10,),_ListTile(title: Text(S.of(context).general_speaker),onTap: () {},),SizedBox(height: 10,),_ListTile(title: Text(S.of(context).general_discover),onTap: () {},),_ListTile(title: Text(S.of(context).general_tool),onTap: () {},),SizedBox(height: 10,),_ListTile(title: Text(S.of(context).general_backup),onTap: () {},),_ListTile(title: Text(S.of(context).general_storage),onTap: () {},),SizedBox(height: 10,),_ListTile(title: Text(S.of(context).general_clear),onTap: () {},),SizedBox(height: 40,),],),),);}}
language.dart
import 'package:flutter/material.dart';import 'package:locale_demo/generated/l10n.dart';class LanguageRadio extends StatefulWidget {@override_LanguageRadioState createState() => _LanguageRadioState();}class _LanguageRadioState extends State<LanguageRadio> {static const localeList = ['en', 'zh_CN', 'zh_TW'];int _localeIndex = 0;static String getLocaleName(index) {return ['English', '简体中文', '繁體中文'][index];}@overrideWidget build(BuildContext context) {return Container(child: Column(children: <Widget>[ListView.builder(itemCount: localeList.length,shrinkWrap: true,itemBuilder: (context, index) {return RadioListTile(value: index,groupValue: _localeIndex,title: Text(getLocaleName(index)),onChanged: (index) {print(index);setState(() {_localeIndex = index;});var value = localeList[index].split('_');S.load(Locale(value[0], value.length == 2 ? value[1] : ''));},);},),SizedBox(height: 20,),Text(S.of(context).general_language),],),);}}class LanguagePage extends StatelessWidget {LanguagePage(BuildContext context);@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text(S.of(context).general_language),),body: LanguageRadio(),);}}
至此,当我们点击了其他语言后,选项下的文字已经实时修改了,点击VSCode的 Restart ,会发现项目全局语言切换了,但是这种方式只能实时修改当前作用域下的Text,而无法实时修改全局的。
接下来我们将使用 Provider 来管理国际化状态,做到实时修改
在 pubspec.yaml 的依赖中添加如下
dependencies:# ...provider: ^4.3.3
provider
ChangeNotifier
ChangeNotifierProvider
Provider
在 lib 目录下,新建一个 model 目录
在 model 目录下新建一个 locale.dart 文件,将 language.dart 中使用的变量放进 model 中,以共享全局
import 'package:flutter/material.dart';class LocaleModel extends ChangeNotifier {int _localeIndex;int get localeIndex => _localeIndex;LocaleModel() {_localeIndex = 0;}static const localeList = ['en', 'zh_CN', 'zh_TW'];static String getLocaleName(index) {return ['English', '简体中文', '繁體中文'][index];}Locale get locale {var value = localeList[_localeIndex].split('_');return Locale(value[0], value.length == 2 ? value[1] : '');}void switchLocale(index) {_localeIndex = index;notifyListeners();}}
main.dart
class App extends StatelessWidget {@overrideWidget build(BuildContext context) {return ChangeNotifierProvider(create: (_) => LocaleModel(),child: Consumer<LocaleModel>(builder: (context, localeModel, child) {return MaterialApp(localizationsDelegates: [S.delegate,GlobalMaterialLocalizations.delegate,GlobalWidgetsLocalizations.delegate,GlobalCupertinoLocalizations.delegate,],supportedLocales: S.delegate.supportedLocales,locale: localeModel.locale,// ...);}),);}}
language.dart
不再需要 StateFulWidget ,直接通过 LocaleModel 获取
class LanguageRadio extends StatelessWidget {@overrideWidget build(BuildContext context) {return Container(child: Column(children: <Widget>[ListView.builder(shrinkWrap: true,itemCount: LocaleModel.localeList.length,itemBuilder: (context, index) {var model = Provider.of<LocaleModel>(context);return RadioListTile(value: index,groupValue: model.localeIndex,title: Text(S.of(context).getLocaleName(index)),onChanged: (index) {model.switchLocale(index);},);},),],););}}
