mirror of
https://github.com/phantomptr/ps5upload.git
synced 2026-10-21 19:33:08 -05:00
Upload, install, convert and manage PS5 game packages over the network. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
78 lines
2.9 KiB
JavaScript
78 lines
2.9 KiB
JavaScript
#!/usr/bin/env node
|
|
// Splits the monolithic `src/i18n.ts` into one file per locale under
|
|
// `src/i18n/locales/<code>.ts`, so each locale can be lazy-loaded as
|
|
// its own Vite chunk. Run once; the main `src/i18n.ts` becomes a thin
|
|
// loader. See the comment in `src/i18n.ts` for the lazy-load design.
|
|
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
|
|
const SRC = path.resolve("src/i18n.ts");
|
|
const OUT_DIR = path.resolve("src/i18n/locales");
|
|
|
|
const text = fs.readFileSync(SRC, "utf8");
|
|
const lines = text.split("\n");
|
|
|
|
// Locate each locale's start line (" en: {" or " \"zh-CN\": {").
|
|
const headerRe = /^\s\s"?([a-zA-Z][a-zA-Z0-9_-]*)"?:\s*\{\s*$/;
|
|
const headers = [];
|
|
for (let i = 0; i < lines.length; i++) {
|
|
const m = lines[i].match(headerRe);
|
|
if (m) headers.push({ code: m[1], lineIdx: i });
|
|
}
|
|
|
|
// Find each block's end by tracking braces from the header's `{`.
|
|
// Returns { lineIdx, col } — col is the byte offset of the matching `}`
|
|
// within that line. Some locales have `,},` on the same line as the
|
|
// last content entry (no own line for the closing brace).
|
|
function findBlockEnd(startLine) {
|
|
let depth = 0;
|
|
for (let i = startLine; i < lines.length; i++) {
|
|
const line = lines[i];
|
|
for (let c = 0; c < line.length; c++) {
|
|
const ch = line[c];
|
|
if (ch === "{") depth++;
|
|
else if (ch === "}") {
|
|
depth--;
|
|
if (depth === 0) return { lineIdx: i, col: c };
|
|
}
|
|
}
|
|
}
|
|
throw new Error(`unterminated block at line ${startLine}`);
|
|
}
|
|
|
|
for (const { code, lineIdx } of headers) {
|
|
const { lineIdx: endLine, col: endCol } = findBlockEnd(lineIdx);
|
|
// Inner body lines: everything strictly between the `{` line and the
|
|
// closing `}` line, plus any content on the closing line up to the
|
|
// `}` itself (17 of 18 locales pack the last entry + `},` on one line).
|
|
const bodyLines = lines.slice(lineIdx + 1, endLine);
|
|
const tail = lines[endLine].slice(0, endCol).replace(/,\s*$/, "");
|
|
if (tail.trim().length > 0) bodyLines.push(tail);
|
|
// De-indent by 4 spaces if every non-empty line starts with that;
|
|
// monolithic file uses 4-space indent inside each locale.
|
|
const dedented = bodyLines.map((l) =>
|
|
l.startsWith(" ") ? l.slice(4) : l,
|
|
);
|
|
const safe = code.replace("-", "_");
|
|
const out = [
|
|
`// Auto-extracted from src/i18n.ts by scripts/split-i18n.mjs.`,
|
|
`// Locale: ${code}. Lazy-loaded via dynamic import in src/i18n.ts.`,
|
|
`import type { Translations } from "../types";`,
|
|
``,
|
|
`const ${safe}: Translations = {`,
|
|
...dedented,
|
|
`};`,
|
|
``,
|
|
`export default ${safe};`,
|
|
``,
|
|
].join("\n");
|
|
const target = path.join(OUT_DIR, `${code}.ts`);
|
|
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
fs.writeFileSync(target, out);
|
|
console.log(`wrote ${target} (${bodyLines.length} lines)`);
|
|
}
|
|
|
|
console.log(`\nDone. ${headers.length} locales extracted.`);
|
|
console.log(`Now manually rewrite src/i18n.ts to lazy-load these chunks.`);
|