Skip to content

Commit fb7ac79

Browse files
committed
feat: build translation file
1 parent c2a950d commit fb7ac79

3 files changed

Lines changed: 87 additions & 0 deletions

File tree

package-lock.json

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"test": "mocha",
2626
"update": "npm version minor --m=\"chore(update): Release v%s\"",
2727
"version": "node scripts/validate.cjs",
28+
"bundle": "node scripts/lang.js",
2829
"types": "tsc",
2930
"//": "versioning scripts",
3031
"patch": "npm version patch --m=\"chore(patch): Release v%s\"",
@@ -52,6 +53,7 @@
5253
"eslint": "^8.31.0",
5354
"eslint-config-airbnb-base": "^15.0.0",
5455
"eslint-plugin-import": "^2.26.0",
56+
"fast-glob": "^3.3.3",
5557
"mocha": "^10.2.0",
5658
"replace": "^1.2.1",
5759
"rollup": "^2.79.2",

scripts/lang.js

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import fs from 'node:fs/promises';
2+
import glob from 'fast-glob';
3+
4+
async function main() {
5+
// Load base "en" first
6+
const data = await bundle(
7+
await glob('lang/en/*.json'),
8+
);
9+
10+
// Now load other languages (if any)
11+
Object.entries(await bundle(
12+
await glob([
13+
'lang/*/*.json',
14+
'!lang/en',
15+
]),
16+
)).forEach(
17+
([lang, obj]) => Object.entries(obj).forEach(
18+
([key, value]) => {
19+
// Check if key exists in "en"
20+
if (!Object.hasOwn(data.en, key)) {
21+
console.warn(`${lang} has extra key "${key}"`);
22+
// assign(data, lang, `???${key}`, value);
23+
// return;
24+
}
25+
assign(data, lang, key, value);
26+
},
27+
),
28+
);
29+
30+
const file = JSON.stringify(sort(data), null, 2);
31+
if (!file) return;
32+
await fs.writeFile('lang/underscript.json', file);
33+
}
34+
35+
function assign(obj = {}, lang = '', key = '', value = '') {
36+
// Only add key if value exists
37+
if (!value) return;
38+
obj[lang] ??= {}; // Does lang exist?
39+
obj[lang][key] = value;
40+
}
41+
42+
/**
43+
* Bundle all files into a single object
44+
* @returns {Promise<Record<string, Record<string, string>>>}
45+
*/
46+
async function bundle(files = []) {
47+
const ret = {};
48+
await Promise.all(files.map(async (file) => {
49+
const [lang, name] = getFileParts(file);
50+
51+
Object.entries(await parse(file)).forEach(
52+
([key, value]) => {
53+
assign(ret, lang, `underscript.${name}.${key}`, value);
54+
},
55+
);
56+
}));
57+
return ret;
58+
}
59+
60+
// Split file path into [lang, name]
61+
function getFileParts(file = '') {
62+
const [/* dir */, lang, name] = file.split('/');
63+
return [lang, name.substring(0, name.lastIndexOf('.'))];
64+
}
65+
66+
async function parse(file) {
67+
const content = await fs.readFile(file);
68+
return JSON.parse(content);
69+
}
70+
71+
function sort(obj = {}) {
72+
const keys = Object.keys(obj);
73+
if (!keys.length) return undefined;
74+
const sorted = {};
75+
keys.sort().forEach(
76+
(key) => {
77+
const value = obj[key];
78+
sorted[key] = typeof value === 'object' ? sort(value) : value;
79+
},
80+
);
81+
return sorted;
82+
}
83+
84+
main();

0 commit comments

Comments
 (0)