From 543123b5e795b367ee6a56d15e7bdcc02f2a8bff Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Wed, 8 Jul 2020 10:53:07 -0400 Subject: [PATCH] feat: add basic xml translator --- scripts/translationScripts/package-lock.json | 56 ++++++++++++++++++ scripts/translationScripts/package.json | 16 ++++++ scripts/translationScripts/qstrConverter.js | 19 +------ scripts/translationScripts/utils.js | 20 +++++++ scripts/translationScripts/xmlTranslator.js | 60 ++++++++++++++++++++ 5 files changed, 155 insertions(+), 16 deletions(-) create mode 100644 scripts/translationScripts/package-lock.json create mode 100644 scripts/translationScripts/package.json create mode 100644 scripts/translationScripts/utils.js create mode 100644 scripts/translationScripts/xmlTranslator.js diff --git a/scripts/translationScripts/package-lock.json b/scripts/translationScripts/package-lock.json new file mode 100644 index 0000000000..cb3302f6cf --- /dev/null +++ b/scripts/translationScripts/package-lock.json @@ -0,0 +1,56 @@ +{ + "name": "translationscripts", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" + }, + "fs-extra": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz", + "integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==", + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" + }, + "jsonfile": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz", + "integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^1.0.0" + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "universalify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", + "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==" + }, + "xml-js": { + "version": "1.6.11", + "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz", + "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==", + "requires": { + "sax": "^1.2.4" + } + } + } +} diff --git a/scripts/translationScripts/package.json b/scripts/translationScripts/package.json new file mode 100644 index 0000000000..35c52b9215 --- /dev/null +++ b/scripts/translationScripts/package.json @@ -0,0 +1,16 @@ +{ + "name": "translationscripts", + "version": "1.0.0", + "description": "These scripts are used to translate the app automatically by reusing the existing translation found in the Status-React repo: https://github.com/status-im/status-react/tree/develop/translations", + "main": "qstrConverter.js", + "dependencies": { + "fs-extra": "^9.0.1", + "xml-js": "^1.6.11" + }, + "devDependencies": {}, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "jrainville", + "license": "ISC" +} diff --git a/scripts/translationScripts/qstrConverter.js b/scripts/translationScripts/qstrConverter.js index 3be1948965..9cf9b6da17 100644 --- a/scripts/translationScripts/qstrConverter.js +++ b/scripts/translationScripts/qstrConverter.js @@ -1,22 +1,9 @@ const fs = require('fs'); -const path = require("path") +const {getAllFiles} = require('./utils'); + const enTranslations = require('./status-react-translations/en.json'); -const getAllFiles = function(dirPath, ext, arrayOfFiles = []) { - const files = fs.readdirSync(dirPath) - - files.forEach(file => { - if (fs.statSync(dirPath + "/" + file).isDirectory()) { - arrayOfFiles = getAllFiles(dirPath + "/" + file, ext, arrayOfFiles) - } else if (!ext || file.endsWith(ext)) { - arrayOfFiles.push(path.join(__dirname, dirPath, "/", file)) - } - }) - - return arrayOfFiles -} - -console.log('Scanning files...') +console.log('Scanning QML files...') const qmlFiles = getAllFiles('../../ui', 'qml'); const translationKeys = Object.keys(enTranslations) diff --git a/scripts/translationScripts/utils.js b/scripts/translationScripts/utils.js new file mode 100644 index 0000000000..9bc57f39bb --- /dev/null +++ b/scripts/translationScripts/utils.js @@ -0,0 +1,20 @@ +const fs = require('fs'); +const path = require("path") + +const getAllFiles = function(dirPath, ext, arrayOfFiles = []) { + const files = fs.readdirSync(dirPath) + + files.forEach(file => { + if (fs.statSync(dirPath + "/" + file).isDirectory()) { + arrayOfFiles = getAllFiles(dirPath + "/" + file, ext, arrayOfFiles) + } else if (!ext || file.endsWith(ext)) { + arrayOfFiles.push(path.join(__dirname, dirPath, "/", file)) + } + }) + + return arrayOfFiles +} + +module.exports = { + getAllFiles +}; diff --git a/scripts/translationScripts/xmlTranslator.js b/scripts/translationScripts/xmlTranslator.js new file mode 100644 index 0000000000..2225be95df --- /dev/null +++ b/scripts/translationScripts/xmlTranslator.js @@ -0,0 +1,60 @@ +const convert = require('xml-js'); +const fs = require('fs'); +const {getAllFiles} = require('./utils'); + +console.log('Scanning TS files...'); +const tsFiles = getAllFiles('../../ui/i18n', 'ts'); + +const options = {compact: true, spaces: 4}; + +tsFiles.forEach(file => { + if (file.endsWith('base.ts')) { + // We skip the base file + return; + } + const fileContent = fs.readFileSync(file).toString(); + + const json = convert.xml2js(fileContent, options); + + const doctype = json["_doctype"]; + const language = json[doctype]._attributes.language; + + let translations; + try { + translations = require(`./status-react-translations/${language}.json`) + } catch (e) { + // No translation file for the exact match, let's use the file name instead + const fileParts = file.split('_'); + console.log('Filep', fileParts); + let langString = fileParts[fileParts.length - 1]; + // Remove the .ts + langString = langString.substring(0, langString.length - 3) + try { + translations = require(`./status-react-translations/${langString}.json`) + } catch (e) { + console.error(`No translation file found for ${language}`); + return; + } + } + + const messages = json[doctype].context.message; + + messages.forEach(message => { + if (!message._attributes || !message._attributes.id) { + return; + } + const messageId = message._attributes.id; + if (!translations[messageId]) { + // Skip this message, as we have no translation + return; + } + + message.translation = { + "_text": translations[messageId] + } + }); + + const xml = convert.js2xml(json, options); + + fs.writeFileSync(file, xml); +});