build method

  1. @override
FutureOr<void> build(
  1. BuildStep buildStep
)

Generates the outputs for a given BuildStep.

Implementation

@override
FutureOr<void> build(BuildStep buildStep) async {
  // only generate once
  if (_generated) return;

  _generated = true;

  final Glob findAssetsPattern = buildConfig.inputDirectory != null
      ? Glob(
          '**${buildConfig.inputDirectory}/**${buildConfig.inputFilePattern}')
      : Glob('**${buildConfig.inputFilePattern}');

  // STEP 1: determine base name and output file name / path

  final assets = <AssetId>[];
  String outputFilePath;

  await buildStep.findAssets(findAssetsPattern).forEach((assetId) {
    assets.add(assetId);
  });

  // CAUTION: in build_runner, the path separator seems to be hard coded to /
  if (buildConfig.outputDirectory != null) {
    // output directory specified, use this path instead
    outputFilePath =
        buildConfig.outputDirectory! + '/' + buildConfig.outputFileName;
  } else {
    // use the directory of the first (random) translation file
    final finalOutputDirectory =
        (assets.first.pathSegments..removeLast()).join('/');
    outputFilePath = '$finalOutputDirectory/${buildConfig.outputFileName}';
  }

  // STEP 2: scan translations
  final translationMap = NamespaceTranslationMap();
  for (final asset in assets) {
    final content = await buildStep.readAsString(asset);
    final Map<String, dynamic> translations;
    try {
      translations = BaseDecoder.getDecoderOfFileType(buildConfig.fileType)
          .decode(content);
    } on FormatException catch (e) {
      throw 'File: ${asset.path}\n$e';
    }

    final fileNameNoExtension =
        asset.pathSegments.last.getFileNameNoExtension();
    final baseFileMatch =
        RegexUtils.baseFileRegex.firstMatch(fileNameNoExtension);
    if (baseFileMatch != null) {
      // base file
      final namespace = baseFileMatch.group(1)!;

      if (buildConfig.fileType == FileType.csv &&
          CsvDecoder.isCompactCSV(content)) {
        // compact csv

        translations.forEach((key, value) {
          final locale = I18nLocale.fromString(key);
          final localeTranslations = value as Map<String, dynamic>;
          translationMap.addTranslations(
            locale: locale,
            namespace: namespace,
            translations: localeTranslations,
          );
        });
      } else {
        // json, yaml or normal csv

        translationMap.addTranslations(
          locale: buildConfig.baseLocale,
          namespace: namespace,
          translations: translations,
        );
      }
    } else {
      // secondary files (strings_x)
      final match =
          RegexUtils.fileWithLocaleRegex.firstMatch(fileNameNoExtension);
      if (match != null) {
        final namespace = match.group(2)!;
        final language = match.group(3)!;
        final script = match.group(5);
        final country = match.group(7);
        final locale = I18nLocale(
          language: language,
          script: script,
          country: country,
        );

        translationMap.addTranslations(
          locale: locale,
          namespace: namespace,
          translations: translations,
        );
      }
    }
  }

  // STEP 3: generate .g.dart content
  final result = GeneratorFacade.generate(
    buildConfig: buildConfig,
    baseName: buildConfig.outputFileName.getFileNameNoExtension(),
    translationMap: translationMap,
  );

  // STEP 4: write output to hard drive
  FileUtils.createMissingFolders(filePath: outputFilePath.toAbsolutePath());
  if (buildConfig.outputFormat == OutputFormat.singleFile) {
    // single file
    FileUtils.writeFile(
      path: outputFilePath,
      content: result.joinAsSingleOutput(),
    );
  } else {
    // multiple files
    FileUtils.writeFile(
      path: BuildResultPaths.mainPath(outputFilePath),
      content: result.header,
    );
    for (final entry in result.translations.entries) {
      final locale = entry.key;
      final localeTranslations = entry.value;
      FileUtils.writeFile(
        path: BuildResultPaths.localePath(
          outputPath: outputFilePath,
          locale: locale,
          pathSeparator: '/',
        ),
        content: localeTranslations,
      );
    }
    if (result.flatMap != null) {
      FileUtils.writeFile(
        path: BuildResultPaths.flatMapPath(
          outputPath: outputFilePath,
          pathSeparator: '/',
        ),
        content: result.flatMap!,
      );
    }
  }
}