in packages/angular_devkit/build_angular/src/utils/process-bundle.ts [229:320]
async function inlineLocalesDirect(ast: ParseResult, options: InlineOptions) {
if (!i18n || i18n.inlineLocales.size === 0) {
return { file: options.filename, diagnostics: [], count: 0 };
}
const { default: generate } = await import('@babel/generator');
const localizeDiag = await loadLocalizeTools();
const diagnostics = new localizeDiag.Diagnostics();
const positions = findLocalizePositions(ast, options, localizeDiag);
if (positions.length === 0 && !options.setLocale) {
return inlineCopyOnly(options);
}
const inputMap = !!options.map && (JSON.parse(options.map) as { sourceRoot?: string });
// Cleanup source root otherwise it will be added to each source entry
const mapSourceRoot = inputMap && inputMap.sourceRoot;
if (inputMap) {
delete inputMap.sourceRoot;
}
// Load Webpack only when needed
if (webpackSources === undefined) {
webpackSources = (await import('webpack')).sources;
}
const { ConcatSource, OriginalSource, ReplaceSource, SourceMapSource } = webpackSources;
for (const locale of i18n.inlineLocales) {
const content = new ReplaceSource(
inputMap
? new SourceMapSource(options.code, options.filename, inputMap)
: new OriginalSource(options.code, options.filename),
);
const isSourceLocale = locale === i18n.sourceLocale;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const translations: any = isSourceLocale ? {} : i18n.locales[locale].translation || {};
for (const position of positions) {
const translated = localizeDiag.translate(
diagnostics,
translations,
position.messageParts,
position.expressions,
isSourceLocale ? 'ignore' : options.missingTranslation || 'warning',
);
const expression = localizeDiag.buildLocalizeReplacement(translated[0], translated[1]);
const { code } = generate(expression);
content.replace(position.start, position.end - 1, code);
}
let outputSource: import('webpack').sources.Source = content;
if (options.setLocale) {
const setLocaleText = `var $localize=Object.assign(void 0===$localize?{}:$localize,{locale:"${locale}"});\n`;
// If locale data is provided, load it and prepend to file
let localeDataSource;
const localeDataPath = i18n.locales[locale] && i18n.locales[locale].dataPath;
if (localeDataPath) {
const localeDataContent = await loadLocaleData(localeDataPath, true, options.es5);
localeDataSource = new OriginalSource(localeDataContent, path.basename(localeDataPath));
}
outputSource = localeDataSource
? // The semicolon ensures that there is no syntax error between statements
new ConcatSource(setLocaleText, localeDataSource, ';\n', content)
: new ConcatSource(setLocaleText, content);
}
const { source: outputCode, map: outputMap } = outputSource.sourceAndMap() as {
source: string;
map: { file: string; sourceRoot?: string };
};
const outputPath = path.join(
options.outputPath,
i18n.flatOutput ? '' : locale,
options.filename,
);
fs.writeFileSync(outputPath, outputCode);
if (inputMap && outputMap) {
outputMap.file = options.filename;
if (mapSourceRoot) {
outputMap.sourceRoot = mapSourceRoot;
}
fs.writeFileSync(outputPath + '.map', JSON.stringify(outputMap));
}
}
return { file: options.filename, diagnostics: diagnostics.messages, count: positions.length };
}