mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-09-29 19:00:47 +00:00
0d8b7e80f6
This tweaks the script for collecting translation keys so that it changes the existing file minimally, and matches the formatting output by weblate. I'm not sure what is the best way to handle keys that are no longer needed. I think it may be best to delete these within weblate, but will need to experiment to see (I'm a weblate newbie). I think I saw keys reappear from weblate if not deleted there.
98 lines
2.6 KiB
JavaScript
98 lines
2.6 KiB
JavaScript
/**
|
|
* Generating translations keys:
|
|
*
|
|
* This code walk through all the files in client directory and its children
|
|
* Get the all keys called by our makeT utils function
|
|
* And add only the new one on our en.client.json file
|
|
*
|
|
*/
|
|
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
const Parser = require("i18next-scanner").Parser;
|
|
const englishKeys = require("../static/locales/en.client.json");
|
|
|
|
const parser = new Parser({
|
|
keySeparator: "/",
|
|
nsSeparator: null,
|
|
});
|
|
|
|
async function* walk(dirs) {
|
|
for (const dir of dirs) {
|
|
for await (const d of await fs.promises.opendir(dir)) {
|
|
const entry = path.join(dir, d.name);
|
|
if (d.isDirectory()) yield* walk([entry]);
|
|
else if (d.isFile()) yield entry;
|
|
}
|
|
}
|
|
}
|
|
|
|
const customHandler = (fileName) => (key, options) => {
|
|
const keyWithFile = `${fileName}/${key}`;
|
|
if (Object.keys(options).includes("count") === true) {
|
|
const keyOne = `${keyWithFile}_one`;
|
|
const keyOther = `${keyWithFile}_other`;
|
|
parser.set(keyOne, key);
|
|
parser.set(keyOther, key);
|
|
} else {
|
|
parser.set(keyWithFile, key);
|
|
}
|
|
};
|
|
|
|
function sort(obj) {
|
|
if (typeof obj !== "object" || Array.isArray(obj))
|
|
return obj;
|
|
const sortedObject = {};
|
|
const keys = Object.keys(obj).sort();
|
|
keys.forEach(key => sortedObject[key] = sort(obj[key]));
|
|
return sortedObject;
|
|
}
|
|
|
|
const getKeysFromFile = (filePath, fileName) => {
|
|
const content = fs.readFileSync(filePath, "utf-8");
|
|
parser.parseFuncFromString(
|
|
content,
|
|
{
|
|
list: [
|
|
"i18next.t",
|
|
"t", // To match the file-level t function created with makeT
|
|
],
|
|
},
|
|
customHandler(fileName)
|
|
);
|
|
const keys = parser.get({ sort: true });
|
|
return keys;
|
|
};
|
|
|
|
// It is highly desirable to retain existing order, to not generate
|
|
// unnecessary merges/conflicts, so we do a specialized merge.
|
|
function merge(target, scanned) {
|
|
for (const key of Object.keys(scanned)) {
|
|
if (!(key in target)) {
|
|
target[key] = scanned[key];
|
|
} else if (typeof target[key] === 'object') {
|
|
merge(target[key], scanned[key]);
|
|
} else {
|
|
scanned[key] = target[key];
|
|
}
|
|
}
|
|
}
|
|
|
|
async function walkTranslation(dirs) {
|
|
for await (const p of walk(dirs)) {
|
|
const { name } = path.parse(p);
|
|
if (p.endsWith('.map')) { continue; }
|
|
getKeysFromFile(p, name);
|
|
}
|
|
const keys = parser.get({ sort: true });
|
|
merge(englishKeys, sort(keys.en.translation));
|
|
await fs.promises.writeFile(
|
|
"static/locales/en.client.json",
|
|
JSON.stringify(englishKeys, null, 4) + '\n', // match weblate's default
|
|
"utf-8"
|
|
);
|
|
return keys;
|
|
}
|
|
|
|
walkTranslation(["_build/app/client", ...process.argv.slice(2)]);
|