AC: Can run a script from package.json "i18n:extract" to add new translation keys found in source files Can see the new translation in all language files Can see an empty string but the key for untranslated phrases Can see all language files synchronised based on the english translation Change-Id: I7181a5224836f5e8f275cee4c975cb6d5199d8c0mr9.3
parent
d02f82e69c
commit
9f1b25c5f9
@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ "$1" == "report" ]; then
|
||||
OTHER_PARAMS=()
|
||||
else
|
||||
OTHER_PARAMS=(--add --json-sort-keys --json-indent-characters "1,tab" --no-detailed-report)
|
||||
fi
|
||||
|
||||
node ./bin/vue-i18n-extract/vue-i18n-extract.js report -v './src/**/*.?(js|vue)' -l './src/i18n/*.json' \
|
||||
--no-dot-notation --add-value-for-languages en --main-language-to-sync-keys en "${OTHER_PARAMS[@]}"
|
@ -0,0 +1 @@
|
||||
Codebase of the tool is vue-i18n-extract:v1.1.11 package
|
@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env node
|
||||
// vim: set filetype=javascript:
|
||||
/* eslint-disable */
|
||||
'use strict';
|
||||
const program = require('commander');
|
||||
const { reportCommand } = require('./vue-i18n-extract.umd.js');
|
||||
|
||||
function increaseDynamic(dummyValue, previous) {
|
||||
return previous + 1;
|
||||
}
|
||||
|
||||
program
|
||||
.command('report', { isDefault: true })
|
||||
.description('Create a report from a glob of your Vue.js source files and your language files.')
|
||||
.requiredOption(
|
||||
'-v, --vueFiles <vueFiles>',
|
||||
'The Vue.js file(s) you want to extract i18n strings from. It can be a path to a folder or to a file. It accepts glob patterns. (ex. *, ?, (pattern|pattern|pattern)',
|
||||
)
|
||||
.requiredOption(
|
||||
'-l, --languageFiles <languageFiles>',
|
||||
'The language file(s) you want to compare your Vue.js file(s) to. It can be a path to a folder or to a file. It accepts glob patterns (ex. *, ?, (pattern|pattern|pattern) ',
|
||||
)
|
||||
.option(
|
||||
'-o, --output <output>',
|
||||
'Use if you want to create a json file out of your report. (ex. -o output.json)',
|
||||
)
|
||||
.option(
|
||||
'-a, --add',
|
||||
'Use if you want to add missing keys into your json language files.',
|
||||
)
|
||||
.option(
|
||||
'-d, --dynamic',
|
||||
'Use if you want to ignore dynamic keys false-positive. Use it 2 times to get dynamic keys report',
|
||||
increaseDynamic,
|
||||
0
|
||||
)
|
||||
.option(
|
||||
'--no-dot-notation',
|
||||
'Use if your language keys are flat, contains dots and you do not use a dot character as a separator for nested key structure'
|
||||
)
|
||||
.option(
|
||||
'--add-value-for-languages <languages>',
|
||||
'Duplicate missing key text to it`s value for specified languages. (Pass them as coma-separated parameter value)',
|
||||
function splitLanguages(value= '') {
|
||||
return value.split(',');
|
||||
}
|
||||
)
|
||||
.option(
|
||||
'--main-language-to-sync-keys <mainLanguage>',
|
||||
'Use it if you want to check and synchronize all translation keys from some lang file to all others. Mainly it should be English lang file'
|
||||
)
|
||||
.option(
|
||||
'--json-sort-keys',
|
||||
'Use if you want to resort language JSON file`s keys alphabetically',
|
||||
false
|
||||
)
|
||||
.option(
|
||||
'--json-indent-characters <jsonIndentCharacters>',
|
||||
'You can specify indentation characters for lines in language JSON files. It will work if JSON language file will be updated, for example because of (--add) option',
|
||||
function checkValue(value) {
|
||||
let [amount, character] = value.split(',');
|
||||
amount = parseInt(amount, 10)
|
||||
if (isNaN(amount) || amount <= 0 || !['space', 'tab'].includes(character)) {
|
||||
console.error(`Unknown or incorrect value format for "--json-indent-characters" option: "${value}"`);
|
||||
process.exit(1)
|
||||
}
|
||||
return value
|
||||
},
|
||||
'2,space'
|
||||
)
|
||||
.option(
|
||||
'--no-detailed-report',
|
||||
'Use if you do not want to see detailed list of the keys output on the screen'
|
||||
)
|
||||
.action(reportCommand);
|
||||
|
||||
program.parseAsync(process.argv);
|
@ -0,0 +1,466 @@
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('path'), require('is-valid-glob'), require('glob'), require('fs'), require('dot-object'), require('js-yaml')) :
|
||||
typeof define === 'function' && define.amd ? define(['exports', 'path', 'is-valid-glob', 'glob', 'fs', 'dot-object', 'js-yaml'], factory) :
|
||||
(global = global || self, factory(global.vueI18NExtract = {}, global.path, global.isValidGlob, global.glob, global.fs, global.dotObject, global.jsYaml));
|
||||
}(this, (function (exports, path, isValidGlob, glob, fs, dot, yaml) {
|
||||
path = path && Object.prototype.hasOwnProperty.call(path, 'default') ? path['default'] : path;
|
||||
isValidGlob = isValidGlob && Object.prototype.hasOwnProperty.call(isValidGlob, 'default') ? isValidGlob['default'] : isValidGlob;
|
||||
glob = glob && Object.prototype.hasOwnProperty.call(glob, 'default') ? glob['default'] : glob;
|
||||
fs = fs && Object.prototype.hasOwnProperty.call(fs, 'default') ? fs['default'] : fs;
|
||||
dot = dot && Object.prototype.hasOwnProperty.call(dot, 'default') ? dot['default'] : dot;
|
||||
yaml = yaml && Object.prototype.hasOwnProperty.call(yaml, 'default') ? yaml['default'] : yaml;
|
||||
|
||||
function _extends() {
|
||||
_extends = Object.assign || function (target) {
|
||||
for (var i = 1; i < arguments.length; i++) {
|
||||
var source = arguments[i];
|
||||
|
||||
for (var key in source) {
|
||||
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
||||
target[key] = source[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return target;
|
||||
};
|
||||
|
||||
return _extends.apply(this, arguments);
|
||||
}
|
||||
|
||||
function readVueFiles(src) {
|
||||
if (!isValidGlob(src)) {
|
||||
throw new Error(`vueFiles isn't a valid glob pattern.`);
|
||||
}
|
||||
|
||||
const targetFiles = glob.sync(src);
|
||||
|
||||
if (targetFiles.length === 0) {
|
||||
throw new Error('vueFiles glob has no files.');
|
||||
}
|
||||
|
||||
return targetFiles.map(f => {
|
||||
const fileName = f.replace(process.cwd(), '');
|
||||
return {
|
||||
fileName,
|
||||
path: f,
|
||||
content: fs.readFileSync(f, 'utf8')
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function* getMatches(file, regExp, captureGroup = 1) {
|
||||
while (true) {
|
||||
const match = regExp.exec(file.content);
|
||||
|
||||
if (match === null) {
|
||||
break;
|
||||
}
|
||||
|
||||
const line = (file.content.substring(0, match.index).match(/\n/g) || []).length + 1;
|
||||
yield {
|
||||
path: match[captureGroup],
|
||||
line,
|
||||
file: file.fileName
|
||||
};
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Extracts translation keys from methods such as `$t` and `$tc`.
|
||||
*
|
||||
* - **regexp pattern**: (?:[$ .]tc?)\(
|
||||
*
|
||||
* **description**: Matches the sequence t( or tc(, optionally with either “$”, “.” or “ ” in front of it.
|
||||
*
|
||||
* - **regexp pattern**: (["'`])
|
||||
*
|
||||
* **description**: 1. capturing group. Matches either “"”, “'”, or “`”.
|
||||
*
|
||||
* - **regexp pattern**: ((?:[^\\]|\\.)*?)
|
||||
*
|
||||
* **description**: 2. capturing group. Matches anything except a backslash
|
||||
* *or* matches any backslash followed by any character (e.g. “\"”, “\`”, “\t”, etc.)
|
||||
*
|
||||
* - **regexp pattern**: \1
|
||||
*
|
||||
* **description**: matches whatever was matched by capturing group 1 (e.g. the starting string character)
|
||||
*
|
||||
* @param file a file object
|
||||
* @returns a list of translation keys found in `file`.
|
||||
*/
|
||||
|
||||
|
||||
function extractMethodMatches(file) {
|
||||
const methodRegExp = /(?:[$ .]tc?)\(\s*?(["'`])((?:[^\\]|\\.)*?)\1/g;
|
||||
return [...getMatches(file, methodRegExp, 2)];
|
||||
}
|
||||
|
||||
function extractComponentMatches(file) {
|
||||
const componentRegExp = /(?:<i18n)(?:.|\n)*?(?:[^:]path=("|'))(.*?)\1/gi;
|
||||
return [...getMatches(file, componentRegExp, 2)];
|
||||
}
|
||||
|
||||
function extractDirectiveMatches(file) {
|
||||
const directiveRegExp = /v-t="'(.*?)'"/g;
|
||||
return [...getMatches(file, directiveRegExp)];
|
||||
}
|
||||
|
||||
function extractI18nItemsFromVueFiles(sourceFiles) {
|
||||
return sourceFiles.reduce((accumulator, file) => {
|
||||
const methodMatches = extractMethodMatches(file);
|
||||
const componentMatches = extractComponentMatches(file);
|
||||
const directiveMatches = extractDirectiveMatches(file);
|
||||
return [...accumulator, ...methodMatches, ...componentMatches, ...directiveMatches];
|
||||
}, []);
|
||||
}
|
||||
|
||||
function parseVueFiles(vueFilesPath) {
|
||||
const filesList = readVueFiles(vueFilesPath);
|
||||
return extractI18nItemsFromVueFiles(filesList);
|
||||
}
|
||||
|
||||
function readLangFiles(src) {
|
||||
if (!isValidGlob(src)) {
|
||||
throw new Error(`languageFiles isn't a valid glob pattern.`);
|
||||
}
|
||||
|
||||
const targetFiles = glob.sync(src);
|
||||
|
||||
if (targetFiles.length === 0) {
|
||||
throw new Error('languageFiles glob has no files.');
|
||||
}
|
||||
|
||||
return targetFiles.map(f => {
|
||||
const langPath = path.resolve(process.cwd(), f);
|
||||
const extension = langPath.substring(langPath.lastIndexOf('.')).toLowerCase();
|
||||
const isJSON = extension === '.json';
|
||||
const isYAML = extension === '.yaml' || extension === '.yml';
|
||||
let langObj;
|
||||
|
||||
if (isJSON) {
|
||||
langObj = JSON.parse(fs.readFileSync(langPath, 'utf8'));
|
||||
} else if (isYAML) {
|
||||
langObj = yaml.safeLoad(fs.readFileSync(langPath, 'utf8'));
|
||||
} else {
|
||||
langObj = eval(fs.readFileSync(langPath, 'utf8'));
|
||||
}
|
||||
|
||||
const fileName = f.replace(process.cwd(), '');
|
||||
return {
|
||||
fileName,
|
||||
path: f,
|
||||
content: JSON.stringify(langObj)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function extractI18nItemsFromLanguageFiles(languageFiles, missingKeysOptions) {
|
||||
return languageFiles.reduce((accumulator, file) => {
|
||||
const language = file.fileName.substring(file.fileName.lastIndexOf('/') + 1, file.fileName.lastIndexOf('.'));
|
||||
|
||||
if (!accumulator[language]) {
|
||||
accumulator[language] = [];
|
||||
}
|
||||
|
||||
const fileContent = JSON.parse(file.content);
|
||||
const flattenedObject = dot.dot(fileContent);
|
||||
Object.keys(flattenedObject).forEach((key, index) => {
|
||||
var _accumulator$language;
|
||||
|
||||
(_accumulator$language = accumulator[language]) == null ? void 0 : _accumulator$language.push({
|
||||
line: index,
|
||||
path: key,
|
||||
file: file.fileName,
|
||||
translated: ((missingKeysOptions.dotNotation ? dot.pick(key, fileContent) : fileContent[key]) || '').trim().length > 0
|
||||
});
|
||||
});
|
||||
return accumulator;
|
||||
}, {});
|
||||
}
|
||||
|
||||
function sortedJSONStringify(obj, indent = 2) {
|
||||
function flattenEntries([key, value]) {
|
||||
return typeof value !== 'object' ? [[key, value]] : [[key, value], ...Object.entries(value).flatMap(flattenEntries)];
|
||||
}
|
||||
|
||||
const allEntries = Object.entries(obj).flatMap(flattenEntries);
|
||||
const sorted = allEntries.map(entry => entry[0]).sort();
|
||||
return JSON.stringify(obj, sorted, indent);
|
||||
}
|
||||
|
||||
function writeMissingToLanguage(resolvedLanguageFiles, missingKeys, missingKeysOptions, outputOptions) {
|
||||
const languageFiles = readLangFiles(resolvedLanguageFiles);
|
||||
languageFiles.forEach(languageFile => {
|
||||
const languageFileContent = JSON.parse(languageFile.content);
|
||||
missingKeys.forEach(item => {
|
||||
if (item.language && languageFile.fileName.includes(item.language) || !item.language) {
|
||||
const keyValue = item.language && missingKeysOptions.addValueForLanguages.includes(item.language) ? item.path : '';
|
||||
|
||||
if (missingKeysOptions.dotNotation) {
|
||||
dot.str(item.path, keyValue, languageFileContent);
|
||||
} else {
|
||||
languageFileContent[item.path] = keyValue;
|
||||
}
|
||||
}
|
||||
});
|
||||
const fileExtension = languageFile.fileName.substring(languageFile.fileName.lastIndexOf('.') + 1);
|
||||
const filePath = path.resolve(process.cwd(), languageFile.fileName);
|
||||
const stringifiedContent = outputOptions.sortKeys ? sortedJSONStringify(languageFileContent, outputOptions.indentationString) : JSON.stringify(languageFileContent, null, outputOptions.indentationString || 2);
|
||||
|
||||
if (fileExtension === 'json') {
|
||||
fs.writeFileSync(filePath, stringifiedContent);
|
||||
} else if (fileExtension === 'js') {
|
||||
const jsFile = `export default ${stringifiedContent}; \n`;
|
||||
fs.writeFileSync(filePath, jsFile);
|
||||
} else if (fileExtension === 'yaml' || fileExtension === 'yml') {
|
||||
const yamlFile = yaml.safeDump(languageFileContent);
|
||||
fs.writeFileSync(filePath, yamlFile);
|
||||
}
|
||||
});
|
||||
}
|
||||
function parseLanguageFiles(languageFilesPath, missingKeysOptions) {
|
||||
const filesList = readLangFiles(languageFilesPath);
|
||||
return extractI18nItemsFromLanguageFiles(filesList, missingKeysOptions);
|
||||
}
|
||||
|
||||
(function (VueI18NExtractReportTypes) {
|
||||
VueI18NExtractReportTypes[VueI18NExtractReportTypes["None"] = 0] = "None";
|
||||
VueI18NExtractReportTypes[VueI18NExtractReportTypes["Missing"] = 1] = "Missing";
|
||||
VueI18NExtractReportTypes[VueI18NExtractReportTypes["Unused"] = 2] = "Unused";
|
||||
VueI18NExtractReportTypes[VueI18NExtractReportTypes["Dynamic"] = 4] = "Dynamic";
|
||||
VueI18NExtractReportTypes[VueI18NExtractReportTypes["All"] = 7] = "All";
|
||||
})(exports.VueI18NExtractReportTypes || (exports.VueI18NExtractReportTypes = {}));
|
||||
|
||||
const mightBeUsedDynamically = function (languageItem, dynamicKeys) {
|
||||
return dynamicKeys.some(dynamicKey => languageItem.path.includes(dynamicKey.path));
|
||||
};
|
||||
|
||||
function extractI18NReport(parsedVueFiles, parsedLanguageFiles, reportType = exports.VueI18NExtractReportTypes.Missing + exports.VueI18NExtractReportTypes.Unused) {
|
||||
const missingKeys = [];
|
||||
const unusedKeys = [];
|
||||
const dynamicKeys = [];
|
||||
const dynamicReportEnabled = reportType & exports.VueI18NExtractReportTypes.Dynamic;
|
||||
Object.keys(parsedLanguageFiles).forEach(language => {
|
||||
let languageItems = parsedLanguageFiles[language];
|
||||
parsedVueFiles.forEach(vueItem => {
|
||||
const usedByVueItem = function (languageItem) {
|
||||
return languageItem.path === vueItem.path || languageItem.path.startsWith(vueItem.path + '.');
|
||||
};
|
||||
|
||||
if (dynamicReportEnabled && (vueItem.path.includes('${') || vueItem.path.endsWith('.'))) {
|
||||
dynamicKeys.push(_extends({}, vueItem, {
|
||||
language
|
||||
}));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!parsedLanguageFiles[language].some(usedByVueItem)) {
|
||||
missingKeys.push(_extends({}, vueItem, {
|
||||
language
|
||||
}));
|
||||
}
|
||||
|
||||
languageItems = languageItems.filter(languageItem => dynamicReportEnabled ? !mightBeUsedDynamically(languageItem, dynamicKeys) && !usedByVueItem(languageItem) : !usedByVueItem(languageItem));
|
||||
});
|
||||
unusedKeys.push(...languageItems.map(item => _extends({}, item, {
|
||||
language
|
||||
})));
|
||||
});
|
||||
let extracts = {};
|
||||
|
||||
if (reportType & exports.VueI18NExtractReportTypes.Missing) {
|
||||
extracts = Object.assign(extracts, {
|
||||
missingKeys
|
||||
});
|
||||
}
|
||||
|
||||
if (reportType & exports.VueI18NExtractReportTypes.Unused) {
|
||||
extracts = Object.assign(extracts, {
|
||||
unusedKeys
|
||||
});
|
||||
}
|
||||
|
||||
if (dynamicReportEnabled) {
|
||||
extracts = Object.assign(extracts, {
|
||||
dynamicKeys
|
||||
});
|
||||
}
|
||||
|
||||
return extracts;
|
||||
}
|
||||
function extractI18NLangFilesSynchronizationReport(parsedLanguageFiles, missingKeysOptions) {
|
||||
const missingKeys = [];
|
||||
|
||||
if (missingKeysOptions.mainLanguageToSyncKeys) {
|
||||
const otherLanguages = _extends({}, parsedLanguageFiles);
|
||||
|
||||
delete otherLanguages[missingKeysOptions.mainLanguageToSyncKeys];
|
||||
const mainLanguageKeys = parsedLanguageFiles[missingKeysOptions.mainLanguageToSyncKeys] || [];
|
||||
mainLanguageKeys.forEach(({
|
||||
path
|
||||
}) => {
|
||||
Object.entries(otherLanguages).forEach(([lang, iItems]) => {
|
||||
if (!iItems.some(iItem => iItem.path === path)) {
|
||||
missingKeys.push({
|
||||
path,
|
||||
language: lang
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
} // detect empty translations for some languages (mainly for English)
|
||||
|
||||
|
||||
Object.entries(parsedLanguageFiles).forEach(([lang, iItems]) => {
|
||||
if (missingKeysOptions.addValueForLanguages.includes(lang)) {
|
||||
iItems.filter(({
|
||||
translated
|
||||
}) => !translated).forEach(({
|
||||
path
|
||||
}) => {
|
||||
missingKeys.push({
|
||||
path,
|
||||
language: lang
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
return {
|
||||
missingKeys
|
||||
};
|
||||
}
|
||||
async function writeReportToFile(report, writePath) {
|
||||
const reportString = JSON.stringify(report);
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.writeFile(writePath, reportString, err => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function createI18NReport(vueFiles, languageFiles, command, missingKeysOptions) {
|
||||
const resolvedVueFiles = path.resolve(process.cwd(), vueFiles);
|
||||
const resolvedLanguageFiles = path.resolve(process.cwd(), languageFiles);
|
||||
const parsedVueFiles = parseVueFiles(resolvedVueFiles);
|
||||
const parsedLanguageFiles = parseLanguageFiles(resolvedLanguageFiles, missingKeysOptions);
|
||||
const reportType = command.dynamic ? exports.VueI18NExtractReportTypes.All : exports.VueI18NExtractReportTypes.Missing + exports.VueI18NExtractReportTypes.Unused;
|
||||
const report = extractI18NReport(parsedVueFiles, parsedLanguageFiles, reportType);
|
||||
const syncReport = extractI18NLangFilesSynchronizationReport(parsedLanguageFiles, missingKeysOptions); // @ts-ignore
|
||||
|
||||
report.missingKeys = [...report.missingKeys, ...syncReport.missingKeys];
|
||||
return report;
|
||||
}
|
||||
|
||||
function getStatisticsForKeys(keysData = []) {
|
||||
const result = {
|
||||
uniqueKeys: {},
|
||||
keysNumbers: {}
|
||||
};
|
||||
result.uniqueKeys = keysData.reduce((accumulator, currentValue) => {
|
||||
const langStatistics = accumulator[currentValue.language || '?'] = accumulator[currentValue.language || '?'] || {};
|
||||
langStatistics[currentValue.path] = (langStatistics[currentValue.path] || 0) + 1;
|
||||
return accumulator;
|
||||
}, {
|
||||
'en': {}
|
||||
});
|
||||
result.keysNumbers = Object.keys(result.uniqueKeys).reduce((acc, language) => {
|
||||
acc[language] = Object.keys(result.uniqueKeys[language]).length;
|
||||
return acc;
|
||||
}, {});
|
||||
return result;
|
||||
}
|
||||
|
||||
async function reportCommand(command) {
|
||||
const {
|
||||
vueFiles,
|
||||
languageFiles,
|
||||
output,
|
||||
add,
|
||||
dynamic,
|
||||
dotNotation,
|
||||
addValueForLanguages,
|
||||
mainLanguageToSyncKeys,
|
||||
jsonSortKeys,
|
||||
jsonIndentCharacters,
|
||||
detailedReport
|
||||
} = command;
|
||||
const outputOptions = {
|
||||
sortKeys: jsonSortKeys,
|
||||
indentationString: ((indentationConfig = '2,space') => {
|
||||
const charactersMap = {
|
||||
'space': ' ',
|
||||
'tab': '\t'
|
||||
};
|
||||
const [charactersAmount, character] = indentationConfig.split(',');
|
||||
return ''.padEnd(Number(charactersAmount), charactersMap[character]);
|
||||
})(jsonIndentCharacters)
|
||||
};
|
||||
const missingKeysOptions = {
|
||||
dotNotation,
|
||||
addValueForLanguages: addValueForLanguages instanceof Array ? addValueForLanguages : addValueForLanguages ? [addValueForLanguages] : [],
|
||||
mainLanguageToSyncKeys
|
||||
};
|
||||
const report = createI18NReport(vueFiles, languageFiles, command, missingKeysOptions);
|
||||
|
||||
if (detailedReport) {
|
||||
if (report.missingKeys) console.info('missing keys: '), console.table(report.missingKeys);
|
||||
if (report.unusedKeys) console.info('unused keys: '), console.table(report.unusedKeys);
|
||||
if (report.dynamicKeys && dynamic && dynamic > 1) console.info('dynamic detected keys: '), console.table(report.dynamicKeys);
|
||||
}
|
||||
|
||||
if (output) {
|
||||
await writeReportToFile(report, path.resolve(process.cwd(), output));
|
||||
console.log(`The report has been has been saved to ${output}`);
|
||||
}
|
||||
|
||||
const summaryReport = _extends({
|
||||
'Missing keys': getStatisticsForKeys(report.missingKeys).keysNumbers,
|
||||
'Unused keys': getStatisticsForKeys(report.unusedKeys).keysNumbers
|
||||
}, dynamic ? {
|
||||
'Dynamic keys': getStatisticsForKeys(report.dynamicKeys).keysNumbers
|
||||
} : {});
|
||||
|
||||
console.info('\nSummary report:');
|
||||
console.table(summaryReport);
|
||||
|
||||
if (add && report.missingKeys && report.missingKeys.length > 0) {
|
||||
const resolvedLanguageFiles = path.resolve(process.cwd(), languageFiles);
|
||||
writeMissingToLanguage(resolvedLanguageFiles, report.missingKeys, missingKeysOptions, outputOptions);
|
||||
console.log('The missing keys have been added to your languages files');
|
||||
}
|
||||
}
|
||||
|
||||
var report = {
|
||||
__proto__: null,
|
||||
createI18NReport: createI18NReport,
|
||||
reportCommand: reportCommand,
|
||||
readVueFiles: readVueFiles,
|
||||
parseVueFiles: parseVueFiles,
|
||||
writeMissingToLanguage: writeMissingToLanguage,
|
||||
parseLanguageFiles: parseLanguageFiles,
|
||||
get VueI18NExtractReportTypes () { return exports.VueI18NExtractReportTypes; },
|
||||
extractI18NReport: extractI18NReport,
|
||||
extractI18NLangFilesSynchronizationReport: extractI18NLangFilesSynchronizationReport,
|
||||
writeReportToFile: writeReportToFile
|
||||
};
|
||||
|
||||
var index = _extends({}, report);
|
||||
|
||||
exports.createI18NReport = createI18NReport;
|
||||
exports.default = index;
|
||||
exports.extractI18NLangFilesSynchronizationReport = extractI18NLangFilesSynchronizationReport;
|
||||
exports.extractI18NReport = extractI18NReport;
|
||||
exports.parseLanguageFiles = parseLanguageFiles;
|
||||
exports.parseVueFiles = parseVueFiles;
|
||||
exports.readVueFiles = readVueFiles;
|
||||
exports.reportCommand = reportCommand;
|
||||
exports.writeMissingToLanguage = writeMissingToLanguage;
|
||||
exports.writeReportToFile = writeReportToFile;
|
||||
|
||||
})));
|
||||
//# sourceMappingURL=vue-i18n-extract.umd.js.map
|
Loading…
Reference in new issue