mirror of https://github.com/wayvr-org/wayvr.git
update translations, use llama.cpp-compatible API instead of ollama, use gemma4 for translations
This commit is contained in:
parent
7a634585a8
commit
3aea4178dc
|
|
@ -88,7 +88,19 @@
|
|||
"LANGUAGE": "Sprache",
|
||||
"REQUIRES_RESTART": "Erfordert Neustart",
|
||||
"GRID_OPACITY": "Bodenraster-Undurchsichtigkeit",
|
||||
"GRID_OPACITY_HELP": "Undurchsichtigkeit des Bodenrasters, wenn der Skybox aktiviert ist"
|
||||
"GRID_OPACITY_HELP": "Undurchsichtigkeit des Bodenrasters, wenn der Skybox aktiviert ist",
|
||||
"BROWSE_ONLINE_CATALOG": "Online-Katalog durchsuchen...",
|
||||
"BROWSE_SKYMAPS": "Skymaps durchsuchen",
|
||||
"COLOR_KEYING": "Farbschlüsselung",
|
||||
"NO_SKYMAPS_FOUND": "Keine Skymaps gefunden",
|
||||
"SELECT_VARIANT": "Variante auswählen",
|
||||
"SHOW_WELCOME_SCREEN": "Begrüßungsbildschirm anzeigen",
|
||||
"SKYBOX": "Skybox",
|
||||
"SKYMAP_ALREADY_DOWNLOADED": "Diese Skymap wurde bereits heruntergeladen. Wählen Sie die gewünschte Aktion aus.",
|
||||
"WATCH_VIEW_ANGLE": "Betrachtungswinkel der Watch",
|
||||
"WATCH_VIEW_ANGLE_HELP": "Steuerung, wie die Watch ausgeblendet wird",
|
||||
"XR_CLICK_SENSITIVITY": "XR-Trigger-Empfindlichkeit",
|
||||
"XR_CLICK_SENSITIVITY_HELP": "Drücken- und Loslass-Werte für analoge Trigger"
|
||||
},
|
||||
"HELLO": "Hallo!",
|
||||
"AUDIO": {
|
||||
|
|
@ -158,5 +170,16 @@
|
|||
"STOP": "Stopp",
|
||||
"FORCE_KILL": "Erzwinge Beenden"
|
||||
},
|
||||
"DEBUG_INFO": "Debug-Informationen"
|
||||
}
|
||||
"DEBUG_INFO": "Debug-Informationen",
|
||||
"CREATION_DATE": "Erstellungsdatum",
|
||||
"DOWNLOADER": "Downloader",
|
||||
"DOWNLOAD_AGAIN": "Erneut herunterladen",
|
||||
"DOWNLOADING_FILE": "Datei wird heruntergeladen...",
|
||||
"GETTING_STARTED": "Erste Schritte",
|
||||
"MODIFICATION_DATE": "Änderungsdatum",
|
||||
"LOADING": "Laden...",
|
||||
"APPLY": "Anwenden",
|
||||
"RELOAD_FROM_DISK": "Von Festplatte neu laden",
|
||||
"TARGET_PATH": "Zielpfad",
|
||||
"VERSION": "Version"
|
||||
}
|
||||
|
|
@ -88,7 +88,19 @@
|
|||
"LANGUAGE": "Idioma",
|
||||
"REQUIRES_RESTART": "Requiere reinicio",
|
||||
"GRID_OPACITY": "Opacidad de la cuadrícula del suelo",
|
||||
"GRID_OPACITY_HELP": "Opacidad de la cuadrícula del suelo cuando el skybox está habilitado"
|
||||
"GRID_OPACITY_HELP": "Opacidad de la cuadrícula del suelo cuando el skybox está habilitado",
|
||||
"BROWSE_ONLINE_CATALOG": "Explorar catálogo en línea...",
|
||||
"BROWSE_SKYMAPS": "Explorar skymaps",
|
||||
"COLOR_KEYING": "Clave de color",
|
||||
"NO_SKYMAPS_FOUND": "No se encontraron skymaps",
|
||||
"SELECT_VARIANT": "Seleccionar variante",
|
||||
"SHOW_WELCOME_SCREEN": "Mostrar pantalla de bienvenida",
|
||||
"SKYBOX": "Skybox",
|
||||
"SKYMAP_ALREADY_DOWNLOADED": "Esta skymap ya ha sido descargada. Selecciona la acción deseada.",
|
||||
"WATCH_VIEW_ANGLE": "Ángulos de visión del Watch",
|
||||
"WATCH_VIEW_ANGLE_HELP": "Controla cómo se desvanece el Watch",
|
||||
"XR_CLICK_SENSITIVITY": "Sensibilidad del gatillo XR",
|
||||
"XR_CLICK_SENSITIVITY_HELP": "Valores de pulsación y liberación para gatillos analógicos"
|
||||
},
|
||||
"HELLO": "¡Hola!",
|
||||
"AUDIO": {
|
||||
|
|
@ -158,5 +170,16 @@
|
|||
"STOP": "Detener",
|
||||
"FORCE_KILL": "Forzar cierre"
|
||||
},
|
||||
"DEBUG_INFO": "Información de depuración"
|
||||
}
|
||||
"DEBUG_INFO": "Información de depuración",
|
||||
"CREATION_DATE": "Fecha de creación",
|
||||
"DOWNLOADER": "Descargador",
|
||||
"DOWNLOAD_AGAIN": "Descargar de nuevo",
|
||||
"DOWNLOADING_FILE": "Descargando archivo...",
|
||||
"GETTING_STARTED": "Primeros pasos",
|
||||
"MODIFICATION_DATE": "Fecha de modificación",
|
||||
"LOADING": "Cargando...",
|
||||
"APPLY": "Aplicar",
|
||||
"RELOAD_FROM_DISK": "Recargar desde el disco",
|
||||
"TARGET_PATH": "Ruta de destino",
|
||||
"VERSION": "Versión"
|
||||
}
|
||||
|
|
@ -109,7 +109,19 @@
|
|||
"LANGUAGE": "Lingua",
|
||||
"REQUIRES_RESTART": "Richiede riavvio",
|
||||
"GRID_OPACITY": "Opacità della griglia del pavimento",
|
||||
"GRID_OPACITY_HELP": "Opacità della griglia del pavimento quando lo skybox è abilitato"
|
||||
"GRID_OPACITY_HELP": "Opacità della griglia del pavimento quando lo skybox è abilitato",
|
||||
"BROWSE_ONLINE_CATALOG": "Sfoglia catalogo online...",
|
||||
"BROWSE_SKYMAPS": "Sfoglia skymap",
|
||||
"COLOR_KEYING": "Keying del colore",
|
||||
"NO_SKYMAPS_FOUND": "Nessuna skymap trovata",
|
||||
"SELECT_VARIANT": "Seleziona variante",
|
||||
"SHOW_WELCOME_SCREEN": "Mostra schermata di benvenuto",
|
||||
"SKYBOX": "Skybox",
|
||||
"SKYMAP_ALREADY_DOWNLOADED": "Questa skymap è già stata scaricata. Seleziona l'azione desiderata.",
|
||||
"WATCH_VIEW_ANGLE": "Angoli di visualizzazione Watch",
|
||||
"WATCH_VIEW_ANGLE_HELP": "Controlla come l'orologio sfuma",
|
||||
"XR_CLICK_SENSITIVITY": "Sensibilità trigger XR",
|
||||
"XR_CLICK_SENSITIVITY_HELP": "Valori di pressione e rilascio per i grilletti analogici"
|
||||
},
|
||||
"APPLICATION_LAUNCHER": "Lanciatore applicazioni",
|
||||
"APPLICATION_STARTED": "Applicazione avviata",
|
||||
|
|
@ -158,5 +170,16 @@
|
|||
"STOP": "Interrompi",
|
||||
"FORCE_KILL": "Uccidi forzatamente"
|
||||
},
|
||||
"DEBUG_INFO": "Informazioni di debug"
|
||||
}
|
||||
"DEBUG_INFO": "Informazioni di debug",
|
||||
"CREATION_DATE": "Data di creazione",
|
||||
"DOWNLOADER": "Downloader",
|
||||
"DOWNLOAD_AGAIN": "Scarica di nuovo",
|
||||
"DOWNLOADING_FILE": "Download del file in corso...",
|
||||
"GETTING_STARTED": "Inizio rapido",
|
||||
"MODIFICATION_DATE": "Data di modifica",
|
||||
"LOADING": "Caricamento...",
|
||||
"APPLY": "Applica",
|
||||
"RELOAD_FROM_DISK": "Ricarica da disco",
|
||||
"TARGET_PATH": "Percorso di destinazione",
|
||||
"VERSION": "Versione"
|
||||
}
|
||||
|
|
@ -88,7 +88,19 @@
|
|||
"LANGUAGE": "言語",
|
||||
"REQUIRES_RESTART": "再起動が必要です",
|
||||
"GRID_OPACITY": "フロアグリッドの不透明度",
|
||||
"GRID_OPACITY_HELP": "スカイボックスが有効なときの床グリッドの不透明度"
|
||||
"GRID_OPACITY_HELP": "スカイボックスが有効なときの床グリッドの不透明度",
|
||||
"BROWSE_ONLINE_CATALOG": "オンラインカタログを閲覧...",
|
||||
"BROWSE_SKYMAPS": "Skymapを閲覧",
|
||||
"COLOR_KEYING": "カラーキーイング",
|
||||
"NO_SKYMAPS_FOUND": "スカイマップが見つかりません",
|
||||
"SELECT_VARIANT": "バリアントを選択",
|
||||
"SHOW_WELCOME_SCREEN": "ウェルカムスクリーンを表示する",
|
||||
"SKYBOX": "スカイボックス",
|
||||
"SKYMAP_ALREADY_DOWNLOADED": "このスカイマップは既にダウンロードされています。希望のアクションを選択してください。",
|
||||
"WATCH_VIEW_ANGLE": "Watchの表示角度",
|
||||
"WATCH_VIEW_ANGLE_HELP": "ウォッチのフェードアウト具合を調整する",
|
||||
"XR_CLICK_SENSITIVITY": "XRトリガー感度",
|
||||
"XR_CLICK_SENSITIVITY_HELP": "アナログトリガーの押し込みと離しの値"
|
||||
},
|
||||
"HELLO": "こんにちは!",
|
||||
"AUDIO": {
|
||||
|
|
@ -158,5 +170,16 @@
|
|||
"STOP": "停止",
|
||||
"FORCE_KILL": "強制終了"
|
||||
},
|
||||
"DEBUG_INFO": "デバッグ情報"
|
||||
}
|
||||
"DEBUG_INFO": "デバッグ情報",
|
||||
"CREATION_DATE": "作成日",
|
||||
"DOWNLOADER": "ダウンローダー",
|
||||
"DOWNLOAD_AGAIN": "再ダウンロード",
|
||||
"DOWNLOADING_FILE": "ファイルをダウンロード中...",
|
||||
"GETTING_STARTED": "はじめに",
|
||||
"MODIFICATION_DATE": "更新日",
|
||||
"LOADING": "読み込み中...",
|
||||
"APPLY": "適用",
|
||||
"RELOAD_FROM_DISK": "ディスクからリロード",
|
||||
"TARGET_PATH": "ターゲットパス",
|
||||
"VERSION": "バージョン"
|
||||
}
|
||||
|
|
@ -83,7 +83,19 @@
|
|||
"REQUIRES_RESTART": "Wymaga restartu",
|
||||
"MISC": "Różne",
|
||||
"GRID_OPACITY": "Przezroczystość siatki podłogowej",
|
||||
"GRID_OPACITY_HELP": "Przezroczystość siatki podłogowej, gdy włączony jest skybox"
|
||||
"GRID_OPACITY_HELP": "Przezroczystość siatki podłogowej, gdy włączony jest skybox",
|
||||
"BROWSE_ONLINE_CATALOG": "Przeglądaj katalog online...",
|
||||
"BROWSE_SKYMAPS": "Przeglądaj skymaps",
|
||||
"COLOR_KEYING": "Kluczowanie kolorem",
|
||||
"NO_SKYMAPS_FOUND": "Nie znaleziono skymap",
|
||||
"SELECT_VARIANT": "Wybierz wariant",
|
||||
"SHOW_WELCOME_SCREEN": "Pokaż ekran powitalny",
|
||||
"SKYBOX": "Skymap",
|
||||
"SKYMAP_ALREADY_DOWNLOADED": "Ta skymapa została już pobrana. Wybierz żądaną akcję.",
|
||||
"WATCH_VIEW_ANGLE": "Kąty widzenia Watch",
|
||||
"WATCH_VIEW_ANGLE_HELP": "Kontroluj, jak zegarek zanika",
|
||||
"XR_CLICK_SENSITIVITY": "Czułość spustu XR",
|
||||
"XR_CLICK_SENSITIVITY_HELP": "Wartości naciśnięcia i zwolnienia dla spustów analogowych"
|
||||
},
|
||||
"APPLICATION_LAUNCHER": "Uruchamiacz aplikacji",
|
||||
"APPLICATIONS": "Aplikacje",
|
||||
|
|
@ -158,5 +170,16 @@
|
|||
"STOP": "Zatrzymaj",
|
||||
"FORCE_KILL": "Wymuś zakończenie"
|
||||
},
|
||||
"DEBUG_INFO": "Informacje debugowania"
|
||||
}
|
||||
"DEBUG_INFO": "Informacje debugowania",
|
||||
"CREATION_DATE": "Data utworzenia",
|
||||
"DOWNLOADER": "Pobieranie",
|
||||
"DOWNLOAD_AGAIN": "Pobierz ponownie",
|
||||
"DOWNLOADING_FILE": "Pobieranie pliku...",
|
||||
"GETTING_STARTED": "Rozpoczęcie",
|
||||
"MODIFICATION_DATE": "Data modyfikacji",
|
||||
"LOADING": "Ładowanie...",
|
||||
"APPLY": "Zastosuj",
|
||||
"RELOAD_FROM_DISK": "Przeładuj z dysku",
|
||||
"TARGET_PATH": "Ścieżka docelowa",
|
||||
"VERSION": "Wersja"
|
||||
}
|
||||
|
|
@ -109,7 +109,19 @@
|
|||
"LANGUAGE": "语言",
|
||||
"REQUIRES_RESTART": "需要重启",
|
||||
"GRID_OPACITY": "地面网格不透明度",
|
||||
"GRID_OPACITY_HELP": "启用天空盒时地板网格的不透明度"
|
||||
"GRID_OPACITY_HELP": "启用天空盒时地板网格的不透明度",
|
||||
"BROWSE_ONLINE_CATALOG": "浏览在线目录...",
|
||||
"BROWSE_SKYMAPS": "浏览 Skymaps",
|
||||
"COLOR_KEYING": "颜色键控",
|
||||
"NO_SKYMAPS_FOUND": "未找到 Skymaps",
|
||||
"SELECT_VARIANT": "选择变体",
|
||||
"SHOW_WELCOME_SCREEN": "显示欢迎屏幕",
|
||||
"SKYBOX": "Skybox",
|
||||
"SKYMAP_ALREADY_DOWNLOADED": "此 Skymap 已下载。请选择所需操作。",
|
||||
"WATCH_VIEW_ANGLE": "Watch 视角角度",
|
||||
"WATCH_VIEW_ANGLE_HELP": "控制表盘的淡出方式",
|
||||
"XR_CLICK_SENSITIVITY": "XR 扳机灵敏度",
|
||||
"XR_CLICK_SENSITIVITY_HELP": "模拟触发器的按下与释放值"
|
||||
},
|
||||
"APPLICATION_LAUNCHER": "应用启动器",
|
||||
"APPLICATION_STARTED": "应用已启动",
|
||||
|
|
@ -158,5 +170,16 @@
|
|||
"STOP": "停止",
|
||||
"FORCE_KILL": "强制关闭"
|
||||
},
|
||||
"DEBUG_INFO": "调试信息"
|
||||
}
|
||||
"DEBUG_INFO": "调试信息",
|
||||
"CREATION_DATE": "创建日期",
|
||||
"DOWNLOADER": "下载器",
|
||||
"DOWNLOAD_AGAIN": "重新下载",
|
||||
"DOWNLOADING_FILE": "正在下载文件...",
|
||||
"GETTING_STARTED": "入门指南",
|
||||
"MODIFICATION_DATE": "修改日期",
|
||||
"LOADING": "正在加载...",
|
||||
"APPLY": "应用",
|
||||
"RELOAD_FROM_DISK": "从磁盘重新加载",
|
||||
"TARGET_PATH": "目标路径",
|
||||
"VERSION": "版本"
|
||||
}
|
||||
|
|
@ -4,9 +4,6 @@
|
|||
"workspaces": {
|
||||
"": {
|
||||
"name": "llm_translator",
|
||||
"dependencies": {
|
||||
"ollama": "^0.5.14",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bun": "latest",
|
||||
"@types/node": "^22.13.13",
|
||||
|
|
@ -27,12 +24,8 @@
|
|||
|
||||
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
|
||||
|
||||
"ollama": ["ollama@0.5.16", "", { "dependencies": { "whatwg-fetch": "^3.6.20" } }, "sha512-OEbxxOIUZtdZgOaTPAULo051F5y+Z1vosxEYOoABPnQKeW7i4O8tJNlxCB+xioyoorVqgjkdj+TA1f1Hy2ug/w=="],
|
||||
|
||||
"typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="],
|
||||
|
||||
"undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
|
||||
|
||||
"whatwg-fetch": ["whatwg-fetch@3.6.20", "", {}, "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg=="],
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ Glossary:
|
|||
- Display: A virtual monitor located in WayVR environment. It has a specific resolution and it contains virtual windows.
|
||||
- Set: A list of virtual overlays you can interact with
|
||||
- Watch: An overlay anchored to your left hand in which you can display a dashboard, see your current date and time or toggle your sets.
|
||||
- Skymap: An equirectangular skybox
|
||||
End of glossary.
|
||||
|
||||
You will be given the input in the code blocks which needs to be translated to {TARGET_LANG} language. Write only the result in codeblocks, do not explain. Keep any newlines and other important formatting-required identifiers as-is, in the same state.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import { exit } from "process";
|
|||
import * as fsp from "fs/promises";
|
||||
import path from "path";
|
||||
import * as fs from "fs";
|
||||
import ollama from 'ollama'
|
||||
|
||||
const model_name = process.env["MODEL"] as string;
|
||||
const template_name = process.env["TEMPLATE"] as string;
|
||||
|
|
@ -24,7 +23,8 @@ if (lang_path === undefined) {
|
|||
Try one of these:
|
||||
LANG_PATH=../../uidev/assets/lang/ ./run.sh
|
||||
LANG_PATH=../../dash-frontend/assets/lang/ ./run.sh
|
||||
LANG_PATH=../../wayvr/src/assets/lang/ ./run.sh`);
|
||||
LANG_PATH=../../wayvr/src/assets/lang/ ./run.sh`,
|
||||
);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
|
@ -37,24 +37,28 @@ if (lang_path === undefined || !fs.existsSync(lang_path)) {
|
|||
const current_path = path.resolve(__dirname);
|
||||
const templates_path = path.resolve(__dirname + "/templates");
|
||||
|
||||
async function loop_object(obj: any, initial_str: string, callback: (key: string, value: string) => Promise<void>) {
|
||||
async function loop_object(
|
||||
obj: any,
|
||||
initial_str: string,
|
||||
callback: (key: string, value: string) => Promise<void>,
|
||||
) {
|
||||
for (var key in obj) {
|
||||
let full_key = initial_str + key;
|
||||
if (typeof obj[key] === "object" && obj[key] !== null) {
|
||||
await loop_object(obj[key], full_key + ".", callback)
|
||||
await loop_object(obj[key], full_key + ".", callback);
|
||||
} else if (obj.hasOwnProperty(key)) {
|
||||
await callback(full_key, obj[key])
|
||||
await callback(full_key, obj[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function extract_backticks(str: string) {
|
||||
const regex = /`([^`]+)`/g;
|
||||
return str.match(regex)?.map(match => match.slice(1, -1).trim());
|
||||
return str.match(regex)?.map((match) => match.slice(1, -1).trim());
|
||||
}
|
||||
|
||||
function set_i18n_key(obj: any, key: string, value: string | undefined) {
|
||||
const parts = key.split('.');
|
||||
const parts = key.split(".");
|
||||
let cur_level = obj;
|
||||
for (let i = 0; i < parts.length - 1; i++) {
|
||||
const part = parts[i]!;
|
||||
|
|
@ -67,7 +71,7 @@ function set_i18n_key(obj: any, key: string, value: string | undefined) {
|
|||
}
|
||||
|
||||
function key_exists(obj: any, key: string) {
|
||||
const parts = key.split('.');
|
||||
const parts = key.split(".");
|
||||
let level = obj;
|
||||
|
||||
for (let i = 0; i < parts.length; i++) {
|
||||
|
|
@ -79,7 +83,7 @@ function key_exists(obj: any, key: string) {
|
|||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
interface Example {
|
||||
key: string;
|
||||
|
|
@ -89,14 +93,24 @@ interface Example {
|
|||
|
||||
interface Template {
|
||||
full_name: string; // "Polish"
|
||||
examples: Example[]
|
||||
examples: Example[];
|
||||
}
|
||||
|
||||
function gen_prompt(description: string, template: Template, key: string, english_translation: string) {
|
||||
function gen_prompt(
|
||||
description: string,
|
||||
template: Template,
|
||||
key: string,
|
||||
english_translation: string,
|
||||
) {
|
||||
let num = 1;
|
||||
for (const example of template.examples) {
|
||||
description += "\nExample " + num + ":\n\n";
|
||||
description += "Translate key `" + example.key + "` from English to " + template.full_name + ":\n\n";
|
||||
description +=
|
||||
"Translate key `" +
|
||||
example.key +
|
||||
"` from English to " +
|
||||
template.full_name +
|
||||
":\n\n";
|
||||
description += "```\n";
|
||||
description += example.en + "\n";
|
||||
description += "```\n\n";
|
||||
|
|
@ -107,7 +121,12 @@ function gen_prompt(description: string, template: Template, key: string, englis
|
|||
num += 1;
|
||||
}
|
||||
description += "\nEnd of examples.\n\n";
|
||||
description += "Translate key `" + key + "` from English to " + template.full_name + ":\n\n";
|
||||
description +=
|
||||
"Translate key `" +
|
||||
key +
|
||||
"` from English to " +
|
||||
template.full_name +
|
||||
":\n\n";
|
||||
description += "```\n";
|
||||
description += english_translation + "\n";
|
||||
description += "```\n";
|
||||
|
|
@ -115,24 +134,39 @@ function gen_prompt(description: string, template: Template, key: string, englis
|
|||
}
|
||||
|
||||
async function run() {
|
||||
const template = JSON.parse(await fsp.readFile(templates_path + "/" + template_name + ".json", "utf-8")) as Template;
|
||||
const template = JSON.parse(
|
||||
await fsp.readFile(templates_path + "/" + template_name + ".json", "utf-8"),
|
||||
) as Template;
|
||||
|
||||
let description_txt = await fsp.readFile(current_path + "/description.txt", "utf-8");
|
||||
description_txt = description_txt.replaceAll("{TARGET_LANG}", template.full_name);
|
||||
let description_txt = await fsp.readFile(
|
||||
current_path + "/description.txt",
|
||||
"utf-8",
|
||||
);
|
||||
description_txt = description_txt.replaceAll(
|
||||
"{TARGET_LANG}",
|
||||
template.full_name,
|
||||
);
|
||||
|
||||
const orig_english_json = JSON.parse(await fsp.readFile(lang_path + "/en.json") as any);
|
||||
const orig_english_json = JSON.parse(
|
||||
(await fsp.readFile(lang_path + "/en.json")) as any,
|
||||
);
|
||||
|
||||
let orig_translated_json = {};
|
||||
try {
|
||||
orig_translated_json = JSON.parse((await fsp.readFile(lang_path + "/" + template_name + ".json")).toString());
|
||||
}
|
||||
catch (_e) { }
|
||||
orig_translated_json = JSON.parse(
|
||||
(
|
||||
await fsp.readFile(lang_path + "/" + template_name + ".json")
|
||||
).toString(),
|
||||
);
|
||||
} catch (_e) {}
|
||||
|
||||
let llm_translated_json = {};
|
||||
const translated_json_path = lang_path + "/" + template_name + ".json";
|
||||
if (await fsp.exists(translated_json_path)) {
|
||||
console.log("Loading file", translated_json_path);
|
||||
llm_translated_json = JSON.parse((await fsp.readFile(translated_json_path)).toString());
|
||||
llm_translated_json = JSON.parse(
|
||||
(await fsp.readFile(translated_json_path)).toString(),
|
||||
);
|
||||
}
|
||||
|
||||
let total_count = 0;
|
||||
|
|
@ -144,7 +178,10 @@ async function run() {
|
|||
if (!key_exists(orig_english_json, key)) {
|
||||
console.log("Removing key", key);
|
||||
set_i18n_key(llm_translated_json, key, undefined);
|
||||
fsp.writeFile(translated_json_path, JSON.stringify(llm_translated_json, undefined, 2));
|
||||
fsp.writeFile(
|
||||
translated_json_path,
|
||||
JSON.stringify(llm_translated_json, undefined, "\t"),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -159,25 +196,50 @@ async function run() {
|
|||
|
||||
console.log("Translating", key, "...");
|
||||
|
||||
const prompt = gen_prompt(description_txt, template, key, english_translation);
|
||||
const prompt = gen_prompt(
|
||||
description_txt,
|
||||
template,
|
||||
key,
|
||||
english_translation,
|
||||
);
|
||||
|
||||
const response = await ollama.chat({
|
||||
model: model_name,
|
||||
messages: [{ role: "user", content: prompt }],
|
||||
options: {
|
||||
const response = await fetch("http://localhost:8080/v1/chat/completions", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
model: model_name,
|
||||
messages: [{ role: "user", content: prompt }],
|
||||
chat_template_kwargs: {
|
||||
enable_thinking: false,
|
||||
},
|
||||
seed: 12345,
|
||||
}
|
||||
})
|
||||
}),
|
||||
});
|
||||
if (!response.ok) {
|
||||
const errorBody = await response.text();
|
||||
throw new Error("API error " + response.status + ": " + errorBody);
|
||||
}
|
||||
const json = (await response.json()) as any;
|
||||
|
||||
const msg = extract_backticks(response.message.content);
|
||||
if (!json.choices || !json.choices[0] || !json.choices[0].message) {
|
||||
console.log("Full response:", JSON.stringify(json, null, "\t"));
|
||||
throw new Error("Unexpected response format: " + JSON.stringify(json));
|
||||
}
|
||||
|
||||
const msg = extract_backticks(json.choices[0].message.content);
|
||||
if (msg === undefined || msg[0] === undefined) {
|
||||
throw new Error("backticks failed. Raw content: " + response.message.content);
|
||||
throw new Error(
|
||||
"backticks failed. Raw content: " + json.choices[0].message.content,
|
||||
);
|
||||
}
|
||||
|
||||
console.log(" >>>", msg);
|
||||
|
||||
set_i18n_key(llm_translated_json, key, msg[0]);
|
||||
fsp.writeFile(translated_json_path, JSON.stringify(llm_translated_json, undefined, 2));
|
||||
fsp.writeFile(
|
||||
translated_json_path,
|
||||
JSON.stringify(llm_translated_json, undefined, "\t"),
|
||||
);
|
||||
});
|
||||
|
||||
console.log("Translation", template_name, "finished");
|
||||
|
|
|
|||
|
|
@ -10,7 +10,5 @@
|
|||
"peerDependencies": {
|
||||
"typescript": "^5"
|
||||
},
|
||||
"dependencies": {
|
||||
"ollama": "^0.5.14"
|
||||
}
|
||||
"dependencies": {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Do not run this script if you don’t have at least 32 GiB of system memory,
|
||||
# unless you have enabled the mmap option in the Ollama startup settings.
|
||||
# Submitting PRs that lack translated strings is okay if you don’t meet the
|
||||
# Do not run this script if you don't have at least 32 GiB of system memory.
|
||||
# Submitting PRs that lack translated strings is okay if you don't meet the
|
||||
# system requirements to run this script, or if you simply prefer not to; we are
|
||||
# regularly updating the missing translation strings anyway.
|
||||
#
|
||||
|
|
@ -13,7 +12,12 @@ cd "$(dirname "$0")"
|
|||
|
||||
bun install
|
||||
|
||||
export MODEL="gemma3:27b"
|
||||
# model URL:
|
||||
# https://huggingface.co/unsloth/gemma-4-26B-A4B-it-GGUF
|
||||
# you can specify your own if you want to.
|
||||
if [ -z "${MODEL}" ]; then
|
||||
export MODEL="gemma-4-26B-A4B-it-UD-Q3_K_M"
|
||||
fi
|
||||
|
||||
TEMPLATE="pl" bun main.ts
|
||||
TEMPLATE="de" bun main.ts
|
||||
|
|
|
|||
Loading…
Reference in New Issue