File

libs/nx/src/executors/extract-i18n/executor.ts

Index

Properties

Properties

baseHref
Type string
code
Type string
import {
  ExecutorContext,
  ProjectConfiguration,
  ProjectGraph,
  joinPathFragments,
  parseTargetString
} from '@nx/devkit';
import { execSync } from 'child_process';
import { normalizeExecutorOptions } from '../shared/normalize-executor-options';
import { ExtractI18nExecutorSchema } from './schema';

const DEFAULT_TRANSLATION_FILE_FORMAT = 'xlf';

interface SourceLocaleConfiguration {
  code: string;
  baseHref: string;
}

export default async function runI18nExtractExecutor(
  options: ExtractI18nExecutorSchema,
  context: ExecutorContext
) {
  try {
    if (!context.projectName) {
      return {
        success: false,
        error: `'projectName' property is missing from Executor context.`
      };
    }

    const buildTarget = options.buildTarget;

    if (!buildTarget) {
      return {
        success: false,
        error: `'buildTarget' property is missing from Executor options.`
      };
    }

    const parsedBuildTarget = parseTargetString(buildTarget, context.projectGraph as ProjectGraph);

    const buildOutputPath: string | undefined =
      context.workspace?.projects[context.projectName].targets?.[parsedBuildTarget.target].options
        .outputPath;

    if (!buildOutputPath) {
      throw new Error(
        `The "outputPath" option is missing from the "${parsedBuildTarget.target}" target. Please configure it and rerun the executor.`
      );
    }

    execSync(
      `npx nx run ${buildTarget} --configuration=production --localize=false --optimization`,
      {
        stdio: 'inherit'
      }
    );

    const outputFileName = options.outFile ?? getI18nOutputFileName(options.format);
    const outputPath = joinPathFragments(options.outputPath ?? '', outputFileName);
    const sourceLocaleConfig: SourceLocaleConfiguration | undefined = (
      context.workspace?.projects[context.projectName] as ProjectConfiguration & {
        i18n: Record<string, SourceLocaleConfiguration>;
      }
    )?.i18n?.['sourceLocale'];

    const normalizedOptions = normalizeExecutorOptions({
      source: joinPathFragments(buildOutputPath, '**/*.js'),
      format: options.format ?? DEFAULT_TRANSLATION_FILE_FORMAT,
      outputPath: outputPath,
      locale: getSourceLocaleCode(sourceLocaleConfig)
    });

    execSync(`npx localize-extract ${normalizedOptions.join(' ')}`, {
      stdio: 'inherit'
    });

    return { success: true };
  } catch (error) {
    console.error(`Error during the localization extraction: ${(error as Error).message}`);
    return { success: false };
  }
}

/**
 * Cherry picked from angular-cli
 * via https://github.com/angular/angular-cli/blob/956e7ea1f53f8e705e7e6a9fa141742f06e907a7/packages/angular_devkit/build_angular/src/builders/extract-i18n/index.ts#L31
 */
function getI18nOutputFileName(format = DEFAULT_TRANSLATION_FILE_FORMAT) {
  switch (format) {
    case 'xmb':
      return 'messages.xmb';
    case 'xlf':
    case 'xlif':
    case 'xliff':
    case 'xlf2':
    case 'xliff2':
      return 'messages.xlf';
    case 'json':
    case 'legacy-migrate':
      return 'messages.json';
    case 'arb':
      return 'messages.arb';
    default:
      throw new Error(`Unsupported format "${format}"`);
  }
}

function getSourceLocaleCode(sourceLocaleConfig: SourceLocaleConfiguration | undefined) {
  if (typeof sourceLocaleConfig === 'object') {
    return sourceLocaleConfig.code;
  }

  return sourceLocaleConfig;
}

results matching ""

    No results matching ""