import fs from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; const scriptDirectory = path.dirname(fileURLToPath(import.meta.url)); const frontendRoot = path.resolve(scriptDirectory, ".."); const i18nPath = path.join(frontendRoot, "web", "static", "js", "i18n.js"); const i18nSource = fs.readFileSync(i18nPath, "utf8"); const definitionsStart = i18nSource.indexOf("const exact ="); const definitionsEnd = i18nSource.indexOf("function readLanguage"); if (definitionsStart < 0 || definitionsEnd < 0) { throw new Error("could not locate i18n definitions"); } const definitions = i18nSource.slice(definitionsStart, definitionsEnd); const dictionaries = new Function(`${definitions}\nreturn { exact, patterns, fragments };`)(); function translate(value) { const source = String(value == null ? "" : value); if (!/[가-힣]/.test(source)) { return source; } const leading = source.match(/^\s*/)?.[0] || ""; const trailing = source.match(/\s*$/)?.[0] || ""; const body = source.slice(leading.length, source.length - trailing.length); if (Object.prototype.hasOwnProperty.call(dictionaries.exact, body)) { return leading + dictionaries.exact[body] + trailing; } for (const pattern of dictionaries.patterns) { if (pattern[0].test(body)) { return leading + body.replace(pattern[0], pattern[1]) + trailing; } } let result = body; dictionaries.fragments.forEach(function (entry) { result = result.split(entry[0]).join(entry[1]); }); return leading + result + trailing; } function filesBelow(directory) { return fs.readdirSync(directory, { withFileTypes: true }).flatMap(function (entry) { const item = path.join(directory, entry.name); return entry.isDirectory() ? filesBelow(item) : [item]; }); } const sourcePaths = [ path.join(frontendRoot, "internal", "mock", "mock_data.go"), path.join(frontendRoot, "web", "static", "js", "integration.js"), ...filesBelow(path.join(frontendRoot, "web", "templates")) ]; const candidates = new Set(); sourcePaths.forEach(function (sourcePath) { const source = fs.readFileSync(sourcePath, "utf8"); for (const match of source.matchAll(/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*')/gs)) { const value = match[0].slice(1, -1); if (/[가-힣]/.test(value) && value.length < 220) { candidates.add(value); } } if (sourcePath.endsWith(".html")) { const visibleSource = source .replace(/]*>[\s\S]*?<\/script>/gi, "") .replace(/]*>[\s\S]*?<\/style>/gi, ""); for (const match of visibleSource.matchAll(/>([^<]*[가-힣][^<]*)