decode method

  1. @override
Map<String, dynamic> decode(
  1. String raw
)
override

Transforms the raw string (json, yaml, csv) to a standardized map structure of Map<String, dynamic>

Children are Map<String, dynamic>, List

No case transformations, etc! Only the raw data represented as a tree.

Implementation

@override
Map<String, dynamic> decode(String raw) {
  final compactCSV = isCompactCSV(raw);
  final parsed = const CsvToListConverter().convert(raw);

  if (compactCSV) {
    final result = <String, Map<String, dynamic>>{};
    final locales = <String?>[]; // list of locales or "comment"-locales

    for (final locale in parsed.first) {
      if (locale is! String) {
        throw 'The first row of the csv file should not contain numbers';
      }
      if (locale.startsWith('(')) {
        locales.add(null);
      } else {
        locales.add(locale);
      }
    }
    locales.removeAt(0); // remove the first locale because it is the key

    for (final locale in locales) {
      if (locale != null) {
        // add the defined locales as root entries
        result[locale] = <String, dynamic>{};
      }
    }

    for (int rowIndex = 1; rowIndex < parsed.length; rowIndex++) {
      // start at second row
      final row = parsed[rowIndex];
      if (row.length < locales.length + 1) {
        throw 'CSV row at index $rowIndex must have ${locales.length + 1} columns but only has ${row.length}.';
      }

      bool commentAdded = false;
      for (int localeIndex = 0; localeIndex < locales.length; localeIndex++) {
        final locale = locales[localeIndex];
        final path = parsed[rowIndex][0];
        final content = parsed[rowIndex][localeIndex + 1].toString();
        if (locale != null) {
          // normal column
          MapUtils.addStringToMap(
            map: result[locale]!,
            destinationPath: path,
            leafContent: content,
          );
        } else if (!commentAdded && content.isNotEmpty) {
          // comment column (only parse the first comment column)
          // add @<path> for all other locales
          for (final localeMap in result.values) {
            final split = path.toString().split('.');
            split[split.length - 1] = '@${split[split.length - 1]}';
            MapUtils.addStringToMap(
              map: localeMap,
              destinationPath: split.join('.'),
              leafContent: content,
            );
          }
          commentAdded = true;
        }
      }
    }
    return result;
  } else {
    // normal csv

    final result = <String, dynamic>{};
    for (final row in parsed) {
      MapUtils.addStringToMap(
        map: result,
        destinationPath: row[0],
        leafContent: row[1].toString(),
      );
    }
    return result;
  }
}