-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathtranslate.ts
More file actions
126 lines (106 loc) · 3.4 KB
/
Copy pathtranslate.ts
File metadata and controls
126 lines (106 loc) · 3.4 KB
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
import { createTranslationClient } from "./module.ts";
const DATA_DIR = "data";
const OUTPUT_DIR = "output";
const SOURCE_FILE = `${DATA_DIR}/zh_tw.json`;
const TRANSLATED_FILE = `${DATA_DIR}/translated.txt`;
type TranslationMap = Record<string, string>;
function isChineseText(value: string) {
return /.*\p{Unified_Ideograph}.*/gv.test(value);
}
async function fetchLatestZhTwFile() {
return await (
await fetch(
"https://assets.mcasset.cloud/latest/assets/minecraft/lang/zh_tw.json",
)
).text();
}
async function ensureWorkspace() {
try {
await Deno.mkdir(DATA_DIR);
await Deno.mkdir(OUTPUT_DIR);
// deno-lint-ignore no-empty
} catch (_) {}
}
async function ensureFile(path: string) {
try {
await Deno.lstat(path);
return true;
} catch (err) {
if (!(err instanceof Deno.errors.NotFound)) {
throw err;
}
await Deno.create(path);
return false;
}
}
async function loadTranslationMap(path: string, exists: boolean) {
return JSON.parse(
exists ? await Deno.readTextFile(path) : "{\n}",
) as TranslationMap;
}
function getNewLines(oldFile: string, newFile: string) {
const oldFileLines = oldFile.split("\n");
const newFileLines = newFile.split("\n");
return newFileLines.filter((line) => !oldFileLines.includes(line));
}
function parseKeyValue(line: string) {
const processedLine = line.endsWith(",")
? line.trim().slice(0, -1)
: line.trim();
const obj = JSON.parse(`{${processedLine}}`) as Record<string, string>;
const key = Object.keys(obj)[0];
return { key, value: obj[key] };
}
async function saveTranslationMap(translated: TranslationMap) {
await Deno.writeTextFile(
TRANSLATED_FILE,
JSON.stringify(translated, null, 2),
);
}
async function main() {
await ensureWorkspace();
const oldExists = await ensureFile(SOURCE_FILE);
const translatedExists = await ensureFile(TRANSLATED_FILE);
const translate = await createTranslationClient();
const translated = await loadTranslationMap(
TRANSLATED_FILE,
translatedExists,
);
const oldFile = oldExists ? await Deno.readTextFile(SOURCE_FILE) : "{\n}";
const newFile = await fetchLatestZhTwFile();
if (oldFile == newFile) {
console.log("No updates, exiting...");
Deno.exit(0);
}
await Deno.writeTextFile(SOURCE_FILE, newFile);
const newLines = getNewLines(oldFile, newFile);
const totalItems = newLines.length;
let processedItems = 0;
for await (const line of newLines) {
processedItems++;
const progressPercentage = Math.floor((processedItems / totalItems) * 100);
const { key, value } = parseKeyValue(line);
console.log(
`[${processedItems}/${totalItems} ${progressPercentage}%] Translating ${value} (${key})...`,
);
if (isChineseText(value)) {
try {
const translatedValue = await translate(value);
console.log(`Result: ${translatedValue}`);
translated[key] = translatedValue;
await saveTranslationMap(translated);
} catch (err) {
console.error(`Translate failed for ${key}:`, err);
// Preserve original text so the file remains usable, then continue.
translated[key] = "[UNTRANSLATED] " + value;
await saveTranslationMap(translated);
continue;
}
} else {
translated[key] = value;
await saveTranslationMap(translated);
}
}
console.log(`[${totalItems}/${totalItems} 100%] Translation complete.`);
}
await main();