diff --git a/package.json b/package.json index 4742906..602869d 100644 --- a/package.json +++ b/package.json @@ -67,14 +67,13 @@ }, "scripts": { "start": "npm run build-css && npm-run-all -p watch-css start-js", - "start-js": "react-scripts start", + "start-js": "npm run generate-language-list && react-scripts start", "start-fake": "npm run make-fake-data && REACT_APP_FAKE_API=1 npm run start", "build": "npm-run-all build-css build-js", "build-fake": "npm run make-fake-data && REACT_APP_FAKE_API=1 npm run build", - "build-js": "react-scripts build", + "build-js": "npm run generate-language-list && react-scripts build", "build-css": "node-sass-chokidar --include-path ./node_modules ./src/scss -o ./src/scss", "watch-css": "node-sass-chokidar --include-path ./node_modules ./src/scss -o ./src/scss --watch --recursive", - "update-translations": "node scripts/update-translations.js && npm run generate-language-list", "generate-language-list": "node scripts/generate-language-list.js", "make-fake-data": "node scripts/make-fake-data.js", "test": "react-scripts test --env=jsdom", diff --git a/scripts/update-translations.js b/scripts/update-translations.js deleted file mode 100644 index a830aab..0000000 --- a/scripts/update-translations.js +++ /dev/null @@ -1,169 +0,0 @@ -/* Pi-hole: A black hole for Internet advertisements - * (c) 2019 Pi-hole, LLC (https://pi-hole.net) - * Network-wide ad blocking via your own hardware. - * - * Web Interface - * Update translations from POEditor - * - * This file is copyright under the latest version of the EUPL. - * Please see LICENSE file for your rights under this license. */ - -const fs = require("fs-extra"); -const fetch = require("node-fetch"); -const MultiProgress = require("multi-progress"); - -const PROJECT_ID = 66305; -const I18N_FOLDER = "public/i18n"; - -const multi = new MultiProgress(process.stderr); - -const apiToken = process.env.POEDITOR_API_TOKEN; - -if (!apiToken) { - console.log("Please set the POEDITOR_API_TOKEN environment variable"); - process.exit(1); -} - -/** - * Convert a key-value map into a format for application/x-www-form-urlencoded - * - * @param data the key-value map - * @returns {string} the encoded data - */ -function makeFormData(data) { - return Object.keys(data) - .map(key => `${key}=${data[key]}`) - .join("&"); -} - -/** - * Return a list of languages which are at least 90% translated - */ -function getTranslatedLanguages() { - return fetch("https://api.poeditor.com/v2/languages/list", { - method: "POST", - body: makeFormData({ - api_token: apiToken, - id: PROJECT_ID - }), - headers: { "Content-Type": "application/x-www-form-urlencoded" } - }) - .then(response => response.json()) - .then(data => { - return data.result.languages - .filter(lang => lang.percentage >= 70) - .map(lang => lang.code); - }); -} - -/** - * Fetch a list of tagged strings from a language - * - * @param lang the language code - * @param tag the tag - * @param bar the progress bar - */ -function fetchTag(lang, tag, bar) { - fetch("https://api.poeditor.com/v2/projects/export", { - method: "POST", - body: makeFormData({ - api_token: apiToken, - id: PROJECT_ID, - language: lang, - type: "json", - tags: tag - }), - headers: { "Content-Type": "application/x-www-form-urlencoded" } - }) - .then(exportResponse => { - bar.tick(); - return exportResponse.json(); - }) - .then(exportData => fetch(exportData.result.url)) - .then(langResponse => { - bar.tick(); - return langResponse.json(); - }) - .then(langData => { - const parsedData = langData.reduce((map, item) => { - // Check for plurals - if (typeof item.definition === "string") { - map[item.term] = item.definition; - } else if (item.definition === null) { - // Don't add missing strings. They will be loaded from the fallback language. - return map; - } else { - // Check if there's just singular and plural - if (Object.keys(item.definition).length === 2) { - map[item.term] = item.definition["one"]; - map[item.term + "_plural"] = item.definition["other"]; - } else { - // Map POEditor's plural keys to i18next's plural suffixes - const pluralMap = { - zero: "0", - one: "1", - two: "2", - few: "3", - many: "4", - other: "5" - }; - - // Add the various plural keys - for (let plural of Object.keys(item.definition)) - map[item.term + "_" + pluralMap[plural]] = - item.definition[plural]; - } - } - - return map; - }, {}); - - fs.outputFileSync( - `${I18N_FOLDER}/${lang}/${tag}.json`, - JSON.stringify(parsedData, null, 4) - ); - bar.tick(); - }); -} - -/** - * Fetch all the tags of the language. - * - * @param lang the language - */ -function fetchAllTags(lang) { - const tags = [ - "common", - "location", - "dashboard", - "query-log", - "lists", - "login", - "footer", - "settings", - "api-errors", - "preferences" - ]; - - const bar = multi.newBar(`${lang}\t:percent\t[:bar]`, { - // 3 steps per tag: export, download, and parse - total: 3 * tags.length - }); - - // Render at 0% - bar.tick(0); - - for (const tag of tags) fetchTag(lang, tag, bar); -} - -// Remove old translations -console.log("Deleting old translations"); -fs.emptyDirSync(I18N_FOLDER); - -// Get the translated languages and download the translations -console.log("Fetching languages"); -getTranslatedLanguages().then(languages => { - console.log(`Languages over 70% translated: ${languages.join(", ")}`); - - for (const lang of languages) fetchAllTags(lang); -}); diff --git a/src/languages.json b/src/languages.json index 21c0eb4..b3de7b9 100644 --- a/src/languages.json +++ b/src/languages.json @@ -1 +1 @@ -["bg","ca","de","en","es","fr","it","pt","tr"] \ No newline at end of file +["ar","bg","ca","cs","da","de","el","en","es","fr","he","hr","hu","it","nl","pl","pt","ro","sk","sl","sv","tr","zh"] \ No newline at end of file