#!/usr/bin/env node /** * i18n:add-language – lägg till ett nytt språk i ett kommando. * * node scripts/i18n-add-language.mjs "" * ex: node scripts/i18n-add-language.mjs el el-GR "Ελληνικά" * * Gör ALL plumbing automatiskt: * 1. Skapar src/locales//common.json – kopia av svenska (platshållare), * så appen funkar direkt och paritetsvakten är nöjd från start. * 2. Registrerar språket i src/lib/i18n.ts (import + SUPPORTED_LANGUAGES + resources). * 3. Lägger språkväljar-etiketten profile.language. = "" i ALLA * locale-filer (annars faller vakten på saknad nyckel). * * Kvar för dig: översätt värdena i src/locales//common.json och kör * `pnpm --filter @app/mobile i18n:check` – den listar exakt vad som ev. fattas. * * Endast textinsättning (aldrig omsortering) → minimala diffar på befintliga filer. */ import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync, statSync } from "node:fs"; import { join } from "node:path"; const ROOT = process.cwd(); // apps/mobile const LOC = join(ROOT, "src/locales"); const I18N = join(ROOT, "src/lib/i18n.ts"); const [code, tag, ...labelParts] = process.argv.slice(2); const label = labelParts.join(" "); if (!code || !tag || !label) { console.error('Användning: node scripts/i18n-add-language.mjs ""'); console.error('Exempel: node scripts/i18n-add-language.mjs el el-GR "Ελληνικά"'); process.exit(1); } if (!/^[a-z]{2,3}$/.test(code)) { console.error(`Ogiltig språkkod "${code}" – 2–3 gemener (t.ex. el, cs, uk).`); process.exit(1); } if (!/^[a-z]{2,3}-[A-Za-z0-9]{2,4}$/.test(tag)) { console.error(`Ogiltig BCP 47-tagg "${tag}" – t.ex. el-GR, cs-CZ, pt-BR.`); process.exit(1); } if (existsSync(join(LOC, code, "common.json"))) { console.error(`src/locales/${code}/common.json finns redan – avbryter.`); process.exit(1); } const labelKey = `profile.language.${code}`; const labelLine = ` ${JSON.stringify(labelKey)}: ${JSON.stringify(label)},`; const ANCHOR = '"profile.language.sv":'; /** Sätt in etikettraden direkt efter profile.language.sv, annars först i objektet. */ function withLabel(raw) { if (raw.includes(labelKey + '"') || raw.includes(labelKey + "'")) return raw; // finns redan const lines = raw.split("\n"); let at = lines.findIndex((l) => l.includes(ANCHOR)); if (at === -1) at = lines.findIndex((l) => l.trim().startsWith("{")); // fallback: efter { lines.splice(at + 1, 0, labelLine); return lines.join("\n"); } // ---- 1 + 3. Ny fil (kopia av sv + etikett) + etikett i alla befintliga ----- const svRaw = readFileSync(join(LOC, "sv/common.json"), "utf8"); mkdirSync(join(LOC, code), { recursive: true }); writeFileSync(join(LOC, code, "common.json"), withLabel(svRaw)); const existing = readdirSync(LOC).filter((d) => d !== code && statSync(join(LOC, d)).isDirectory()); for (const lang of existing) { const p = join(LOC, lang, "common.json"); writeFileSync(p, withLabel(readFileSync(p, "utf8"))); } // ---- 2. Registrera i i18n.ts (import + SUPPORTED_LANGUAGES + resources) ----- { let lines = readFileSync(I18N, "utf8").split("\n"); const importRe = /^import \w+ from "\.\.\/locales\/\w+\/common\.json";$/; let lastImport = -1; lines.forEach((l, i) => importRe.test(l) && (lastImport = i)); lines.splice(lastImport + 1, 0, `import ${code} from "../locales/${code}/common.json";`); const arrEnd = lines.findIndex((l) => l.trim() === "] as const;"); lines.splice(arrEnd, 0, ` { code: "${code}", tag: "${tag}", labelKey: "${labelKey}" },`); const resRe = /^\s+\w+: \{ common: \w+ \},$/; let lastRes = -1; lines.forEach((l, i) => resRe.test(l) && (lastRes = i)); lines.splice(lastRes + 1, 0, ` ${code}: { common: ${code} },`); writeFileSync(I18N, lines.join("\n")); } const keyCount = svRaw.split("\n").filter((l) => l.includes('": ')).length; console.log(`\n✓ La till "${code}" (${tag}, "${label}").`); console.log( ` • src/locales/${code}/common.json skapad (~${keyCount} nycklar, svenska platshållare)`, ); console.log(` • registrerad i src/lib/i18n.ts (import + SUPPORTED_LANGUAGES + resources)`); console.log(` • ${labelKey} = "${label}" i alla locale-filer`); console.log(`\nNästa steg:`); console.log(` 1. Översätt värdena i src/locales/${code}/common.json`); console.log(` 2. pnpm --filter @app/mobile i18n:check`); console.log(` 3. pnpm --filter @app/mobile typecheck`);