阅读量:0
介绍
多语言方案:flutter_localizations 与 GetX 配合版,好处:命令行生成多语言字符串的引用常量类,缺点:切换语言以后,主界面需要手动触发setState,重绘将最新的Locale数据设置给GetMaterialApp。
目录
运行效果
一、安装
dependencies: flutter_localizations: sdk: flutter intl: any get: ^4.6.6 flutter: uses-material-design: true generate: true
二、使用
1.lib文件夹中新建文件夹l10n/arb,并在其中创建app_en.arb 、app_zh.arb、app_zh_HK.arb文件
app_en.arb类
{ "@@locale": "en", "appName": "BraveComponent", "@appName": { "description": "备注" }, "helloWorld": "HelloWorld", "followerSystemLanguage": "FollowerSystemLanguage", "simplifiedChinese": "SimplifiedChinese", "traditionalChinese": "TraditionalChinese", "english": "English", "setting": "Setting", "multiLanguage": "MultiLanguage", "theme": "Theme" }
app_zh.arb类
{ "@@locale": "zh", "appName": "BraveComponent", "@appName": { "description": "备注" }, "helloWorld": "你好,世界", "followerSystemLanguage": "跟随系统语言", "simplifiedChinese": "简体中文", "traditionalChinese": "繁体中文", "english": "英文", "setting": "设置", "multiLanguage": "多语言", "theme": "主题" }
app_zh.arb类
{ "@@locale": "zh_HK", "appName": "BraveComponent", "@appName": { "description": "備注" }, "helloWorld": "妳好,世界", "followerSystemLanguage": "跟隨系統語言", "simplifiedChinese": "簡體中文", "traditionalChinese": "繁體中文", "english": "英文", "setting": "設置", "multiLanguage": "多語言", "theme": "主題" }
2.项目的根目录中添加l10n.yaml,配置如下
arb-dir: lib/l10n/arb template-arb-file: app_zh.arb output-localization-file: app_localizations.dart output-class: AppLocalizations use-deferred-loading: true nullable-getter: false
3.添加完成之后,执行命令flutter gen-l10n
,执行命令flutter run
,.dart_tools会自动生成相关的文件
4.MaterialApp改成GetMaterialApp配置国际化字段
l10n_app.dart类代码
import 'package:brave_component/core/utils/language_utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:get/get.dart'; import 'l10n/l10n.dart'; import 'routes/route_pages.dart'; import 'routes/route_path.dart'; class L10nApp extends StatefulWidget { bool _init = true; L10nApp({super.key}); @override State<L10nApp> createState() => L10nAppState(); } class L10nAppState extends State<L10nApp> { // 供外部使用的_AppSetting实例,用于修改app的状态 static AppSetting setting = AppSetting.instance; @override void initState() { super.initState(); //第一次进入app时,获取本地多语言的countryCode if (widget._init) { setting.setLocale(); widget._init = false; } // 更改语言 setting.changeLocale = () { setState(() {}); }; } @override Widget build(BuildContext context) { return GetMaterialApp( initialRoute: RoutePath.l10n_main, getPages: RoutePages.getPages, title: 'component', theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true, ), locale: setting._locale, fallbackLocale: const Locale("zh", "CN"), localeResolutionCallback: (deviceLocale, supportedLocales) { print('当前语言:${deviceLocale.toString()}'); return; }, supportedLocales: AppLocalizations.supportedLocales, localizationsDelegates: const [ AppLocalizations.delegate, GlobalCupertinoLocalizations.delegate, GlobalWidgetsLocalizations.delegate, GlobalMaterialLocalizations.delegate ], ); } } class AppSetting { AppSetting._(); static final AppSetting _instance = AppSetting._(); static AppSetting get instance => _instance; Locale? _locale; Function()? changeLocale; void setLocale() { _locale = LanguageUtils.getLocale(); } }
language_utils.dart类代码
import 'package:brave_component/l10n/l10n.dart'; import 'package:flutter/widgets.dart'; import 'package:get/get.dart'; import '../../l10n_app.dart'; import '../cache/helpers/cache_helper.dart'; import '../enums/language.dart'; class LanguageUtils { static String getLanguage(BuildContext context, String code) { late String language; switch (code) { case 'fs-Lan': language = context.l10n.followerSystemLanguage; break; case 'zh-CN': language = context.l10n.simplifiedChinese; break; case 'zh-HK': language = context.l10n.traditionalChinese; break; case 'en-US': language = context.l10n.english; break; default: language = context.l10n.followerSystemLanguage; break; } return language; } static Locale? getLocale() { Locale? locale; String code = CacheHelper.countryCode; List<String> lang = code.split('-'); locale = (code == Language.fsLan.countryCode) ? Get.deviceLocale : Locale(lang[0], lang[1]); return locale; } static void updateLocale(String countryCode, {bool isL10n = false}) { List<String> lang = countryCode.split('-'); Get.updateLocale((countryCode == Language.fsLan.countryCode) ? Get.deviceLocale! : Locale(lang[0], lang[1])); CacheHelper.saveCountryCode(countryCode); if (isL10n) { L10nAppState.setting.changeLocale!(); } } }
mian.dart类
import 'package:flutter/material.dart'; import 'app.dart'; import 'core/cache/cache/cache.dart'; import 'l10n_app.dart'; void main() async { await Cache.instance.init(); runApp(L10nApp()); //flutter_localizations与GetX配合版的多语言 // runApp(const App()); //GetX版多语言 }
5.调用
- 直接使用 Text(AppLocalizations.of(context).helloWorld)
- 扩展使用
- 扩展BuildContext
extension BuildContextExtension on BuildContext { AppLocalizations get l10n => AppLocalizations.of(this); }
- 使用 Text(context.l10n.helloWorld)
6.多语言切换
l10n_multi_language_view.dart类
import 'package:brave_component/core/enums/language.dart'; import 'package:brave_component/l10n/l10n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../../../../core/res/colours.dart'; import '../../../../../widgets/base/texts.dart'; import 'l10n_multi_language_logic.dart'; class L10nMultiLanguagePage extends StatelessWidget { L10nMultiLanguagePage({super.key}); final logic = Get.find<L10nMultiLanguageLogic>(); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Texts.fontSize18Normal(context.l10n.multiLanguage, color: Colours.titleColor), leading: GestureDetector( onTap: () { Get.back(result: 'changeLanguage'); }, child: const Icon(Icons.arrow_back), ), ), body: Container( padding: const EdgeInsets.symmetric(vertical: 15), // child: ListView( // children: ListTile.divideTiles( // context: context, // tiles: Language.values // .map((e) => // GetBuilder<MultiLanguageLogic>(builder: (logic) { // return ListTile( // title: Texts.fontSize14Normal(e.title, // color: Colours.titleColor), // trailing: e.countryCode == logic.countryCode // ? const Icon(Icons.check, // color: Colours.primaryColor) // : null, // onTap: () { // logic.changeLanguage(e.countryCode); // }, // ); // })) // .toList()) // .toList(), // ), child: ListView.separated( itemBuilder: (context, index) { return _itemContent(context, index); }, separatorBuilder: (_, index) => const Divider(), itemCount: Language.values.length), ), ); } Widget _itemContent(BuildContext context, int index) { return GetBuilder<L10nMultiLanguageLogic>(builder: (logic) { return Container( padding: const EdgeInsets.symmetric(horizontal: 15), height: 44, child: GestureDetector( onTap: () { logic.changeLanguage(Language.values[index].countryCode); }, child: Row( children: [ Expanded( child: Texts.fontSize14Normal(Language.values[index].title, color: Colours.titleColor)), Visibility( visible: logic.countryCode == Language.values[index].countryCode, child: const Icon(Icons.check, color: Colours.primaryColor)) ], ), ), ); }); } }
l10n_multi_language_logic.dart类
import 'package:brave_component/core/cache/helpers/cache_helper.dart'; import 'package:brave_component/core/utils/language_utils.dart'; import 'package:get/get.dart'; class L10nMultiLanguageLogic extends GetxController { late String countryCode; @override void onInit() { super.onInit(); countryCode = CacheHelper.countryCode; } void changeLanguage(String code) { countryCode = code; LanguageUtils.updateLocale(code, isL10n: true);//切换Locale update(); } }
l10n_multi_language_binding.dart类
import 'package:get/get.dart'; import 'l10n_multi_language_logic.dart'; class L10nMultiLanguageBinding extends Bindings { @override void dependencies() { Get.lazyPut(() => L10nMultiLanguageLogic()); } }
language 类
enum Language { fsLan(title: "跟随系统语言", countryCode: "fs-Lan"), zhCN(title: "简体中文", countryCode: "zh-CN"), zhHK(title: "繁体中文", countryCode: "zh-HK"), enUS(title: "English", countryCode: "en-US"); final String title; final String countryCode; const Language({required this.title, required this.countryCode}); }
这里关于GetX的binding用法不会的可以参考Flutter GetX使用—简洁的魅力!这个博主开发的GetX插件,生成模版代码提高研发效率,建议看看用起来。
持久化就不赘述了,参考源码
源码