[英]Black screen on app launch when using i18n from JSON files
I am attempting to build my own implementation of a system for localizing strings for internationalization in Flutter apps, using Flutter's LocalizationsDelegate
, and loading the localized strings from JSON files (one json file for each locale).我正在尝试构建我自己的系统实现,用于在 Flutter 应用程序中本地化字符串以进行国际化,使用 Flutter 的
LocalizationsDelegate
,并从 JSON 文件(每个语言环境一个 json 文件)加载本地化的字符串。
Everything works fine, but when the app is launched, there's a lapse of some milliseconds in which the screen goes black.一切正常,但是当应用程序启动时,屏幕会在几毫秒内变黑。 The reason for this is that, since I am loading the JSON files using
json.decode
, the way I am retrieving the localized strings is asynchronous.这样做的原因是,由于我使用
json.decode
加载 JSON 文件,因此我检索本地化字符串的方式是异步的。 The app loads its MaterialApp
widget and then starts parsing the JSONs for localization.该应用程序加载其
MaterialApp
小部件,然后开始解析 JSON 以进行本地化。 That is when the app goes black until it parses the JSON successfully.那是应用程序在成功解析 JSON 之前变黑的时候。
Here is my implementation of my i18n system:这是我的 i18n 系统的实现:
class Localization extends LocaleCodeAware with LocalizationsProvider {
Localization(this.locale) : super(locale.toString());
final Locale locale;
static Localization of(BuildContext context) =>
Localizations.of<Localization>(context, Localization);
}
class AppLocalizationsDelegate extends LocalizationsDelegate<Localization> {
const AppLocalizationsDelegate();
@override
bool isSupported(Locale locale) => ['en', 'es'].contains(locale.languageCode);
@override
Future<Localization> load(Locale locale) async {
final localization = Localization(locale);
await localization.load();
return localization;
}
@override
bool shouldReload(AppLocalizationsDelegate old) => false;
}
import 'dart:convert';
import 'package:flutter/services.dart';
import 'package:example/resources/asset_paths.dart' as paths;
abstract class LocaleCodeAware {
LocaleCodeAware(this.localeCode);
final String localeCode;
}
mixin LocalizationsProvider on LocaleCodeAware {
static Map<String, String> _values;
Future<void> load() async {
final string = await rootBundle.loadString('${paths.i18n}$localeCode.json');
final Map<String, dynamic> jsonMap = json.decode(string);
_values = jsonMap.map((key, value) => MapEntry(key, value.toString()));
}
String get appTitle => _values['appTitle'];
}
Here is my main.dart
file, with its MaterialApp
widget.这是我的
main.dart
文件,带有它的MaterialApp
小部件。
import 'package:flutter/material.dart';
void main() => runApp(ExampleApp());
class ExampleApp extends StatelessWidget {
@override
Widget build(BuildContext context) => MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(primarySwatch: Colors.blue),
localizationsDelegates: [
const AppLocalizationsDelegate(),
],
supportedLocales: const [Locale("en"), Locale("es")],
home: const AppNavigator(),
);
}
If instead of having the localized strings in JSON files, I assign a Map<String, String>
to my _values
map, and I load the strings directly from there, the black screen issue is gone, because the values are hardcoded and can be loaded synchronously.如果我没有在 JSON 文件中使用本地化字符串,而是将
Map<String, String>
分配给我的_values
映射,然后直接从那里加载字符串,那么黑屏问题就消失了,因为这些值是硬编码的并且可以加载同步。
So my question is, how can I have my app wait in splash screen until the localized strings are loaded from the JSON files?所以我的问题是,如何让我的应用程序在启动画面中等待,直到从 JSON 文件加载本地化字符串?
Do you have any errors in your logs?您的日志中是否有任何错误? The black screen could only be caused by 1. The current route not building a visible page or 2. The
build()
function of the current route throwing exceptions.黑屏只能由1.当前路由未构建可见页面或2.当前路由的
build()
函数抛出异常引起。
As for loading the localizations while on the splash screen, you can do that within your main()
function:至于在启动屏幕上加载本地化,您可以在
main()
函数中执行此操作:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
List<Locale> locales = WidgetsBinding.instance.window.locales;
// ... logic to decide which locale to use and load localizations for
final string = await rootBundle.loadString('${paths.i18n}$localeCode.json');
final Map<String, dynamic> jsonMap = json.decode(string);
runApp(ExampleApp(jsonMap));
}
This way, you can read the JSON file and convert it to a Map
while on the splash screen, and then pass it to ExampleApp
, which can in turn pass it to AppLocalizationsDelegate
, which can store it as a local variable and use it within load()
.这样,您可以在启动画面上读取 JSON 文件并将其转换为
Map
,然后将其传递给ExampleApp
,后者又可以将其传递给AppLocalizationsDelegate
,后者可以将其存储为局部变量并在load()
使用它load()
.
结帐easy_localization包,它比最简单的有
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.