From 367f6c6ac50056b211bfa6ff4df0acd746bb88ac Mon Sep 17 00:00:00 2001 From: Matteias Collet Date: Fri, 10 Jul 2020 00:57:26 +0200 Subject: [PATCH] add translation comparison script --- package.json | 1 + scripts/compare_translations.js | 56 +++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 scripts/compare_translations.js diff --git a/package.json b/package.json index 48c8cad..b0cd785 100755 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "dev": "yarn codes:inject && vuepress dev site", "build": "yarn codes:inject && vuepress build site", "format": "prettier --write ./site/**/*{.md,.js,.json,.vue}", + "translations:compare": "node ./scripts/compare_translations.js", "codes:inject": "node ./scripts/inject_codes.js && yarn format", "codes:clean": "node ./scripts/clean_codes.js && yarn format" }, diff --git a/scripts/compare_translations.js b/scripts/compare_translations.js new file mode 100644 index 0000000..038a509 --- /dev/null +++ b/scripts/compare_translations.js @@ -0,0 +1,56 @@ +const path = require('path'); +const locales = require(path.join(__dirname, '../site/.vuepress/i18n/locales.json')); + +/** + * Gets all leave nodes from the specified object + * @param {*} node The root node + * @param {*} path The already visited path + */ +const getLeaves = (node, path = null) => { + if (typeof node === 'string') return leavePaths.push(path); + if (typeof node != 'object') throw new Error(typeof node); + const currentPath = path ? `${path}.` : ''; + Object.keys(node).forEach((key) => getLeaves(node[key], `${currentPath}${key}`)); +}; + +/** + * Gets a nested property of the specified node + * @param {*} node The root node + * @param {*} path The property path + */ +const getNestedProperty = (node, path) => { + const props = path.split('.'); + let currentValue = node; + + while (currentValue && props.length > 0) { + currentValue = currentValue[props.shift()]; + } + + return currentValue; +}; + +// Load the translation files +const translations = Object.keys(locales).map((locale) => ({ + lang: locales[locale].lang, + values: require(path.join(__dirname, `../site/.vuepress/i18n/${locales[locale].lang}.json`)), +})); + +// Set the default translation +const defaultTranslation = translations.find((t) => t.lang === locales['/'].lang); +console.log(`Default translation set to ${defaultTranslation.lang}`); + +// Holds the paths to all leave nodes of the default translation +const leavePaths = []; +getLeaves(defaultTranslation.values); +console.log('Detected translations: ', leavePaths); + +// Compare all translations to the default translation +translations.forEach((t) => { + console.log(`Comparing ${t.lang} to ${defaultTranslation.lang}`); + + leavePaths.forEach((p) => { + const value = getNestedProperty(t.values, p); + if (value == null || typeof value !== 'string') + console.warn(`${t.lang} is missing a translation at '${p}'`); + }); +});