Skip to content

Commit 8d9ef71

Browse files
authored
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
1 parent a0ab1e4 commit 8d9ef71

File tree

3 files changed

+97
-0
lines changed

3 files changed

+97
-0
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
"i18n:extract": "yarn run i18next -c public/locales/i18next-parser.config.js 'public/**/*.{tsx,ts}' 'packages/grafana-ui/**/*.{tsx,ts}' && yarn i18n:pseudo",
5050
"i18n:compile": "echo 'no i18n compile yet, all good'",
5151
"i18n:pseudo": "node ./public/locales/pseudo.js",
52+
"i18n:stats": "node ./scripts/cli/reportI18nStats.mjs",
5253
"betterer": "betterer",
5354
"betterer:merge": "betterer merge",
5455
"betterer:stats": "ts-node --transpile-only --project ./scripts/cli/tsconfig.json ./scripts/cli/reportBettererStats.ts",

scripts/ci-frontend-metrics.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@ do
4646
BETTERER_STATS+="\"grafana.ci-code.betterer.${name}\": \"${value}\","
4747
done <<< "$(yarn betterer:stats)"
4848

49+
I18N_STATS=""
50+
while read -r name value
51+
do
52+
I18N_STATS+=$'\n '
53+
I18N_STATS+="\"grafana.ci-code.i18n.${name}\": \"${value}\","
54+
done <<< "$(yarn i18n:stats)"
55+
4956
THEME_TOKEN_USAGE=""
5057
while read -r name value
5158
do
@@ -56,6 +63,7 @@ done <<< "$(yarn themes:usage | awk '$4 == "@grafana/theme-token-usage" {print $
5663
echo "Metrics: {
5764
$THEME_TOKEN_USAGE
5865
$BETTERER_STATS
66+
$I18N_STATS
5967
\"grafana.ci-code.strictErrors\": \"${ERROR_COUNT}\",
6068
\"grafana.ci-code.accessibilityErrors\": \"${ACCESSIBILITY_ERRORS}\",
6169
\"grafana.ci-code.directives\": \"${DIRECTIVES}\",

scripts/cli/reportI18nStats.mjs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/// @ts-check
2+
3+
import { readdir, stat, readFile } from 'fs/promises';
4+
import path, { dirname } from 'path';
5+
import { fileURLToPath } from 'url';
6+
7+
const LOCALES_DIR = path.resolve(dirname(fileURLToPath(import.meta.url)), '..', '..', 'public', 'locales');
8+
9+
const locales = await readdir(LOCALES_DIR);
10+
11+
/**
12+
* @type {Array<{ language: string, untranslatedCount: number, translatedCount: number }>}
13+
*/
14+
const stats = [];
15+
16+
for (const fileName of locales) {
17+
const filePath = path.join(LOCALES_DIR, fileName, 'grafana.json');
18+
if (!(await exists(filePath))) {
19+
continue;
20+
}
21+
22+
const messages = await readFile(filePath);
23+
const parsedMessages = JSON.parse(messages.toString());
24+
25+
let translatedCount = 0;
26+
let untranslatedCount = 0;
27+
28+
eachMessage(parsedMessages, (value) => {
29+
if (value === '') {
30+
untranslatedCount += 1;
31+
} else {
32+
translatedCount += 1;
33+
}
34+
});
35+
36+
stats.push({
37+
language: fileName,
38+
translatedCount,
39+
untranslatedCount,
40+
});
41+
}
42+
43+
for (const stat of stats) {
44+
logStat(`untranslated.${stat.language}`, stat.untranslatedCount);
45+
logStat(`translated.${stat.language}`, stat.translatedCount);
46+
}
47+
48+
/**
49+
* @param {string} filePath
50+
*/
51+
async function exists(filePath) {
52+
try {
53+
await stat(filePath);
54+
return true;
55+
} catch (err) {
56+
if (err.code === 'ENOENT' || err.code === 'ENOTDIR') {
57+
return false;
58+
}
59+
throw err;
60+
}
61+
}
62+
63+
/**
64+
* @param {unknown} value
65+
* @param {(v: string) => void} callback
66+
*/
67+
function eachMessage(value, callback) {
68+
if (typeof value === 'object') {
69+
for (const key in value) {
70+
const element = value[key];
71+
eachMessage(element, callback);
72+
}
73+
} else if (typeof value === 'string') {
74+
callback(value);
75+
} else {
76+
throw new Error(`Unknown value ${value} in eachMessage`);
77+
}
78+
}
79+
80+
/**
81+
* @param {string} name
82+
* @param {string | number} value
83+
*/
84+
function logStat(name, value) {
85+
// Note that this output format must match the parsing in ci-frontend-metrics.sh
86+
// which expects the two values to be separated by a space
87+
console.log(`${name} ${value}`);
88+
}

0 commit comments

Comments
 (0)