-
-
Notifications
You must be signed in to change notification settings - Fork 131
/
Copy pathcatalogs.js
129 lines (113 loc) · 3.61 KB
/
catalogs.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import fs from 'node:fs';
// Dependency from Lingui, not listed in package.json
import PO from 'pofile';
let listedLocales = [];
try {
listedLocales = JSON.parse(
fs.readFileSync('src/data/listed-locales.json', 'utf8'),
);
} catch (e) {}
const DEFAULT_LANG = 'en';
const IGNORE_LANGS = [DEFAULT_LANG, 'pseudo-LOCALE'];
const files = fs.readdirSync('src/locales');
const catalogs = {};
const enCatalog = files.find((file) => file.endsWith('en.po'));
const enContent = fs.readFileSync(`src/locales/${enCatalog}`, 'utf8');
const enPo = PO.parse(enContent);
const total = enPo.items.length;
console.log('Total strings:', total);
const codeMaps = {
'kab-KAB': 'kab',
};
files.forEach((file) => {
if (file.endsWith('.po')) {
const code = file.replace(/\.po$/, '');
if (IGNORE_LANGS.includes(code)) return;
const content = fs.readFileSync(`src/locales/${file}`, 'utf8');
const po = PO.parse(content);
const { items } = po;
// Percentage of translated strings
const translated = items.filter(
(item) => item.msgstr !== '' && item.msgstr[0] !== '',
).length;
const percentage = Math.round((translated / total) * 100);
po.percentage = percentage;
if (percentage > 0) {
// Ignore empty catalogs
catalogs[codeMaps[code] || code] = percentage;
}
}
});
const regionMaps = {
'zh-CN': 'zh-Hans',
'zh-TW': 'zh-Hant',
};
function IDN(inputCode, outputCode) {
let result;
const regionlessInputCode =
regionMaps[inputCode] || inputCode.replace(/-[a-z]+$/i, '');
const regionlessOutputCode =
regionMaps[outputCode] || outputCode.replace(/-[a-z]+$/i, '');
const inputCodes =
regionlessInputCode !== inputCode
? [inputCode, regionlessInputCode]
: [inputCode];
const outputCodes =
regionlessOutputCode !== outputCode
? [regionlessOutputCode, outputCode]
: [outputCode];
for (const inputCode of inputCodes) {
for (const outputCode of outputCodes) {
try {
result = new Intl.DisplayNames([inputCode], {
type: 'language',
}).of(outputCode);
break;
} catch (e) {}
}
if (result) break;
}
return result;
}
const fullCatalogs = Object.entries(catalogs)
// sort by key
.sort((a, b) => a[0].localeCompare(b[0]))
.map(([code, completion]) => {
const nativeName = IDN(code, code);
const name = IDN('en', code);
return { code, nativeName, name, completion };
});
// Set listed: true if completion > PERCENTAGE_THRESHOLD
const PERCENTAGE_THRESHOLD = 50;
const listedCatalogs = fullCatalogs.map((catalog) => ({
...catalog,
// Once listed, always listed
// A locale may exceed percentage threshold today, but not tomorrow
// So it should't suddenly become unlisted
listed:
listedLocales.includes(catalog.code) ||
catalog.completion >= PERCENTAGE_THRESHOLD,
}));
// Sort by completion
const sortedCatalogs = [...listedCatalogs].sort(
(a, b) => b.completion - a.completion,
);
console.table(sortedCatalogs);
console.log(
`Total listed/unlisted: ${listedCatalogs.filter((c) => c.listed).length}/${
listedCatalogs.filter((c) => !c.listed).length
}`,
);
const path = 'src/data/catalogs.json';
fs.writeFileSync(path, JSON.stringify(listedCatalogs, null, 2));
console.log('File written:', path);
const path2 = 'src/data/listed-locales.json';
const codes = listedCatalogs.filter((c) => c.listed).map((c) => c.code);
if (codes.length >= listedLocales.length) {
fs.writeFileSync(path2, JSON.stringify(codes, null, 2));
console.log('File written:', path2);
} else {
console.error(
`Number of listed locales reduced from ${listedLocales.length} to ${codes.length}.`,
);
}