我正在尝试将我的应用本地化。我为支持的语言创建了所需的string.arb文件。
AppLocalizations.of(context)
为什么需要上下文?
我只是想访问文件/语言环境文件/类中的命名字符串。 在应用程序中的某个时候,我建立了一个列表,稍后通过使用单独的类覆盖某些字段来填充它。
但是,该类没有上下文,但是我想在其中使用本地化的字符串。 我可以写一个方法让我输入的任何字符串都本地化吗?
答案 0 :(得分:5)
如果您不想使用软件包,那么这里有一个对我有用的解决方案。现在,我见过的AppLocalizations
中最多的common implementation通常有以下两行:
//.........
static const LocalizationsDelegate<AppLocalizations> delegate =
_AppLocalizationsDelegate();
static AppLocalizations of(BuildContext context) {
return Localizations.of<AppLocalizations>(context, AppLocalizations);
}
//.........
委托的实现如下所示:
class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
const _AppLocalizationsDelegate();
@override
Future<AppLocalizations> load(Locale locale) async {
AppLocalizations localizations = new AppLocalizations(locale);
await localizations.load();
return localizations;
}
//... the rest omitted for brevity
}
请注意,委托上的load方法将返回Future<AppLocalizations>
。通常,从main调用一次load方法,然后再调用一次,因此您可以通过向委托添加AppLocalizations
的静态实例来利用该方法。所以现在您的代表看起来像这样:
class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
const _AppLocalizationsDelegate();
static AppLocalizations instance;
@override
Future<AppLocalizations> load(Locale locale) async {
AppLocalizations localizations = new AppLocalizations(locale);
await localizations.load();
instance = localizations; // set the static instance here
return localizations;
}
//... the rest omitted for brevity
}
然后在您的AppLocalizations
班上,您将拥有:
//.........
static const LocalizationsDelegate<AppLocalizations> delegate =
_AppLocalizationsDelegate();
static AppLocalizations of(BuildContext context) {
return Localizations.of<AppLocalizations>(context, AppLocalizations);
}
static AppLocalizations get instance => _AppLocalizationsDelegate.instance; // add this
//.........
现在,在您的翻译助手方法中,您可以:
String tr(String key) {
return AppLocalizations.instance.translate(key);
}
不需要上下文。
答案 1 :(得分:0)
有一个名为easy_localization的库,它无需上下文即可进行本地化,您可以简单地使用该库。库还提供了更方便的方法,可编写更少的代码并仍然本地化应用程序的所有部分。主类示例:
void main() {
WidgetsFlutterBinding.ensureInitialized();
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
]).then((_) {
runApp(EasyLocalization(
child: MyApp(),
useOnlyLangCode: true,
startLocale: Locale('nl'),
fallbackLocale: Locale('nl'),
supportedLocales: [
Locale('nl'),
Locale('en'),
],
path: 'lang',
));
});
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: SplashScreen(),
supportedLocales: EasyLocalization.of(context).supportedLocales,
locale: EasyLocalization.of(context).locale,
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
DefaultCupertinoLocalizations.delegate,
EasyLocalization.of(context).delegate,
],
localeResolutionCallback: (locale, supportedLocales) {
if (locale == null) {
EasyLocalization.of(context).locale = supportedLocales.first;
Intl.defaultLocale = '${supportedLocales.first}';
return supportedLocales.first;
}
for (Locale supportedLocale in supportedLocales) {
if (supportedLocale.languageCode == locale.languageCode) {
EasyLocalization.of(context).locale = supportedLocale;
Intl.defaultLocale = '$supportedLocale';
return supportedLocale;
}
}
EasyLocalization.of(context).locale = supportedLocales.first;
Intl.defaultLocale = '${supportedLocales.first}';
return supportedLocales.first;
},
);
}
}
也不要忘记将本地化路径添加到您的pubspec.yamal
文件中!
完成所有这些操作后,您可以像这样在Text
小部件中使用它即可:
Text(tr('someJsonKey'),),
答案 2 :(得分:0)
就我而言,我使用的是最小国际化版本。
根据 Minimal internationalization version 调整 chinloyal 的回答。
应用 chinloyal 的解决方案,但有以下区别:
从这里:
@override
Future<AppLocalizations> load(Locale locale) {
return SynchronousFuture<AppLocalizations>(AppLocalizations(locale));
}
为此:
@override
Future<AppLocalizations> load(Locale locale) async {
var localizations =
await SynchronousFuture<AppLocalizations>(AppLocalizations(locale));
instance = localizations; // set the static instance here
return localizations;
}
答案 3 :(得分:0)
我们可以通过使用 get_it 轻松解决这个问题,我们可以在此设置后的任何地方使用该字符串。
将此安装到您的 vscode Flutter Intl VSCode Extension
设置pubspec.yaml
dependencies:
flutter:
sdk: flutter
flutter_localizations: # Add this line
sdk: flutter # Add this line
intl: ^0.17.0 # Add this line
get_it: ^7.2.0 # Add this line
flutter:
uses-material-design: true
generate: true # Add this line
flutter_intl: # Add this line
enabled: true # Add this line
class_name: I10n # Add this line
main_locale: en # Add this line
arb_dir: lib/core/localization/l10n # Add this line
output_dir: lib/core/localization/generated # Add this line
设置 main.dart
import 'package:component_gallery/core/localization/generated/l10n.dart';
import 'package:component_gallery/locator.dart';
import 'package:component_gallery/ui/pages/home.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
void main() {
setupLocator();
runApp(App());
}
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: [
I10n.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: I10n.delegate.supportedLocales,
localeResolutionCallback: (deviceLocale, supportedLocales) {
if (supportedLocales
.map((e) => e.languageCode)
.contains(deviceLocale?.languageCode)) {
return deviceLocale;
} else {
return const Locale('en', '');
}
},
home: HomePage(),
);
}
}
设置locator.dart
import 'package:component_gallery/core/services/navigation_service.dart';
import 'package:get_it/get_it.dart';
GetIt locator = GetIt.instance;
void setupLocator() {
locator.registerLazySingleton(() => I10n());
}
在没有上下文的情况下与 Get_it 一起使用
final I10n _i10n = locator<I10n>();
class MessageComponent extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Text(
_i10n.sample,
textAlign: TextAlign.center,
);
}
}