forked from L1Z0/NoN-Translations
119 lines
3.9 KiB
TypeScript
Executable File
119 lines
3.9 KiB
TypeScript
Executable File
#!/usr/bin/env ts-node
|
|
|
|
import fs from 'fs';
|
|
|
|
// a sample tool that merge (zh|en)(sfw|nsfw) ver together for edit faster
|
|
// for other language translator: if you need to use this script, just edit `targetLangFiles` and `workFile`.
|
|
|
|
const targetLangFiles: LanguageInstance[] = [
|
|
{suffix: "en_us_nsfw", file: "NSFW (Default Pack)/en_us.json", overrideSuffix: "en_us_sfw", ro: true},
|
|
{suffix: "en_us_sfw", file: "SFW (baked in NoN)/en_us.json", ro: true},
|
|
{suffix: "zh_cn_nsfw", file: "NSFW (Default Pack)/zh_cn.json", overrideSuffix: "zh_cn_sfw"},
|
|
{suffix: "zh_cn_nsfw_meme", file: "zh_cn_meme.json", overrideSuffix: "zh_cn_sfw"},
|
|
{suffix: "zh_cn_sfw", file: "SFW (baked in NoN)/zh_cn.json"}
|
|
]
|
|
const workFile = "zh_cn.json"
|
|
|
|
type LanguageInstance = {
|
|
suffix: string,
|
|
file: string,
|
|
data?: Record<string, string>,
|
|
outputBuffer?: KVPair[];
|
|
overrideSuffix?: string,
|
|
override?: LanguageInstance,
|
|
ro?: boolean // read only, don't edit.
|
|
}
|
|
|
|
const mainLangFile = "SFW (baked in NoN)/en_us.json";
|
|
|
|
const KEEP_SAME_OVERRIDE_LINES = !(process.env.KEEP_SAME_OVERRIDE_LINES ?? "").match(/^(0|false)?$/i)
|
|
if(KEEP_SAME_OVERRIDE_LINES) console.warn("enabled KEEP_SAME_OVERRIDE_LINES, same lines will not be removed")
|
|
|
|
const targetLangFilesBySuffix: Record<string, LanguageInstance> = {}
|
|
for (let l of targetLangFiles) {
|
|
if (!l.suffix.match(/^[a-z0-9-_]+$/i)) throw new Error(`bad Suffix: ${JSON.stringify(l.suffix)} that not match ^[a-z0-9-_]+$ (ignore case)`)
|
|
targetLangFilesBySuffix[l.suffix] = l
|
|
}
|
|
for (let l of targetLangFiles) {
|
|
if (l.overrideSuffix) l.override = targetLangFilesBySuffix[l.overrideSuffix]
|
|
}
|
|
|
|
|
|
type KVPair = [string, string];
|
|
|
|
function parseOrdered(src: string): KVPair[] {
|
|
const o: KVPair[] = [];
|
|
JSON.parse(src, (k, v) => {
|
|
if (k === '') return v
|
|
if (typeof k !== "string" || typeof v !== "string") throw new Error(`unexpected k/v:${JSON.stringify([k, v])}`)
|
|
o.push([k, v])
|
|
return v;
|
|
});
|
|
return o;
|
|
}
|
|
|
|
function stringify(data: KVPair[]): string {
|
|
const s = JSON.stringify
|
|
const body = data.map(([k, v]) => ` ${s(k)}: ${s(v)}`).join(",\n")
|
|
return `{\n${body}\n}\n`
|
|
}
|
|
|
|
const keyOrder = parseOrdered(fs.readFileSync(mainLangFile, "utf-8")).map(([k, v]) => k)
|
|
|
|
|
|
function genMergedLang(): void {
|
|
for (const l of targetLangFiles) {
|
|
l.data = JSON.parse(fs.readFileSync(l.file, "utf-8")) as Record<string, string>
|
|
}
|
|
|
|
const output: KVPair[] = []
|
|
for (let key of keyOrder) {
|
|
for (let l of targetLangFiles) {
|
|
let value = l.data?.[key];
|
|
if (l.override?.data?.[key] === value) value = undefined
|
|
if (typeof value === "undefined" && KEEP_SAME_OVERRIDE_LINES) value = l.override?.data?.[key]
|
|
if (value) output.push([`${key}.${l.suffix}`, value])
|
|
}
|
|
}
|
|
fs.writeFileSync(workFile, stringify(output))
|
|
}
|
|
|
|
function writeBackLang() {
|
|
const mergedKeys: Record<string, string> = JSON.parse(fs.readFileSync(workFile, "utf-8"));
|
|
for (let l of targetLangFiles) {
|
|
l.outputBuffer = []
|
|
}
|
|
for (let key of keyOrder) {
|
|
for (let l of targetLangFiles) {
|
|
let s = mergedKeys[`${key}.${l.suffix}`]
|
|
if (typeof s !== "string" && KEEP_SAME_OVERRIDE_LINES && l.override?.suffix) s = mergedKeys[`${key}.${l.override.suffix}`]
|
|
if (typeof s === "string") l.outputBuffer?.push([key, s])
|
|
}
|
|
}
|
|
|
|
for (let l of targetLangFiles) {
|
|
if (l.ro || !l.outputBuffer) continue
|
|
fs.writeFileSync(l.file, stringify(l.outputBuffer))
|
|
}
|
|
}
|
|
|
|
;(() => {
|
|
let files = [targetLangFiles.map(l => l.file), workFile].flat()
|
|
let latestFile = files.reduce<{ mtime: Date, fileName: string } | null>(
|
|
(latest, file) => {
|
|
if (!fs.existsSync(file)) return latest
|
|
let stat = fs.statSync(file);
|
|
if (!latest) return {mtime: stat.mtime, fileName: file};
|
|
return stat.mtime > latest.mtime ? {mtime: stat.mtime, fileName: file} : latest
|
|
}, null);
|
|
if (!latestFile) return
|
|
|
|
if (latestFile.fileName === workFile) {
|
|
console.log("write back to split versions")
|
|
writeBackLang()
|
|
} else {
|
|
console.log("generate the merge version");
|
|
genMergedLang()
|
|
}
|
|
|
|
})(); |