From a66e87823c005bd5c4e73828347e4d382409f43c Mon Sep 17 00:00:00 2001 From: Timo Bejan Date: Tue, 22 Sep 2020 10:42:23 +0300 Subject: [PATCH] automatic i18n translation using google api --- workspace.json => angular.json | 0 package-lock.json | 0 tools/auto-i18n/README.md | 4 + tools/auto-i18n/translate.js | 115 ++++++++++++++++++++++++++ tools/auto-i18n/translateCache-de.txt | 33 ++++++++ 5 files changed, 152 insertions(+) rename workspace.json => angular.json (100%) delete mode 100644 package-lock.json create mode 100644 tools/auto-i18n/README.md create mode 100644 tools/auto-i18n/translate.js create mode 100644 tools/auto-i18n/translateCache-de.txt diff --git a/workspace.json b/angular.json similarity index 100% rename from workspace.json rename to angular.json diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index e69de29bb..000000000 diff --git a/tools/auto-i18n/README.md b/tools/auto-i18n/README.md new file mode 100644 index 000000000..4ead3c221 --- /dev/null +++ b/tools/auto-i18n/README.md @@ -0,0 +1,4 @@ +# Run Example +node translate.js ./../../apps/red-ui/src/assets/i18n/en.json de +# API KEY +AIzaSyC2fOUHLV6nhmCSwKcacaNqumn20k8Ic_M diff --git a/tools/auto-i18n/translate.js b/tools/auto-i18n/translate.js new file mode 100644 index 000000000..10c02b172 --- /dev/null +++ b/tools/auto-i18n/translate.js @@ -0,0 +1,115 @@ +#!/usr/bin/env node + +const fs = require('fs'); +const moment = require('moment'); +const _ = require('lodash'); +const path = require('path'); +const agent = require('superagent-promise')(require('superagent'), Promise); +const { translate } = require("google-translate-api-browser"); +let dicc = {}; + +//Lang Codes https://ctrlq.org/code/19899-google-translate-languages + +if (process.argv.length >= 4) { + + //Args + const inputFile = process.argv[2]; + const destinationCodes = process.argv[3].split(','); + const apiKey = process.argv.length > 4 && process.argv[4]; + + const apiUrl = _.template('https://www.googleapis.com/language/translate/v2?key=<%= apiKey %>&q=<%= value %>&source=en&target=<%= languageKey %>'); + + const transformResponse = (res) => { + return _.get(JSON.parse(res.text), ['data', 'translations', 0, 'translatedText'], ''); + } + + const getCache = (languageKey) => { + try { + dicc[languageKey] = {}; + let fileContent = fs.readFileSync(`./translateCache-${languageKey}.txt`, 'utf-8').split('\n'); + fileContent.map((line)=> { + let cached = line.split('|'); + if(cached[0]) dicc[languageKey][cached[0]] = cached[1]; + }); + } catch (error) { + + } + } + const cachedIndex = (key, value, languageKey) => { + const line = key + '|' + value + '\n'; + dicc[languageKey][key] = value; + fs.appendFileSync(`./translateCache-${languageKey}.txt`, line); + return value; + } + + function iterLeaves(value, keyChain, accumulator, languageKey) { + accumulator = accumulator || {}; + keyChain = keyChain || []; + if (_.isObject(value)) { + return _.chain(value).reduce((handlers, v, k) => { + return handlers.concat(iterLeaves(v, keyChain.concat(k), accumulator, languageKey)); + }, []).flattenDeep().value(); + } else { + if(typeof value !== 'string') + return value; + + return function () { + if(!(value in dicc[languageKey])) { + console.log(_.template('Translating <%= value %> to <%= languageKey %>')({value, languageKey})); + + let prom; + //Translates individual string to language code + if(apiKey != '') { + //using apiKey + prom = agent('GET', apiUrl({ + value: encodeURI(value), + languageKey, + apiKey + })).then(transformResponse) + } + else { + //using free api key + prom = translate(value, { to: languageKey }) + } + + return prom.then((res) => cachedIndex(value, res, languageKey)) + .catch((err) => console.log(err)) + .then((text) => { + //Sets the value in the accumulator + _.set(accumulator, keyChain, text); + + //This needs to be returned to it's eventually written to json + return accumulator; + }); + } + else { + console.log(value + ' cached: ' + dicc[languageKey][value]); + _.set(accumulator, keyChain, dicc[languageKey][value]); + return accumulator; + } + }; + } + } + + Promise.all(_.reduce(destinationCodes, (sum, languageKey) => { + const fileName = _.template('./<%= languageKey %>-<%= timeStamp %>.json')({ + languageKey, + timeStamp: moment().unix() + }); + + //read languageKey Cache. + getCache(languageKey); + + //Starts with the top level strings + return sum.concat(_.reduce(iterLeaves(JSON.parse(fs.readFileSync(path.resolve(inputFile), 'utf-8')), undefined, undefined, languageKey), (promiseChain, fn) => { + return promiseChain.then(fn); + }, Promise.resolve()).then((payload) => { + fs.writeFileSync(fileName, JSON.stringify(payload)); + }).then(_.partial(console.log, 'Successfully translated all nodes, file output at ' + fileName))); + }, [])).then(() => { + process.exit(); + }); + +} else { + console.error('You must provide an input json file and a comma-separated list of destination language codes.'); +} diff --git a/tools/auto-i18n/translateCache-de.txt b/tools/auto-i18n/translateCache-de.txt new file mode 100644 index 000000000..8d926fee3 --- /dev/null +++ b/tools/auto-i18n/translateCache-de.txt @@ -0,0 +1,33 @@ +Confirm Action|Aktion bestätigen +This action requires confirmation, do you wish to proceed?|Diese Aktion muss bestätigt werden. Möchten Sie fortfahren? +Yes|Ja +No|Nein +Projects|Projekte +My Account|Mein Konto +Logout|Ausloggen +New Project|Neues Projekt +Edit Project|Projekt bearbeiten +Description|Beschreibung +Name|Name +Save Project|Projekt speichern +You currently have no projects. You can start your work by creating a new one!|Sie haben derzeit keine Projekte. Sie können Ihre Arbeit beginnen, indem Sie eine neue erstellen! +Download Redaction Report|Redaktionsbericht herunterladen +Sorting|Sortierung +Last Updated (Desc)|Zuletzt aktualisiert (Beschreibung) +Last Updated (Asc)|Zuletzt aktualisiert (Asc) +Name (Desc)|Name (Beschreibung) +Failed to delete file: {{filename}}|Fehler beim Löschen der Datei: {{Dateiname}} +Status: {{status}}|Status: {{status}} +Number of pages: {{numberOfPages}}|Anzahl der Seiten: {{numberOfPages}} +Analysis count: {{numberOfAnalyses}}|Anzahl der Analysen: {{numberOfAnalyses}} +Last updated: {{lastUpdated}}|Letzte Aktualisierung: {{lastUpdated}} +Project Overview|Projektübersicht +Upload Files|Daten hochladen +Requested project: {{projectId}} does not exist! Back to Project Listing. |Angefordertes Projekt: {{projectId}} existiert nicht! Zurück zur Projektliste. +Failed to delete project: {{projectName}}|Projekt konnte nicht gelöscht werden: {{projectName}} +File Details|Dateidetails +Date added: {{added}}|Datum hinzugefügt: {{hinzugefügt}} +Failed to upload file: {{name}}|Datei konnte nicht hochgeladen werden: {{name}} +Language|Sprache +English|Englisch +German|Deutsche