【发布时间】:2020-12-19 14:20:55
【问题描述】:
我在我的应用程序中使用基于颤振文档的本地化。
请参见此处:https://flutter.dev/docs/development/accessibility-and-localization/internationalization
我使用 get_it 包(4.0.4 版)来检索像本地化委托这样的单例对象。不幸的是,它需要一个BuildContext 属性。有时在我的应用程序中我没有上下文引用,所以如果它像这样工作会很好:GetIt.I<AppLocalizations>() 而不是这个:AppLocalizations.of(context)。如果您像这样设置 get_it,它仍然可以毫无问题地实现: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;
}
还有一些 intl 生成的 dart 代码和 .arb 文件对于说明问题并不那么重要。
总而言之,在这种情况下,如何在不使用上下文的情况下将我的 AppLocalizations 类用作单例?也许我最初的方法很糟糕,可以通过我所代表的其他方式来完成。如果您有解决方案,请告诉我。
谢谢。
【问题讨论】: