Flutter parse array from localization JSON file
I know this might not be the best way to do this but it's just a way I found. You could also save your values in a different json asset file and parse it normally using json.decode() but I needed this to handle it easier with localization.
So I found a simple solution to this instead of adding function to localization class.
I get my array in the Widget as string from my localization file (like any other localization string) like so:
var list = AppLocalization.of(context).translate('cities');//this will return [Paris, Lyon, Nice] as a string
then I do the following:
list = list.replaceAll(RegExp("\\[|\\]"), ''); //removes square brackets from the string
var cityList = list.split(','); //splits the city names by the comma as a
print(cityList); //prints [Paris, Lyon, Nice] as List<String>
Also I implemented another way to get nested json array like in
{
"title" : "My account",
"name" : "John",
"cities" : ["Paris", "Lyon", "Nice"],
"areas" :
{
"paris" : ["area1", "area2", "area3"],
"lyon": ["area1", "area2", "area3"]
}
}
I do this to get paris areas...
var areas = AppLocalization.of(context).translate('areas'); //this gets the whole map as a string.
areas = areas.replaceAll(RegExp("\\[|\\]|\\{|\\}"), '');//this removes leading and trailing {[ ]}
var splitValues = areas.split(':');
var mapValues = Map.fromIterable(test, key: (item) => splitValues[0],value: (item) => item.split(','),);
var parisAreas = mapValues.map((key, value) =>
MapEntry<String, List<String>>(key, List<String>.from(value)));
AhWagih
Updated on December 24, 2022Comments
-
AhWagih over 1 year
I'm trying to add an array of cities' names to my localization json file but I can't decode it back to an array after it is converted to string.
en-US.json
{ "title" : "My account", "name" : "John", "cities" : ["Paris", "Lyon", "Nice"] }
AppLocalization.dart
class AppLocalizations { final Locale locale; AppLocalizations(this.locale); static AppLocalizations of(BuildContext context) { return Localizations.of<AppLocalizations>(context, AppLocalizations); } static const LocalizationsDelegate<AppLocalizations> delegate = _AppLocalizationsDelegate(); Map<String, String> _localizationStrings; Future<bool> load() async { String jsonString = await rootBundle.loadString( 'assets/translations/${locale.languageCode}-${locale.countryCode}.json'); Map<String, dynamic> jsonMap = json.decode(jsonString); _localizationStrings = jsonMap.map((key, value) { return MapEntry(key, value.toString()); }); return true; } Future<void> setLocale(Locale locale) async { final SharedPreferences _prefs = await SharedPreferences.getInstance(); final _languageCode = locale.languageCode; await _prefs.setString('locale', _languageCode); print('locale saved!'); } static Future<Locale> getLocale() async { final SharedPreferences _prefs = await SharedPreferences.getInstance(); final String _languageCode = _prefs.getString('locale'); if (_languageCode == null) return null; Locale _locale; _languageCode == 'en' ? _locale = Locale('en', 'US') : _locale = Locale('ar', 'EG'); return _locale; } String translate(String key) { return _localizationStrings[key]; } } class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> { const _AppLocalizationsDelegate(); @override bool isSupported(Locale locale) { return ['en', 'ar'].contains(locale.languageCode); } @override Future<AppLocalizations> load(Locale locale) async { AppLocalizations localization = AppLocalizations(locale); await localization.load(); return localization; } @override bool shouldReload(LocalizationsDelegate<AppLocalizations> old) { return false; } }
In my widget I try to access the array through
List<String> _cities = AppLocalization.of(context).translate('cities');
this works and if I print _cities.toString() it prints [Paris, Lyon, Nice].
THE PROBLEM
When I try to decode _cities to an array using
json.decode(_cities)
I always get a format error Unhandled Exception: FormatException: Unexpected character (at character 2).I believe the array is converted to String in this function
_localizationStrings = jsonMap.map((key, value) { return MapEntry(key, value.toString()); });
How can I parse it back to an array??
I'm open to all kind of suggestions. Thank you
-
AhWagih over 3 yearsSolution doesn't work because _localizationStrings[key] is of type List<dynamic> so I get an error but to get it work I did the following
Map<String, dynamic> _localizationStrings; instead of Map<String, String> _localizationStrings;
and here I removed the toString on value_localizationStrings = jsonMap.map((key, value) { return MapEntry(key, value); });
List<dynamic> localizedList(String key) { return _localizationStrings[key] as List<String>; }
in my widget I now have to cast the returned List<dynamic> to List<String>list = list.cast<String>().toList();
-
AhWagih over 3 yearsBut I'm not comfortable with all these changes in the localization class. My use case is to use the list to fill a dropdown menu (with city name in both languages) but the list is much bigger than in the example so I don't want to hard code it. maybe there's a better solution to this?
-
AhWagih over 3 yearsThanks for your help but the new answer doesn't solve the issue either because I get my array string from my localization JSON file. I found a more elegant solution and I will post it.