Files
SnapOtter/scripts/generate-conversion-i18n.mjs
T

186 lines
6.4 KiB
JavaScript
Raw Normal View History

import { readFileSync, writeFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { CONVERSION_PRESETS } from "../packages/shared/src/conversion-presets.ts";
const __dirname = dirname(fileURLToPath(import.meta.url));
const I18N_DIR = join(__dirname, "../packages/shared/src/i18n");
const BEGIN = " // BEGIN conversion-presets (generated by scripts/generate-conversion-i18n.mjs)";
const END = " // END conversion-presets";
// Per-locale phrasing: name template and description template. {from}/{to} are format labels (kept as-is).
const L = {
en: {
name: (f, t) => `${f} to ${t}`,
desc: (f, t) => `Convert ${f} to ${t} online. Fast, free, private, no signup.`,
},
de: {
name: (f, t) => `${f} in ${t} umwandeln`,
desc: (f, t) => `${f} online in ${t} umwandeln. Schnell, kostenlos und privat.`,
},
es: {
name: (f, t) => `${f} a ${t}`,
desc: (f, t) => `Convierte ${f} a ${t} en línea. Rápido, gratis y privado.`,
},
fr: {
name: (f, t) => `${f} en ${t}`,
desc: (f, t) => `Convertir ${f} en ${t} en ligne. Rapide, gratuit et privé.`,
},
it: {
name: (f, t) => `Da ${f} a ${t}`,
desc: (f, t) => `Converti ${f} in ${t} online. Veloce, gratuito e privato.`,
},
"pt-BR": {
name: (f, t) => `${f} para ${t}`,
desc: (f, t) => `Converta ${f} para ${t} online. Rápido, grátis e privado.`,
},
nl: {
name: (f, t) => `${f} naar ${t}`,
desc: (f, t) => `Zet ${f} online om naar ${t}. Snel, gratis en privé.`,
},
sv: {
name: (f, t) => `${f} till ${t}`,
desc: (f, t) => `Konvertera ${f} till ${t} online. Snabbt, gratis och privat.`,
},
pl: {
name: (f, t) => `${f} na ${t}`,
desc: (f, t) => `Konwertuj ${f} na ${t} online. Szybko, za darmo i prywatnie.`,
},
ru: {
name: (f, t) => `${f} в ${t}`,
desc: (f, t) => `Конвертируйте ${f} в ${t} онлайн. Быстро, бесплатно и приватно.`,
},
uk: {
name: (f, t) => `${f} у ${t}`,
desc: (f, t) => `Конвертуйте ${f} у ${t} онлайн. Швидко, безкоштовно та приватно.`,
},
tr: {
name: (f, t) => `${f} - ${t}`,
desc: (f, t) => `${f} dosyasını çevrimiçi ${t} biçimine dönüştürün. Hızlı, ücretsiz ve gizli.`,
},
ar: {
name: (f, t) => `${f} إلى ${t}`,
desc: (f, t) => `حوّل ${f} إلى ${t} عبر الإنترنت. سريع ومجاني وخاص.`,
},
hi: {
name: (f, t) => `${f} से ${t}`,
desc: (f, t) => `${f} को ${t} में ऑनलाइन बदलें। तेज़, मुफ़्त और निजी।`,
},
vi: {
name: (f, t) => `${f} sang ${t}`,
desc: (f, t) => `Chuyển đổi ${f} sang ${t} trực tuyến. Nhanh, miễn phí và riêng tư.`,
},
id: {
name: (f, t) => `${f} ke ${t}`,
desc: (f, t) => `Konversi ${f} ke ${t} online. Cepat, gratis, dan privat.`,
},
th: {
name: (f, t) => `${f} เป็น ${t}`,
desc: (f, t) => `แปลง ${f} เป็น ${t} ออนไลน์ รวดเร็ว ฟรี และเป็นส่วนตัว`,
},
ja: {
name: (f, t) => `${f}${t}に変換`,
desc: (f, t) => `${f}${t}にオンラインで変換。高速、無料、プライベート。`,
},
ko: {
name: (f, t) => `${f}을(를) ${t}(으)로`,
desc: (f, t) => `${f}을(를) ${t}(으)로 온라인 변환. 빠르고 무료이며 비공개입니다.`,
},
"zh-CN": {
name: (f, t) => `${f}${t}`,
desc: (f, t) => `在线将 ${f} 转换为 ${t}。快速、免费、私密。`,
},
"zh-TW": {
name: (f, t) => `${f}${t}`,
desc: (f, t) => `線上將 ${f} 轉換為 ${t}。快速、免費、私密。`,
},
};
// Localized "Extract Text from Image (OCR)" per locale (keep the "(OCR)" token literal).
const OCR_NAMES = {
en: "Extract Text from Image (OCR)",
de: "Text aus Bild extrahieren (OCR)",
es: "Extraer texto de imagen (OCR)",
fr: "Extraire le texte d'une image (OCR)",
it: "Estrai testo da immagine (OCR)",
"pt-BR": "Extrair texto de imagem (OCR)",
nl: "Tekst uit afbeelding halen (OCR)",
sv: "Extrahera text från bild (OCR)",
pl: "Wyodrębnij tekst z obrazu (OCR)",
ru: "Извлечь текст из изображения (OCR)",
uk: "Витягти текст із зображення (OCR)",
tr: "Görüntüden Metin Çıkarma (OCR)",
ar: "استخراج النص من صورة (OCR)",
hi: "छवि से टेक्स्ट निकालें (OCR)",
vi: "Trích xuất văn bản từ ảnh (OCR)",
id: "Ekstrak Teks dari Gambar (OCR)",
th: "แยกข้อความจากรูปภาพ (OCR)",
ja: "画像から文字を抽出 (OCR)",
ko: "이미지에서 텍스트 추출 (OCR)",
"zh-CN": "从图片提取文字 (OCR)",
"zh-TW": "從圖片擷取文字 (OCR)",
};
function block(locale) {
const tpl = L[locale] ?? L.en;
const lines = CONVERSION_PRESETS.map((p) => {
const name = tpl.name(p.from, p.to).replace(/[\\"]/g, "\\$&");
const desc = tpl.desc(p.from, p.to).replace(/[\\"]/g, "\\$&");
return ` "${p.id}": { name: "${name}", description: "${desc}" },`;
});
return [BEGIN, ...lines, END].join("\n");
}
function escapeRe(s) {
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
/** Rename the display tools.ocr.name (the first `ocr:` block, the one whose first key is `name`). */
function renameOcr(src, locale) {
const name = (OCR_NAMES[locale] ?? OCR_NAMES.en).replace(/[\\"]/g, "\\$&");
return src.replace(/(ocr:\s*\{\s*name:\s*")(?:[^"\\]|\\.)*(")/, `$1${name}$2`);
}
function injectInto(file, locale) {
let src = readFileSync(file, "utf8");
const gen = block(locale);
if (src.includes(BEGIN)) {
src = src.replace(new RegExp(`${escapeRe(BEGIN)}[\\s\\S]*?${escapeRe(END)}`), gen);
} else {
// Insert right after the `tools: {` line.
src = src.replace(/(\n\s*tools:\s*\{\n)/, `$1${gen}\n`);
}
src = renameOcr(src, locale);
writeFileSync(file, src);
}
const LOCALES = [
"en",
"zh-CN",
"zh-TW",
"ja",
"ko",
"es",
"fr",
"it",
"pt-BR",
"de",
"nl",
"sv",
"ru",
"pl",
"uk",
"ar",
"tr",
"hi",
"vi",
"id",
"th",
];
for (const code of LOCALES) {
injectInto(join(I18N_DIR, `${code}.ts`), code);
}
console.log(
`Injected ${CONVERSION_PRESETS.length} preset entries into ${LOCALES.length} locales; renamed tools.ocr.name`,
);