如何在flutter本地化中读取嵌套的json?

cra*_*ear 6 json localization flutter

我是扑的新手。

我在我的 flutter 项目中应用了本地化,一切正常,直到我编辑我的 json 语言文件以具有嵌套对象。

如何正确调用嵌套的json对象?

我尝试使用点来调用它,但它抛出错误“必须提供非空字符串...”

AppLocalizations.of(context).translate('Intro.Header')
Run Code Online (Sandbox Code Playgroud)

这是我的 json

{
  "Intro": {
    "Header": "Introduction",
    "Content": "This is...."
  },
  "Test": "This is test",
}
Run Code Online (Sandbox Code Playgroud)

如果我直接调用“测试”,我没有问题。

AppLocalizations.of(context).translate('Test')
Run Code Online (Sandbox Code Playgroud)

如何阅读标题和内容?

小智 2

我知道这个问题很老了,但我发现它是因为我遇到了同样的问题并正在寻找解决方案。我无法在互联网上找到一个解决方案,所以我试图自己解决它,当我做到这一点时,我想在这里展示我的解决方案。这个解决方案可能不是最好的,因为我对 Dart/Flutter 还很陌生,但至少它有效。

由于问题的所有者没有提供他的设置,我将采用给定的该视频的状态。

[...] 
Map<String, String> _localizeStrings;
[...]
_localizeStrings = jsonMap.map((key, value) {
  return MapEntry(key, value.toString());
});
[...]
String translate(String key) {
  return _localizeStrings[key];
}
[...]
Run Code Online (Sandbox Code Playgroud)

这就是给定的状态,它完全是为平面 json 结构设置的。为了能够使用嵌套结构,我们的映射_localizeStrings应该是类型Map<String, dynamic>,因为键始终是字符串,但值可以是字符串或另一个映射。下一步我们需要.toString()从 中删除value. 作为最后一步,我们将实现一个用“.”分割给定键的函数。并会一键一键地沿着地图向下爬。我们将返回它获得的最后一个值,.toString()因为这应该是我们想要的字符串。

所以这是我的解决方案:

import 'dart:async';
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class AppLocalizations {
  final Locale locale;
  static const LocalizationsDelegate<AppLocalizations> delegate =
      _AppLocalizationsDelegate();

  AppLocalizations(this.locale);

  static AppLocalizations of(BuildContext context) {
    return Localizations.of<AppLocalizations>(context, AppLocalizations);
  }

  Map<String, dynamic> _localizeStrings;

  Future<bool> load() async {
    String jsonString =
        await rootBundle.loadString('lang/${locale.languageCode}.json');
    Map<String, dynamic> jsonMap = json.decode(jsonString);

    _localizeStrings = jsonMap.map((key, value) {
      return MapEntry(key, value);
    });

    return true;
  }

  String translate(String key) {
    var nestedMap = _getNestedValue(key);    
    return nestedMap.toString();
  }

  dynamic _getNestedValue(String keyPath) {
    Map keyMap = keyPath.split('.').asMap();
    var nestedMap;
    keyMap.forEach((index, key) {
      if (index == 0) {
        nestedMap = _localizeStrings[key];
      } else
        nestedMap = nestedMap[key];
    });
    return nestedMap;
  }
}

class _AppLocalizationsDelegate
    extends LocalizationsDelegate<AppLocalizations> {
  const _AppLocalizationsDelegate();

  @override
  bool isSupported(Locale locale) {
    return ['en', 'de'].contains(locale.languageCode);
  }

  @override
  Future<AppLocalizations> load(Locale locale) async {
    AppLocalizations localizations = new AppLocalizations(locale);
    await localizations.load();
    return localizations;
  }

  @override
  bool shouldReload(LocalizationsDelegate<AppLocalizations> old) => false;
}
Run Code Online (Sandbox Code Playgroud)