2024-06-18 10:34:17 +00:00
|
|
|
import { ftlToJSON, JSONToFtl } from 'ftl-tx';
|
2023-04-03 11:04:32 +00:00
|
|
|
import fs from 'fs-extra';
|
|
|
|
import { dirname, join } from 'path';
|
|
|
|
import { fileURLToPath } from 'url';
|
2023-05-29 10:02:09 +00:00
|
|
|
import { ftlFileBaseNames as sourceFileBaseNames } from './config.js';
|
2023-04-03 11:04:32 +00:00
|
|
|
import { onError, onProgress, onSuccess } from './utils.js';
|
|
|
|
|
|
|
|
const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..');
|
|
|
|
const localesDir = join(ROOT, 'chrome', 'locale');
|
2024-06-18 10:34:17 +00:00
|
|
|
const TRANSIFEX_FILE_NAME = 'zotero.json';
|
2023-04-03 11:04:32 +00:00
|
|
|
|
2023-04-13 05:22:29 +00:00
|
|
|
function getLocaleDir(locale) {
|
|
|
|
return join(localesDir, locale, 'zotero');
|
|
|
|
}
|
2023-04-03 11:04:32 +00:00
|
|
|
|
|
|
|
async function getFTL() {
|
|
|
|
const t1 = performance.now();
|
2023-05-29 10:02:09 +00:00
|
|
|
|
2023-04-13 05:22:29 +00:00
|
|
|
const foundLocales = (await fs.readdir(localesDir, { withFileTypes: true }))
|
2023-04-03 11:04:32 +00:00
|
|
|
.filter(dirent => dirent.isDirectory())
|
2023-04-13 05:22:29 +00:00
|
|
|
.map(dirent => dirent.name)
|
|
|
|
// Valid locale codes only
|
|
|
|
.filter(name => /^[a-z]{2}(-[A-Z]{2})?$/.test(name));
|
2023-05-29 10:02:09 +00:00
|
|
|
|
2023-04-03 11:04:32 +00:00
|
|
|
let count = 0;
|
2024-06-18 10:34:17 +00:00
|
|
|
for (let locale of foundLocales) {
|
|
|
|
// Skip source locale
|
|
|
|
if (locale == 'en-US') {
|
|
|
|
continue;
|
2023-04-03 11:04:32 +00:00
|
|
|
}
|
2024-06-18 10:34:17 +00:00
|
|
|
|
|
|
|
const jsonFilePath = join(getLocaleDir(locale), TRANSIFEX_FILE_NAME);
|
|
|
|
let jsonFromTransifex = {};
|
|
|
|
try {
|
|
|
|
const json = await fs.readJSON(jsonFilePath);
|
|
|
|
jsonFromTransifex = json;
|
|
|
|
}
|
|
|
|
catch (e) {
|
|
|
|
// no .json file from transifex
|
|
|
|
}
|
|
|
|
|
|
|
|
for (let sourceFileBaseName of sourceFileBaseNames) {
|
2023-05-29 10:02:09 +00:00
|
|
|
const ftlFilePath = join(getLocaleDir(locale), sourceFileBaseName + '.ftl');
|
|
|
|
let jsonFromLocalFTL = {};
|
|
|
|
try {
|
|
|
|
const ftl = await fs.readFile(ftlFilePath, 'utf8');
|
2024-06-18 10:34:17 +00:00
|
|
|
jsonFromLocalFTL = ftlToJSON(ftl);
|
2023-05-29 10:02:09 +00:00
|
|
|
}
|
|
|
|
catch (e) {
|
|
|
|
// no local .ftl file
|
|
|
|
}
|
2024-06-21 12:54:16 +00:00
|
|
|
let baseFTL;
|
2024-06-18 10:34:17 +00:00
|
|
|
let jsonFromEnUSFTL = {};
|
2024-06-21 12:54:16 +00:00
|
|
|
|
2023-05-29 10:02:09 +00:00
|
|
|
try {
|
2024-06-18 10:34:17 +00:00
|
|
|
const enUSFtlPath = join(getLocaleDir('en-US'), sourceFileBaseName + '.ftl');
|
2024-06-21 12:54:16 +00:00
|
|
|
baseFTL = await fs.readFile(enUSFtlPath, 'utf8');
|
|
|
|
jsonFromEnUSFTL = ftlToJSON(baseFTL);
|
2023-05-29 10:02:09 +00:00
|
|
|
}
|
|
|
|
catch (e) {
|
2024-06-21 12:54:16 +00:00
|
|
|
throw new Error(`No en-US .ftl file for ${sourceFileBaseName}.ftl`);
|
2023-05-29 10:02:09 +00:00
|
|
|
}
|
2024-06-21 12:54:16 +00:00
|
|
|
|
2024-06-18 10:34:17 +00:00
|
|
|
const mergedSourceJSON = { ...jsonFromEnUSFTL, ...jsonFromLocalFTL };
|
|
|
|
const sourceKeys = Object.keys(mergedSourceJSON);
|
|
|
|
const translated = new Map();
|
|
|
|
|
|
|
|
for (let key of sourceKeys) {
|
2024-06-21 12:54:16 +00:00
|
|
|
// ignore empty messages from transifex
|
|
|
|
if (key in jsonFromTransifex && jsonFromTransifex[key]?.string) {
|
2024-06-18 10:34:17 +00:00
|
|
|
translated.set(key, jsonFromTransifex[key]);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
translated.set(key, mergedSourceJSON[key]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-01 09:08:41 +00:00
|
|
|
try {
|
|
|
|
const ftl = JSONToFtl(Object.fromEntries(translated), baseFTL);
|
|
|
|
const outFtlPath = join(getLocaleDir(locale), sourceFileBaseName + '.ftl');
|
|
|
|
await fs.outputFile(outFtlPath, ftl);
|
|
|
|
onProgress(`${locale}/${sourceFileBaseName}.ftl`, null, 'localize');
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
catch (e) {
|
|
|
|
e.message = `Failed to localize "${locale}": ${e.message}`;
|
|
|
|
throw e;
|
|
|
|
}
|
2023-04-03 11:04:32 +00:00
|
|
|
}
|
|
|
|
}
|
2023-05-29 10:02:09 +00:00
|
|
|
|
2023-04-03 11:04:32 +00:00
|
|
|
const t2 = performance.now();
|
|
|
|
return ({
|
2024-06-18 10:34:17 +00:00
|
|
|
action: 'localize',
|
2023-04-03 11:04:32 +00:00
|
|
|
count,
|
2023-04-13 05:22:29 +00:00
|
|
|
totalCount: count,
|
2023-04-03 11:04:32 +00:00
|
|
|
processingTime: t2 - t1
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
|
|
(async () => {
|
|
|
|
try {
|
|
|
|
onSuccess(await getFTL());
|
|
|
|
}
|
|
|
|
catch (err) {
|
|
|
|
process.exitCode = 1;
|
|
|
|
global.isError = true;
|
|
|
|
onError(err);
|
|
|
|
}
|
|
|
|
})();
|
|
|
|
}
|