From 8d9ef716fef86b4bb2a27d61112c4df955e532aa Mon Sep 17 00:00:00 2001 From: Josh Hunt Date: Wed, 11 Oct 2023 09:26:39 +0000 Subject: [PATCH] I18N: Collect stats on number of untranslated strings in message catalogues (#76272) * I18N: Collect stats on number of untranslated strings in message catalogues * eachLeaf -> eachMessage * use __dirname --- package.json | 1 + scripts/ci-frontend-metrics.sh | 8 +++ scripts/cli/reportI18nStats.mjs | 88 +++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 scripts/cli/reportI18nStats.mjs diff --git a/package.json b/package.json index cc695fb4f66..39cb8f06f81 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "i18n:extract": "yarn run i18next -c public/locales/i18next-parser.config.js 'public/**/*.{tsx,ts}' 'packages/grafana-ui/**/*.{tsx,ts}' && yarn i18n:pseudo", "i18n:compile": "echo 'no i18n compile yet, all good'", "i18n:pseudo": "node ./public/locales/pseudo.js", + "i18n:stats": "node ./scripts/cli/reportI18nStats.mjs", "betterer": "betterer", "betterer:merge": "betterer merge", "betterer:stats": "ts-node --transpile-only --project ./scripts/cli/tsconfig.json ./scripts/cli/reportBettererStats.ts", diff --git a/scripts/ci-frontend-metrics.sh b/scripts/ci-frontend-metrics.sh index 1817697ec16..7fec6a1c3fc 100755 --- a/scripts/ci-frontend-metrics.sh +++ b/scripts/ci-frontend-metrics.sh @@ -46,6 +46,13 @@ do BETTERER_STATS+="\"grafana.ci-code.betterer.${name}\": \"${value}\"," done <<< "$(yarn betterer:stats)" +I18N_STATS="" +while read -r name value +do + I18N_STATS+=$'\n ' + I18N_STATS+="\"grafana.ci-code.i18n.${name}\": \"${value}\"," +done <<< "$(yarn i18n:stats)" + THEME_TOKEN_USAGE="" while read -r name value do @@ -56,6 +63,7 @@ done <<< "$(yarn themes:usage | awk '$4 == "@grafana/theme-token-usage" {print $ echo "Metrics: { $THEME_TOKEN_USAGE $BETTERER_STATS + $I18N_STATS \"grafana.ci-code.strictErrors\": \"${ERROR_COUNT}\", \"grafana.ci-code.accessibilityErrors\": \"${ACCESSIBILITY_ERRORS}\", \"grafana.ci-code.directives\": \"${DIRECTIVES}\", diff --git a/scripts/cli/reportI18nStats.mjs b/scripts/cli/reportI18nStats.mjs new file mode 100644 index 00000000000..b34b5074ea6 --- /dev/null +++ b/scripts/cli/reportI18nStats.mjs @@ -0,0 +1,88 @@ +/// @ts-check + +import { readdir, stat, readFile } from 'fs/promises'; +import path, { dirname } from 'path'; +import { fileURLToPath } from 'url'; + +const LOCALES_DIR = path.resolve(dirname(fileURLToPath(import.meta.url)), '..', '..', 'public', 'locales'); + +const locales = await readdir(LOCALES_DIR); + +/** + * @type {Array<{ language: string, untranslatedCount: number, translatedCount: number }>} + */ +const stats = []; + +for (const fileName of locales) { + const filePath = path.join(LOCALES_DIR, fileName, 'grafana.json'); + if (!(await exists(filePath))) { + continue; + } + + const messages = await readFile(filePath); + const parsedMessages = JSON.parse(messages.toString()); + + let translatedCount = 0; + let untranslatedCount = 0; + + eachMessage(parsedMessages, (value) => { + if (value === '') { + untranslatedCount += 1; + } else { + translatedCount += 1; + } + }); + + stats.push({ + language: fileName, + translatedCount, + untranslatedCount, + }); +} + +for (const stat of stats) { + logStat(`untranslated.${stat.language}`, stat.untranslatedCount); + logStat(`translated.${stat.language}`, stat.translatedCount); +} + +/** + * @param {string} filePath + */ +async function exists(filePath) { + try { + await stat(filePath); + return true; + } catch (err) { + if (err.code === 'ENOENT' || err.code === 'ENOTDIR') { + return false; + } + throw err; + } +} + +/** + * @param {unknown} value + * @param {(v: string) => void} callback + */ +function eachMessage(value, callback) { + if (typeof value === 'object') { + for (const key in value) { + const element = value[key]; + eachMessage(element, callback); + } + } else if (typeof value === 'string') { + callback(value); + } else { + throw new Error(`Unknown value ${value} in eachMessage`); + } +} + +/** + * @param {string} name + * @param {string | number} value + */ +function logStat(name, value) { + // Note that this output format must match the parsing in ci-frontend-metrics.sh + // which expects the two values to be separated by a space + console.log(`${name} ${value}`); +}