ng-extract-i18n-merge
Version:
Extract and merge i18n xliff translation files for angular projects.
114 lines (113 loc) • 7.68 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.ngAdd = void 0;
const schematics_1 = require("@angular-devkit/schematics");
const workspace_1 = require("@schematics/angular/utility/workspace");
const core_1 = require("@angular-devkit/core");
function getTargetFiles(i18nExtension) {
var _a;
const locales = (i18nExtension === null || i18nExtension === void 0 ? void 0 : i18nExtension.locales) ? Object.values(i18nExtension === null || i18nExtension === void 0 ? void 0 : i18nExtension.locales) : undefined;
const files = locales === null || locales === void 0 ? void 0 : locales.map(locale => typeof locale === 'string' ? locale : selectTargetFile(locale === null || locale === void 0 ? void 0 : locale.translation));
return (_a = files === null || files === void 0 ? void 0 : files.filter(f => f !== undefined)) !== null && _a !== void 0 ? _a : [];
}
function selectTargetFile(translation) {
if (typeof translation === 'string') {
return translation || undefined;
}
if (!translation || translation.length === 1) {
return translation === null || translation === void 0 ? void 0 : translation[0];
}
// simple heuristic: shortest path (translations from third parties are probably from node_modules..)
const sorted = [...translation].sort((a, b) => a.length === b.length ? 0 : (a.length > b.length ? 1 : -1));
return sorted[0];
}
function getFormatFromTargetFile(targetFilePath, tree, context) {
var _a;
if (targetFilePath) {
const content = (_a = tree.read(targetFilePath)) === null || _a === void 0 ? void 0 : _a.toString();
const m = content === null || content === void 0 ? void 0 : content.match(/<xliff[^>]*version=["']([^"']+)["']/i);
if (m) {
switch (m[1]) {
case '1.2':
return 'xlf';
case '2.0':
return 'xlf2';
default:
context.logger.warn(`unexpected xliff version in ${targetFilePath}: ${m[1]}`);
return undefined;
}
}
}
return undefined;
}
function getOutFileRelativeToOutputPath(outFile, outputPathFromExtractI18nOptions, outputPathFromTargetFiles, tree, outputPath) {
const potentialBasePathsForOutFile = [
outputPathFromExtractI18nOptions,
outputPathFromTargetFiles,
'src/locales',
'.'
].filter(p => !!p);
const basePathForOutFile = potentialBasePathsForOutFile.find(p => tree.exists((0, core_1.normalize)(`${p}/${outFile}`)));
return basePathForOutFile ? (0, core_1.relative)(`/${outputPath}`, `/${basePathForOutFile}/${outFile}`) : outFile;
}
// noinspection JSUnusedGlobalSymbols
function ngAdd(_options) {
return (tree, context) => {
return (0, workspace_1.updateWorkspace)(async (workspace) => {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
const projectName = _options.project || Array.from(workspace.projects.keys())[0];
const projectWorkspace = workspace.projects.get(projectName);
if (!projectWorkspace) {
throw new schematics_1.SchematicsException(`Project ${projectName} not found!`);
}
// infer target files:
const i18nExtension = projectWorkspace.extensions.i18n;
// alternative: search tree for *.xlf? --> not performant, contains node_modules
const files = getTargetFiles(i18nExtension);
if (!(files === null || files === void 0 ? void 0 : files.length)) {
context.logger.warn('Could not infer translation target files, please setup angular i18n and re-run `ng add ng-extract-i18n-merge`: https://angular.io/guide/i18n-common-merge#define-locales-in-the-build-configuration');
}
else {
context.logger.info('Found target translation files: ' + JSON.stringify(files));
}
// infer outputPath
const existingI18nTargetOptions = (_a = projectWorkspace.targets.get('extract-i18n')) === null || _a === void 0 ? void 0 : _a.options;
const outputPathFromExtractI18nOptions = existingI18nTargetOptions === null || existingI18nTargetOptions === void 0 ? void 0 : existingI18nTargetOptions.outputPath;
const outputPathFromTargetFiles = (_b = files === null || files === void 0 ? void 0 : files[0]) === null || _b === void 0 ? void 0 : _b.substring(0, (_d = (_c = files === null || files === void 0 ? void 0 : files[0]) === null || _c === void 0 ? void 0 : _c.lastIndexOf('/')) !== null && _d !== void 0 ? _d : (_e = files === null || files === void 0 ? void 0 : files[0]) === null || _e === void 0 ? void 0 : _e.length);
const outputPath = (0, core_1.normalize)((_f = outputPathFromExtractI18nOptions !== null && outputPathFromExtractI18nOptions !== void 0 ? outputPathFromExtractI18nOptions : outputPathFromTargetFiles) !== null && _f !== void 0 ? _f : 'src/locales');
context.logger.info(`inferred output path: ${outputPath}`);
const buildTarget = (_h = (_g = existingI18nTargetOptions === null || existingI18nTargetOptions === void 0 ? void 0 : existingI18nTargetOptions.browserTarget) !== null && _g !== void 0 ? _g : existingI18nTargetOptions === null || existingI18nTargetOptions === void 0 ? void 0 : existingI18nTargetOptions.buildTarget) !== null && _h !== void 0 ? _h : `${projectName}:build`;
// infer format:
const formatFromExtractI18nOptions = existingI18nTargetOptions === null || existingI18nTargetOptions === void 0 ? void 0 : existingI18nTargetOptions.format;
const formatFromTargetFiles = getFormatFromTargetFile(files === null || files === void 0 ? void 0 : files[0], tree, context);
const format = (_j = formatFromExtractI18nOptions !== null && formatFromExtractI18nOptions !== void 0 ? formatFromExtractI18nOptions : formatFromTargetFiles) !== null && _j !== void 0 ? _j : 'xlf2';
context.logger.info(`inferred format: ${format}`);
// remove path from files
const filesWithoutOutputPath = files === null || files === void 0 ? void 0 : files.map(f => (0, core_1.relative)(`/${outputPath}`, `/${f}`));
const target = projectWorkspace.targets.get('extract-i18n');
const builderOptions = {
buildTarget: buildTarget,
format,
outputPath,
targetFiles: filesWithoutOutputPath !== null && filesWithoutOutputPath !== void 0 ? filesWithoutOutputPath : []
};
const outFileRelativeToOutputPath = getOutFileRelativeToOutputPath((_k = existingI18nTargetOptions === null || existingI18nTargetOptions === void 0 ? void 0 : existingI18nTargetOptions.outFile) !== null && _k !== void 0 ? _k : 'messages.xlf', outputPathFromExtractI18nOptions, outputPathFromTargetFiles, tree, outputPath);
if (outFileRelativeToOutputPath !== 'messages.xlf') {
builderOptions.sourceFile = outFileRelativeToOutputPath;
}
if (target) {
context.logger.info(`Overwriting previous extract-i18n entry in project ${projectName}.`);
target.builder = 'ng-extract-i18n-merge:ng-extract-i18n-merge';
target.options = builderOptions;
}
else {
projectWorkspace.targets.add({
name: 'extract-i18n',
builder: 'ng-extract-i18n-merge:ng-extract-i18n-merge',
options: builderOptions,
});
}
});
};
}
exports.ngAdd = ngAdd;
;