我正在使用基于Flutter文档的本地化实现。请参考以下链接:https://flutter.dev/docs/development/accessibility-and-localization/internationalization
我使用了get_it包(版本4.0.4),用来检索单例对象,例如Localization delegate。不幸的是,它需要一个BuildContext属性。有时在我的应用程序中,我没有上下文引用,所以如果可以像这样工作就好了:
对我来说有点难以正确解释它,因此我在最小示例中重新创建了该问题。
我注释掉了一些会导致编译时错误的代码,但它展示了我如何想象它完成的方式。 main.dart
初始路线。
一些国际化生成的Dart代码和.ARb文件并不重要,无法说明问题。
总之,我该如何实现将我的AppLocalizations类作为单例使用,而不需要像在这样的情况下使用上下文?也许我的初始方法不好,可以用其他方式完成。如果您有解决方案,请告诉我。
谢谢。
GetIt.I<AppLocalizations>()
而不是这样:AppLocalizations.of(context)
。仍然可以通过以下方式实现: GetIt.I.registerLazySingleton(() => AppLocalizations.of(context));
但问题是你至少需要一次上下文才能使其有效。此外,如果你想立即在初始路由中显示本地化文本,则更难在需要时获取已正确初始化的BuildContext
。对我来说有点难以正确解释它,因此我在最小示例中重新创建了该问题。
我注释掉了一些会导致编译时错误的代码,但它展示了我如何想象它完成的方式。 main.dart
GetIt getIt = GetIt.instance;
void setupGetIt() {
// How to get BuildContext properly if no context is available yet?
// Compile time error.
// getIt.registerLazySingleton(() => AppLocalizations.of(context));
}
void main() {
setupGetIt();
runApp(MyApp());
}
class MyApp extends StatefulWidget {
MyApp({Key key}) : super(key: key);
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
Widget build(BuildContext context) {
// The above line also won't work. It has BuildContext but Applocalizations.of(context) won't work
// because it's above in the Widget tree and not yet setted up.
getIt.registerLazySingleton(() => AppLocalizations.of(context));
return MaterialApp(
supportedLocales: const [
Locale('en', 'US'),
Locale('hu', 'HU'),
],
localizationsDelegates: const [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
localeResolutionCallback: (locale, supportedLocales) {
// check if locale is supported
for (final supportedLocale in supportedLocales) {
if (supportedLocale.languageCode == locale?.languageCode &&
supportedLocale.countryCode == locale?.countryCode) {
return supportedLocale;
}
}
// if locale is not supported then return the first (default) one
return supportedLocales.first;
},
// You may pass the BuildContext here for Page1 in it's constructor
// but in a more advanced routing case it's not a maintanable solution.
home: Page1(),
);
}
}
初始路线。
class PageBase extends StatelessWidget {
final String title;
final Widget content;
PageBase(this.title, this.content);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: content,
);
}
}
class Page1 extends PageBase {
// It won't run because I need the context but clearly I don't have it.
// And in a real app you also don't want to pass the context all over the place
if you have many routes to manage.
Page1(String title)
: super(AppLocalizations.of(context).title, Center(child: Text('Hello')));
// Intended solution
// I don't know how to properly initialize getIt AppLocalizations singleton by the time
// it tries to retrieve it
Page1.withGetIt(String title)
: super(getIt<AppLocalizations>().title, Center(child: Text('Hello')));
}
locales.dart
String globalLocaleName;
class AppLocalizations {
//AppLocalizations(this.localeName);
static AppLocalizations of(BuildContext context) {
return Localizations.of<AppLocalizations>(context, AppLocalizations);
}
static const LocalizationsDelegate<AppLocalizations> delegate =
_AppLocalizationsDelegate();
static Future<AppLocalizations> load(Locale locale) async {
final String name =
locale.countryCode.isEmpty ? locale.languageCode : locale.toString();
final String localeName = Intl.canonicalizedLocale(name);
return initializeMessages(localeName).then((_) {
globalLocaleName = localeName;
return AppLocalizations();
});
}
String get title => Intl.message(
'This is the title.',
name: 'title',
);
}
class _AppLocalizationsDelegate
extends LocalizationsDelegate<AppLocalizations> {
// This delegate instance will never change (it doesn't even have fields!)
// It can provide a constant constructor.
const _AppLocalizationsDelegate();
@override
bool isSupported(Locale locale) {
return ['en', 'hu'].contains(locale.languageCode);
}
@override
Future<AppLocalizations> load(Locale locale) => AppLocalizations.load(locale);
@override
bool shouldReload(_AppLocalizationsDelegate old) => false;
}
一些国际化生成的Dart代码和.ARb文件并不重要,无法说明问题。
总之,我该如何实现将我的AppLocalizations类作为单例使用,而不需要像在这样的情况下使用上下文?也许我的初始方法不好,可以用其他方式完成。如果您有解决方案,请告诉我。
谢谢。