dynamicsmobile
Version:
Allows development of off-line mobile and web business apps over the Dynamics Mobile platform. More info on https://www.dynamicsmobile.com
739 lines (628 loc) • 29.9 kB
JavaScript
const fs = require('fs');
const path = require('path');
const chalk = require('chalk');
function mergeLanguageFile(globalArray, filePath, type, fileMustExists) {
if (!globalArray)
throw 'globalArray is required';
if (!filePath)
throw 'filePath is required'
let languageFile;
if (fileMustExists) {
if (!fs.existsSync(filePath)) {
throw new Error(`File ${filePath} does not exists!`);
}
}
if (fs.existsSync(filePath))
languageFile = JSON.parse(fs.readFileSync(filePath, 'utf8'));
if (languageFile) {
for(const key in languageFile){
const existing = globalArray.find(res2 =>{ return res2.name == key });
if (!existing) {
if (type == 'from') {
globalArray.push({
name: key,
from: languageFile[key],
to: ''
});
}
else {
globalArray.push({
name: key,
from: '',
to: languageFile[key]
});
}
}
else {
if (type == 'from') {
existing.from = languageFile[key]
}
else {
existing.to = languageFile[key]
}
}
};
}
}
function readFilesRecursive(srcPath, patternsArray, __allFiles) {
const files = fs.readdirSync(srcPath);
files.forEach(file => {
const stat = fs.lstatSync(path.join(srcPath, file));
if (stat.isDirectory()) {
readFilesRecursive(path.join(srcPath, file), patternsArray, __allFiles);
}
else {
patternsArray.forEach(p => {
if (file.indexOf(p) >= 0) {
__allFiles.push(path.join(srcPath, file));
}
})
}
});
}
const yarg = require("yargs")
.usage('Usage: i18n -- <command> [options]')
.example('export', 'npm run i18n export -- --from en --to fr --file french.csv')
.example('extract', 'npm run i18n extract -- --to fr')
.command('export', 'Exports language translation from json to csv', yarg => {
return yarg
.options("from", { demandOption: true, description: ' source language - the laguage to include as a reference' })
.options("to", { demandOption: true, type: 'string', description: ' target language - language supposed to be translated' })
.options("file", { demandOption: true, type: 'string', description: 'target file path - e.g. the path to the resulting CSV file' })
},
argv => {
const outputPath = `./${argv.file}`;
const arr = [{ id: "$$$header", name: 'Item', from: argv.from, to: argv.to }];
mergeLanguageFile(arr, `./src/locales/${argv.from}.json`, 'from', true);
mergeLanguageFile(arr, `./src/locales/${argv.to}.json`, 'to', false);
mergeLanguageFile(arr, `./ext/locales/${argv.from}.json`, 'from', false);
mergeLanguageFile(arr, `./ext/locales/${argv.to}.json`, 'to', false);
fs.writeFileSync(outputPath, arr.map(element => { return `${element.name},"${element.from}","${element.to}"` }).join('\n'), 'utf8');
})
.command('translate', 'Checks for no translated srings and replaces them with translation resources', yarg => {
return yarg.option('save', { default: false, type: 'boolean' })
},
argv => {
if (!fs.existsSync('./ext')) {
fixNonTranslatedFiles(argv, './src');
}
else {
fixNonTranslatedFiles(argv, './ext');
fixNonTranslatedFiles(argv, './src');
}
})
.command('extract', 'Extracts translation resources from source code and updates the target language file', yarg => {
return yarg.options("to", { demandOption: true, type: 'string' })
.option('override', { default: false, type: 'boolean' })
},
argv => {
console.log(chalk.white.bgBlue.bold(' DMS '), 'Dynamics Mobile i18n is working...');
if (!fs.existsSync('./ext')) {
console.log(chalk.white.bgBlue.bold(' DMS '), chalk.white('Extraction of translation resources from ' + chalk.white.bold('./src/') + ' started...'));
extractTranslatableResourceFromExtensionApp(argv, './ext');
extractTranslatableResourceFromExtensionApp(argv, './src');
}
else {
console.log(chalk.white.bgBlue.bold(' DMS '), chalk.white('Extraction of translation resources from ' + chalk.white.bold('./ext/') + ' started...'));
extractTranslatableResourceFromExtensionApp(argv, './ext');
extractTranslatableResourceFromExtensionApp(argv, './src');
}
})
.command('import', 'Import language translation from csv', yarg => {
return yarg
.options("to", { demandOption: true, type: 'string', description: ' target language - language where the translations will be imported' })
.options("file", { demandOption: true, type: 'string', description: 'source file path - e.g. the path to the souce CSV file' })
.options("col", { demandOption: true, type: 'string', description: 'the number of the column, which contains the translation - 0 is the first column' })
},
argv => {
importLanguageFile(argv);
})
.command('boextract', 'Extracts translation resources from business objects and updates the target language file', yarg => {
return yarg.options("to", { demandOption: true, type: 'string' })
.option('override', { default: false, type: 'boolean' })
},
argv => {
console.log(chalk.white.bgBlue.bold(' DMS '), 'Dynamics Mobile i18n is working...');
if (!fs.existsSync('./ext')) {
console.log(chalk.white.bgBlue.bold(' DMS '), chalk.white('Extraction of BO translation resources from ' + chalk.white.bold('./src/') + ' started...'));
extractBusinessObjectTranslatableResourceFromExtensionApp(argv, './ext');
extractBusinessObjectTranslatableResourceFromExtensionApp(argv, './src');
}
else {
console.log(chalk.white.bgBlue.bold(' DMS '), chalk.white('Extraction of BO translation resources from ' + chalk.white.bold('./ext/') + ' started...'));
extractBusinessObjectTranslatableResourceFromExtensionApp(argv, './ext');
extractBusinessObjectTranslatableResourceFromExtensionApp(argv, './src');
}
})
.command('menuextract', 'Extracts translation resources from menu and updates the target language file', yarg => {
return yarg.options("to", { demandOption: true, type: 'string' })
.option('override', { default: false, type: 'boolean' })
},
argv => {
console.log(chalk.white.bgBlue.bold(' DMS '), 'Dynamics Mobile i18n is working...');
if (!fs.existsSync('./ext')) {
console.log(chalk.white.bgBlue.bold(' DMS '), chalk.white('Extraction of menu translation resources from ' + chalk.white.bold('./src/') + ' started...'));
extractMenuTranslatableResourceFromExtensionApp(argv, './ext');
extractMenuTranslatableResourceFromExtensionApp(argv, './src');
}
else {
console.log(chalk.white.bgBlue.bold(' DMS '), chalk.white('Extraction of menu translation resources from ' + chalk.white.bold('./ext/') + ' started...'));
extractMenuTranslatableResourceFromExtensionApp(argv, './ext');
extractMenuTranslatableResourceFromExtensionApp(argv, './src');
}
})
.command('fromlegacy', 'Extracts legacy translation(./Translations) to new translations (./locales) ', yarg => { },
argv => {
console.log(chalk.white.bgBlue.bold(' DMS '), 'Dynamics Mobile i18n is working...');
var languages = {};
//move translations into locales
//get all translations from the src folder
const translations = fs.readdirSync(path.resolve('./src/Translations'));
for (const translation of translations) {
const translationFilePath = path.resolve('./src/Translations', translation);
const translationFile = fs.readFileSync(translationFilePath);
const translationContent = JSON.parse(translationFile);
const localeCode = translation.split('.')[0];
if (!languages[localeCode]) {
languages[localeCode] = {};
}
console.log('************', translationContent.resources);
translationContent.resources.forEach(element => {
languages[localeCode][element.name] = element.text;
});
const p = path.resolve(path.resolve('./src/locales'), `${localeCode}.json`);
console.log('************', p);
fs.writeFileSync(p, JSON.stringify(languages[localeCode]))
}
console.log(chalk.white.bgBlue.bold(' DMS '), 'Dynamics Mobile i18n work completed...');
})
.demandCommand()
.recommendCommands()
.showHelpOnFail()
.command({
command: '*',
handler() {
console.log(chalk.white.bgRed(' DMS '), chalk.red('ERROR: Please provide a valid command'));
}
})
.argv;
function importLanguageFile(argv) {
const sourceCSVFilePath = argv.file.trim().replace(/"/g, '');
let targetLangFilePath = `./src/locales/${argv.to}.json`;
const col = parseInt(argv.col);
console.log(chalk.white.bgBlue.bold(' DMS '), chalk.white(`Importing "${sourceCSVFilePath}" into language file "${targetLangFilePath}"`));
if (!fs.existsSync(sourceCSVFilePath)) {
console.log(chalk.white.bgRed.bold(' DMS '), chalk.white(`Source CSV file "${sourceCSVFilePath}" does not exists!"`));
process.exit(1);
}
if (fs.existsSync('./ext/locales'))
targetLangFilePath = `./ext/locales/${argv.to}.json`;
if (!col || col <= 0) {
console.log(chalk.white.bgRed.bold(' DMS '), chalk.white(`Argument "col" must be integer greater than 0`));
process.exit(1);
}
//load target language, if any
let targetLanguageContent = {};
if (fs.existsSync(targetLangFilePath))
targetLanguageContent = JSON.parse(fs.readFileSync(targetLangFilePath));
//load csv
const csvText = fs.readFileSync(sourceCSVFilePath, 'utf8');
const csvLines = csvText.split('\n');
let newResourcesCount = 0;
let existingResourcesCount = 0;
csvLines.forEach((line, lineIndex) => {
if (lineIndex == 0)
return;
const columns = line.split(',');
let resourceId;
let translated;
columns.forEach((column, colIndex) => {
const colText = column.trim().replace(/"/g, '');
if (colIndex == 0) {
resourceId = colText;
}
if (colIndex == col) {
translated = colText;
}
});
if (resourceId && translated) {
const targetItem = targetLanguageContent[resourceId];
if (targetItem) {
targetItem = translated;
existingResourcesCount++;
}
else {
newResourcesCount++
targetLanguageContent[resourceId]= translated;
}
}
});
console.log(chalk.white.bgBlue.bold(' DMS '), chalk.white(`Importing completed to lang "${argv.to}". Added resources: ${newResourcesCount}, Updated resources: ${existingResourcesCount}`));
if (argv.dump) {
console.log('Dumping resources:');
console.log(`#\tid\t\t\t${argv.to}`);
console.log(`----------------------------------`);
for(const key in targetLanguageContent){
console.log(`${key}\t${targetLanguageContent[key]}`);
}
}
fs.writeFileSync(targetLangFilePath, JSON.stringify(targetLanguageContent));
}
//find non translated strings in all HTML files and shows them in the console
//optionally replaces them in the files
function fixNonTranslatedFiles(argv, srcPath) {
if (!fs.existsSync(srcPath))
return;
const files = [];
readFilesRecursive(srcPath, ['.ts', '.html'], files);
//const regex2 = new RegExp('>[a-zA-Z0-9]+</[^i]', 'g');
// ([a-zA-Z\u0020]*>)([a-zA-Z0-9\u0020.!-#$&=|]+)(?=<\cls/[^i]{1})
const regex2 = new RegExp('<([\\w]+)[^>]*>([0-9a-zA-Z._\\u0020-!? :]+)</\\1>', 'g');
let detectedFiles = 0;
let detectedResources = 0;
files.forEach(file => {
let content = fs.readFileSync(file, 'utf8');
const fileReplacements = [];
if (file.indexOf('.html') > 0) {
//test for strings which needs to be made as translation resources
while ((m2 = regex2.exec(content)) !== null) {
// This is necessary to avoid infinite loops with zero-width matches
if (m2.index === regex2.lastIndex) {
regex2.lastIndex++;
}
const match = m2[2];
const tag = m2[1].trim();
if (tag.length = 0 || match.length == 0 || match == '.' || match == '..' || match == '...' || tag == 'i')
continue;
if (match.trim() == '')
continue;
const id = "txt" + match.replace(/[\u0020.-]/g, '').replace(':', '').replace(' ', '');
const obj = { id: id, text: `>${match}</`, toReplace: `>{#${id}#}</` };
fileReplacements.push(obj);
detectedResources++
}
if (fileReplacements.length) {
detectedFiles++;
console.log('');
console.log(chalk.white.bgBlue(' DMS '), chalk.white.bgBlack(`Non-translated strings in: ${file}`));
fileReplacements.forEach(obj => {
console.log(` ${obj.text.replace(/[<>/]/g, '')} => ${obj.toReplace.replace(/[<>/]/g, '')}`);
});
}
//console.log('');
if (argv.save) {
fileReplacements.forEach(element => {
content = content.replace(element.text, element.toReplace);
});
//console.log('saving ', file);
fs.writeFileSync(file, content, 'utf8');
}
}
});
console.log(chalk.white.bgBlack(' DMS '), chalk.white.bgBlack(`Detected ${detectedResources} non-translated strings in ${detectedFiles} files`));
if (argv.save) {
}
else {
console.log(chalk.white.bgBlack(' DMS '), chalk.white.bgBlack('Changes were not saved. Use --save command line option to force saving'));
}
}
// function extractTranslatableResourceFromSourceApp(argv) {
// const srcPath = './src'
// if (!fs.existsSync(srcPath))
// return;
// const files = [];
// readFilesRecursive(srcPath,['.ts','.html'], files);
// const allTranslationResourcesFromSourceCode = [];
// const regex = new RegExp('\{#[a-zA-Z0-9]*#\}', 'g');
// files.forEach(file => {
// const content = fs.readFileSync(file, 'utf8');
// //test for existing translation resources
// while ((m1 = regex.exec(content)) !== null) {
// // This is necessary to avoid infinite loops with zero-width matches
// if (m1.index === regex.lastIndex) {
// regex.lastIndex++;
// }
// // The result can be accessed through the `m`-variable.
// m1.forEach((match, groupIndex) => {
// //console.log(`Found match, group ${groupIndex}: ${match}`);
// const index = allTranslationResourcesFromSourceCode.indexOf(match);
// if (index < 0)
// allTranslationResourcesFromSourceCode.push(match);
// });
// }
// });
// const targetLanguageFilePath = path.join(srcPath, 'Translations', `${argv.to}.lang.json`);
// let targetLanguageContent;
// if (fs.existsSync(targetLanguageFilePath) && !argv.override) {
// targetLanguageContent = JSON.parse(fs.readFileSync(targetLanguageFilePath));
// }
// else {
// targetLanguageContent = { resources: [] };
// }
// let resourcesTranslatedCount = 0;
// const actualOutput = targetLanguageContent;
// allTranslationResourcesFromSourceCode.forEach(r => {
// const found = actualOutput.resources.find(rt => { return rt.name == (r.replace('{#', '').replace('#}', '')) });
// if (!found) {
// actualOutput.resources.push({ name: r.replace('{#', '').replace('#}', ''), text: "" });
// resourcesTranslatedCount++;
// }
// });
// fs.writeFileSync(targetLanguageFilePath, JSON.stringify(actualOutput), 'utf8');
// console.log(chalk.white.bgBlue.bold(' DMS '), chalk.white(`Extraction to language file "${targetLanguageFilePath}" was created successfully with ${resourcesTranslatedCount} new resources and total of ${actualOutput.resources.length} resources`));
// }
function extractTranslatableResourceFromExtensionApp(argv, srcPath) {
if (!fs.existsSync(srcPath))
return;
const files = [];
readFilesRecursive(srcPath, ['.ts', '.html'], files);
const allTranslationResourcesFromSourceCode = [];
const regex = new RegExp('\{#[a-zA-Z0-9 ]*#\}', 'g');
//console.log('files: ', files);
files.forEach(file => {
const content = fs.readFileSync(file, 'utf8');
//test for existing translation resources
while ((m1 = regex.exec(content)) !== null) {
// This is necessary to avoid infinite loops with zero-width matches
if (m1.index === regex.lastIndex) {
regex.lastIndex++;
}
// The result can be accessed through the `m`-variable.
m1.forEach((match, groupIndex) => {
//console.log(`Found match, group ${groupIndex}: ${match}`);
const index = allTranslationResourcesFromSourceCode.indexOf(match);
if (index < 0)
allTranslationResourcesFromSourceCode.push(match);
});
}
});
const targetLanguageFilePath = path.join(srcPath, 'locales', `${argv.to}.json`);
let alreadyTranslateResources;
//load existing resources
if (fs.existsSync(targetLanguageFilePath) && !argv.override) {
alreadyTranslateResources = JSON.parse(fs.readFileSync(targetLanguageFilePath));
}
else {
alreadyTranslateResources = { };
}
const actualOutput = {};
for(const key in alreadyTranslateResources){
actualOutput[key] = alreadyTranslateResources[key];
}
let resourcesTranslatedCount = 0;
allTranslationResourcesFromSourceCode.forEach(r => {
const found = alreadyTranslateResources[r.replace('{#', '').replace('#}', '')];
if (!found) {
actualOutput[r.replace('{#', '').replace('#}', '')] = "";
resourcesTranslatedCount++;
}
});
fs.writeFileSync(targetLanguageFilePath, JSON.stringify(actualOutput), 'utf8');
console.log(chalk.white.bgBlue.bold(' DMS '), chalk.white(`Extraction to language file "${targetLanguageFilePath}" was created successfully with ${resourcesTranslatedCount} new resources and total of ${actualOutput.resources.length} resources`));
}
function escapeTranslationResName(name) {
if (!name)
return "[unknown]";
return name.replace(/-/g, '_').replace(/ /g, '_').replace(/\./g, '').replace(/%/g, '').replace(/#/g, '');
}
function applyResourceOnEntity(bo, itemType, isPlural, name, label, allTranslationResourcesFromSourceCode, allTranslationLabelsFromSourceCode) {
//console.log(bo,'=>', itemType);
let hasChanges = false;
let newLabel;
if (label && label.indexOf('{#') < 0) {
//there is non-translated label
hasChanges = true;
if (itemType == 'entity') {
newLabel = `{#e${bo.name}${isPlural ? '_plural' : ''}#}`
}
else
if (itemType == 'menu') {
newLabel = `{#menu${escapeTranslationResName(label)}#}`
}
else {
//field
newLabel = `{#ef${bo.name}_${escapeTranslationResName(label)}#}`
}
}
else
if (!label) {
//no label at all
hasChanges = true;
if (itemType == 'entity') {
newLabel = `{#e${bo.name}${isPlural ? '_plural' : ''}#}`
}
else
if (itemType == 'menu') {
newLabel = `{#menu${escapeTranslationResName(name)}#}`
}
else {
//field
newLabel = `{#ef${bo.name}_${escapeTranslationResName(name)}#}`
}
}
else {
//there is translated label
hasChanges = false;
newLabel = label;
}
//console.log(originalLabel,',',newLabel);
const index = allTranslationResourcesFromSourceCode.indexOf(newLabel);
if (index < 0) {
let x = label ? label : name;
if (x && x.indexOf('{#') >= 0) {
//handle view groups
x = x.replace('{#', '').replace('#}', '');
}
if (!x || x == 'label' || x.indexOf('{#') >= 0) {
console.log(bo.name, '=>', itemType, ' ', x, ' ', label, ' ', name)
throw new Error('oops')
}
allTranslationResourcesFromSourceCode.push(newLabel);
allTranslationLabelsFromSourceCode.push(x)
}
//console.log({ hasChanges: hasChanges, label: newLabel })
return { hasChanges: hasChanges, label: newLabel };
}
function extractBusinessObjectTranslatableResourceFromExtensionApp(argv, srcPath) {
if (!fs.existsSync(srcPath))
return;
const files = [];
readFilesRecursive(srcPath, ['.bo.json'], files);
const allTranslationResourcesFromSourceCode = [];
const allTranslationLabelsFromSourceCode = [];
let hasChanges = false;
files.forEach(file => {
const content = fs.readFileSync(file, 'utf8');
const entityName = path.basename(file).split('.')[0];
const bo = JSON.parse(content)[entityName];
//console.log('***', entityName, '***')
//entity label
var changes = applyResourceOnEntity(bo, 'entity', false, bo.name, bo.label, allTranslationResourcesFromSourceCode, allTranslationLabelsFromSourceCode);
if (changes.hasChanges) {
bo.label = changes.label;
hasChanges = true;
}
//entity plural label
changes = applyResourceOnEntity(bo, 'entity', true, bo.name, bo.pluralLabel, allTranslationResourcesFromSourceCode, allTranslationLabelsFromSourceCode);
if (changes.hasChanges) {
bo.pluralLabel = changes.label;
hasChanges = true;
}
//entity properties
for (const propName in bo.properties) {
changes = applyResourceOnEntity(bo, 'entityfield', false, propName, bo.properties[propName].label, allTranslationResourcesFromSourceCode, allTranslationLabelsFromSourceCode);
if (changes.hasChanges) {
bo.properties[propName].label = changes.label;
hasChanges = true;
}
}
//view props and groups
for (const viewName in bo.views) {
const v = bo.views[viewName];
v.properties.forEach(p => {
if (p.type == 'group') {
changes = applyResourceOnEntity(bo, 'group', false, p.name, p.name, allTranslationResourcesFromSourceCode, allTranslationLabelsFromSourceCode);
if (changes.hasChanges) {
p.name = changes.label;
hasChanges = true;
}
}
else {
changes = applyResourceOnEntity(bo, 'viewfield', false, p.name, p.label, allTranslationResourcesFromSourceCode, allTranslationLabelsFromSourceCode);
if (changes.hasChanges) {
p.label = changes.label;
hasChanges = true;
}
}
})
}
if (hasChanges) {
console.log('Writing ', file)
const newBO = {};
newBO[entityName] = bo;
fs.writeFileSync(file, JSON.stringify(newBO));
}
});
const targetLanguageFilePath = path.join(srcPath, 'locales', `${argv.to}.json`);
let alreadyTranslateResources;
//load ext
if (fs.existsSync(targetLanguageFilePath) && !argv.override) {
alreadyTranslateResources = JSON.parse(fs.readFileSync(targetLanguageFilePath));
}
else {
alreadyTranslateResources = { };
}
const actualOutput = alreadyTranslateResources;
//load and add existing ./src
const content = JSON.parse(fs.readFileSync(path.join(srcPath, 'locales', `${argv.to}.json`)));
for(const srcKey in content){
const found = alreadyTranslateResources[srcKey];
if (!found) {
alreadyTranslateResources[srcKey] = ''
} else {
}
};
throw new Error('the code is not finished yet for the new locales feature....')
// let resourcesTranslatedCount = 0;
// for(const srcKey in allTranslationResourcesFromSourceCode){
// const found = alreadyTranslateResources.resources.find(rt => { return rt.name == (r.replace('{#', '').replace('#}', '')) });
// if (!found) {
// actualOutput.resources.push({ name: r.replace('{#', '').replace('#}', ''), text: allTranslationLabelsFromSourceCode[index] });
// resourcesTranslatedCount++;
// }
// };
// fs.writeFileSync(targetLanguageFilePath, JSON.stringify(actualOutput), 'utf8');
// console.log(chalk.white.bgBlue.bold(' DMS '), chalk.white(`Extraction to language file "${targetLanguageFilePath}" was created successfully with ${resourcesTranslatedCount} new resources and total of ${actualOutput.resources.length} resources`));
}
var globalHashChanges = false;
function processMenuItem(menuItem, hasChanges, allTranslationResourcesFromSourceCode, allTranslationLabelsFromSourceCode) {
var changes = applyResourceOnEntity(menuItem, 'menu', false, menuItem.taskId, menuItem.label, allTranslationResourcesFromSourceCode, allTranslationLabelsFromSourceCode);
if (changes.hasChanges) {
menuItem.label = changes.label;
globalHashChanges = true;
}
if (menuItem.items) {
menuItem.items.forEach(i => {
var ch = processMenuItem(i, true, allTranslationResourcesFromSourceCode, allTranslationLabelsFromSourceCode);
});
}
return true;
}
function extractMenuTranslatableResourceFromExtensionApp(argv, srcPath) {
if (!fs.existsSync(srcPath))
return;
const files = [];
readFilesRecursive(srcPath, ['root-menu.json'], files);
const allTranslationResourcesFromSourceCode = [];
const allTranslationLabelsFromSourceCode = [];
let hasChanges = true;
files.forEach(file => {
const content = fs.readFileSync(file, 'utf8');
const menu = JSON.parse(content);
menu.items.forEach(
i => {
var changes = processMenuItem(i, true, allTranslationResourcesFromSourceCode, allTranslationLabelsFromSourceCode);
hasChanges = hasChanges & changes;
}
);
menu.quickItems.forEach(
i => {
var changes = processMenuItem(i, true, allTranslationResourcesFromSourceCode, allTranslationLabelsFromSourceCode);
hasChanges = hasChanges & changes;
}
);
if (globalHashChanges) {
console.log('Writing ', file)
fs.writeFileSync(file, JSON.stringify(menu));
}
});
const targetLanguageFilePath = path.join(srcPath, 'locales', `${argv.to}.json`);
let alreadyTranslateResources;
//load ext
if (fs.existsSync(targetLanguageFilePath) && !argv.override) {
alreadyTranslateResources = JSON.parse(fs.readFileSync(targetLanguageFilePath));
}
else {
alreadyTranslateResources = { };
}
const actualOutput = alreadyTranslateResources;
//load and add existing ./src
const content = JSON.parse(fs.readFileSync(path.join(srcPath, 'locales', `${argv.to}.json`)));
for(const sourceKey in content){
const found = alreadyTranslateResources[sourceKey];
if (!found) {
alreadyTranslateResources[sourceKey]='';
} else {
}
};
let resourcesTranslatedCount = 0;
allTranslationResourcesFromSourceCode.forEach((r, index) => {
const found = alreadyTranslateResources[r.replace('{#', '').replace('#}', '')];
if (!found) {
actualOutput[r.replace('{#', '').replace('#}', '')]=allTranslationLabelsFromSourceCode[index];
resourcesTranslatedCount++;
}
});
fs.writeFileSync(targetLanguageFilePath, JSON.stringify(actualOutput), 'utf8');
console.log(chalk.white.bgBlue.bold(' DMS '), chalk.white(`Extraction to language file "${targetLanguageFilePath}" was created successfully with ${resourcesTranslatedCount} new resources and total of ${actualOutput.resources.length} resources`));
}