mirror of
https://github.com/Mintplex-Labs/anything-llm.git
synced 2025-03-13 05:32:24 +00:00
* wip onboarding translations * add normalized EN reference for languages * add zh/zh-tw translations * Fix translations
157 lines
4.1 KiB
JavaScript
157 lines
4.1 KiB
JavaScript
// This script is used to normalize the translations files to ensure they are all the same.
|
|
// This will take the en file and compare it to all other files and ensure they are all the same.
|
|
// If a non-en file is missing a key, it will be added to the file and set to null
|
|
import { resources } from "./resources.js";
|
|
import fs from "fs";
|
|
const languageNames = new Intl.DisplayNames(Object.keys(resources), {
|
|
type: "language",
|
|
});
|
|
|
|
function langDisplayName(lang) {
|
|
return languageNames.of(lang);
|
|
}
|
|
|
|
function compareStructures(lang, a, b, subdir = null) {
|
|
//if a and b aren't the same type, they can't be equal
|
|
if (typeof a !== typeof b && a !== null && b !== null) {
|
|
console.log("Invalid type comparison", [
|
|
{
|
|
lang,
|
|
a: typeof a,
|
|
b: typeof b,
|
|
values: {
|
|
a,
|
|
b,
|
|
},
|
|
...(!!subdir ? { subdir } : {}),
|
|
},
|
|
]);
|
|
return false;
|
|
}
|
|
|
|
// Need the truthy guard because
|
|
// typeof null === 'object'
|
|
if (a && typeof a === "object") {
|
|
var keysA = Object.keys(a).sort(),
|
|
keysB = Object.keys(b).sort();
|
|
|
|
//if a and b are objects with different no of keys, unequal
|
|
if (keysA.length !== keysB.length) {
|
|
console.log("Keys are missing!", {
|
|
[lang]: keysA,
|
|
en: keysB,
|
|
...(!!subdir ? { subdir } : {}),
|
|
diff: {
|
|
added: keysB.filter((key) => !keysA.includes(key)),
|
|
removed: keysA.filter((key) => !keysB.includes(key)),
|
|
},
|
|
});
|
|
return false;
|
|
}
|
|
|
|
//if keys aren't all the same, unequal
|
|
if (
|
|
!keysA.every(function (k, i) {
|
|
return k === keysB[i];
|
|
})
|
|
) {
|
|
console.log("Keys are not equal!", {
|
|
[lang]: keysA,
|
|
en: keysB,
|
|
...(!!subdir ? { subdir } : {}),
|
|
});
|
|
return false;
|
|
}
|
|
|
|
//recurse on the values for each key
|
|
return keysA.every(function (key) {
|
|
//if we made it here, they have identical keys
|
|
return compareStructures(lang, a[key], b[key], key);
|
|
});
|
|
|
|
//for primitives just ignore since we don't check values.
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
function normalizeTranslations(lang, source, target, subdir = null) {
|
|
// Handle primitives - if target exists, keep it, otherwise set null
|
|
if (!source || typeof source !== "object") {
|
|
return target ?? null;
|
|
}
|
|
|
|
// Handle objects
|
|
const normalized = target && typeof target === "object" ? { ...target } : {};
|
|
|
|
// Add all keys from source (English), setting to null if missing
|
|
for (const key of Object.keys(source)) {
|
|
normalized[key] = normalizeTranslations(
|
|
lang,
|
|
source[key],
|
|
normalized[key],
|
|
key
|
|
);
|
|
}
|
|
|
|
return normalized;
|
|
}
|
|
|
|
function ISOToFilename(lang) {
|
|
const ISO_TO_FILENAME = {
|
|
"zh-tw": "zh_TW",
|
|
pt: "pt_BR",
|
|
vi: "vn",
|
|
};
|
|
return ISO_TO_FILENAME[lang] || lang.replace("-", "_");
|
|
}
|
|
|
|
const failed = [];
|
|
const TRANSLATIONS = {};
|
|
for (const [lang, { common }] of Object.entries(resources)) {
|
|
TRANSLATIONS[lang] = common;
|
|
}
|
|
|
|
const PRIMARY = { ...TRANSLATIONS["en"] };
|
|
delete TRANSLATIONS["en"];
|
|
|
|
console.log(
|
|
`The following translation files will be normalized against the English file: [${Object.keys(
|
|
TRANSLATIONS
|
|
).join(",")}]`
|
|
);
|
|
|
|
// Normalize each non-English translation
|
|
for (const [lang, translations] of Object.entries(TRANSLATIONS)) {
|
|
const normalized = normalizeTranslations(lang, PRIMARY, translations);
|
|
|
|
// Update the translations in resources
|
|
resources[lang].common = normalized;
|
|
|
|
// Verify the structure matches
|
|
const passed = compareStructures(lang, normalized, PRIMARY);
|
|
console.log(`${langDisplayName(lang)} (${lang}): ${passed ? "✅" : "❌"}`);
|
|
!passed && failed.push(lang);
|
|
|
|
const langFilename = ISOToFilename(lang);
|
|
fs.writeFileSync(
|
|
`./${langFilename}/common.js`,
|
|
`// Anything with "null" requires a translation. Contribute to translation via a PR!
|
|
const TRANSLATIONS = ${JSON.stringify(normalized, null, 2)}
|
|
|
|
export default TRANSLATIONS;`
|
|
);
|
|
}
|
|
|
|
if (failed.length !== 0) {
|
|
throw new Error(
|
|
`Error verifying normalized translations. Please check the logs.`,
|
|
failed
|
|
);
|
|
}
|
|
|
|
console.log(
|
|
`👍 All translation files have been normalized to match the English schema!`
|
|
);
|
|
|
|
process.exit(0);
|