3、 Flutter Intl
多语言国际化
在Android Studio中菜单Tools找到flutter intl创建多语言配置。
创建后会在pubspec.yaml出现
flutter_intl:
enabled: true
在工程的lib会生成l10n与generated文件夹
l10n包含
intl_en.arb
intl_zn.arb
我们在intl_en.arb添加
{
'home': "Home",
}
在intl_zn.arb添加
{
'home': "首页",
}
创建LocalModel
// 共享状态
class SessionChangeNotifier with ChangeNotifier {
Session get session => Global.session;
String? get getToken => Global.session.token;
@override
void notifyListeners() {
// 保存Profile变更
Global.saveProfile();
//通知依赖的Widget更新
super.notifyListeners();
}
}
class LocaleModel extends SessionChangeNotifier {
// 获取当前用户的APP语言配置Locale类,如果为null,则语言跟随系统语言
Locale? getLocale() {
if (session.locale == null) return null;
var t = session.locale?.split("_");
LoggerManager().debug("getLocale t:${t}");
if (t != null && t.length == 2) {
LoggerManager().debug("Locale t:${t}");
return Locale(t[0], t[1]);
}
return null;
}
// 获取当前Locale的字符串表示
String get locale => session.locale ?? "";
// 用户改变APP语言后,通知依赖项更新,新语言会立即生效
set locale(String locale) {
LoggerManager().debug("locale:${locale}, profile.locale:${session.locale}");
if (locale != session.locale) {
session.locale = locale;
notifyListeners();
}
}
}
在Main的入口中设置
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: providers,
child: Consumer3(
builder: (context, themeModel, localeModel, userModel, child) {
return RefreshConfiguration(
hideFooterWhenNotFull: false, //列表数据不满一页,不触发加载更多
child: ScreenUtilInit(
designSize: const Size(375.0, 667.0),
minTextAdapt: true,
splitScreenMode: true,
builder: (context, child) {
return child ??
buildMaterialApp(
context, localeModel, themeModel, userModel);
},
child:
buildMaterialApp(context, localeModel, themeModel, userModel),
),
);
},
),
);
}
Widget buildMaterialApp(BuildContext context, LocaleModel localeModel,
ThemeModel themeModel, UserModel userModel) {
return MaterialApp(
theme: ThemeData(
fontFamily: "PingFang SC",
primarySwatch: themeModel.theme,
),
navigatorKey: OneContext().key,
debugShowCheckedModeBanner: false,
supportedLocales: S.delegate.supportedLocales,
locale: localeModel.getLocale(),
initialRoute: buildInitialRoute(
appModel: Provider.of(context, listen: false),
userModel: userModel,
),
onGenerateRoute: RouterManager.generateRoute,
navigatorObservers: buildObservers(),
localizationsDelegates: const [
S.delegate,
RefreshLocalizations.delegate, //下拉刷新
GlobalCupertinoLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate
],
localeResolutionCallback: (_locale, supportedLocales) {
if (localeModel.getLocale() != null) {
//如果已经选定语言,则不跟随系统
return localeModel.getLocale();
} else {
//跟随系统
LoggerManager().debug("_locale:${_locale}");
Locale locale;
if (supportedLocales.contains(_locale)) {
locale = _locale!;
} else {
//如果系统语言不是中文简体或美国英语,则默认使用美国英语
locale = Locale('en', 'US');
}
return locale;
}
},
builder: EasyLoading.init(builder: (BuildContext context, Widget? child) {
return OneContext().builder(
context,
child,
observers: buildObservers(),
);
}),
home: buildGlobalGesture(context),
);
}
Widget buildGlobalGesture(BuildContext context) {
return GestureDetector(
onTap: () {
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus &&
currentFocus.focusedChild != null) {
FocusManager.instance.primaryFocus?.unfocus();
// 也可以使用如下方式隐藏键盘:
// SystemChannels.textInput.invokeMethod('TextInput.hide');
}
},
);
}
List buildObservers() {
return [MyNavigatorObserver()];
}
String? buildInitialRoute(
{required AppModel appModel, required UserModel userModel}) {
String? initialRoute;
// String? isAgree = localeModel.isAgree;
String? isAgree = "1";
if ("1" == isAgree) {
if (userModel.isLogin) {
initialRoute = RouterName.main;
} else {
initialRoute = RouterName.login;
}
} else {
initialRoute = RouterName.agreement;
}
return initialRoute;
}
}
之后我们可以在具体使用的地方这个配置的home。
return Scaffold(
appBar: MyAppBar(
label: S.of(context).home,
isBackButton: false,
),
body:Container(),);
更换语言环境页面
class LanguagePage extends StatefulWidget {
const LanguagePage({Key? key, this.arguments}) : super(key: key);
final Object? arguments;
@override
State createState() => _LanguagePageState();
}
class _LanguagePageState extends State {
@override
Widget build(BuildContext context) {
var color = Theme.of(context).primaryColor;
var localeModel = Provider.of(context);
Widget _buildLanguageItem(String lan, value) {
LoggerManager().debug("_buildLanguageItem:${lan}, value:${value}");
return SettingCheckItemWidget(
title: lan,
content: "",
checkColor: color,
isSelected: localeModel.locale == value,
onPressed: () {
// 此行代码会通知MaterialApp重新build
localeModel.locale = value;
},
);
}
return Scaffold(
appBar: MyAppBar(
onPressed: () {
navigatorBack();
},
label: S.of(context).language,
isBackButton: true,
),
body: ListView.builder(
padding: EdgeInsets.symmetric(vertical: 15.0, horizontal: 10.0),
addRepaintBoundaries: false,
addAutomaticKeepAlives: false,
itemCount: 3,
itemBuilder: (context, index) {
if (index == 0) {
return _buildLanguageItem("中文简体", "zh_CN");
}
if (index == 1) {
return _buildLanguageItem("English", "en_US");
}
if (index == 2) {
return _buildLanguageItem(S.of(context).autoBySystem, null);
}
return Container();
},
),
);
}
void userEnterApp() {
// 点击进入app
NavigatorPageRouter.pushReplacementNamed(RouterName.main);
}
void navigatorBack() {
NavigatorPageRouter.pop();
}
}