@formatjs/cli-lib
Version:
Lib for CLI for formatjs.
91 lines (90 loc) • 3.69 kB
JavaScript
import { parse } from '@formatjs/icu-messageformat-parser';
import { outputFile, readJSON } from 'fs-extra';
import stringify from 'json-stable-stringify';
import { debug, warn, writeStdout } from './console_utils';
import { resolveBuiltinFormatter } from './formatters';
import { generateENXA, generateENXB, generateXXAC, generateXXHA, generateXXLS, } from './pseudo_locale';
/**
* Aggregate `inputFiles` into a single JSON blob and compile.
* Also checks for conflicting IDs.
* Then returns the serialized result as a `string` since key order
* makes a difference in some vendor.
* @param inputFiles Input files
* @param opts Options
* @returns serialized result in string format
*/
export async function compile(inputFiles, opts = {}) {
debug('Compiling files:', inputFiles);
const { ast, format, pseudoLocale, skipErrors, ignoreTag } = opts;
const formatter = await resolveBuiltinFormatter(format);
const messages = {};
const messageAsts = {};
const idsWithFileName = {};
const compiledFiles = await Promise.all(inputFiles.map(f => readJSON(f).then(formatter.compile)));
debug('Compiled files:', compiledFiles);
for (let i = 0; i < inputFiles.length; i++) {
const inputFile = inputFiles[i];
debug('Processing file:', inputFile);
const compiled = compiledFiles[i];
for (const id in compiled) {
if (messages[id] && messages[id] !== compiled[id]) {
throw new Error(`Conflicting ID "${id}" with different translation found in these 2 files:
ID: ${id}
Message from ${idsWithFileName[id]}: ${messages[id]}
Message from ${inputFile}: ${compiled[id]}
`);
}
try {
const msgAst = parse(compiled[id], { ignoreTag });
messages[id] = compiled[id];
switch (pseudoLocale) {
case 'xx-LS':
messageAsts[id] = generateXXLS(msgAst);
break;
case 'xx-AC':
messageAsts[id] = generateXXAC(msgAst);
break;
case 'xx-HA':
messageAsts[id] = generateXXHA(msgAst);
break;
case 'en-XA':
messageAsts[id] = generateENXA(msgAst);
break;
case 'en-XB':
messageAsts[id] = generateENXB(msgAst);
break;
default:
messageAsts[id] = msgAst;
break;
}
idsWithFileName[id] = inputFile;
}
catch (e) {
warn('Error validating message "%s" with ID "%s" in file "%s"', compiled[id], id, inputFile);
if (!skipErrors) {
throw e;
}
}
}
}
return stringify(ast ? messageAsts : messages, {
space: 2,
cmp: formatter.compareMessages || undefined,
});
}
/**
* Aggregate `inputFiles` into a single JSON blob and compile.
* Also checks for conflicting IDs and write output to `outFile`.
* @param inputFiles Input files
* @param compileOpts options
* @returns A `Promise` that resolves if file was written successfully
*/
export default async function compileAndWrite(inputFiles, compileOpts = {}) {
const { outFile, ...opts } = compileOpts;
const serializedResult = (await compile(inputFiles, opts)) + '\n';
if (outFile) {
debug('Writing output file:', outFile);
return outputFile(outFile, serializedResult);
}
await writeStdout(serializedResult);
}