Added --translate to MeshCentral server and allow translated custom web pages to be served.

This commit is contained in:
Ylian Saint-Hilaire 2020-01-27 17:52:20 -08:00
parent 3580a8f433
commit 790d5be6e9
4 changed files with 87 additions and 17 deletions

View File

@ -154,19 +154,52 @@ function CreateMeshCentralServer(config, args) {
// Perform web site translations into different languages
if (obj.args.translate) {
// Check if translate.json is in the "meshcentral-data" folder, if so use that and translate default pages.
// TODO
// Check NodeJS version
const NodeJSVer = Number(process.version.match(/^v(\d+\.\d+)/)[1]);
if (NodeJSVer < 8) { console.log("Translation feature requires Node v8 or above, current version is " + process.version + "."); process.exit(); return; }
// Check if translate.json is in the "meshcentral-data" folder, if so use that and translate default pages.
var translationFile = null, customTranslation = false;
if (require('fs').existsSync(obj.path.join(obj.datapath, 'translate.json'))) { translationFile = obj.path.join(obj.datapath, 'translate.json'); console.log("Using translate.json in meshentral-data."); customTranslation = true; }
if (translationFile == null) { if (require('fs').existsSync(obj.path.join(__dirname, 'translate', 'translate.json'))) { translationFile = obj.path.join(__dirname, 'translate', 'translate.json'); console.log("Using default translate.json."); } }
if (translationFile == null) { console.log("Unable to find translate.json."); process.exit(); return; }
// Perform translation operations
var didSomething = false;
process.chdir('./translate');
var translateEngine = require('./translate/translate.js')
if (customTranslation == true) {
// Translate all of the default files using custom translation file
translateEngine.startEx(['', '', 'minifyall']);
translateEngine.startEx(['', '', 'translateall']);
translateEngine.startEx(['', '', 'extractall']);
process.exit();
translateEngine.startEx(['', '', 'translateall', translationFile]);
translateEngine.startEx(['', '', 'extractall', translationFile]);
didSomething = true;
}
// Check is "meshcentral-web" exists, if so, translate all pages in that folder.
// TODO
if (obj.webViewsOverridePath != null) {
didSomething = true;
var files = obj.fs.readdirSync(obj.webViewsOverridePath);
for (var i in files) {
var file = obj.path.join(obj.webViewsOverridePath, files[i]);
if (file.endsWith('.handlebars') && !file.endsWith('-min.handlebars')) {
translateEngine.startEx(['', '', 'translate', '*', translationFile, file, '--subdir:translations']);
}
}
}
if (obj.webPublicOverridePath != null) {
didSomething = true;
var files = obj.fs.readdirSync(obj.webPublicOverridePath);
for (var i in files) {
var file = obj.path.join(obj.webPublicOverridePath, files[i]);
if (file.endsWith('.htm') && !file.endsWith('-min.htm')) {
translateEngine.startEx(['', '', 'translate', '*', translationFile, file, '--subdir:translations']);
}
}
}
if (didSomething == false) { console.log("Nothing to do."); }
process.exit();
return;
}

View File

@ -1,6 +1,6 @@
{
"name": "meshcentral",
"version": "0.4.8-a",
"version": "0.4.8-b",
"keywords": [
"Remote Management",
"Intel AMT",

View File

@ -112,7 +112,7 @@ function startEx(argv) {
log(' EXTRACT [languagefile] [files]');
log(' Extract strings from web pages and generate a language (.json) file.');
log('');
log(' EXTRACTALL');
log(' EXTRACTALL (languagefile)');
log(' Extract all MeshCentral strings from web pages and generate the languages.json file.');
log('');
log(' TRANSLATE [language] [languagefile] [files]');
@ -196,7 +196,15 @@ function startEx(argv) {
}
// Extract or translate all MeshCentral strings
if (command == 'extractall') { extract("translate.json", meshCentralSourceFiles); }
if (command == 'extractall') {
if (argv.length > 4) { lang = argv[4].toLowerCase(); }
var translationFile = 'translate.json';
if (argv.length > 3) {
if (fs.existsSync(argv[3]) == false) { log('Unable to find: ' + argv[3]); return; } else { translationFile = argv[3]; }
}
extract(translationFile, meshCentralSourceFiles, translationFile);
}
if (command == 'translateall') {
if (fs.existsSync('../views/translations') == false) { fs.mkdirSync('../views/translations'); }
if (fs.existsSync('../public/translations') == false) { fs.mkdirSync('../public/translations'); }
@ -226,11 +234,16 @@ function startEx(argv) {
var langFile = argv[4];
if (fs.existsSync(langFile) == false) { log("Missing language file: " + langFile); process.exit(); return; }
var sources = [];
for (var i = 5; i < argv.length; i++) { if (fs.existsSync(argv[i]) == false) { log("Missing file: " + argv[i]); process.exit(); return; } sources.push(argv[i]); }
var sources = [], subdir = null;
for (var i = 5; i < argv.length; i++) {
if (argv[i].startsWith('--subdir:')) {
subdir = argv[i].substring(9);
} else {
if (fs.existsSync(argv[i]) == false) { log("Missing file: " + argv[i]); process.exit(); return; } sources.push(argv[i]);
}
}
if (sources.length == 0) { log("No source files specified."); process.exit(); return; }
translate(lang, langFile, sources, false);
translate(lang, langFile, sources, subdir);
}
if (command == 'minifyall') {
@ -414,7 +427,7 @@ function translateSingleThreaded(lang, langFile, sources, createSubDir) {
try { langFileData = JSON.parse(fs.readFileSync(langFile)); } catch (ex) { }
if ((langFileData == null) || (langFileData.strings == null)) { log("Invalid language file."); process.exit(); return; }
if (lang != null) {
if ((lang != null) && (lang != '*')) {
// Translate a single language
translateEx(lang, langFileData, sources, createSubDir);
} else {
@ -553,7 +566,11 @@ function translateFromHtml(lang, file, createSubDir) {
var outname = file;
var outnamemin = null;
if (createSubDir != null) { outname = path.join(path.dirname(file), createSubDir, path.basename(file)); }
if (createSubDir != null) {
var outfolder = path.join(path.dirname(file), createSubDir);
if (fs.existsSync(outfolder) == false) { fs.mkdirSync(outfolder); }
outname = path.join(path.dirname(file), createSubDir, path.basename(file));
}
if (outname.endsWith('.handlebars')) {
outnamemin = (outname.substring(0, outname.length - 11) + '-min_' + lang + '.handlebars');
outname = (outname.substring(0, outname.length - 11) + '_' + lang + '.handlebars');

View File

@ -4332,7 +4332,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
// Render a page using the proper language
function render(req, res, filename, args) {
if ((obj.parent.webViewsOverridePath == null) && (obj.renderPages != null)) {
if (obj.renderPages != null) {
// If a user set a localization, use that
if ((req.query.lang == null) && (req.session != null) && (req.session.userid)) {
var user = obj.users[req.session.userid];
@ -4375,6 +4375,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
// Get the list of pages with different languages that can be rendered
function getRenderList() {
// Fetch default rendeing pages
var translateFolder = null;
if (obj.fs.existsSync('views/translations')) { translateFolder = 'views/translations'; }
if (obj.fs.existsSync(obj.path.join(__dirname, 'views', 'translations'))) { translateFolder = obj.path.join(__dirname, 'views', 'translations'); }
@ -4395,6 +4396,25 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
}
}
}
// See if there are any custom rending pages that will override the default ones
if (obj.parent.webViewsOverridePath != null) {
translateFolder = null;
if (obj.fs.existsSync(obj.path.join(obj.parent.webViewsOverridePath, 'translations'))) { translateFolder = obj.path.join(obj.parent.webViewsOverridePath, 'translations'); }
var files = obj.fs.readdirSync(translateFolder);
for (var i in files) {
var name = files[i];
if (name.endsWith('.handlebars')) {
name = name.substring(0, name.length - 11);
var xname = name.split('_');
if (xname.length == 2) {
if (obj.renderPages[xname[0]] == null) { obj.renderPages[xname[0]] = {}; }
obj.renderPages[xname[0]][xname[1]] = obj.path.join(translateFolder, name);
if (obj.renderLanguages.indexOf(xname[1]) == -1) { obj.renderLanguages.push(xname[1]); }
}
}
}
}
}
}