Sal*_*rke 9 localization flutter
我正在尝试在颤振中本地化我的应用程序。我为支持的语言创建了所需的 string.arb 文件。
为什么AppLocalizations.of(context)需要上下文?
我只想访问文件/语言环境文件/类中的命名字符串。在应用程序的某个时刻,我构建了一个列表,稍后通过使用单独的类覆盖某些字段来填充它。
但是,这个类没有上下文,但我想在其中使用本地化的字符串。我可以编写一个方法来获取我放入的任何字符串的本地化吗?
zap*_*zap 14
我们可以通过使用get_it轻松解决这个问题,我们可以在设置之后的任何地方使用该字符串。
将其安装到您的 vscode Flutter Intl VSCode 扩展
设置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
Run Code Online (Sandbox Code Playgroud)
设置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(),
);
}
}
Run Code Online (Sandbox Code Playgroud)
设置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());
}
Run Code Online (Sandbox Code Playgroud)
将其与 Get_it 一起使用,无需上下文作为
final I10n _i10n = locator<I10n>();
class MessageComponent extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Text(
_i10n.sample,
textAlign: TextAlign.center,
);
}
}
Run Code Online (Sandbox Code Playgroud)
Stu*_*uck 11
如果您知道所需的Locale那么您可以使用:
final locale = Locale('en');
AppLocalizations t = await AppLocalizations.delegate.load(locale);
println(t.someTranslationKey);
Run Code Online (Sandbox Code Playgroud)
Locale('en')您可以实现某种解析器来找出所需的区域设置,而不是硬编码。支持的语言是AppLocalizations.supportedLocales.
有一个名为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;
},
);
}
}
Run Code Online (Sandbox Code Playgroud)
另外不要忘记将本地化路径放入您的pubspec.yamal文件!
完成所有这些后,您可以简单地在Text小部件中使用它,如下所示:
Text(tr('someJsonKey'),),
Run Code Online (Sandbox Code Playgroud)
如果您不想使用软件包,那么这里有一个对我有用的解决方案。现在最常见的实现的AppLocalizations,我平时看到有以下两行:
//.........
static const LocalizationsDelegate<AppLocalizations> delegate =
_AppLocalizationsDelegate();
static AppLocalizations of(BuildContext context) {
return Localizations.of<AppLocalizations>(context, AppLocalizations);
}
//.........
Run Code Online (Sandbox Code Playgroud)
委托的实现看起来像这样:
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
}
Run Code Online (Sandbox Code Playgroud)
请注意委托上的 load 方法返回一个Future<AppLocalizations>. load 方法通常从 main 调用一次,以后不再调用,因此您可以通过向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
}
Run Code Online (Sandbox Code Playgroud)
那么在你的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
//.........
Run Code Online (Sandbox Code Playgroud)
现在在您的翻译助手方法中,您可以拥有:
String tr(String key) {
return AppLocalizations.instance.translate(key);
}
Run Code Online (Sandbox Code Playgroud)
不需要上下文。
最新:当前的Flutter Intl插件使这种方法变得过时,至少如果您使用受支持的 IDE。你有一个上下文无关的替代方案:
S.current.translationKey
Run Code Online (Sandbox Code Playgroud)
上一篇:从Stuck的建议出发,这是我找到的最终解决方案。它不像使用上下文进行简单查找那么便宜,因此仅在确实必要时才使用它,并确保调用它一次并尽可能多地使用它。但即使您根本没有上下文,例如,您处于后台服务或任何其他没有 UI 的程序部分,这种方法也有效。
S.current.translationKey
Run Code Online (Sandbox Code Playgroud)
使用方法和平常一样:
Future<AppLocalizations> loadLocalization() async {
final parts = Intl.getCurrentLocale().split('_');
final locale = Locale(parts.first, parts.last);
return await AppLocalizations.delegate.load(locale);
}
Run Code Online (Sandbox Code Playgroud)
更新:我在评论中建议的单例可能如下所示:
final t = await loadLocalization();
print(t.translationKey);
Run Code Online (Sandbox Code Playgroud)
并使用如下:
final t = await Localization().loadCurrent();
Run Code Online (Sandbox Code Playgroud)
要跟踪语言更改,请从您的 main 调用此命令build():
PlatformDispatcher.instance.onLocaleChanged = () => Localization().invalidate();
Run Code Online (Sandbox Code Playgroud)
我花了 2 美分,只是为了不失去解决方案:)
我完全明白为什么 Flutter 本地化解决方案需要 BuildContext - 完全有道理。但是,如果我明确不希望运行时语言切换,并且对应用程序重新启动感到满意?
这就是我想出的解决方案,看起来效果很好。
假设您已遵循 Flutter 的官方本地化步骤,请创建一个用于访问该类的全局变量AppLocalizations。
i18n.dart:
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
AppLocalizations get tr => _tr!; // helper function to avoid typing '!' all the time
AppLocalizations? _tr; // global variable
class AppTranslations {
static init(BuildContext context) {
_tr = AppLocalizations.of(context);
}
}
Run Code Online (Sandbox Code Playgroud)
现在,在主包装器(下面的包装器MaterialApp)中的某个位置调用来设置当前所选语言环境的本地化:
AppTranslations.init(context);
Run Code Online (Sandbox Code Playgroud)
它可能是主部件initState(),甚至build()是主部件的部件(显然,多次调用它是安全的)。
现在您只需调用:
import 'package:my_app/i18n.dart'
...
Text(tr.welcome_text)
// or
print(tr.welcome_text);
...
Run Code Online (Sandbox Code Playgroud)
我已经在使用easy_localization包,所以这对我来说很容易。
我用来获取没有上下文的应用程序语言的技巧如下
en-US.json
{
"app_locale":"en"
}
Run Code Online (Sandbox Code Playgroud)
ar-SA.json
{
"app_locale":"ar"
}
Run Code Online (Sandbox Code Playgroud)
像实用程序/扩展函数中的方式一样使用它
LocaleKeys.app_locale.tr() //will return 'en' for English, 'ar' for Arabic
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7573 次 |
| 最近记录: |