import { Glob, pathToFileURL } from "bun"; import camelCase from "just-camel-case"; import { capitalize } from "~/utils/strings"; const glob = new Glob("locales/*/*.json"); const targetPath = pathToFileURL("./app/modules/i18n/resources.server.ts"); function main() { const record: Record = {}; const lines: string[] = [ "// This file is generated by scripts/generate-resources-file.ts", "\n", ]; for (const file of glob.scanSync(".")) { const [, lang, namespace] = file.replace(".json", "").split("/"); if (!record[lang]) { record[lang] = []; } record[lang].push(namespace); } lines.push(...imports(record)); lines.push("\n"); lines.push("export const resources = {", ...resourcesObject(record), "};"); lines.push("\n"); lines.push("export type Namespace = keyof typeof resources.en;"); Bun.write(targetPath, lines.join("\n")); } function imports(record: Record) { const lines: string[] = []; for (const lang in record) { const namespaces = record[lang]; const imports = namespaces.map( (namespace) => `import ${namespaceLangToLocalVar(lang, namespace)} from "../../../locales/${lang}/${namespace}.json";`, ); lines.push(...imports); } return lines; } function namespaceLangToLocalVar(lang: string, namespace: string) { const base = camelCase(namespace); if (lang === "en") return base; return `${base}${capitalize(camelCase(lang))}`; } function resourcesObject(record: Record) { const lines: string[] = []; for (const lang in record) { const namespaces = record[lang]; lines.push( ` "${lang}": {`, ...namespaces.map( (namespace) => `${namespace.includes("-") ? `"${namespace}"` : namespace}: ${namespaceLangToLocalVar(lang, namespace)},`, ), " },", ); } return lines; } main();