@dialexjs/cli 0.2.3 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/api.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { loadFile } from "magicast";
2
- import { I18nConfig } from "dialexjs";
2
+ import { DialexConfig } from "dialexjs";
3
3
  //#region src/utils/dictionary-edit.d.ts
4
4
  /**
5
5
  * AST-level helpers for reading and editing `.content.ts` dictionary files.
@@ -208,7 +208,7 @@ interface ProjectDictionary {
208
208
  }
209
209
  interface Project {
210
210
  root: string;
211
- config: I18nConfig;
211
+ config: DialexConfig;
212
212
  dictionaries: ProjectDictionary[];
213
213
  /** Dictionary files that could not be parsed into an editable shape. */
214
214
  unsupported: string[];
package/dist/api.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { C as saveDictionaryFile, S as renderDictionaryFile, T as generateDictionaries, _ as listLeaves, a as parseStaticConfig, b as locationOf, c as analyzeProject, d as TODO_PREFIX, f as copyLeaf, g as hasPath, h as getString, i as DEFAULT_STATIC_CONFIG, l as relativeFile, m as getLeafSource, n as loadStaticProject, o as readStaticConfig, p as dictionaryLocation, r as toKey, s as DEFAULT_SOURCE_GLOB, t as loadProject, u as scanReferences, v as listLocales, w as setString, x as parseDictionaryText, y as loadDictionaryFile } from "./project-BnG6V2I0.mjs";
1
+ import { C as saveDictionaryFile, S as renderDictionaryFile, T as generateDictionaries, _ as listLeaves, a as parseStaticConfig, b as locationOf, c as analyzeProject, d as TODO_PREFIX, f as copyLeaf, g as hasPath, h as getString, i as DEFAULT_STATIC_CONFIG, l as relativeFile, m as getLeafSource, n as loadStaticProject, o as readStaticConfig, p as dictionaryLocation, r as toKey, s as DEFAULT_SOURCE_GLOB, t as loadProject, u as scanReferences, v as listLocales, w as setString, x as parseDictionaryText, y as loadDictionaryFile } from "./project-ClQxaIMc.mjs";
2
2
  export { DEFAULT_SOURCE_GLOB, DEFAULT_STATIC_CONFIG, TODO_PREFIX, analyzeProject, copyLeaf, dictionaryLocation, generateDictionaries, getLeafSource, getString, hasPath, listLeaves, listLocales, loadDictionaryFile, loadProject, loadStaticProject, locationOf, parseDictionaryText, parseStaticConfig, readStaticConfig, relativeFile, renderDictionaryFile, saveDictionaryFile, scanReferences, setString, toKey };
package/dist/index.mjs CHANGED
@@ -1,14 +1,15 @@
1
1
  #!/usr/bin/env node
2
- import { C as saveDictionaryFile, D as logger, E as runGenerate, T as generateDictionaries, _ as listLeaves, c as analyzeProject, d as TODO_PREFIX, f as copyLeaf, g as hasPath, h as getString, r as toKey, t as loadProject, v as listLocales, w as setString, y as loadDictionaryFile } from "./project-BnG6V2I0.mjs";
2
+ import { C as saveDictionaryFile, D as logger, E as runGenerate, T as generateDictionaries, _ as listLeaves, c as analyzeProject, d as TODO_PREFIX, f as copyLeaf, g as hasPath, h as getString, r as toKey, t as loadProject, v as listLocales, w as setString, y as loadDictionaryFile } from "./project-ClQxaIMc.mjs";
3
3
  import { Command } from "commander";
4
4
  import fs from "node:fs";
5
5
  import path from "node:path";
6
6
  import fg from "fast-glob";
7
- import { resolveI18nConfig } from "dialexjs/scanner";
7
+ import { resolveDialexConfig } from "dialexjs/scanner";
8
8
  import pc from "picocolors";
9
9
  import * as p from "@clack/prompts";
10
10
  import { loadFile, parseModule, writeFile } from "magicast";
11
11
  import { addNuxtModule, addVitePlugin } from "magicast/helpers";
12
+ import { fileURLToPath } from "node:url";
12
13
  import { argumentSignature, getArguments, isIcuStructured, parseMessage } from "dialexjs/icu";
13
14
  //#region src/utils/detector.ts
14
15
  /**
@@ -114,6 +115,57 @@ function detectFramework(root) {
114
115
  };
115
116
  }
116
117
  //#endregion
118
+ //#region src/utils/package-json.ts
119
+ /** Version of this CLI, which the other Dialex packages share. Read from the nearest package.json. */
120
+ function cliVersion() {
121
+ let dir = path.dirname(fileURLToPath(import.meta.url));
122
+ for (let i = 0; i < 4; i++) {
123
+ try {
124
+ const pkg = JSON.parse(fs.readFileSync(path.join(dir, "package.json"), "utf-8"));
125
+ if (pkg.name === "@dialexjs/cli") return pkg.version;
126
+ } catch {}
127
+ dir = path.dirname(dir);
128
+ }
129
+ }
130
+ /** The install command for the package manager a project uses, judged by its lockfile. */
131
+ function installCommand(root) {
132
+ const has = (file) => fs.existsSync(path.join(root, file));
133
+ if (has("bun.lock") || has("bun.lockb")) return "bun install";
134
+ if (has("pnpm-lock.yaml")) return "pnpm install";
135
+ if (has("yarn.lock")) return "yarn install";
136
+ return "npm install";
137
+ }
138
+ const sorted = (deps) => Object.fromEntries(Object.entries(deps).sort(([a], [b]) => a.localeCompare(b)));
139
+ /**
140
+ * Adds the packages a Dialex project needs: `dialexjs` as a dependency and the CLI as a dev
141
+ * dependency (the `dx:generate` script runs it). Packages already listed anywhere are left alone.
142
+ * Returns the names it added.
143
+ */
144
+ function addRequiredPackages(pkg, version = cliVersion()) {
145
+ const range = version ? `^${version}` : "latest";
146
+ const listed = (name) => [
147
+ pkg.dependencies,
148
+ pkg.devDependencies,
149
+ pkg.peerDependencies
150
+ ].some((deps) => deps && name in deps);
151
+ const added = [];
152
+ if (!listed("dialexjs")) {
153
+ pkg.dependencies = sorted({
154
+ ...pkg.dependencies,
155
+ dialexjs: range
156
+ });
157
+ added.push("dialexjs");
158
+ }
159
+ if (!listed("@dialexjs/cli")) {
160
+ pkg.devDependencies = sorted({
161
+ ...pkg.devDependencies,
162
+ "@dialexjs/cli": range
163
+ });
164
+ added.push("@dialexjs/cli");
165
+ }
166
+ return added;
167
+ }
168
+ //#endregion
117
169
  //#region src/commands/init.ts
118
170
  async function runInit(options = {}) {
119
171
  const root = options.cwd || process.cwd();
@@ -269,11 +321,11 @@ export default defineConfig({
269
321
  const vMod = await loadFile(vConfig);
270
322
  addVitePlugin(vMod, {
271
323
  from: "dialexjs/vite",
272
- imported: "i18nPlugin",
273
- constructor: "i18nPlugin"
324
+ imported: "dialexPlugin",
325
+ constructor: "dialexPlugin"
274
326
  });
275
327
  await writeFile(vMod, vConfig);
276
- logger.success(`Injected i18nPlugin() into ${pc.bold(path.basename(vConfig))} via Magicast`);
328
+ logger.success(`Injected dialexPlugin() into ${pc.bold(path.basename(vConfig))} via Magicast`);
277
329
  break;
278
330
  } catch {}
279
331
  }
@@ -316,13 +368,20 @@ ${localeList.map((loc) => ` ${loc}: {
316
368
  const pkgPath = path.join(root, "package.json");
317
369
  if (fs.existsSync(pkgPath)) try {
318
370
  const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
371
+ const added = addRequiredPackages(pkg);
319
372
  pkg.scripts = pkg.scripts || {};
320
- if (!pkg.scripts["dx:generate"]) {
321
- pkg.scripts["dx:generate"] = "dx generate";
322
- fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf-8");
323
- logger.success("Added \"dx:generate\" script to package.json");
373
+ const addScript = !pkg.scripts["dx:generate"];
374
+ if (addScript) pkg.scripts["dx:generate"] = "dx generate";
375
+ if (added.length > 0 || addScript) fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf-8");
376
+ if (added.length > 0) {
377
+ logger.success(`Added ${added.join(" and ")} to package.json`);
378
+ logger.info(`Run ${pc.bold(installCommand(root))} to install them.`);
324
379
  }
325
- } catch {}
380
+ if (addScript) logger.success("Added \"dx:generate\" script to package.json");
381
+ } catch {
382
+ logger.warn("Could not update package.json; add dialexjs and @dialexjs/cli manually.");
383
+ }
384
+ else logger.warn("No package.json found; install dialexjs and @dialexjs/cli in your project.");
326
385
  if (options.ai === true || options.yes && options.ai !== false && options.noAi !== true) try {
327
386
  const skillDir = path.join(root, ".agents/skills/dialex");
328
387
  fs.mkdirSync(skillDir, { recursive: true });
@@ -385,11 +444,11 @@ This project uses [Dialex](https://github.com/awaiden/dialex) for type-safe inte
385
444
  case "hono":
386
445
  logger.log(`
387
446
  import { Hono } from "hono";
388
- import { i18n } from "dialexjs/hono";
447
+ import { dialex } from "dialexjs/hono";
389
448
  import dictionaries from "./src/dialex.generated.js";
390
449
 
391
450
  const app = new Hono();
392
- app.use("*", i18n({ dictionaries }));
451
+ app.use("*", dialex({ dictionaries }));
393
452
 
394
453
  app.get("/", (c) => {
395
454
  const dict = c.var.getDictionary("home");
@@ -400,11 +459,11 @@ app.get("/", (c) => {
400
459
  case "fastify":
401
460
  logger.log(`
402
461
  import Fastify from "fastify";
403
- import { i18nPlugin } from "dialexjs/fastify";
462
+ import { dialexPlugin } from "dialexjs/fastify";
404
463
  import dictionaries from "./src/dialex.generated.js";
405
464
 
406
465
  const app = Fastify();
407
- await app.register(i18nPlugin, { dictionaries });
466
+ await app.register(dialexPlugin, { dictionaries });
408
467
 
409
468
  app.get("/", (req) => {
410
469
  const dict = req.getDictionary("home");
@@ -415,11 +474,11 @@ app.get("/", (req) => {
415
474
  case "express":
416
475
  logger.log(`
417
476
  import express from "express";
418
- import { i18n } from "dialexjs/express";
477
+ import { dialex } from "dialexjs/express";
419
478
  import dictionaries from "./src/dialex.generated.js";
420
479
 
421
480
  const app = express();
422
- app.use(i18n({ dictionaries }));
481
+ app.use(dialex({ dictionaries }));
423
482
 
424
483
  app.get("/", (req, res) => {
425
484
  const dict = req.getDictionary("home");
@@ -430,11 +489,11 @@ app.get("/", (req, res) => {
430
489
  case "koa":
431
490
  logger.log(`
432
491
  import Koa from "koa";
433
- import { i18n } from "dialexjs/koa";
492
+ import { dialex } from "dialexjs/koa";
434
493
  import dictionaries from "./src/dialex.generated.js";
435
494
 
436
495
  const app = new Koa();
437
- app.use(i18n({ dictionaries }));
496
+ app.use(dialex({ dictionaries }));
438
497
 
439
498
  app.use((ctx) => {
440
499
  const dict = ctx.getDictionary("home");
@@ -445,11 +504,11 @@ app.use((ctx) => {
445
504
  case "nestjs":
446
505
  logger.log(`
447
506
  import { Module } from "@nestjs/common";
448
- import { I18nModule } from "dialexjs/nestjs";
507
+ import { DialexModule } from "dialexjs/nestjs";
449
508
  import dictionaries from "./src/dialex.generated.js";
450
509
 
451
510
  @Module({
452
- imports: [I18nModule.forRoot({ dictionaries })],
511
+ imports: [DialexModule.forRoot({ dictionaries })],
453
512
  })
454
513
  export class AppModule {}
455
514
  `);
@@ -468,11 +527,11 @@ export default async function Page({ params }: { params: Promise<{ locale: strin
468
527
  case "elysia":
469
528
  logger.log(`
470
529
  import { Elysia } from "elysia";
471
- import { i18n } from "dialexjs/elysia";
530
+ import { dialex } from "dialexjs/elysia";
472
531
  import dictionaries from "./src/dialex.generated.js";
473
532
 
474
533
  new Elysia()
475
- .use(i18n({ dictionaries }))
534
+ .use(dialex({ dictionaries }))
476
535
  .get("/", ({ getDictionary }) => ({ title: getDictionary("home").title }))
477
536
  .listen(3000);
478
537
  `);
@@ -480,10 +539,10 @@ new Elysia()
480
539
  case "sveltekit":
481
540
  logger.log(`
482
541
  // src/hooks.server.ts
483
- import { i18nHandle } from "dialexjs/sveltekit";
542
+ import { dialexHandle } from "dialexjs/sveltekit";
484
543
  import dictionaries from "./dialex.generated.js";
485
544
 
486
- export const handle = i18nHandle({ dictionaries });
545
+ export const handle = dialexHandle({ dictionaries });
487
546
 
488
547
  // src/app.html: <html lang="%dialex.lang%">
489
548
  // In load functions: locals.getDictionary("home")
@@ -492,10 +551,10 @@ export const handle = i18nHandle({ dictionaries });
492
551
  case "astro":
493
552
  logger.log(`
494
553
  // src/middleware.ts
495
- import { i18n } from "dialexjs/astro";
554
+ import { dialex } from "dialexjs/astro";
496
555
  import dictionaries from "./dialex.generated.js";
497
556
 
498
- export const onRequest = i18n({ dictionaries });
557
+ export const onRequest = dialex({ dictionaries });
499
558
 
500
559
  // In pages: Astro.locals.getDictionary("home")
501
560
  `);
@@ -504,10 +563,10 @@ export const onRequest = i18n({ dictionaries });
504
563
  logger.log(`
505
564
  // src/main.ts
506
565
  import { createApp } from "vue";
507
- import { createI18n } from "dialexjs/vue";
566
+ import { createDialex } from "dialexjs/vue";
508
567
  import App from "./App.vue";
509
568
 
510
- createApp(App).use(createI18n()).mount("#app");
569
+ createApp(App).use(createDialex()).mount("#app");
511
570
 
512
571
  // In components: const dict = useDictionary("home")
513
572
  `);
@@ -579,7 +638,7 @@ async function runCheck(options = {}) {
579
638
  const root = options.cwd || process.cwd();
580
639
  const quiet = options.json === true;
581
640
  const inlineConfig = options.config ? { configFile: options.config } : {};
582
- const config = resolveI18nConfig(root, inlineConfig);
641
+ const config = resolveDialexConfig(root, inlineConfig);
583
642
  const include = config.include || "**/*.content.ts";
584
643
  const configuredLocales = config.locales || [];
585
644
  const defaultLocale = config.defaultLocale || "en";
@@ -684,7 +743,7 @@ async function runExport(options = {}) {
684
743
  "csv",
685
744
  "xliff"
686
745
  ].includes(format)) throw new Error(`Unsupported format "${format}". Use json, csv, or xliff.`);
687
- const outDir = path.resolve(root, options.out || "i18n-export");
746
+ const outDir = path.resolve(root, options.out || "dialex-export");
688
747
  const project = await loadProject(root, options.config);
689
748
  const defaultLocale = project.config.defaultLocale || "en";
690
749
  const table = /* @__PURE__ */ new Map();
@@ -1045,7 +1104,7 @@ async function runTranslate(options = {}) {
1045
1104
  //#endregion
1046
1105
  //#region src/index.ts
1047
1106
  const program = new Command();
1048
- program.name("dialex").description("Dialex CLI - High-performance, type-safe internationalization compiler and tooling").version("0.2.3");
1107
+ program.name("dialex").description("Dialex CLI - High-performance, type-safe internationalization compiler and tooling").version("0.3.0");
1049
1108
  program.command("generate").alias("gen").description("Generate standalone dictionary bundle and TypeScript declarations").option("-w, --watch", "Watch dictionary files for changes").option("-o, --output <path>", "Custom output file path for generated dictionaries").option("-c, --config <path>", "Custom config path").option("--json", "Print machine-readable JSON").action(async (opts) => {
1050
1109
  await runGenerate(opts);
1051
1110
  });
@@ -1055,7 +1114,7 @@ program.command("init").description("Initialize Dialex in the current project").
1055
1114
  program.command("check").alias("lint").description("Verify dictionary key parity and locale completeness").option("-c, --config <path>", "Custom config path").option("--json", "Print machine-readable JSON").option("--github", "Print GitHub Actions annotations").option("--fix", "Insert missing keys marked with [TODO]").option("--src <globs...>", "Source globs to scan for dictionary references").action(async (opts) => {
1056
1115
  await runCheck(opts);
1057
1116
  });
1058
- program.command("export").description("Export dictionary strings for translators (json, csv, or xliff)").option("-f, --format <format>", "Output format: json, csv, xliff", "json").option("-o, --out <dir>", "Output directory", "i18n-export").option("-l, --locale <locales...>", "Limit to these locales").option("-c, --config <path>", "Custom config path").option("--json", "Print machine-readable JSON").action(async (opts) => {
1117
+ program.command("export").description("Export dictionary strings for translators (json, csv, or xliff)").option("-f, --format <format>", "Output format: json, csv, xliff", "json").option("-o, --out <dir>", "Output directory", "dialex-export").option("-l, --locale <locales...>", "Limit to these locales").option("-c, --config <path>", "Custom config path").option("--json", "Print machine-readable JSON").action(async (opts) => {
1059
1118
  await runExport(opts);
1060
1119
  });
1061
1120
  program.command("import <file>").description("Write translated strings from a json, csv, or xliff file back into dictionaries").option("-f, --format <format>", "Input format (inferred from the extension)").option("-l, --locale <locale>", "Locale for single-locale files").option("--allow-new", "Add keys that do not exist in any locale yet").option("-c, --config <path>", "Custom config path").option("--json", "Print machine-readable JSON").action(async (file, opts) => {
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/utils/detector.ts","../src/commands/init.ts","../src/commands/check.ts","../src/commands/export.ts","../src/commands/import.ts","../src/translate/placeholders.ts","../src/commands/translate.ts","../src/index.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\n\nexport type SupportedFramework =\n | \"next\"\n | \"react\"\n | \"hono\"\n | \"express\"\n | \"fastify\"\n | \"koa\"\n | \"nestjs\"\n | \"elysia\"\n | \"sveltekit\"\n | \"astro\"\n | \"vue\"\n | \"nuxt\";\n\nexport interface DetectedFramework {\n framework: SupportedFramework;\n confidence: \"high\" | \"medium\" | \"fallback\";\n matchedRule: string;\n}\n\n/**\n * Automatically inspects package.json dependencies and configuration files\n * to detect the active framework in the target project.\n */\nexport function detectFramework(root: string): DetectedFramework {\n const pkgPath = path.join(root, \"package.json\");\n if (fs.existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf-8\"));\n const allDeps = {\n ...pkg.dependencies,\n ...pkg.devDependencies,\n };\n\n if (\"nuxt\" in allDeps) {\n return {\n framework: \"nuxt\",\n confidence: \"high\",\n matchedRule: \"package.json dependencies (nuxt)\",\n };\n }\n if (\"@sveltejs/kit\" in allDeps) {\n return {\n framework: \"sveltekit\",\n confidence: \"high\",\n matchedRule: \"package.json dependencies (@sveltejs/kit)\",\n };\n }\n if (\"astro\" in allDeps) {\n return {\n framework: \"astro\",\n confidence: \"high\",\n matchedRule: \"package.json dependencies (astro)\",\n };\n }\n if (\"next\" in allDeps) {\n return {\n framework: \"next\",\n confidence: \"high\",\n matchedRule: \"package.json dependencies (next)\",\n };\n }\n if (\"@nestjs/core\" in allDeps || \"@nestjs/common\" in allDeps) {\n return {\n framework: \"nestjs\",\n confidence: \"high\",\n matchedRule: \"package.json dependencies (@nestjs/core)\",\n };\n }\n if (\"fastify\" in allDeps) {\n return {\n framework: \"fastify\",\n confidence: \"high\",\n matchedRule: \"package.json dependencies (fastify)\",\n };\n }\n if (\"koa\" in allDeps) {\n return {\n framework: \"koa\",\n confidence: \"high\",\n matchedRule: \"package.json dependencies (koa)\",\n };\n }\n if (\"express\" in allDeps) {\n return {\n framework: \"express\",\n confidence: \"high\",\n matchedRule: \"package.json dependencies (express)\",\n };\n }\n if (\"elysia\" in allDeps) {\n return {\n framework: \"elysia\",\n confidence: \"high\",\n matchedRule: \"package.json dependencies (elysia)\",\n };\n }\n if (\"hono\" in allDeps) {\n return {\n framework: \"hono\",\n confidence: \"high\",\n matchedRule: \"package.json dependencies (hono)\",\n };\n }\n if (\"vue\" in allDeps && !(\"react\" in allDeps)) {\n return {\n framework: \"vue\",\n confidence: \"high\",\n matchedRule: \"package.json dependencies (vue)\",\n };\n }\n if (\"react\" in allDeps || \"vite\" in allDeps) {\n return {\n framework: \"react\",\n confidence: \"high\",\n matchedRule: \"package.json dependencies (react/vite)\",\n };\n }\n } catch {\n // Ignore JSON parse errors\n }\n }\n\n // Check filesystem configurations\n if (\n fs.existsSync(path.join(root, \"next.config.js\")) ||\n fs.existsSync(path.join(root, \"next.config.mjs\")) ||\n fs.existsSync(path.join(root, \"next.config.ts\"))\n ) {\n return {\n framework: \"next\",\n confidence: \"medium\",\n matchedRule: \"next.config file presence\",\n };\n }\n\n const configRules: [SupportedFramework, string][] = [\n [\"nuxt\", \"nuxt.config\"],\n [\"sveltekit\", \"svelte.config\"],\n [\"astro\", \"astro.config\"],\n ];\n for (const [framework, base] of configRules) {\n if ([\"js\", \"mjs\", \"ts\"].some((ext) => fs.existsSync(path.join(root, `${base}.${ext}`)))) {\n return { framework, confidence: \"medium\", matchedRule: `${base} file presence` };\n }\n }\n\n if (\n fs.existsSync(path.join(root, \"vite.config.js\")) ||\n fs.existsSync(path.join(root, \"vite.config.mjs\")) ||\n fs.existsSync(path.join(root, \"vite.config.ts\"))\n ) {\n return {\n framework: \"react\",\n confidence: \"medium\",\n matchedRule: \"vite.config file presence\",\n };\n }\n\n return {\n framework: \"hono\",\n confidence: \"fallback\",\n matchedRule: \"default fallback\",\n };\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\nimport { parseModule, loadFile, writeFile } from \"magicast\";\nimport { addNuxtModule, addVitePlugin } from \"magicast/helpers\";\nimport { generateDictionaries } from \"./generate.js\";\nimport { detectFramework, type SupportedFramework } from \"../utils/detector.js\";\nimport { logger } from \"../utils/logger.js\";\n\nexport interface InitOptions {\n cwd?: string;\n framework?: string;\n defaultLocale?: string;\n locales?: string;\n yes?: boolean;\n ai?: boolean;\n noAi?: boolean;\n}\n\nexport async function runInit(options: InitOptions = {}) {\n const root = options.cwd || process.cwd();\n const detected = detectFramework(root);\n const isInteractive = !options.yes && process.stdin.isTTY;\n\n let framework = (options.framework as SupportedFramework) || detected.framework;\n let defaultLocale = options.defaultLocale || \"en\";\n let localesInput = options.locales || \"en,tr\";\n\n if (isInteractive) {\n p.intro(pc.bgCyan(pc.black(\" dialex init \")));\n\n const frameworkOptions: { value: SupportedFramework; label: string; hint?: string }[] = [\n {\n value: \"hono\",\n label: \"Hono\",\n hint: detected.framework === \"hono\" ? \"detected\" : undefined,\n },\n {\n value: \"express\",\n label: \"Express\",\n hint: detected.framework === \"express\" ? \"detected\" : undefined,\n },\n {\n value: \"fastify\",\n label: \"Fastify\",\n hint: detected.framework === \"fastify\" ? \"detected\" : undefined,\n },\n {\n value: \"koa\",\n label: \"Koa\",\n hint: detected.framework === \"koa\" ? \"detected\" : undefined,\n },\n {\n value: \"nestjs\",\n label: \"NestJS\",\n hint: detected.framework === \"nestjs\" ? \"detected\" : undefined,\n },\n {\n value: \"next\",\n label: \"Next.js\",\n hint: detected.framework === \"next\" ? \"detected\" : undefined,\n },\n {\n value: \"react\",\n label: \"React / Vite\",\n hint: detected.framework === \"react\" ? \"detected\" : undefined,\n },\n {\n value: \"elysia\",\n label: \"Elysia\",\n hint: detected.framework === \"elysia\" ? \"detected\" : undefined,\n },\n {\n value: \"sveltekit\",\n label: \"SvelteKit\",\n hint: detected.framework === \"sveltekit\" ? \"detected\" : undefined,\n },\n {\n value: \"astro\",\n label: \"Astro\",\n hint: detected.framework === \"astro\" ? \"detected\" : undefined,\n },\n {\n value: \"vue\",\n label: \"Vue / Vite\",\n hint: detected.framework === \"vue\" ? \"detected\" : undefined,\n },\n {\n value: \"nuxt\",\n label: \"Nuxt\",\n hint: detected.framework === \"nuxt\" ? \"detected\" : undefined,\n },\n ];\n\n const selectedFramework = await p.select({\n message: `Framework detected as ${pc.bold(detected.framework)} (${detected.matchedRule}). Select framework:`,\n options: frameworkOptions,\n initialValue: detected.framework,\n });\n\n if (p.isCancel(selectedFramework)) {\n p.cancel(\"Operation cancelled.\");\n return;\n }\n framework = selectedFramework as SupportedFramework;\n\n const inputDefault = await p.text({\n message: \"What is your default locale?\",\n initialValue: \"en\",\n validate: (v) => (!v || !v.trim() ? \"Default locale cannot be empty\" : undefined),\n });\n\n if (p.isCancel(inputDefault)) {\n p.cancel(\"Operation cancelled.\");\n return;\n }\n defaultLocale = inputDefault.trim();\n\n const inputLocales = await p.text({\n message: \"Comma-separated list of supported locales:\",\n initialValue: `${defaultLocale},tr`,\n validate: (v) => (!v || !v.trim() ? \"Locales list cannot be empty\" : undefined),\n });\n\n if (p.isCancel(inputLocales)) {\n p.cancel(\"Operation cancelled.\");\n return;\n }\n localesInput = inputLocales.trim();\n\n if (options.ai === undefined && options.noAi === undefined) {\n const confirmAi = await p.confirm({\n message: \"Configure AI agent support (Claude/Cursor skills, .mcp.json, AGENTS.md)?\",\n initialValue: true,\n });\n if (!p.isCancel(confirmAi)) {\n options.ai = confirmAi;\n }\n }\n } else {\n logger.info(`Auto-detected framework: ${pc.bold(framework)} (${detected.matchedRule})`);\n }\n\n const localeList = Array.from(\n new Set([\n defaultLocale,\n ...localesInput\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean),\n ]),\n );\n\n // 1. AST generation or update for dialex.config.ts / i18n.config.ts via Magicast\n const configPath = fs.existsSync(path.join(root, \"dialex.config.ts\"))\n ? path.join(root, \"dialex.config.ts\")\n : fs.existsSync(path.join(root, \"i18n.config.ts\"))\n ? path.join(root, \"i18n.config.ts\")\n : path.join(root, \"dialex.config.ts\");\n const configFileName = path.basename(configPath);\n\n try {\n if (fs.existsSync(configPath)) {\n const mod = await loadFile(configPath);\n if (mod && mod.exports.default) {\n if (mod.exports.default.$args && mod.exports.default.$args[0]) {\n mod.exports.default.$args[0].defaultLocale = defaultLocale;\n mod.exports.default.$args[0].locales = localeList;\n }\n await writeFile(mod, configPath);\n logger.success(`Updated ${pc.bold(configFileName)} via Magicast`);\n }\n } else {\n const mod = parseModule(`import { defineConfig } from \"dialexjs\";\n\nexport default defineConfig({});\n`);\n mod.exports.default.$args[0].defaultLocale = defaultLocale;\n mod.exports.default.$args[0].locales = localeList;\n await writeFile(mod, configPath);\n logger.success(`Created ${pc.bold(configFileName)} via Magicast`);\n }\n } catch (err: any) {\n logger.warn(`Magicast config update notice: ${err.message || String(err)}`);\n // Fallback safe string write if AST parser encounters non-standard syntax\n const fallback = `import { defineConfig } from \"dialexjs\";\n\nexport default defineConfig({\n defaultLocale: \"${defaultLocale}\",\n locales: [${localeList.map((l) => `\"${l}\"`).join(\", \")}],\n});\n`;\n fs.writeFileSync(configPath, fallback, \"utf-8\");\n }\n\n // 2. Magicast AST injection for Vite and Nuxt projects\n if (framework === \"react\" || framework === \"vue\") {\n const possibleViteConfigs = [\n path.join(root, \"vite.config.ts\"),\n path.join(root, \"vite.config.js\"),\n path.join(root, \"vite.config.mjs\"),\n ];\n for (const vConfig of possibleViteConfigs) {\n if (fs.existsSync(vConfig)) {\n try {\n const vMod = await loadFile(vConfig);\n addVitePlugin(vMod, {\n from: \"dialexjs/vite\",\n imported: \"i18nPlugin\",\n constructor: \"i18nPlugin\",\n });\n await writeFile(vMod, vConfig);\n logger.success(\n `Injected i18nPlugin() into ${pc.bold(path.basename(vConfig))} via Magicast`,\n );\n break;\n } catch {\n // If already added or non-standard, continue\n }\n }\n }\n }\n\n if (framework === \"nuxt\") {\n const nuxtConfig = [\"nuxt.config.ts\", \"nuxt.config.js\", \"nuxt.config.mjs\"]\n .map((f) => path.join(root, f))\n .find((f) => fs.existsSync(f));\n if (nuxtConfig) {\n try {\n const nMod = await loadFile(nuxtConfig);\n addNuxtModule(nMod, \"dialexjs/nuxt\", \"dialex\", {\n defaultLocale,\n locales: localeList,\n });\n await writeFile(nMod, nuxtConfig);\n logger.success(\n `Registered dialexjs/nuxt in ${pc.bold(path.basename(nuxtConfig))} via Magicast`,\n );\n } catch {\n logger.warn(\"Could not update the Nuxt config; add the dialexjs/nuxt module manually.\");\n }\n }\n }\n\n // 3. Create starter dictionary in src/ (or root)\n const targetDir = fs.existsSync(path.join(root, \"src\")) ? path.join(root, \"src\") : root;\n const dictPath = path.join(targetDir, \"home.content.ts\");\n if (!fs.existsSync(dictPath)) {\n const dictRecords = localeList\n .map(\n (loc) => ` ${loc}: {\n title: \"Welcome to Dialex (${loc})!\",\n description: \"Type-safe internationalization.\",\n greeting: (name: string) => \"Hello, \" + name + \"!\",\n },`,\n )\n .join(\"\\n\");\n\n const dictContent = `import { defineDictionary } from \"dialexjs\";\n\nexport default defineDictionary(\"home\", {\n${dictRecords}\n});\n`;\n fs.writeFileSync(dictPath, dictContent, \"utf-8\");\n logger.success(`Created starter dictionary at ${pc.bold(path.relative(root, dictPath))}`);\n } else {\n logger.info(\"home.content.ts already exists, skipping creation.\");\n }\n\n // 4. Run standalone dictionary generation immediately\n generateDictionaries(root);\n logger.success(\"Generated types and standalone dictionary registry!\");\n\n // 5. Update package.json scripts\n const pkgPath = path.join(root, \"package.json\");\n if (fs.existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf-8\"));\n pkg.scripts = pkg.scripts || {};\n if (!pkg.scripts[\"dx:generate\"]) {\n pkg.scripts[\"dx:generate\"] = \"dx generate\";\n fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + \"\\n\", \"utf-8\");\n logger.success('Added \"dx:generate\" script to package.json');\n }\n } catch {\n // Ignore JSON parse errors\n }\n }\n\n // 6. AI Agent Integration (.agents/skills, .mcp.json, AGENTS.md)\n const shouldSetupAi =\n options.ai === true || (options.yes && options.ai !== false && options.noAi !== true);\n if (shouldSetupAi) {\n try {\n // 6a. Copy or create skill in .agents/skills/dialex/SKILL.md\n const skillDir = path.join(root, \".agents/skills/dialex\");\n fs.mkdirSync(skillDir, { recursive: true });\n const skillContent = `---\nname: dialex\ndescription: Guide for internationalizing JavaScript and TypeScript apps with Dialex. Use when adding translations, creating content dictionaries, configuring locales, or using Dialex with frameworks like Next.js, React, Express, Hono, Fastify, SvelteKit, and Nuxt.\n---\n\n# Dialex Internationalization\n\nDialex is a high-performance, type-safe internationalization toolchain for JavaScript and TypeScript.\n\n## Core Concepts\n- Dictionaries are defined with \\`defineDictionary(\"name\", { ... })\\` in \\`*.content.ts\\` files.\n- Keys must match across all locales.\n- ICU message syntax is supported for plurals and selects.\n- Parity is validated at compile time with \\`dialex check\\`.\n\n## Useful Commands\n- \\`dialex check --json\\`: Check dictionary parity and references.\n- \\`dialex check --fix\\`: Automatically insert missing keys marked with [TODO].\n- \\`dialex generate\\`: Rebuild standalone dictionary bundle and types.\n- \\`dialex translate --locale <locale>\\`: Automatically translate missing keys.\n`;\n fs.writeFileSync(path.join(skillDir, \"SKILL.md\"), skillContent, \"utf-8\");\n\n // 6b. Merge .mcp.json\n const mcpConfigPath = path.join(root, \".mcp.json\");\n let mcpConfig: Record<string, any> = {};\n if (fs.existsSync(mcpConfigPath)) {\n try {\n mcpConfig = JSON.parse(fs.readFileSync(mcpConfigPath, \"utf-8\"));\n } catch {\n mcpConfig = {};\n }\n }\n mcpConfig.mcpServers = mcpConfig.mcpServers || {};\n mcpConfig.mcpServers.dialex = mcpConfig.mcpServers.dialex || {\n command: \"npx\",\n args: [\"@dialexjs/mcp\"],\n };\n fs.writeFileSync(mcpConfigPath, JSON.stringify(mcpConfig, null, 2) + \"\\n\", \"utf-8\");\n\n // 6c. Add snippet to AGENTS.md if absent\n const agentsMdPath = path.join(root, \"AGENTS.md\");\n const dialexAgentSnippet = `\n## Internationalization (Dialex)\n\nThis project uses [Dialex](https://github.com/awaiden/dialex) for type-safe internationalization.\n- Dictionaries are in \\`*.content.ts\\` files using \\`defineDictionary\\`.\n- Run \\`dialex check --json\\` to verify parity.\n- Run \\`dialex check --fix\\` to insert missing keys marked with \\`[TODO]\\`.\n- Run \\`dx generate\\` (alias of \\`dialex\\`) or \\`npm run dx:generate\\` to compile dictionary bundles and update types.\n`;\n if (!fs.existsSync(agentsMdPath)) {\n fs.writeFileSync(agentsMdPath, dialexAgentSnippet.trimStart(), \"utf-8\");\n } else {\n const existing = fs.readFileSync(agentsMdPath, \"utf-8\");\n if (!existing.includes(\"Dialex\")) {\n fs.writeFileSync(agentsMdPath, existing.trimEnd() + \"\\n\" + dialexAgentSnippet, \"utf-8\");\n }\n }\n\n logger.success(\"Configured AI assistant support (.agents/skills, .mcp.json, AGENTS.md)\");\n } catch (err: any) {\n logger.warn(`Could not finish AI configuration: ${err.message || String(err)}`);\n }\n }\n\n // 7. Framework-specific quickstart instructions\n logger.log(\"\");\n logger.info(pc.bold(`Quick start for ${framework.toUpperCase()}:`));\n\n switch (framework) {\n case \"hono\":\n logger.log(`\nimport { Hono } from \"hono\";\nimport { i18n } from \"dialexjs/hono\";\nimport dictionaries from \"./src/dialex.generated.js\";\n\nconst app = new Hono();\napp.use(\"*\", i18n({ dictionaries }));\n\napp.get(\"/\", (c) => {\n const dict = c.var.getDictionary(\"home\");\n return c.json({ title: dict.title });\n});\n`);\n break;\n case \"fastify\":\n logger.log(`\nimport Fastify from \"fastify\";\nimport { i18nPlugin } from \"dialexjs/fastify\";\nimport dictionaries from \"./src/dialex.generated.js\";\n\nconst app = Fastify();\nawait app.register(i18nPlugin, { dictionaries });\n\napp.get(\"/\", (req) => {\n const dict = req.getDictionary(\"home\");\n return { title: dict.title };\n});\n`);\n break;\n case \"express\":\n logger.log(`\nimport express from \"express\";\nimport { i18n } from \"dialexjs/express\";\nimport dictionaries from \"./src/dialex.generated.js\";\n\nconst app = express();\napp.use(i18n({ dictionaries }));\n\napp.get(\"/\", (req, res) => {\n const dict = req.getDictionary(\"home\");\n res.json({ title: dict.title });\n});\n`);\n break;\n case \"koa\":\n logger.log(`\nimport Koa from \"koa\";\nimport { i18n } from \"dialexjs/koa\";\nimport dictionaries from \"./src/dialex.generated.js\";\n\nconst app = new Koa();\napp.use(i18n({ dictionaries }));\n\napp.use((ctx) => {\n const dict = ctx.getDictionary(\"home\");\n ctx.body = { title: dict.title };\n});\n`);\n break;\n case \"nestjs\":\n logger.log(`\nimport { Module } from \"@nestjs/common\";\nimport { I18nModule } from \"dialexjs/nestjs\";\nimport dictionaries from \"./src/dialex.generated.js\";\n\n@Module({\n imports: [I18nModule.forRoot({ dictionaries })],\n})\nexport class AppModule {}\n`);\n break;\n case \"next\":\n logger.log(`\nimport { getDictionary } from \"dialexjs/server\";\n\nexport default async function Page({ params }: { params: Promise<{ locale: string }> }) {\n const { locale = \"en\" } = await params;\n const dict = getDictionary(\"home\", locale);\n return <h1>{dict.title}</h1>;\n}\n`);\n break;\n case \"elysia\":\n logger.log(`\nimport { Elysia } from \"elysia\";\nimport { i18n } from \"dialexjs/elysia\";\nimport dictionaries from \"./src/dialex.generated.js\";\n\nnew Elysia()\n .use(i18n({ dictionaries }))\n .get(\"/\", ({ getDictionary }) => ({ title: getDictionary(\"home\").title }))\n .listen(3000);\n`);\n break;\n case \"sveltekit\":\n logger.log(`\n// src/hooks.server.ts\nimport { i18nHandle } from \"dialexjs/sveltekit\";\nimport dictionaries from \"./dialex.generated.js\";\n\nexport const handle = i18nHandle({ dictionaries });\n\n// src/app.html: <html lang=\"%dialex.lang%\">\n// In load functions: locals.getDictionary(\"home\")\n`);\n break;\n case \"astro\":\n logger.log(`\n// src/middleware.ts\nimport { i18n } from \"dialexjs/astro\";\nimport dictionaries from \"./dialex.generated.js\";\n\nexport const onRequest = i18n({ dictionaries });\n\n// In pages: Astro.locals.getDictionary(\"home\")\n`);\n break;\n case \"vue\":\n logger.log(`\n// src/main.ts\nimport { createApp } from \"vue\";\nimport { createI18n } from \"dialexjs/vue\";\nimport App from \"./App.vue\";\n\ncreateApp(App).use(createI18n()).mount(\"#app\");\n\n// In components: const dict = useDictionary(\"home\")\n`);\n break;\n case \"nuxt\":\n logger.log(`\n// nuxt.config.ts\nexport default defineNuxtConfig({\n modules: [\"dialexjs/nuxt\"],\n});\n\n// In components: const dict = useDictionary(\"home\")\n`);\n break;\n default:\n logger.log(`\nImport dictionaries and register your framework middleware to begin!\nRun \\`npm run dx:generate\\` whenever you add new dictionary files.\n`);\n break;\n }\n\n if (isInteractive) {\n p.outro(pc.green(\"✔ dialex is configured and ready to go!\"));\n }\n}\n","import path from \"node:path\";\nimport fg from \"fast-glob\";\nimport pc from \"picocolors\";\nimport { resolveI18nConfig } from \"dialexjs/scanner\";\nimport { analyzeProject, type AnalysisIssue } from \"../analysis.js\";\nimport { logger } from \"../utils/logger.js\";\nimport {\n TODO_PREFIX,\n copyLeaf,\n hasPath,\n listLeaves,\n listLocales,\n loadDictionaryFile,\n saveDictionaryFile,\n} from \"../utils/dictionary-edit.js\";\n\nexport interface CheckOptions {\n cwd?: string;\n config?: string;\n exitOnError?: boolean;\n /** Print machine-readable JSON instead of human output. */\n json?: boolean;\n /** Also print GitHub Actions workflow annotations. */\n github?: boolean;\n /** Insert missing keys (marked with `[TODO]`) before checking. */\n fix?: boolean;\n /** Globs of source files to scan for dictionary references. */\n src?: string[];\n}\n\nexport interface CheckAnnotation {\n level: \"error\" | \"warning\";\n message: string;\n line?: number;\n}\n\nexport interface CheckDiagnostic {\n file: string;\n name?: string;\n errors: string[];\n warnings: string[];\n annotations: CheckAnnotation[];\n}\n\nexport interface CheckResult {\n success: boolean;\n diagnostics: CheckDiagnostic[];\n totalIssues: number;\n totalWarnings: number;\n /** Number of missing keys inserted by `--fix`. */\n fixed: number;\n}\n\nconst DICTIONARY_IGNORE = [\"**/node_modules/**\", \"**/dist/**\", \"**/.next/**\"];\n\nfunction addIssue(diag: CheckDiagnostic, issue: AnalysisIssue) {\n const level = issue.level === \"error\" ? \"error\" : \"warning\";\n (level === \"error\" ? diag.errors : diag.warnings).push(issue.message);\n diag.annotations.push({\n level,\n message: issue.message,\n line: issue.range ? issue.range.start.line + 1 : undefined,\n });\n}\n\n/**\n * Inserts keys that exist in one locale but not in another, copying the default-locale value\n * (strings get a `[TODO]` prefix). Returns how many keys were inserted.\n */\nasync function applyFixes(\n files: string[],\n configuredLocales: string[],\n defaultLocale: string,\n): Promise<number> {\n let fixed = 0;\n\n for (const file of files) {\n const df = await loadDictionaryFile(file);\n // Spreads and computed keys hide keys from the syntax tree; inserting would be guesswork.\n if (!df?.complete) continue;\n\n const present = listLocales(df);\n const targets = Array.from(new Set([...present, ...configuredLocales]));\n const sourceOrder = [defaultLocale, ...present.filter((l) => l !== defaultLocale)].filter((l) =>\n present.includes(l),\n );\n\n const allPaths = new Map<string, string[]>();\n for (const locale of present) {\n for (const leaf of listLeaves(df, locale)) allPaths.set(leaf.path.join(\"\\u0000\"), leaf.path);\n }\n\n let changed = false;\n for (const target of targets) {\n for (const leafPath of allPaths.values()) {\n if (hasPath(df, target, leafPath)) continue;\n const source = sourceOrder.find((l) => l !== target && hasPath(df, l, leafPath));\n if (source && copyLeaf(df, source, target, leafPath, (v) => `${TODO_PREFIX}${v}`)) {\n fixed++;\n changed = true;\n }\n }\n }\n\n if (changed) await saveDictionaryFile(df);\n }\n\n return fixed;\n}\n\nfunction escapeAnnotation(value: string): string {\n return value.replace(/%/g, \"%25\").replace(/\\r/g, \"%0D\").replace(/\\n/g, \"%0A\");\n}\n\nexport async function runCheck(options: CheckOptions = {}): Promise<CheckResult> {\n const root = options.cwd || process.cwd();\n const quiet = options.json === true;\n const inlineConfig = options.config ? { configFile: options.config } : {};\n const config = resolveI18nConfig(root, inlineConfig);\n const include = config.include || \"**/*.content.ts\";\n const configuredLocales = config.locales || [];\n const defaultLocale = config.defaultLocale || \"en\";\n\n const files = fg.sync(include, { cwd: root, absolute: true, ignore: DICTIONARY_IGNORE });\n\n if (files.length === 0) {\n if (!quiet) {\n const patternStr = Array.isArray(include) ? include.join(\", \") : include;\n logger.warn(`No dictionary files found matching \"${patternStr}\".`);\n }\n const empty: CheckResult = {\n success: true,\n diagnostics: [],\n totalIssues: 0,\n totalWarnings: 0,\n fixed: 0,\n };\n if (quiet) console.log(JSON.stringify(empty, null, 2));\n return empty;\n }\n\n let fixed = 0;\n if (options.fix) {\n fixed = await applyFixes(files, configuredLocales, defaultLocale);\n if (fixed > 0 && !quiet) {\n logger.success(\n `Inserted ${fixed} missing key${fixed === 1 ? \"\" : \"s\"} marked ${TODO_PREFIX.trim()}`,\n );\n }\n }\n\n const analysis = await analyzeProject({\n root,\n config,\n src: options.src && options.src.length > 0 ? options.src : undefined,\n runtime: true,\n });\n\n // Group issues per file, dictionary files first (the analysis reports them first)\n const byFile = new Map<string, CheckDiagnostic>();\n const dictionaryFiles = new Set(analysis.files);\n for (const issue of analysis.issues) {\n if (issue.level === \"info\") continue;\n const rel = path.relative(root, issue.file);\n let diag = byFile.get(rel);\n if (!diag) {\n diag = { file: rel, errors: [], warnings: [], annotations: [] };\n byFile.set(rel, diag);\n }\n if (dictionaryFiles.has(issue.file) && issue.dictionary && !diag.name)\n diag.name = issue.dictionary;\n addIssue(diag, issue);\n }\n const diagnostics = [...byFile.values()];\n\n const totalIssues = diagnostics.reduce((n, d) => n + d.errors.length, 0);\n const totalWarnings = diagnostics.reduce((n, d) => n + d.warnings.length, 0);\n const reported = diagnostics.filter((d) => d.errors.length > 0 || d.warnings.length > 0);\n const result: CheckResult = {\n success: totalIssues === 0,\n diagnostics: reported,\n totalIssues,\n totalWarnings,\n fixed,\n };\n\n if (options.github) {\n for (const d of reported) {\n for (const a of d.annotations) {\n const location = `file=${d.file}${a.line ? `,line=${a.line}` : \"\"}`;\n console.log(`::${a.level} ${location},title=dialex::${escapeAnnotation(a.message)}`);\n }\n }\n }\n\n if (quiet) {\n console.log(JSON.stringify(result, null, 2));\n } else if (reported.length > 0) {\n logger.log(\"\");\n if (totalIssues > 0) {\n logger.error(\n `Found ${totalIssues} issue${totalIssues === 1 ? \"\" : \"s\"} across ${reported.filter((d) => d.errors.length > 0).length} file${reported.length === 1 ? \"\" : \"s\"}:`,\n );\n }\n logger.log(\"\");\n\n for (const d of reported) {\n logger.log(` ${pc.underline(pc.bold(d.file))} ${d.name ? pc.dim(`(${d.name})`) : \"\"}:`);\n for (const a of d.annotations) {\n const where = a.line ? pc.dim(`:${a.line}`) : \"\";\n const mark = a.level === \"error\" ? pc.red(\"✖\") : pc.yellow(\"⚠\");\n logger.log(` ${mark} ${a.message}${where}`);\n }\n logger.log(\"\");\n }\n }\n\n if (totalIssues > 0) {\n if (options.exitOnError !== false) process.exit(1);\n return result;\n }\n\n if (!quiet) {\n const warningNote =\n totalWarnings > 0 ? ` (${totalWarnings} warning${totalWarnings === 1 ? \"\" : \"s\"})` : \"\";\n logger.success(\n `All ${files.length} dictionary file${files.length === 1 ? \"\" : \"s\"} passed checks with 0 issues${warningNote}!`,\n );\n }\n return result;\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { listLeaves, listLocales } from \"../utils/dictionary-edit.js\";\nimport { loadProject, toKey } from \"../utils/project.js\";\nimport { logger } from \"../utils/logger.js\";\n\nexport type TranslationFormat = \"json\" | \"csv\" | \"xliff\";\n\nexport interface ExportOptions {\n cwd?: string;\n config?: string;\n format?: TranslationFormat;\n /** Output directory, relative to `cwd`. */\n out?: string;\n /** Limit the export to these locales. */\n locale?: string[];\n /** Print machine-readable JSON instead of human output. */\n json?: boolean;\n}\n\nexport interface ExportResult {\n success: boolean;\n files: string[];\n keys: number;\n /** Function values cannot be exported as plain text. */\n skippedFunctions: number;\n skippedFiles: string[];\n}\n\nexport const escapeXml = (value: string) =>\n value.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\").replace(/\"/g, \"&quot;\");\n\nexport const csvCell = (value: string) =>\n /[\",\\r\\n]/.test(value) ? `\"${value.replace(/\"/g, '\"\"')}\"` : value;\n\nexport async function runExport(options: ExportOptions = {}): Promise<ExportResult> {\n const root = options.cwd || process.cwd();\n const format = options.format || \"json\";\n if (![\"json\", \"csv\", \"xliff\"].includes(format)) {\n throw new Error(`Unsupported format \"${format}\". Use json, csv, or xliff.`);\n }\n const outDir = path.resolve(root, options.out || \"i18n-export\");\n\n const project = await loadProject(root, options.config);\n const defaultLocale = project.config.defaultLocale || \"en\";\n\n // locale -> key -> value (insertion order = source order)\n const table = new Map<string, Map<string, string>>();\n const orderedKeys = new Set<string>();\n let skippedFunctions = 0;\n\n const localeSet = new Set<string>(project.config.locales || []);\n for (const { df } of project.dictionaries) listLocales(df).forEach((l) => localeSet.add(l));\n let locales = Array.from(localeSet);\n if (options.locale && options.locale.length > 0) {\n locales = locales.filter((l) => options.locale!.includes(l) || l === defaultLocale);\n }\n for (const locale of locales) table.set(locale, new Map());\n\n for (const { name, df } of project.dictionaries) {\n for (const locale of listLocales(df)) {\n if (!table.has(locale)) continue;\n for (const leaf of listLeaves(df, locale)) {\n if (leaf.kind === \"string\" && leaf.value !== undefined) {\n const key = toKey(name, leaf.path);\n table.get(locale)!.set(key, leaf.value);\n orderedKeys.add(key);\n } else if (locale === defaultLocale) {\n skippedFunctions++;\n }\n }\n }\n }\n\n fs.mkdirSync(outDir, { recursive: true });\n const files: string[] = [];\n const write = (name: string, content: string) => {\n const file = path.join(outDir, name);\n fs.writeFileSync(file, content, \"utf-8\");\n files.push(path.relative(root, file));\n };\n\n if (format === \"json\") {\n for (const [locale, values] of table) {\n write(`${locale}.json`, JSON.stringify(Object.fromEntries(values), null, 2) + \"\\n\");\n }\n } else if (format === \"csv\") {\n const header = [\"key\", ...table.keys()].map(csvCell).join(\",\");\n const rows = [...orderedKeys].map((key) =>\n [key, ...[...table.values()].map((v) => v.get(key) ?? \"\")].map(csvCell).join(\",\"),\n );\n write(\"translations.csv\", [header, ...rows].join(\"\\n\") + \"\\n\");\n } else {\n const source = table.get(defaultLocale);\n for (const [locale, values] of table) {\n if (locale === defaultLocale) continue;\n const units = [...orderedKeys].map((key) => {\n const src = source?.get(key) ?? \"\";\n const target = values.get(key);\n const targetXml = target === undefined ? \"\" : `<target>${escapeXml(target)}</target>`;\n return ` <trans-unit id=\"${escapeXml(key)}\"><source>${escapeXml(src)}</source>${targetXml}</trans-unit>`;\n });\n write(\n `${locale}.xlf`,\n `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<xliff version=\"1.2\" xmlns=\"urn:oasis:names:tc:xliff:document:1.2\">\n <file original=\"dialex\" source-language=\"${escapeXml(defaultLocale)}\" target-language=\"${escapeXml(locale)}\" datatype=\"plaintext\">\n <body>\n${units.join(\"\\n\")}\n </body>\n </file>\n</xliff>\n`,\n );\n }\n }\n\n const quiet = options.json === true;\n\n const result: ExportResult = {\n success: true,\n files,\n keys: orderedKeys.size,\n skippedFunctions,\n skippedFiles: project.unsupported,\n };\n\n if (quiet) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n logger.success(\n `Exported ${orderedKeys.size} key${orderedKeys.size === 1 ? \"\" : \"s\"} to ${files.length} ${format} file${files.length === 1 ? \"\" : \"s\"} in ${path.relative(root, outDir) || \".\"}`,\n );\n if (skippedFunctions > 0) {\n logger.warn(\n `${skippedFunctions} function value${skippedFunctions === 1 ? \"\" : \"s\"} skipped (not translatable as text)`,\n );\n }\n for (const file of project.unsupported)\n logger.warn(`Skipped ${file}: unsupported dictionary shape`);\n }\n\n return result;\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport {\n getString,\n hasPath,\n listLocales,\n saveDictionaryFile,\n setString,\n} from \"../utils/dictionary-edit.js\";\nimport { argumentSignature, parseMessage } from \"dialexjs/icu\";\nimport { loadProject } from \"../utils/project.js\";\nimport { logger } from \"../utils/logger.js\";\nimport type { TranslationFormat } from \"./export.js\";\n\nexport interface ImportOptions {\n cwd?: string;\n config?: string;\n /** File to import (`.json`, `.csv`, or `.xlf`/`.xliff`). */\n file: string;\n format?: TranslationFormat;\n /** Locale for single-locale files. Defaults to the file name (`tr.json`) or XLIFF target language. */\n locale?: string;\n /** Allow keys that do not exist in any locale yet. */\n allowNew?: boolean;\n /** Print machine-readable JSON instead of human output. */\n json?: boolean;\n}\n\nexport interface ImportEntry {\n locale: string;\n key: string;\n value: string;\n}\n\nexport interface ImportResult {\n success: boolean;\n created: number;\n updated: number;\n /** Function/non-text values that cannot be overwritten. */\n skipped: string[];\n /** Values refused because they are invalid ICU or change the message arguments. */\n rejected: string[];\n unknown: string[];\n errors: string[];\n}\n\nconst unescapeXml = (value: string) =>\n value\n .replace(/&lt;/g, \"<\")\n .replace(/&gt;/g, \">\")\n .replace(/&quot;/g, '\"')\n .replace(/&apos;/g, \"'\")\n .replace(/&amp;/g, \"&\");\n\nexport function parseCsv(text: string): string[][] {\n const rows: string[][] = [];\n let row: string[] = [];\n let cell = \"\";\n let quoted = false;\n\n for (let i = 0; i < text.length; i++) {\n const ch = text[i];\n if (quoted) {\n if (ch === '\"' && text[i + 1] === '\"') {\n cell += '\"';\n i++;\n } else if (ch === '\"') {\n quoted = false;\n } else {\n cell += ch;\n }\n } else if (ch === '\"') {\n quoted = true;\n } else if (ch === \",\") {\n row.push(cell);\n cell = \"\";\n } else if (ch === \"\\n\" || ch === \"\\r\") {\n if (ch === \"\\r\" && text[i + 1] === \"\\n\") i++;\n row.push(cell);\n rows.push(row);\n row = [];\n cell = \"\";\n } else {\n cell += ch;\n }\n }\n if (cell !== \"\" || row.length > 0) {\n row.push(cell);\n rows.push(row);\n }\n return rows.filter((r) => r.some((c) => c !== \"\"));\n}\n\nexport function parseEntries(\n content: string,\n format: TranslationFormat,\n fallbackLocale: string | undefined,\n): ImportEntry[] {\n const entries: ImportEntry[] = [];\n\n if (format === \"json\") {\n const data = JSON.parse(content) as Record<string, unknown>;\n const isNested =\n Object.keys(data).length > 0 &&\n Object.values(data).every((v) => v && typeof v === \"object\" && !Array.isArray(v));\n if (isNested) {\n for (const [locale, values] of Object.entries(data)) {\n for (const [key, value] of Object.entries(values as Record<string, unknown>)) {\n if (typeof value === \"string\") entries.push({ locale, key, value });\n }\n }\n } else {\n if (!fallbackLocale) throw new Error(\"Cannot infer the locale; pass --locale.\");\n for (const [key, value] of Object.entries(data)) {\n if (typeof value === \"string\") entries.push({ locale: fallbackLocale, key, value });\n }\n }\n } else if (format === \"csv\") {\n const [header, ...rows] = parseCsv(content);\n if (!header || header[0] !== \"key\") throw new Error('CSV must start with a \"key\" column.');\n for (const row of rows) {\n header.slice(1).forEach((locale, i) => {\n const value = row[i + 1];\n if (value !== undefined && value !== \"\") entries.push({ locale, key: row[0], value });\n });\n }\n } else {\n const locale = /target-language=\"([^\"]*)\"/.exec(content)?.[1] ?? fallbackLocale;\n if (!locale) throw new Error(\"Cannot infer the locale; pass --locale.\");\n const unit = /<trans-unit\\b[^>]*\\bid=\"([^\"]*)\"[^>]*>([\\s\\S]*?)<\\/trans-unit>/g;\n for (const match of content.matchAll(unit)) {\n const target = /<target\\b[^>]*>([\\s\\S]*?)<\\/target>/.exec(match[2])?.[1];\n if (target !== undefined && target !== \"\") {\n entries.push({ locale, key: unescapeXml(match[1]), value: unescapeXml(target) });\n }\n }\n }\n\n return entries;\n}\n\nfunction inferFormat(file: string): TranslationFormat {\n const ext = path.extname(file).toLowerCase();\n if (ext === \".json\") return \"json\";\n if (ext === \".csv\") return \"csv\";\n if (ext === \".xlf\" || ext === \".xliff\") return \"xliff\";\n throw new Error(`Cannot infer format from \"${ext}\". Pass --format json|csv|xliff.`);\n}\n\n/**\n * Why `value` must not replace the current text, if it is an ICU message that is invalid or uses\n * different arguments than the same key in another locale.\n */\nfunction icuProblem(\n df: Parameters<typeof getString>[0],\n defaultLocale: string,\n locale: string,\n keyPath: string[],\n value: string,\n): string | undefined {\n if (!value.includes(\"{\")) return undefined;\n\n let signature: string;\n try {\n signature = argumentSignature(parseMessage(value));\n } catch (error) {\n return `invalid ICU: ${(error as Error).message}`;\n }\n\n const locales = listLocales(df);\n for (const other of [defaultLocale, ...locales.filter((l) => l !== defaultLocale)]) {\n if (other === locale) continue;\n const reference = getString(df, other, keyPath);\n if (!reference?.includes(\"{\")) continue;\n try {\n const expected = argumentSignature(parseMessage(reference));\n return expected === signature\n ? undefined\n : `arguments differ from \"${other}\": expected ${expected || \"none\"}, found ${signature || \"none\"}`;\n } catch {\n continue;\n }\n }\n return undefined;\n}\n\nexport async function runImport(options: ImportOptions): Promise<ImportResult> {\n const root = options.cwd || process.cwd();\n const file = path.resolve(root, options.file);\n const format = options.format || inferFormat(file);\n const fallbackLocale = options.locale ?? path.basename(file, path.extname(file));\n\n const entries = parseEntries(\n fs.readFileSync(file, \"utf-8\"),\n format,\n options.locale ?? fallbackLocale,\n );\n const project = await loadProject(root, options.config);\n const byName = new Map(project.dictionaries.map((d) => [d.name, d]));\n\n const quiet = options.json === true;\n const result: ImportResult = {\n success: true,\n created: 0,\n updated: 0,\n skipped: [],\n rejected: [],\n unknown: [],\n errors: [],\n };\n const touched = new Set<string>();\n\n for (const { locale, key, value } of entries) {\n const [name, ...keyPath] = key.split(\".\");\n const dict = byName.get(name);\n if (!dict || keyPath.length === 0) {\n result.unknown.push(key);\n continue;\n }\n\n const exists = listLocales(dict.df).some((l) => hasPath(dict.df, l, keyPath));\n if (!exists && !options.allowNew) {\n result.unknown.push(key);\n continue;\n }\n\n const problem = icuProblem(\n dict.df,\n project.config.defaultLocale ?? \"en\",\n locale,\n keyPath,\n value,\n );\n if (problem) {\n result.rejected.push(`${locale}:${key} (${problem})`);\n continue;\n }\n\n const outcome = setString(dict.df, locale, keyPath, value);\n if (outcome === \"skipped\") {\n result.skipped.push(`${locale}:${key}`);\n } else {\n result[outcome]++;\n touched.add(dict.rel);\n }\n }\n\n for (const dict of project.dictionaries) {\n if (touched.has(dict.rel)) await saveDictionaryFile(dict.df);\n }\n\n if (result.rejected.length > 0) {\n result.success = false;\n }\n\n if (quiet) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n logger.success(\n `Imported ${result.created + result.updated} value${result.created + result.updated === 1 ? \"\" : \"s\"} (${result.created} added, ${result.updated} updated)`,\n );\n if (result.unknown.length > 0) {\n logger.warn(\n `${result.unknown.length} unknown key${result.unknown.length === 1 ? \"\" : \"s\"} ignored (use --allow-new to add): ${result.unknown.slice(0, 5).join(\", \")}${result.unknown.length > 5 ? \", ...\" : \"\"}`,\n );\n }\n if (result.rejected.length > 0) {\n logger.warn(\n `${result.rejected.length} value${result.rejected.length === 1 ? \"\" : \"s\"} rejected: ${result.rejected.slice(0, 5).join(\"; \")}`,\n );\n }\n if (result.skipped.length > 0) {\n logger.warn(\n `${result.skipped.length} non-text value${result.skipped.length === 1 ? \"\" : \"s\"} left unchanged: ${result.skipped.slice(0, 5).join(\", \")}`,\n );\n }\n }\n\n return result;\n}\n","import { getArguments, isIcuStructured, parseMessage } from \"dialexjs/icu\";\n\n/** `{name}`, `%s` / `%1$d`, and HTML/XML tags: text that must survive translation unchanged. */\nconst PLACEHOLDER = /\\{[^{}]+\\}|%\\d*\\$?[sdif]|<\\/?[A-Za-z][^<>]*>/g;\n\nexport function extractPlaceholders(text: string): string[] {\n return text.match(PLACEHOLDER) ?? [];\n}\n\n/**\n * ICU plural/select messages put translatable text inside `{...}` branches, so brace matching\n * is meaningless for them. Compare the structure instead: the same arguments with the same\n * types, every `select` key and every exact `=N` plural match preserved. A translation may\n * add or drop plural categories (`one`, `few`, ...), because languages need different ones.\n */\nfunction preservesIcuStructure(source: string, translated: string): boolean {\n try {\n const before = getArguments(parseMessage(source));\n const after = getArguments(parseMessage(translated));\n const sameArguments =\n before.length === after.length &&\n before.every((a) => after.some((b) => a.name === b.name && a.type === b.type));\n if (!sameArguments) return false;\n\n return before.every((a) => {\n const other = after.find((b) => b.name === a.name && b.type === a.type)!;\n const keep =\n a.type === \"select\"\n ? (a.selectors ?? [])\n : (a.selectors ?? []).filter((selector) => selector.startsWith(\"=\"));\n return keep.every((selector) => other.selectors?.includes(selector));\n });\n } catch {\n return false;\n }\n}\n\n/** True when every placeholder of `source` appears in `translated` (as many times as in the source). */\nexport function preservesPlaceholders(source: string, translated: string): boolean {\n if (isIcuStructured(source)) return preservesIcuStructure(source, translated);\n\n const remaining = extractPlaceholders(translated);\n for (const placeholder of extractPlaceholders(source)) {\n const index = remaining.indexOf(placeholder);\n if (index === -1) return false;\n remaining.splice(index, 1);\n }\n return true;\n}\n","import pc from \"picocolors\";\nimport type { TranslateProvider } from \"dialexjs\";\nimport {\n TODO_PREFIX,\n listLeaves,\n listLocales,\n saveDictionaryFile,\n setString,\n} from \"../utils/dictionary-edit.js\";\nimport { loadProject, toKey, type ProjectDictionary } from \"../utils/project.js\";\nimport { isIcuStructured } from \"dialexjs/icu\";\nimport { preservesPlaceholders } from \"../translate/placeholders.js\";\nimport { logger } from \"../utils/logger.js\";\n\nexport interface TranslateOptions {\n cwd?: string;\n config?: string;\n /** Target locales. Defaults to every configured locale except the source. */\n locale?: string[];\n /** Locale to translate from. Defaults to `translate.sourceLocale`, then `defaultLocale`. */\n source?: string;\n /** List what would be translated without calling the provider or writing files. */\n dryRun?: boolean;\n /** Overrides the provider from the config (used by tests). */\n provider?: TranslateProvider;\n /** Print machine-readable JSON instead of human output. */\n json?: boolean;\n}\n\nexport interface PendingTranslation {\n file: string;\n locale: string;\n key: string;\n source: string;\n /** Present after translation. */\n translated?: string;\n}\n\nexport interface TranslateResult {\n success: boolean;\n dryRun: boolean;\n pending: PendingTranslation[];\n translated: number;\n /** Translations rejected because they changed placeholders, or that could not be written. */\n rejected: string[];\n}\n\ninterface Task extends PendingTranslation {\n dict: ProjectDictionary;\n path: string[];\n}\n\nexport async function runTranslate(options: TranslateOptions = {}): Promise<TranslateResult> {\n const root = options.cwd || process.cwd();\n const project = await loadProject(root, options.config);\n const settings = project.config.translate;\n const provider = options.provider ?? settings?.provider;\n\n if (!provider && !options.dryRun) {\n throw new Error(\n \"No translate provider configured. Add `translate: { provider: claudeProvider() }` to dialex.config.ts \" +\n '(import it from \"@dialexjs/cli/translate\").',\n );\n }\n\n const source = options.source ?? settings?.sourceLocale ?? project.config.defaultLocale ?? \"en\";\n const everyLocale = new Set<string>(project.config.locales ?? []);\n for (const { df } of project.dictionaries) listLocales(df).forEach((l) => everyLocale.add(l));\n const targets = (options.locale?.length ? options.locale : [...everyLocale]).filter(\n (l) => l !== source,\n );\n\n // 1. Collect strings that are missing or still marked [TODO]\n const tasks: Task[] = [];\n for (const dict of project.dictionaries) {\n const sourceLeaves = listLeaves(dict.df, source).filter(\n (leaf) => leaf.kind === \"string\" && leaf.value !== undefined,\n );\n\n for (const locale of targets) {\n const existing = new Map(\n listLeaves(dict.df, locale).map((leaf) => [leaf.path.join(\"\\u0000\"), leaf]),\n );\n for (const leaf of sourceLeaves) {\n const current = existing.get(leaf.path.join(\"\\u0000\"));\n const needs =\n !current || (current.kind === \"string\" && current.value?.startsWith(TODO_PREFIX));\n if (needs) {\n tasks.push({\n dict,\n path: leaf.path,\n file: dict.rel,\n locale,\n key: toKey(dict.name, leaf.path),\n source: leaf.value!,\n });\n }\n }\n }\n }\n\n const quiet = options.json === true;\n\n const result: TranslateResult = {\n success: true,\n dryRun: options.dryRun === true,\n pending: tasks,\n translated: 0,\n rejected: [],\n };\n\n if (tasks.length === 0) {\n if (quiet) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n logger.success(`Nothing to translate from \"${source}\".`);\n }\n return result;\n }\n\n if (options.dryRun) {\n if (quiet) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n logger.info(\n `Would translate ${tasks.length} string${tasks.length === 1 ? \"\" : \"s\"} from \"${source}\":`,\n );\n for (const t of tasks) {\n logger.log(` ${pc.dim(t.locale)} ${t.key} ${pc.dim(JSON.stringify(t.source))}`);\n }\n }\n return result;\n }\n\n // 2. Translate per target locale, de-duplicating identical source strings\n const touched = new Set<ProjectDictionary>();\n for (const locale of targets) {\n const localeTasks = tasks.filter((t) => t.locale === locale);\n if (localeTasks.length === 0) continue;\n\n // Providers that cannot keep ICU plural/select structure intact never see those messages\n const sendable = provider!.supportsIcu\n ? localeTasks\n : localeTasks.filter((task) => {\n if (!isIcuStructured(task.source)) return true;\n result.rejected.push(\n `${locale}:${task.key} (provider does not support ICU plural/select messages)`,\n );\n return false;\n });\n if (sendable.length === 0) continue;\n\n const unique = [...new Set(sendable.map((t) => t.source))];\n if (!quiet) {\n logger.info(\n `Translating ${unique.length} string${unique.length === 1 ? \"\" : \"s\"} to \"${locale}\" with ${provider!.name ?? \"provider\"}...`,\n );\n }\n const translations = await provider!.translate(unique, source, locale);\n if (translations.length !== unique.length) {\n throw new Error(\n `Provider returned ${translations.length} translations for ${unique.length} strings.`,\n );\n }\n const byText = new Map(unique.map((text, i) => [text, translations[i]]));\n\n for (const task of sendable) {\n const translated = byText.get(task.source);\n if (typeof translated !== \"string\" || translated.trim() === \"\") {\n result.rejected.push(`${locale}:${task.key} (empty translation)`);\n continue;\n }\n if (!preservesPlaceholders(task.source, translated)) {\n result.rejected.push(`${locale}:${task.key} (placeholders changed)`);\n continue;\n }\n if (setString(task.dict.df, locale, task.path, translated) === \"skipped\") {\n result.rejected.push(`${locale}:${task.key} (not a text value)`);\n continue;\n }\n task.translated = translated;\n result.translated++;\n touched.add(task.dict);\n }\n }\n\n for (const dict of touched) await saveDictionaryFile(dict.df);\n\n if (result.rejected.length > 0) {\n result.success = false;\n }\n\n if (quiet) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n logger.success(\n `Translated ${result.translated} of ${tasks.length} string${tasks.length === 1 ? \"\" : \"s\"}.`,\n );\n if (result.rejected.length > 0) {\n logger.warn(\n `${result.rejected.length} left unchanged: ${result.rejected.slice(0, 5).join(\"; \")}${result.rejected.length > 5 ? \"; ...\" : \"\"}`,\n );\n }\n }\n return result;\n}\n","#!/usr/bin/env node\n\nimport { Command } from \"commander\";\nimport { runGenerate } from \"./commands/generate.js\";\nimport { runInit } from \"./commands/init.js\";\nimport { logger } from \"./utils/logger.js\";\nimport { runCheck } from \"./commands/check.js\";\nimport { runExport } from \"./commands/export.js\";\nimport { runImport } from \"./commands/import.js\";\nimport { runTranslate } from \"./commands/translate.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"dialex\")\n .description(\"Dialex CLI - High-performance, type-safe internationalization compiler and tooling\")\n .version(\"0.2.3\");\n\nprogram\n .command(\"generate\")\n .alias(\"gen\")\n .description(\"Generate standalone dictionary bundle and TypeScript declarations\")\n .option(\"-w, --watch\", \"Watch dictionary files for changes\")\n .option(\"-o, --output <path>\", \"Custom output file path for generated dictionaries\")\n .option(\"-c, --config <path>\", \"Custom config path\")\n .option(\"--json\", \"Print machine-readable JSON\")\n .action(async (opts) => {\n await runGenerate(opts);\n });\n\nprogram\n .command(\"init\")\n .description(\"Initialize Dialex in the current project\")\n .option(\n \"-f, --framework <framework>\",\n \"Target framework (hono, express, fastify, koa, nestjs, next, react)\",\n )\n .option(\"-d, --default-locale <locale>\", \"Default locale (e.g. en)\")\n .option(\"-l, --locales <locales>\", \"Comma-separated supported locales (e.g. en,tr)\")\n .option(\"-y, --yes\", \"Skip prompts and use defaults\")\n .option(\"--ai\", \"Configure AI agent support (.agents/skills, .mcp.json, AGENTS.md)\")\n .option(\"--no-ai\", \"Skip AI agent configuration\")\n .action(async (opts) => {\n await runInit(opts);\n });\n\nprogram\n .command(\"check\")\n .alias(\"lint\")\n .description(\"Verify dictionary key parity and locale completeness\")\n .option(\"-c, --config <path>\", \"Custom config path\")\n .option(\"--json\", \"Print machine-readable JSON\")\n .option(\"--github\", \"Print GitHub Actions annotations\")\n .option(\"--fix\", \"Insert missing keys marked with [TODO]\")\n .option(\"--src <globs...>\", \"Source globs to scan for dictionary references\")\n .action(async (opts) => {\n await runCheck(opts);\n });\n\nprogram\n .command(\"export\")\n .description(\"Export dictionary strings for translators (json, csv, or xliff)\")\n .option(\"-f, --format <format>\", \"Output format: json, csv, xliff\", \"json\")\n .option(\"-o, --out <dir>\", \"Output directory\", \"i18n-export\")\n .option(\"-l, --locale <locales...>\", \"Limit to these locales\")\n .option(\"-c, --config <path>\", \"Custom config path\")\n .option(\"--json\", \"Print machine-readable JSON\")\n .action(async (opts) => {\n await runExport(opts);\n });\n\nprogram\n .command(\"import <file>\")\n .description(\"Write translated strings from a json, csv, or xliff file back into dictionaries\")\n .option(\"-f, --format <format>\", \"Input format (inferred from the extension)\")\n .option(\"-l, --locale <locale>\", \"Locale for single-locale files\")\n .option(\"--allow-new\", \"Add keys that do not exist in any locale yet\")\n .option(\"-c, --config <path>\", \"Custom config path\")\n .option(\"--json\", \"Print machine-readable JSON\")\n .action(async (file, opts) => {\n await runImport({ file, ...opts });\n });\n\nprogram\n .command(\"translate\")\n .description(\"Fill missing translations with the provider configured in dialex.config.ts\")\n .option(\"-l, --locale <locales...>\", \"Target locales (default: all configured)\")\n .option(\n \"-s, --source <locale>\",\n \"Source locale (default: translate.sourceLocale or defaultLocale)\",\n )\n .option(\"--dry-run\", \"List what would be translated without calling the provider\")\n .option(\"-c, --config <path>\", \"Custom config path\")\n .option(\"--json\", \"Print machine-readable JSON\")\n .action(async (opts) => {\n try {\n await runTranslate(opts);\n } catch (err: any) {\n if (opts.json) {\n console.log(JSON.stringify({ success: false, error: err.message || String(err) }, null, 2));\n } else {\n logger.error(err.message || String(err));\n }\n process.exit(1);\n }\n });\n\nprogram.parse();\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/utils/detector.ts","../src/utils/package-json.ts","../src/commands/init.ts","../src/commands/check.ts","../src/commands/export.ts","../src/commands/import.ts","../src/translate/placeholders.ts","../src/commands/translate.ts","../src/index.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\n\nexport type SupportedFramework =\n | \"next\"\n | \"react\"\n | \"hono\"\n | \"express\"\n | \"fastify\"\n | \"koa\"\n | \"nestjs\"\n | \"elysia\"\n | \"sveltekit\"\n | \"astro\"\n | \"vue\"\n | \"nuxt\";\n\nexport interface DetectedFramework {\n framework: SupportedFramework;\n confidence: \"high\" | \"medium\" | \"fallback\";\n matchedRule: string;\n}\n\n/**\n * Automatically inspects package.json dependencies and configuration files\n * to detect the active framework in the target project.\n */\nexport function detectFramework(root: string): DetectedFramework {\n const pkgPath = path.join(root, \"package.json\");\n if (fs.existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf-8\"));\n const allDeps = {\n ...pkg.dependencies,\n ...pkg.devDependencies,\n };\n\n if (\"nuxt\" in allDeps) {\n return {\n framework: \"nuxt\",\n confidence: \"high\",\n matchedRule: \"package.json dependencies (nuxt)\",\n };\n }\n if (\"@sveltejs/kit\" in allDeps) {\n return {\n framework: \"sveltekit\",\n confidence: \"high\",\n matchedRule: \"package.json dependencies (@sveltejs/kit)\",\n };\n }\n if (\"astro\" in allDeps) {\n return {\n framework: \"astro\",\n confidence: \"high\",\n matchedRule: \"package.json dependencies (astro)\",\n };\n }\n if (\"next\" in allDeps) {\n return {\n framework: \"next\",\n confidence: \"high\",\n matchedRule: \"package.json dependencies (next)\",\n };\n }\n if (\"@nestjs/core\" in allDeps || \"@nestjs/common\" in allDeps) {\n return {\n framework: \"nestjs\",\n confidence: \"high\",\n matchedRule: \"package.json dependencies (@nestjs/core)\",\n };\n }\n if (\"fastify\" in allDeps) {\n return {\n framework: \"fastify\",\n confidence: \"high\",\n matchedRule: \"package.json dependencies (fastify)\",\n };\n }\n if (\"koa\" in allDeps) {\n return {\n framework: \"koa\",\n confidence: \"high\",\n matchedRule: \"package.json dependencies (koa)\",\n };\n }\n if (\"express\" in allDeps) {\n return {\n framework: \"express\",\n confidence: \"high\",\n matchedRule: \"package.json dependencies (express)\",\n };\n }\n if (\"elysia\" in allDeps) {\n return {\n framework: \"elysia\",\n confidence: \"high\",\n matchedRule: \"package.json dependencies (elysia)\",\n };\n }\n if (\"hono\" in allDeps) {\n return {\n framework: \"hono\",\n confidence: \"high\",\n matchedRule: \"package.json dependencies (hono)\",\n };\n }\n if (\"vue\" in allDeps && !(\"react\" in allDeps)) {\n return {\n framework: \"vue\",\n confidence: \"high\",\n matchedRule: \"package.json dependencies (vue)\",\n };\n }\n if (\"react\" in allDeps || \"vite\" in allDeps) {\n return {\n framework: \"react\",\n confidence: \"high\",\n matchedRule: \"package.json dependencies (react/vite)\",\n };\n }\n } catch {\n // Ignore JSON parse errors\n }\n }\n\n // Check filesystem configurations\n if (\n fs.existsSync(path.join(root, \"next.config.js\")) ||\n fs.existsSync(path.join(root, \"next.config.mjs\")) ||\n fs.existsSync(path.join(root, \"next.config.ts\"))\n ) {\n return {\n framework: \"next\",\n confidence: \"medium\",\n matchedRule: \"next.config file presence\",\n };\n }\n\n const configRules: [SupportedFramework, string][] = [\n [\"nuxt\", \"nuxt.config\"],\n [\"sveltekit\", \"svelte.config\"],\n [\"astro\", \"astro.config\"],\n ];\n for (const [framework, base] of configRules) {\n if ([\"js\", \"mjs\", \"ts\"].some((ext) => fs.existsSync(path.join(root, `${base}.${ext}`)))) {\n return { framework, confidence: \"medium\", matchedRule: `${base} file presence` };\n }\n }\n\n if (\n fs.existsSync(path.join(root, \"vite.config.js\")) ||\n fs.existsSync(path.join(root, \"vite.config.mjs\")) ||\n fs.existsSync(path.join(root, \"vite.config.ts\"))\n ) {\n return {\n framework: \"react\",\n confidence: \"medium\",\n matchedRule: \"vite.config file presence\",\n };\n }\n\n return {\n framework: \"hono\",\n confidence: \"fallback\",\n matchedRule: \"default fallback\",\n };\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n/** Version of this CLI, which the other Dialex packages share. Read from the nearest package.json. */\nexport function cliVersion(): string | undefined {\n let dir = path.dirname(fileURLToPath(import.meta.url));\n for (let i = 0; i < 4; i++) {\n try {\n const pkg = JSON.parse(fs.readFileSync(path.join(dir, \"package.json\"), \"utf-8\"));\n if (pkg.name === \"@dialexjs/cli\") return pkg.version;\n } catch {\n // keep walking up\n }\n dir = path.dirname(dir);\n }\n return undefined;\n}\n\n/** The install command for the package manager a project uses, judged by its lockfile. */\nexport function installCommand(root: string): string {\n const has = (file: string) => fs.existsSync(path.join(root, file));\n if (has(\"bun.lock\") || has(\"bun.lockb\")) return \"bun install\";\n if (has(\"pnpm-lock.yaml\")) return \"pnpm install\";\n if (has(\"yarn.lock\")) return \"yarn install\";\n return \"npm install\";\n}\n\ntype Dependencies = Record<string, string>;\n\nconst sorted = (deps: Dependencies): Dependencies =>\n Object.fromEntries(Object.entries(deps).sort(([a], [b]) => a.localeCompare(b)));\n\n/**\n * Adds the packages a Dialex project needs: `dialexjs` as a dependency and the CLI as a dev\n * dependency (the `dx:generate` script runs it). Packages already listed anywhere are left alone.\n * Returns the names it added.\n */\nexport function addRequiredPackages(pkg: Record<string, any>, version = cliVersion()): string[] {\n const range = version ? `^${version}` : \"latest\";\n const listed = (name: string) =>\n [pkg.dependencies, pkg.devDependencies, pkg.peerDependencies].some(\n (deps) => deps && name in deps,\n );\n const added: string[] = [];\n\n if (!listed(\"dialexjs\")) {\n pkg.dependencies = sorted({ ...pkg.dependencies, dialexjs: range });\n added.push(\"dialexjs\");\n }\n if (!listed(\"@dialexjs/cli\")) {\n pkg.devDependencies = sorted({ ...pkg.devDependencies, \"@dialexjs/cli\": range });\n added.push(\"@dialexjs/cli\");\n }\n return added;\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\nimport { parseModule, loadFile, writeFile } from \"magicast\";\nimport { addNuxtModule, addVitePlugin } from \"magicast/helpers\";\nimport { generateDictionaries } from \"./generate.js\";\nimport { detectFramework, type SupportedFramework } from \"../utils/detector.js\";\nimport { logger } from \"../utils/logger.js\";\nimport { addRequiredPackages, installCommand } from \"../utils/package-json.js\";\n\nexport interface InitOptions {\n cwd?: string;\n framework?: string;\n defaultLocale?: string;\n locales?: string;\n yes?: boolean;\n ai?: boolean;\n noAi?: boolean;\n}\n\nexport async function runInit(options: InitOptions = {}) {\n const root = options.cwd || process.cwd();\n const detected = detectFramework(root);\n const isInteractive = !options.yes && process.stdin.isTTY;\n\n let framework = (options.framework as SupportedFramework) || detected.framework;\n let defaultLocale = options.defaultLocale || \"en\";\n let localesInput = options.locales || \"en,tr\";\n\n if (isInteractive) {\n p.intro(pc.bgCyan(pc.black(\" dialex init \")));\n\n const frameworkOptions: { value: SupportedFramework; label: string; hint?: string }[] = [\n {\n value: \"hono\",\n label: \"Hono\",\n hint: detected.framework === \"hono\" ? \"detected\" : undefined,\n },\n {\n value: \"express\",\n label: \"Express\",\n hint: detected.framework === \"express\" ? \"detected\" : undefined,\n },\n {\n value: \"fastify\",\n label: \"Fastify\",\n hint: detected.framework === \"fastify\" ? \"detected\" : undefined,\n },\n {\n value: \"koa\",\n label: \"Koa\",\n hint: detected.framework === \"koa\" ? \"detected\" : undefined,\n },\n {\n value: \"nestjs\",\n label: \"NestJS\",\n hint: detected.framework === \"nestjs\" ? \"detected\" : undefined,\n },\n {\n value: \"next\",\n label: \"Next.js\",\n hint: detected.framework === \"next\" ? \"detected\" : undefined,\n },\n {\n value: \"react\",\n label: \"React / Vite\",\n hint: detected.framework === \"react\" ? \"detected\" : undefined,\n },\n {\n value: \"elysia\",\n label: \"Elysia\",\n hint: detected.framework === \"elysia\" ? \"detected\" : undefined,\n },\n {\n value: \"sveltekit\",\n label: \"SvelteKit\",\n hint: detected.framework === \"sveltekit\" ? \"detected\" : undefined,\n },\n {\n value: \"astro\",\n label: \"Astro\",\n hint: detected.framework === \"astro\" ? \"detected\" : undefined,\n },\n {\n value: \"vue\",\n label: \"Vue / Vite\",\n hint: detected.framework === \"vue\" ? \"detected\" : undefined,\n },\n {\n value: \"nuxt\",\n label: \"Nuxt\",\n hint: detected.framework === \"nuxt\" ? \"detected\" : undefined,\n },\n ];\n\n const selectedFramework = await p.select({\n message: `Framework detected as ${pc.bold(detected.framework)} (${detected.matchedRule}). Select framework:`,\n options: frameworkOptions,\n initialValue: detected.framework,\n });\n\n if (p.isCancel(selectedFramework)) {\n p.cancel(\"Operation cancelled.\");\n return;\n }\n framework = selectedFramework as SupportedFramework;\n\n const inputDefault = await p.text({\n message: \"What is your default locale?\",\n initialValue: \"en\",\n validate: (v) => (!v || !v.trim() ? \"Default locale cannot be empty\" : undefined),\n });\n\n if (p.isCancel(inputDefault)) {\n p.cancel(\"Operation cancelled.\");\n return;\n }\n defaultLocale = inputDefault.trim();\n\n const inputLocales = await p.text({\n message: \"Comma-separated list of supported locales:\",\n initialValue: `${defaultLocale},tr`,\n validate: (v) => (!v || !v.trim() ? \"Locales list cannot be empty\" : undefined),\n });\n\n if (p.isCancel(inputLocales)) {\n p.cancel(\"Operation cancelled.\");\n return;\n }\n localesInput = inputLocales.trim();\n\n if (options.ai === undefined && options.noAi === undefined) {\n const confirmAi = await p.confirm({\n message: \"Configure AI agent support (Claude/Cursor skills, .mcp.json, AGENTS.md)?\",\n initialValue: true,\n });\n if (!p.isCancel(confirmAi)) {\n options.ai = confirmAi;\n }\n }\n } else {\n logger.info(`Auto-detected framework: ${pc.bold(framework)} (${detected.matchedRule})`);\n }\n\n const localeList = Array.from(\n new Set([\n defaultLocale,\n ...localesInput\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean),\n ]),\n );\n\n // 1. AST generation or update for dialex.config.ts / i18n.config.ts via Magicast\n const configPath = fs.existsSync(path.join(root, \"dialex.config.ts\"))\n ? path.join(root, \"dialex.config.ts\")\n : fs.existsSync(path.join(root, \"i18n.config.ts\"))\n ? path.join(root, \"i18n.config.ts\")\n : path.join(root, \"dialex.config.ts\");\n const configFileName = path.basename(configPath);\n\n try {\n if (fs.existsSync(configPath)) {\n const mod = await loadFile(configPath);\n if (mod && mod.exports.default) {\n if (mod.exports.default.$args && mod.exports.default.$args[0]) {\n mod.exports.default.$args[0].defaultLocale = defaultLocale;\n mod.exports.default.$args[0].locales = localeList;\n }\n await writeFile(mod, configPath);\n logger.success(`Updated ${pc.bold(configFileName)} via Magicast`);\n }\n } else {\n const mod = parseModule(`import { defineConfig } from \"dialexjs\";\n\nexport default defineConfig({});\n`);\n mod.exports.default.$args[0].defaultLocale = defaultLocale;\n mod.exports.default.$args[0].locales = localeList;\n await writeFile(mod, configPath);\n logger.success(`Created ${pc.bold(configFileName)} via Magicast`);\n }\n } catch (err: any) {\n logger.warn(`Magicast config update notice: ${err.message || String(err)}`);\n // Fallback safe string write if AST parser encounters non-standard syntax\n const fallback = `import { defineConfig } from \"dialexjs\";\n\nexport default defineConfig({\n defaultLocale: \"${defaultLocale}\",\n locales: [${localeList.map((l) => `\"${l}\"`).join(\", \")}],\n});\n`;\n fs.writeFileSync(configPath, fallback, \"utf-8\");\n }\n\n // 2. Magicast AST injection for Vite and Nuxt projects\n if (framework === \"react\" || framework === \"vue\") {\n const possibleViteConfigs = [\n path.join(root, \"vite.config.ts\"),\n path.join(root, \"vite.config.js\"),\n path.join(root, \"vite.config.mjs\"),\n ];\n for (const vConfig of possibleViteConfigs) {\n if (fs.existsSync(vConfig)) {\n try {\n const vMod = await loadFile(vConfig);\n addVitePlugin(vMod, {\n from: \"dialexjs/vite\",\n imported: \"dialexPlugin\",\n constructor: \"dialexPlugin\",\n });\n await writeFile(vMod, vConfig);\n logger.success(\n `Injected dialexPlugin() into ${pc.bold(path.basename(vConfig))} via Magicast`,\n );\n break;\n } catch {\n // If already added or non-standard, continue\n }\n }\n }\n }\n\n if (framework === \"nuxt\") {\n const nuxtConfig = [\"nuxt.config.ts\", \"nuxt.config.js\", \"nuxt.config.mjs\"]\n .map((f) => path.join(root, f))\n .find((f) => fs.existsSync(f));\n if (nuxtConfig) {\n try {\n const nMod = await loadFile(nuxtConfig);\n addNuxtModule(nMod, \"dialexjs/nuxt\", \"dialex\", {\n defaultLocale,\n locales: localeList,\n });\n await writeFile(nMod, nuxtConfig);\n logger.success(\n `Registered dialexjs/nuxt in ${pc.bold(path.basename(nuxtConfig))} via Magicast`,\n );\n } catch {\n logger.warn(\"Could not update the Nuxt config; add the dialexjs/nuxt module manually.\");\n }\n }\n }\n\n // 3. Create starter dictionary in src/ (or root)\n const targetDir = fs.existsSync(path.join(root, \"src\")) ? path.join(root, \"src\") : root;\n const dictPath = path.join(targetDir, \"home.content.ts\");\n if (!fs.existsSync(dictPath)) {\n const dictRecords = localeList\n .map(\n (loc) => ` ${loc}: {\n title: \"Welcome to Dialex (${loc})!\",\n description: \"Type-safe internationalization.\",\n greeting: (name: string) => \"Hello, \" + name + \"!\",\n },`,\n )\n .join(\"\\n\");\n\n const dictContent = `import { defineDictionary } from \"dialexjs\";\n\nexport default defineDictionary(\"home\", {\n${dictRecords}\n});\n`;\n fs.writeFileSync(dictPath, dictContent, \"utf-8\");\n logger.success(`Created starter dictionary at ${pc.bold(path.relative(root, dictPath))}`);\n } else {\n logger.info(\"home.content.ts already exists, skipping creation.\");\n }\n\n // 4. Run standalone dictionary generation immediately\n generateDictionaries(root);\n logger.success(\"Generated types and standalone dictionary registry!\");\n\n // 5. Update package.json: required packages and the generate script\n const pkgPath = path.join(root, \"package.json\");\n if (fs.existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf-8\"));\n const added = addRequiredPackages(pkg);\n pkg.scripts = pkg.scripts || {};\n const addScript = !pkg.scripts[\"dx:generate\"];\n if (addScript) pkg.scripts[\"dx:generate\"] = \"dx generate\";\n\n if (added.length > 0 || addScript) {\n fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + \"\\n\", \"utf-8\");\n }\n if (added.length > 0) {\n logger.success(`Added ${added.join(\" and \")} to package.json`);\n logger.info(`Run ${pc.bold(installCommand(root))} to install them.`);\n }\n if (addScript) logger.success('Added \"dx:generate\" script to package.json');\n } catch {\n logger.warn(\"Could not update package.json; add dialexjs and @dialexjs/cli manually.\");\n }\n } else {\n logger.warn(\"No package.json found; install dialexjs and @dialexjs/cli in your project.\");\n }\n\n // 6. AI Agent Integration (.agents/skills, .mcp.json, AGENTS.md)\n const shouldSetupAi =\n options.ai === true || (options.yes && options.ai !== false && options.noAi !== true);\n if (shouldSetupAi) {\n try {\n // 6a. Copy or create skill in .agents/skills/dialex/SKILL.md\n const skillDir = path.join(root, \".agents/skills/dialex\");\n fs.mkdirSync(skillDir, { recursive: true });\n const skillContent = `---\nname: dialex\ndescription: Guide for internationalizing JavaScript and TypeScript apps with Dialex. Use when adding translations, creating content dictionaries, configuring locales, or using Dialex with frameworks like Next.js, React, Express, Hono, Fastify, SvelteKit, and Nuxt.\n---\n\n# Dialex Internationalization\n\nDialex is a high-performance, type-safe internationalization toolchain for JavaScript and TypeScript.\n\n## Core Concepts\n- Dictionaries are defined with \\`defineDictionary(\"name\", { ... })\\` in \\`*.content.ts\\` files.\n- Keys must match across all locales.\n- ICU message syntax is supported for plurals and selects.\n- Parity is validated at compile time with \\`dialex check\\`.\n\n## Useful Commands\n- \\`dialex check --json\\`: Check dictionary parity and references.\n- \\`dialex check --fix\\`: Automatically insert missing keys marked with [TODO].\n- \\`dialex generate\\`: Rebuild standalone dictionary bundle and types.\n- \\`dialex translate --locale <locale>\\`: Automatically translate missing keys.\n`;\n fs.writeFileSync(path.join(skillDir, \"SKILL.md\"), skillContent, \"utf-8\");\n\n // 6b. Merge .mcp.json\n const mcpConfigPath = path.join(root, \".mcp.json\");\n let mcpConfig: Record<string, any> = {};\n if (fs.existsSync(mcpConfigPath)) {\n try {\n mcpConfig = JSON.parse(fs.readFileSync(mcpConfigPath, \"utf-8\"));\n } catch {\n mcpConfig = {};\n }\n }\n mcpConfig.mcpServers = mcpConfig.mcpServers || {};\n mcpConfig.mcpServers.dialex = mcpConfig.mcpServers.dialex || {\n command: \"npx\",\n args: [\"@dialexjs/mcp\"],\n };\n fs.writeFileSync(mcpConfigPath, JSON.stringify(mcpConfig, null, 2) + \"\\n\", \"utf-8\");\n\n // 6c. Add snippet to AGENTS.md if absent\n const agentsMdPath = path.join(root, \"AGENTS.md\");\n const dialexAgentSnippet = `\n## Internationalization (Dialex)\n\nThis project uses [Dialex](https://github.com/awaiden/dialex) for type-safe internationalization.\n- Dictionaries are in \\`*.content.ts\\` files using \\`defineDictionary\\`.\n- Run \\`dialex check --json\\` to verify parity.\n- Run \\`dialex check --fix\\` to insert missing keys marked with \\`[TODO]\\`.\n- Run \\`dx generate\\` (alias of \\`dialex\\`) or \\`npm run dx:generate\\` to compile dictionary bundles and update types.\n`;\n if (!fs.existsSync(agentsMdPath)) {\n fs.writeFileSync(agentsMdPath, dialexAgentSnippet.trimStart(), \"utf-8\");\n } else {\n const existing = fs.readFileSync(agentsMdPath, \"utf-8\");\n if (!existing.includes(\"Dialex\")) {\n fs.writeFileSync(agentsMdPath, existing.trimEnd() + \"\\n\" + dialexAgentSnippet, \"utf-8\");\n }\n }\n\n logger.success(\"Configured AI assistant support (.agents/skills, .mcp.json, AGENTS.md)\");\n } catch (err: any) {\n logger.warn(`Could not finish AI configuration: ${err.message || String(err)}`);\n }\n }\n\n // 7. Framework-specific quickstart instructions\n logger.log(\"\");\n logger.info(pc.bold(`Quick start for ${framework.toUpperCase()}:`));\n\n switch (framework) {\n case \"hono\":\n logger.log(`\nimport { Hono } from \"hono\";\nimport { dialex } from \"dialexjs/hono\";\nimport dictionaries from \"./src/dialex.generated.js\";\n\nconst app = new Hono();\napp.use(\"*\", dialex({ dictionaries }));\n\napp.get(\"/\", (c) => {\n const dict = c.var.getDictionary(\"home\");\n return c.json({ title: dict.title });\n});\n`);\n break;\n case \"fastify\":\n logger.log(`\nimport Fastify from \"fastify\";\nimport { dialexPlugin } from \"dialexjs/fastify\";\nimport dictionaries from \"./src/dialex.generated.js\";\n\nconst app = Fastify();\nawait app.register(dialexPlugin, { dictionaries });\n\napp.get(\"/\", (req) => {\n const dict = req.getDictionary(\"home\");\n return { title: dict.title };\n});\n`);\n break;\n case \"express\":\n logger.log(`\nimport express from \"express\";\nimport { dialex } from \"dialexjs/express\";\nimport dictionaries from \"./src/dialex.generated.js\";\n\nconst app = express();\napp.use(dialex({ dictionaries }));\n\napp.get(\"/\", (req, res) => {\n const dict = req.getDictionary(\"home\");\n res.json({ title: dict.title });\n});\n`);\n break;\n case \"koa\":\n logger.log(`\nimport Koa from \"koa\";\nimport { dialex } from \"dialexjs/koa\";\nimport dictionaries from \"./src/dialex.generated.js\";\n\nconst app = new Koa();\napp.use(dialex({ dictionaries }));\n\napp.use((ctx) => {\n const dict = ctx.getDictionary(\"home\");\n ctx.body = { title: dict.title };\n});\n`);\n break;\n case \"nestjs\":\n logger.log(`\nimport { Module } from \"@nestjs/common\";\nimport { DialexModule } from \"dialexjs/nestjs\";\nimport dictionaries from \"./src/dialex.generated.js\";\n\n@Module({\n imports: [DialexModule.forRoot({ dictionaries })],\n})\nexport class AppModule {}\n`);\n break;\n case \"next\":\n logger.log(`\nimport { getDictionary } from \"dialexjs/server\";\n\nexport default async function Page({ params }: { params: Promise<{ locale: string }> }) {\n const { locale = \"en\" } = await params;\n const dict = getDictionary(\"home\", locale);\n return <h1>{dict.title}</h1>;\n}\n`);\n break;\n case \"elysia\":\n logger.log(`\nimport { Elysia } from \"elysia\";\nimport { dialex } from \"dialexjs/elysia\";\nimport dictionaries from \"./src/dialex.generated.js\";\n\nnew Elysia()\n .use(dialex({ dictionaries }))\n .get(\"/\", ({ getDictionary }) => ({ title: getDictionary(\"home\").title }))\n .listen(3000);\n`);\n break;\n case \"sveltekit\":\n logger.log(`\n// src/hooks.server.ts\nimport { dialexHandle } from \"dialexjs/sveltekit\";\nimport dictionaries from \"./dialex.generated.js\";\n\nexport const handle = dialexHandle({ dictionaries });\n\n// src/app.html: <html lang=\"%dialex.lang%\">\n// In load functions: locals.getDictionary(\"home\")\n`);\n break;\n case \"astro\":\n logger.log(`\n// src/middleware.ts\nimport { dialex } from \"dialexjs/astro\";\nimport dictionaries from \"./dialex.generated.js\";\n\nexport const onRequest = dialex({ dictionaries });\n\n// In pages: Astro.locals.getDictionary(\"home\")\n`);\n break;\n case \"vue\":\n logger.log(`\n// src/main.ts\nimport { createApp } from \"vue\";\nimport { createDialex } from \"dialexjs/vue\";\nimport App from \"./App.vue\";\n\ncreateApp(App).use(createDialex()).mount(\"#app\");\n\n// In components: const dict = useDictionary(\"home\")\n`);\n break;\n case \"nuxt\":\n logger.log(`\n// nuxt.config.ts\nexport default defineNuxtConfig({\n modules: [\"dialexjs/nuxt\"],\n});\n\n// In components: const dict = useDictionary(\"home\")\n`);\n break;\n default:\n logger.log(`\nImport dictionaries and register your framework middleware to begin!\nRun \\`npm run dx:generate\\` whenever you add new dictionary files.\n`);\n break;\n }\n\n if (isInteractive) {\n p.outro(pc.green(\"✔ dialex is configured and ready to go!\"));\n }\n}\n","import path from \"node:path\";\nimport fg from \"fast-glob\";\nimport pc from \"picocolors\";\nimport { resolveDialexConfig } from \"dialexjs/scanner\";\nimport { analyzeProject, type AnalysisIssue } from \"../analysis.js\";\nimport { logger } from \"../utils/logger.js\";\nimport {\n TODO_PREFIX,\n copyLeaf,\n hasPath,\n listLeaves,\n listLocales,\n loadDictionaryFile,\n saveDictionaryFile,\n} from \"../utils/dictionary-edit.js\";\n\nexport interface CheckOptions {\n cwd?: string;\n config?: string;\n exitOnError?: boolean;\n /** Print machine-readable JSON instead of human output. */\n json?: boolean;\n /** Also print GitHub Actions workflow annotations. */\n github?: boolean;\n /** Insert missing keys (marked with `[TODO]`) before checking. */\n fix?: boolean;\n /** Globs of source files to scan for dictionary references. */\n src?: string[];\n}\n\nexport interface CheckAnnotation {\n level: \"error\" | \"warning\";\n message: string;\n line?: number;\n}\n\nexport interface CheckDiagnostic {\n file: string;\n name?: string;\n errors: string[];\n warnings: string[];\n annotations: CheckAnnotation[];\n}\n\nexport interface CheckResult {\n success: boolean;\n diagnostics: CheckDiagnostic[];\n totalIssues: number;\n totalWarnings: number;\n /** Number of missing keys inserted by `--fix`. */\n fixed: number;\n}\n\nconst DICTIONARY_IGNORE = [\"**/node_modules/**\", \"**/dist/**\", \"**/.next/**\"];\n\nfunction addIssue(diag: CheckDiagnostic, issue: AnalysisIssue) {\n const level = issue.level === \"error\" ? \"error\" : \"warning\";\n (level === \"error\" ? diag.errors : diag.warnings).push(issue.message);\n diag.annotations.push({\n level,\n message: issue.message,\n line: issue.range ? issue.range.start.line + 1 : undefined,\n });\n}\n\n/**\n * Inserts keys that exist in one locale but not in another, copying the default-locale value\n * (strings get a `[TODO]` prefix). Returns how many keys were inserted.\n */\nasync function applyFixes(\n files: string[],\n configuredLocales: string[],\n defaultLocale: string,\n): Promise<number> {\n let fixed = 0;\n\n for (const file of files) {\n const df = await loadDictionaryFile(file);\n // Spreads and computed keys hide keys from the syntax tree; inserting would be guesswork.\n if (!df?.complete) continue;\n\n const present = listLocales(df);\n const targets = Array.from(new Set([...present, ...configuredLocales]));\n const sourceOrder = [defaultLocale, ...present.filter((l) => l !== defaultLocale)].filter((l) =>\n present.includes(l),\n );\n\n const allPaths = new Map<string, string[]>();\n for (const locale of present) {\n for (const leaf of listLeaves(df, locale)) allPaths.set(leaf.path.join(\"\\u0000\"), leaf.path);\n }\n\n let changed = false;\n for (const target of targets) {\n for (const leafPath of allPaths.values()) {\n if (hasPath(df, target, leafPath)) continue;\n const source = sourceOrder.find((l) => l !== target && hasPath(df, l, leafPath));\n if (source && copyLeaf(df, source, target, leafPath, (v) => `${TODO_PREFIX}${v}`)) {\n fixed++;\n changed = true;\n }\n }\n }\n\n if (changed) await saveDictionaryFile(df);\n }\n\n return fixed;\n}\n\nfunction escapeAnnotation(value: string): string {\n return value.replace(/%/g, \"%25\").replace(/\\r/g, \"%0D\").replace(/\\n/g, \"%0A\");\n}\n\nexport async function runCheck(options: CheckOptions = {}): Promise<CheckResult> {\n const root = options.cwd || process.cwd();\n const quiet = options.json === true;\n const inlineConfig = options.config ? { configFile: options.config } : {};\n const config = resolveDialexConfig(root, inlineConfig);\n const include = config.include || \"**/*.content.ts\";\n const configuredLocales = config.locales || [];\n const defaultLocale = config.defaultLocale || \"en\";\n\n const files = fg.sync(include, { cwd: root, absolute: true, ignore: DICTIONARY_IGNORE });\n\n if (files.length === 0) {\n if (!quiet) {\n const patternStr = Array.isArray(include) ? include.join(\", \") : include;\n logger.warn(`No dictionary files found matching \"${patternStr}\".`);\n }\n const empty: CheckResult = {\n success: true,\n diagnostics: [],\n totalIssues: 0,\n totalWarnings: 0,\n fixed: 0,\n };\n if (quiet) console.log(JSON.stringify(empty, null, 2));\n return empty;\n }\n\n let fixed = 0;\n if (options.fix) {\n fixed = await applyFixes(files, configuredLocales, defaultLocale);\n if (fixed > 0 && !quiet) {\n logger.success(\n `Inserted ${fixed} missing key${fixed === 1 ? \"\" : \"s\"} marked ${TODO_PREFIX.trim()}`,\n );\n }\n }\n\n const analysis = await analyzeProject({\n root,\n config,\n src: options.src && options.src.length > 0 ? options.src : undefined,\n runtime: true,\n });\n\n // Group issues per file, dictionary files first (the analysis reports them first)\n const byFile = new Map<string, CheckDiagnostic>();\n const dictionaryFiles = new Set(analysis.files);\n for (const issue of analysis.issues) {\n if (issue.level === \"info\") continue;\n const rel = path.relative(root, issue.file);\n let diag = byFile.get(rel);\n if (!diag) {\n diag = { file: rel, errors: [], warnings: [], annotations: [] };\n byFile.set(rel, diag);\n }\n if (dictionaryFiles.has(issue.file) && issue.dictionary && !diag.name)\n diag.name = issue.dictionary;\n addIssue(diag, issue);\n }\n const diagnostics = [...byFile.values()];\n\n const totalIssues = diagnostics.reduce((n, d) => n + d.errors.length, 0);\n const totalWarnings = diagnostics.reduce((n, d) => n + d.warnings.length, 0);\n const reported = diagnostics.filter((d) => d.errors.length > 0 || d.warnings.length > 0);\n const result: CheckResult = {\n success: totalIssues === 0,\n diagnostics: reported,\n totalIssues,\n totalWarnings,\n fixed,\n };\n\n if (options.github) {\n for (const d of reported) {\n for (const a of d.annotations) {\n const location = `file=${d.file}${a.line ? `,line=${a.line}` : \"\"}`;\n console.log(`::${a.level} ${location},title=dialex::${escapeAnnotation(a.message)}`);\n }\n }\n }\n\n if (quiet) {\n console.log(JSON.stringify(result, null, 2));\n } else if (reported.length > 0) {\n logger.log(\"\");\n if (totalIssues > 0) {\n logger.error(\n `Found ${totalIssues} issue${totalIssues === 1 ? \"\" : \"s\"} across ${reported.filter((d) => d.errors.length > 0).length} file${reported.length === 1 ? \"\" : \"s\"}:`,\n );\n }\n logger.log(\"\");\n\n for (const d of reported) {\n logger.log(` ${pc.underline(pc.bold(d.file))} ${d.name ? pc.dim(`(${d.name})`) : \"\"}:`);\n for (const a of d.annotations) {\n const where = a.line ? pc.dim(`:${a.line}`) : \"\";\n const mark = a.level === \"error\" ? pc.red(\"✖\") : pc.yellow(\"⚠\");\n logger.log(` ${mark} ${a.message}${where}`);\n }\n logger.log(\"\");\n }\n }\n\n if (totalIssues > 0) {\n if (options.exitOnError !== false) process.exit(1);\n return result;\n }\n\n if (!quiet) {\n const warningNote =\n totalWarnings > 0 ? ` (${totalWarnings} warning${totalWarnings === 1 ? \"\" : \"s\"})` : \"\";\n logger.success(\n `All ${files.length} dictionary file${files.length === 1 ? \"\" : \"s\"} passed checks with 0 issues${warningNote}!`,\n );\n }\n return result;\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { listLeaves, listLocales } from \"../utils/dictionary-edit.js\";\nimport { loadProject, toKey } from \"../utils/project.js\";\nimport { logger } from \"../utils/logger.js\";\n\nexport type TranslationFormat = \"json\" | \"csv\" | \"xliff\";\n\nexport interface ExportOptions {\n cwd?: string;\n config?: string;\n format?: TranslationFormat;\n /** Output directory, relative to `cwd`. */\n out?: string;\n /** Limit the export to these locales. */\n locale?: string[];\n /** Print machine-readable JSON instead of human output. */\n json?: boolean;\n}\n\nexport interface ExportResult {\n success: boolean;\n files: string[];\n keys: number;\n /** Function values cannot be exported as plain text. */\n skippedFunctions: number;\n skippedFiles: string[];\n}\n\nexport const escapeXml = (value: string) =>\n value.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\").replace(/\"/g, \"&quot;\");\n\nexport const csvCell = (value: string) =>\n /[\",\\r\\n]/.test(value) ? `\"${value.replace(/\"/g, '\"\"')}\"` : value;\n\nexport async function runExport(options: ExportOptions = {}): Promise<ExportResult> {\n const root = options.cwd || process.cwd();\n const format = options.format || \"json\";\n if (![\"json\", \"csv\", \"xliff\"].includes(format)) {\n throw new Error(`Unsupported format \"${format}\". Use json, csv, or xliff.`);\n }\n const outDir = path.resolve(root, options.out || \"dialex-export\");\n\n const project = await loadProject(root, options.config);\n const defaultLocale = project.config.defaultLocale || \"en\";\n\n // locale -> key -> value (insertion order = source order)\n const table = new Map<string, Map<string, string>>();\n const orderedKeys = new Set<string>();\n let skippedFunctions = 0;\n\n const localeSet = new Set<string>(project.config.locales || []);\n for (const { df } of project.dictionaries) listLocales(df).forEach((l) => localeSet.add(l));\n let locales = Array.from(localeSet);\n if (options.locale && options.locale.length > 0) {\n locales = locales.filter((l) => options.locale!.includes(l) || l === defaultLocale);\n }\n for (const locale of locales) table.set(locale, new Map());\n\n for (const { name, df } of project.dictionaries) {\n for (const locale of listLocales(df)) {\n if (!table.has(locale)) continue;\n for (const leaf of listLeaves(df, locale)) {\n if (leaf.kind === \"string\" && leaf.value !== undefined) {\n const key = toKey(name, leaf.path);\n table.get(locale)!.set(key, leaf.value);\n orderedKeys.add(key);\n } else if (locale === defaultLocale) {\n skippedFunctions++;\n }\n }\n }\n }\n\n fs.mkdirSync(outDir, { recursive: true });\n const files: string[] = [];\n const write = (name: string, content: string) => {\n const file = path.join(outDir, name);\n fs.writeFileSync(file, content, \"utf-8\");\n files.push(path.relative(root, file));\n };\n\n if (format === \"json\") {\n for (const [locale, values] of table) {\n write(`${locale}.json`, JSON.stringify(Object.fromEntries(values), null, 2) + \"\\n\");\n }\n } else if (format === \"csv\") {\n const header = [\"key\", ...table.keys()].map(csvCell).join(\",\");\n const rows = [...orderedKeys].map((key) =>\n [key, ...[...table.values()].map((v) => v.get(key) ?? \"\")].map(csvCell).join(\",\"),\n );\n write(\"translations.csv\", [header, ...rows].join(\"\\n\") + \"\\n\");\n } else {\n const source = table.get(defaultLocale);\n for (const [locale, values] of table) {\n if (locale === defaultLocale) continue;\n const units = [...orderedKeys].map((key) => {\n const src = source?.get(key) ?? \"\";\n const target = values.get(key);\n const targetXml = target === undefined ? \"\" : `<target>${escapeXml(target)}</target>`;\n return ` <trans-unit id=\"${escapeXml(key)}\"><source>${escapeXml(src)}</source>${targetXml}</trans-unit>`;\n });\n write(\n `${locale}.xlf`,\n `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<xliff version=\"1.2\" xmlns=\"urn:oasis:names:tc:xliff:document:1.2\">\n <file original=\"dialex\" source-language=\"${escapeXml(defaultLocale)}\" target-language=\"${escapeXml(locale)}\" datatype=\"plaintext\">\n <body>\n${units.join(\"\\n\")}\n </body>\n </file>\n</xliff>\n`,\n );\n }\n }\n\n const quiet = options.json === true;\n\n const result: ExportResult = {\n success: true,\n files,\n keys: orderedKeys.size,\n skippedFunctions,\n skippedFiles: project.unsupported,\n };\n\n if (quiet) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n logger.success(\n `Exported ${orderedKeys.size} key${orderedKeys.size === 1 ? \"\" : \"s\"} to ${files.length} ${format} file${files.length === 1 ? \"\" : \"s\"} in ${path.relative(root, outDir) || \".\"}`,\n );\n if (skippedFunctions > 0) {\n logger.warn(\n `${skippedFunctions} function value${skippedFunctions === 1 ? \"\" : \"s\"} skipped (not translatable as text)`,\n );\n }\n for (const file of project.unsupported)\n logger.warn(`Skipped ${file}: unsupported dictionary shape`);\n }\n\n return result;\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport {\n getString,\n hasPath,\n listLocales,\n saveDictionaryFile,\n setString,\n} from \"../utils/dictionary-edit.js\";\nimport { argumentSignature, parseMessage } from \"dialexjs/icu\";\nimport { loadProject } from \"../utils/project.js\";\nimport { logger } from \"../utils/logger.js\";\nimport type { TranslationFormat } from \"./export.js\";\n\nexport interface ImportOptions {\n cwd?: string;\n config?: string;\n /** File to import (`.json`, `.csv`, or `.xlf`/`.xliff`). */\n file: string;\n format?: TranslationFormat;\n /** Locale for single-locale files. Defaults to the file name (`tr.json`) or XLIFF target language. */\n locale?: string;\n /** Allow keys that do not exist in any locale yet. */\n allowNew?: boolean;\n /** Print machine-readable JSON instead of human output. */\n json?: boolean;\n}\n\nexport interface ImportEntry {\n locale: string;\n key: string;\n value: string;\n}\n\nexport interface ImportResult {\n success: boolean;\n created: number;\n updated: number;\n /** Function/non-text values that cannot be overwritten. */\n skipped: string[];\n /** Values refused because they are invalid ICU or change the message arguments. */\n rejected: string[];\n unknown: string[];\n errors: string[];\n}\n\nconst unescapeXml = (value: string) =>\n value\n .replace(/&lt;/g, \"<\")\n .replace(/&gt;/g, \">\")\n .replace(/&quot;/g, '\"')\n .replace(/&apos;/g, \"'\")\n .replace(/&amp;/g, \"&\");\n\nexport function parseCsv(text: string): string[][] {\n const rows: string[][] = [];\n let row: string[] = [];\n let cell = \"\";\n let quoted = false;\n\n for (let i = 0; i < text.length; i++) {\n const ch = text[i];\n if (quoted) {\n if (ch === '\"' && text[i + 1] === '\"') {\n cell += '\"';\n i++;\n } else if (ch === '\"') {\n quoted = false;\n } else {\n cell += ch;\n }\n } else if (ch === '\"') {\n quoted = true;\n } else if (ch === \",\") {\n row.push(cell);\n cell = \"\";\n } else if (ch === \"\\n\" || ch === \"\\r\") {\n if (ch === \"\\r\" && text[i + 1] === \"\\n\") i++;\n row.push(cell);\n rows.push(row);\n row = [];\n cell = \"\";\n } else {\n cell += ch;\n }\n }\n if (cell !== \"\" || row.length > 0) {\n row.push(cell);\n rows.push(row);\n }\n return rows.filter((r) => r.some((c) => c !== \"\"));\n}\n\nexport function parseEntries(\n content: string,\n format: TranslationFormat,\n fallbackLocale: string | undefined,\n): ImportEntry[] {\n const entries: ImportEntry[] = [];\n\n if (format === \"json\") {\n const data = JSON.parse(content) as Record<string, unknown>;\n const isNested =\n Object.keys(data).length > 0 &&\n Object.values(data).every((v) => v && typeof v === \"object\" && !Array.isArray(v));\n if (isNested) {\n for (const [locale, values] of Object.entries(data)) {\n for (const [key, value] of Object.entries(values as Record<string, unknown>)) {\n if (typeof value === \"string\") entries.push({ locale, key, value });\n }\n }\n } else {\n if (!fallbackLocale) throw new Error(\"Cannot infer the locale; pass --locale.\");\n for (const [key, value] of Object.entries(data)) {\n if (typeof value === \"string\") entries.push({ locale: fallbackLocale, key, value });\n }\n }\n } else if (format === \"csv\") {\n const [header, ...rows] = parseCsv(content);\n if (!header || header[0] !== \"key\") throw new Error('CSV must start with a \"key\" column.');\n for (const row of rows) {\n header.slice(1).forEach((locale, i) => {\n const value = row[i + 1];\n if (value !== undefined && value !== \"\") entries.push({ locale, key: row[0], value });\n });\n }\n } else {\n const locale = /target-language=\"([^\"]*)\"/.exec(content)?.[1] ?? fallbackLocale;\n if (!locale) throw new Error(\"Cannot infer the locale; pass --locale.\");\n const unit = /<trans-unit\\b[^>]*\\bid=\"([^\"]*)\"[^>]*>([\\s\\S]*?)<\\/trans-unit>/g;\n for (const match of content.matchAll(unit)) {\n const target = /<target\\b[^>]*>([\\s\\S]*?)<\\/target>/.exec(match[2])?.[1];\n if (target !== undefined && target !== \"\") {\n entries.push({ locale, key: unescapeXml(match[1]), value: unescapeXml(target) });\n }\n }\n }\n\n return entries;\n}\n\nfunction inferFormat(file: string): TranslationFormat {\n const ext = path.extname(file).toLowerCase();\n if (ext === \".json\") return \"json\";\n if (ext === \".csv\") return \"csv\";\n if (ext === \".xlf\" || ext === \".xliff\") return \"xliff\";\n throw new Error(`Cannot infer format from \"${ext}\". Pass --format json|csv|xliff.`);\n}\n\n/**\n * Why `value` must not replace the current text, if it is an ICU message that is invalid or uses\n * different arguments than the same key in another locale.\n */\nfunction icuProblem(\n df: Parameters<typeof getString>[0],\n defaultLocale: string,\n locale: string,\n keyPath: string[],\n value: string,\n): string | undefined {\n if (!value.includes(\"{\")) return undefined;\n\n let signature: string;\n try {\n signature = argumentSignature(parseMessage(value));\n } catch (error) {\n return `invalid ICU: ${(error as Error).message}`;\n }\n\n const locales = listLocales(df);\n for (const other of [defaultLocale, ...locales.filter((l) => l !== defaultLocale)]) {\n if (other === locale) continue;\n const reference = getString(df, other, keyPath);\n if (!reference?.includes(\"{\")) continue;\n try {\n const expected = argumentSignature(parseMessage(reference));\n return expected === signature\n ? undefined\n : `arguments differ from \"${other}\": expected ${expected || \"none\"}, found ${signature || \"none\"}`;\n } catch {\n continue;\n }\n }\n return undefined;\n}\n\nexport async function runImport(options: ImportOptions): Promise<ImportResult> {\n const root = options.cwd || process.cwd();\n const file = path.resolve(root, options.file);\n const format = options.format || inferFormat(file);\n const fallbackLocale = options.locale ?? path.basename(file, path.extname(file));\n\n const entries = parseEntries(\n fs.readFileSync(file, \"utf-8\"),\n format,\n options.locale ?? fallbackLocale,\n );\n const project = await loadProject(root, options.config);\n const byName = new Map(project.dictionaries.map((d) => [d.name, d]));\n\n const quiet = options.json === true;\n const result: ImportResult = {\n success: true,\n created: 0,\n updated: 0,\n skipped: [],\n rejected: [],\n unknown: [],\n errors: [],\n };\n const touched = new Set<string>();\n\n for (const { locale, key, value } of entries) {\n const [name, ...keyPath] = key.split(\".\");\n const dict = byName.get(name);\n if (!dict || keyPath.length === 0) {\n result.unknown.push(key);\n continue;\n }\n\n const exists = listLocales(dict.df).some((l) => hasPath(dict.df, l, keyPath));\n if (!exists && !options.allowNew) {\n result.unknown.push(key);\n continue;\n }\n\n const problem = icuProblem(\n dict.df,\n project.config.defaultLocale ?? \"en\",\n locale,\n keyPath,\n value,\n );\n if (problem) {\n result.rejected.push(`${locale}:${key} (${problem})`);\n continue;\n }\n\n const outcome = setString(dict.df, locale, keyPath, value);\n if (outcome === \"skipped\") {\n result.skipped.push(`${locale}:${key}`);\n } else {\n result[outcome]++;\n touched.add(dict.rel);\n }\n }\n\n for (const dict of project.dictionaries) {\n if (touched.has(dict.rel)) await saveDictionaryFile(dict.df);\n }\n\n if (result.rejected.length > 0) {\n result.success = false;\n }\n\n if (quiet) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n logger.success(\n `Imported ${result.created + result.updated} value${result.created + result.updated === 1 ? \"\" : \"s\"} (${result.created} added, ${result.updated} updated)`,\n );\n if (result.unknown.length > 0) {\n logger.warn(\n `${result.unknown.length} unknown key${result.unknown.length === 1 ? \"\" : \"s\"} ignored (use --allow-new to add): ${result.unknown.slice(0, 5).join(\", \")}${result.unknown.length > 5 ? \", ...\" : \"\"}`,\n );\n }\n if (result.rejected.length > 0) {\n logger.warn(\n `${result.rejected.length} value${result.rejected.length === 1 ? \"\" : \"s\"} rejected: ${result.rejected.slice(0, 5).join(\"; \")}`,\n );\n }\n if (result.skipped.length > 0) {\n logger.warn(\n `${result.skipped.length} non-text value${result.skipped.length === 1 ? \"\" : \"s\"} left unchanged: ${result.skipped.slice(0, 5).join(\", \")}`,\n );\n }\n }\n\n return result;\n}\n","import { getArguments, isIcuStructured, parseMessage } from \"dialexjs/icu\";\n\n/** `{name}`, `%s` / `%1$d`, and HTML/XML tags: text that must survive translation unchanged. */\nconst PLACEHOLDER = /\\{[^{}]+\\}|%\\d*\\$?[sdif]|<\\/?[A-Za-z][^<>]*>/g;\n\nexport function extractPlaceholders(text: string): string[] {\n return text.match(PLACEHOLDER) ?? [];\n}\n\n/**\n * ICU plural/select messages put translatable text inside `{...}` branches, so brace matching\n * is meaningless for them. Compare the structure instead: the same arguments with the same\n * types, every `select` key and every exact `=N` plural match preserved. A translation may\n * add or drop plural categories (`one`, `few`, ...), because languages need different ones.\n */\nfunction preservesIcuStructure(source: string, translated: string): boolean {\n try {\n const before = getArguments(parseMessage(source));\n const after = getArguments(parseMessage(translated));\n const sameArguments =\n before.length === after.length &&\n before.every((a) => after.some((b) => a.name === b.name && a.type === b.type));\n if (!sameArguments) return false;\n\n return before.every((a) => {\n const other = after.find((b) => b.name === a.name && b.type === a.type)!;\n const keep =\n a.type === \"select\"\n ? (a.selectors ?? [])\n : (a.selectors ?? []).filter((selector) => selector.startsWith(\"=\"));\n return keep.every((selector) => other.selectors?.includes(selector));\n });\n } catch {\n return false;\n }\n}\n\n/** True when every placeholder of `source` appears in `translated` (as many times as in the source). */\nexport function preservesPlaceholders(source: string, translated: string): boolean {\n if (isIcuStructured(source)) return preservesIcuStructure(source, translated);\n\n const remaining = extractPlaceholders(translated);\n for (const placeholder of extractPlaceholders(source)) {\n const index = remaining.indexOf(placeholder);\n if (index === -1) return false;\n remaining.splice(index, 1);\n }\n return true;\n}\n","import pc from \"picocolors\";\nimport type { TranslateProvider } from \"dialexjs\";\nimport {\n TODO_PREFIX,\n listLeaves,\n listLocales,\n saveDictionaryFile,\n setString,\n} from \"../utils/dictionary-edit.js\";\nimport { loadProject, toKey, type ProjectDictionary } from \"../utils/project.js\";\nimport { isIcuStructured } from \"dialexjs/icu\";\nimport { preservesPlaceholders } from \"../translate/placeholders.js\";\nimport { logger } from \"../utils/logger.js\";\n\nexport interface TranslateOptions {\n cwd?: string;\n config?: string;\n /** Target locales. Defaults to every configured locale except the source. */\n locale?: string[];\n /** Locale to translate from. Defaults to `translate.sourceLocale`, then `defaultLocale`. */\n source?: string;\n /** List what would be translated without calling the provider or writing files. */\n dryRun?: boolean;\n /** Overrides the provider from the config (used by tests). */\n provider?: TranslateProvider;\n /** Print machine-readable JSON instead of human output. */\n json?: boolean;\n}\n\nexport interface PendingTranslation {\n file: string;\n locale: string;\n key: string;\n source: string;\n /** Present after translation. */\n translated?: string;\n}\n\nexport interface TranslateResult {\n success: boolean;\n dryRun: boolean;\n pending: PendingTranslation[];\n translated: number;\n /** Translations rejected because they changed placeholders, or that could not be written. */\n rejected: string[];\n}\n\ninterface Task extends PendingTranslation {\n dict: ProjectDictionary;\n path: string[];\n}\n\nexport async function runTranslate(options: TranslateOptions = {}): Promise<TranslateResult> {\n const root = options.cwd || process.cwd();\n const project = await loadProject(root, options.config);\n const settings = project.config.translate;\n const provider = options.provider ?? settings?.provider;\n\n if (!provider && !options.dryRun) {\n throw new Error(\n \"No translate provider configured. Add `translate: { provider: claudeProvider() }` to dialex.config.ts \" +\n '(import it from \"@dialexjs/cli/translate\").',\n );\n }\n\n const source = options.source ?? settings?.sourceLocale ?? project.config.defaultLocale ?? \"en\";\n const everyLocale = new Set<string>(project.config.locales ?? []);\n for (const { df } of project.dictionaries) listLocales(df).forEach((l) => everyLocale.add(l));\n const targets = (options.locale?.length ? options.locale : [...everyLocale]).filter(\n (l) => l !== source,\n );\n\n // 1. Collect strings that are missing or still marked [TODO]\n const tasks: Task[] = [];\n for (const dict of project.dictionaries) {\n const sourceLeaves = listLeaves(dict.df, source).filter(\n (leaf) => leaf.kind === \"string\" && leaf.value !== undefined,\n );\n\n for (const locale of targets) {\n const existing = new Map(\n listLeaves(dict.df, locale).map((leaf) => [leaf.path.join(\"\\u0000\"), leaf]),\n );\n for (const leaf of sourceLeaves) {\n const current = existing.get(leaf.path.join(\"\\u0000\"));\n const needs =\n !current || (current.kind === \"string\" && current.value?.startsWith(TODO_PREFIX));\n if (needs) {\n tasks.push({\n dict,\n path: leaf.path,\n file: dict.rel,\n locale,\n key: toKey(dict.name, leaf.path),\n source: leaf.value!,\n });\n }\n }\n }\n }\n\n const quiet = options.json === true;\n\n const result: TranslateResult = {\n success: true,\n dryRun: options.dryRun === true,\n pending: tasks,\n translated: 0,\n rejected: [],\n };\n\n if (tasks.length === 0) {\n if (quiet) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n logger.success(`Nothing to translate from \"${source}\".`);\n }\n return result;\n }\n\n if (options.dryRun) {\n if (quiet) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n logger.info(\n `Would translate ${tasks.length} string${tasks.length === 1 ? \"\" : \"s\"} from \"${source}\":`,\n );\n for (const t of tasks) {\n logger.log(` ${pc.dim(t.locale)} ${t.key} ${pc.dim(JSON.stringify(t.source))}`);\n }\n }\n return result;\n }\n\n // 2. Translate per target locale, de-duplicating identical source strings\n const touched = new Set<ProjectDictionary>();\n for (const locale of targets) {\n const localeTasks = tasks.filter((t) => t.locale === locale);\n if (localeTasks.length === 0) continue;\n\n // Providers that cannot keep ICU plural/select structure intact never see those messages\n const sendable = provider!.supportsIcu\n ? localeTasks\n : localeTasks.filter((task) => {\n if (!isIcuStructured(task.source)) return true;\n result.rejected.push(\n `${locale}:${task.key} (provider does not support ICU plural/select messages)`,\n );\n return false;\n });\n if (sendable.length === 0) continue;\n\n const unique = [...new Set(sendable.map((t) => t.source))];\n if (!quiet) {\n logger.info(\n `Translating ${unique.length} string${unique.length === 1 ? \"\" : \"s\"} to \"${locale}\" with ${provider!.name ?? \"provider\"}...`,\n );\n }\n const translations = await provider!.translate(unique, source, locale);\n if (translations.length !== unique.length) {\n throw new Error(\n `Provider returned ${translations.length} translations for ${unique.length} strings.`,\n );\n }\n const byText = new Map(unique.map((text, i) => [text, translations[i]]));\n\n for (const task of sendable) {\n const translated = byText.get(task.source);\n if (typeof translated !== \"string\" || translated.trim() === \"\") {\n result.rejected.push(`${locale}:${task.key} (empty translation)`);\n continue;\n }\n if (!preservesPlaceholders(task.source, translated)) {\n result.rejected.push(`${locale}:${task.key} (placeholders changed)`);\n continue;\n }\n if (setString(task.dict.df, locale, task.path, translated) === \"skipped\") {\n result.rejected.push(`${locale}:${task.key} (not a text value)`);\n continue;\n }\n task.translated = translated;\n result.translated++;\n touched.add(task.dict);\n }\n }\n\n for (const dict of touched) await saveDictionaryFile(dict.df);\n\n if (result.rejected.length > 0) {\n result.success = false;\n }\n\n if (quiet) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n logger.success(\n `Translated ${result.translated} of ${tasks.length} string${tasks.length === 1 ? \"\" : \"s\"}.`,\n );\n if (result.rejected.length > 0) {\n logger.warn(\n `${result.rejected.length} left unchanged: ${result.rejected.slice(0, 5).join(\"; \")}${result.rejected.length > 5 ? \"; ...\" : \"\"}`,\n );\n }\n }\n return result;\n}\n","#!/usr/bin/env node\n\nimport { Command } from \"commander\";\nimport { runGenerate } from \"./commands/generate.js\";\nimport { runInit } from \"./commands/init.js\";\nimport { logger } from \"./utils/logger.js\";\nimport { runCheck } from \"./commands/check.js\";\nimport { runExport } from \"./commands/export.js\";\nimport { runImport } from \"./commands/import.js\";\nimport { runTranslate } from \"./commands/translate.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"dialex\")\n .description(\"Dialex CLI - High-performance, type-safe internationalization compiler and tooling\")\n .version(\"0.3.0\");\n\nprogram\n .command(\"generate\")\n .alias(\"gen\")\n .description(\"Generate standalone dictionary bundle and TypeScript declarations\")\n .option(\"-w, --watch\", \"Watch dictionary files for changes\")\n .option(\"-o, --output <path>\", \"Custom output file path for generated dictionaries\")\n .option(\"-c, --config <path>\", \"Custom config path\")\n .option(\"--json\", \"Print machine-readable JSON\")\n .action(async (opts) => {\n await runGenerate(opts);\n });\n\nprogram\n .command(\"init\")\n .description(\"Initialize Dialex in the current project\")\n .option(\n \"-f, --framework <framework>\",\n \"Target framework (hono, express, fastify, koa, nestjs, next, react)\",\n )\n .option(\"-d, --default-locale <locale>\", \"Default locale (e.g. en)\")\n .option(\"-l, --locales <locales>\", \"Comma-separated supported locales (e.g. en,tr)\")\n .option(\"-y, --yes\", \"Skip prompts and use defaults\")\n .option(\"--ai\", \"Configure AI agent support (.agents/skills, .mcp.json, AGENTS.md)\")\n .option(\"--no-ai\", \"Skip AI agent configuration\")\n .action(async (opts) => {\n await runInit(opts);\n });\n\nprogram\n .command(\"check\")\n .alias(\"lint\")\n .description(\"Verify dictionary key parity and locale completeness\")\n .option(\"-c, --config <path>\", \"Custom config path\")\n .option(\"--json\", \"Print machine-readable JSON\")\n .option(\"--github\", \"Print GitHub Actions annotations\")\n .option(\"--fix\", \"Insert missing keys marked with [TODO]\")\n .option(\"--src <globs...>\", \"Source globs to scan for dictionary references\")\n .action(async (opts) => {\n await runCheck(opts);\n });\n\nprogram\n .command(\"export\")\n .description(\"Export dictionary strings for translators (json, csv, or xliff)\")\n .option(\"-f, --format <format>\", \"Output format: json, csv, xliff\", \"json\")\n .option(\"-o, --out <dir>\", \"Output directory\", \"dialex-export\")\n .option(\"-l, --locale <locales...>\", \"Limit to these locales\")\n .option(\"-c, --config <path>\", \"Custom config path\")\n .option(\"--json\", \"Print machine-readable JSON\")\n .action(async (opts) => {\n await runExport(opts);\n });\n\nprogram\n .command(\"import <file>\")\n .description(\"Write translated strings from a json, csv, or xliff file back into dictionaries\")\n .option(\"-f, --format <format>\", \"Input format (inferred from the extension)\")\n .option(\"-l, --locale <locale>\", \"Locale for single-locale files\")\n .option(\"--allow-new\", \"Add keys that do not exist in any locale yet\")\n .option(\"-c, --config <path>\", \"Custom config path\")\n .option(\"--json\", \"Print machine-readable JSON\")\n .action(async (file, opts) => {\n await runImport({ file, ...opts });\n });\n\nprogram\n .command(\"translate\")\n .description(\"Fill missing translations with the provider configured in dialex.config.ts\")\n .option(\"-l, --locale <locales...>\", \"Target locales (default: all configured)\")\n .option(\n \"-s, --source <locale>\",\n \"Source locale (default: translate.sourceLocale or defaultLocale)\",\n )\n .option(\"--dry-run\", \"List what would be translated without calling the provider\")\n .option(\"-c, --config <path>\", \"Custom config path\")\n .option(\"--json\", \"Print machine-readable JSON\")\n .action(async (opts) => {\n try {\n await runTranslate(opts);\n } catch (err: any) {\n if (opts.json) {\n console.log(JSON.stringify({ success: false, error: err.message || String(err) }, null, 2));\n } else {\n logger.error(err.message || String(err));\n }\n process.exit(1);\n }\n });\n\nprogram.parse();\n"],"mappings":"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"}
@@ -2,7 +2,7 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import fg from "fast-glob";
4
4
  import chokidar from "chokidar";
5
- import { generateDts, resolveI18nConfig } from "dialexjs/scanner";
5
+ import { generateDts, resolveDialexConfig } from "dialexjs/scanner";
6
6
  import pc from "picocolors";
7
7
  import { generateCode, parseExpression, parseModule, writeFile } from "magicast";
8
8
  import { pathToFileURL } from "node:url";
@@ -19,7 +19,7 @@ const logger = {
19
19
  //#region src/commands/generate.ts
20
20
  function generateDictionaries(root, options = {}) {
21
21
  const inlineConfig = options.config ? { configFile: options.config } : {};
22
- const config = resolveI18nConfig(root, inlineConfig);
22
+ const config = resolveDialexConfig(root, inlineConfig);
23
23
  const include = config.include || "**/*.content.ts";
24
24
  const files = fg.sync(include, {
25
25
  cwd: root,
@@ -98,7 +98,7 @@ async function runGenerate(options = {}) {
98
98
  if (options.watch) {
99
99
  logger.info("Watching for dictionary changes (-w, --watch)...");
100
100
  const inlineConfig = options.config ? { configFile: options.config } : {};
101
- const pattern = resolveI18nConfig(root, inlineConfig).include || "**/*.content.ts";
101
+ const pattern = resolveDialexConfig(root, inlineConfig).include || "**/*.content.ts";
102
102
  chokidar.watch(pattern, {
103
103
  cwd: root,
104
104
  ignoreInitial: true,
@@ -479,8 +479,8 @@ const SOURCE_IGNORE = [
479
479
  "**/dialex.config.*",
480
480
  "**/i18n.config.*"
481
481
  ];
482
- /** `getDictionary("x")`, `useDictionary("x")`, `@I18nDictionary("x")` */
483
- const DICTIONARY_CALL = /\b(?:getDictionary|useDictionary|I18nDictionary)\(\s*(["'`])([^"'`$\n]+)\1/dg;
482
+ /** `getDictionary("x")`, `useDictionary("x")`, `@DialexDictionary("x")` */
483
+ const DICTIONARY_CALL = /\b(?:getDictionary|useDictionary|DialexDictionary)\(\s*(["'`])([^"'`$\n]+)\1/dg;
484
484
  /** `t("dictionary.path.to.key")` */
485
485
  const T_CALL = /(?<![\w$.])t\(\s*(["'`])([\w-]+(?:\.[\w-]+)+)\1/dg;
486
486
  /** Finds `getDictionary("x")`-style and `t("x.y.z")` references in source text. */
@@ -963,7 +963,7 @@ async function loadDictionaries(root, config) {
963
963
  * every dictionary file for AST-level reading and editing.
964
964
  */
965
965
  async function loadProject(root, configFile) {
966
- const config = resolveI18nConfig(root, configFile ? { configFile } : {});
966
+ const config = resolveDialexConfig(root, configFile ? { configFile } : {});
967
967
  return {
968
968
  root,
969
969
  config,
@@ -989,4 +989,4 @@ const toKey = (dictionary, keyPath) => [dictionary, ...keyPath].join(".");
989
989
  //#endregion
990
990
  export { saveDictionaryFile as C, logger as D, runGenerate as E, renderDictionaryFile as S, generateDictionaries as T, listLeaves as _, parseStaticConfig as a, locationOf as b, analyzeProject as c, TODO_PREFIX as d, copyLeaf as f, hasPath as g, getString as h, DEFAULT_STATIC_CONFIG as i, relativeFile as l, getLeafSource as m, loadStaticProject as n, readStaticConfig as o, dictionaryLocation as p, toKey as r, DEFAULT_SOURCE_GLOB as s, loadProject as t, scanReferences as u, listLocales as v, setString as w, parseDictionaryText as x, loadDictionaryFile as y };
991
991
 
992
- //# sourceMappingURL=project-BnG6V2I0.mjs.map
992
+ //# sourceMappingURL=project-ClQxaIMc.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-ClQxaIMc.mjs","names":["unwrapNode","propertyKeyName","isObjectNode","findProperty"],"sources":["../src/utils/logger.ts","../src/commands/generate.ts","../src/utils/dictionary-edit.ts","../src/utils/icu-check.ts","../src/analysis.ts","../src/utils/static-config.ts","../src/utils/project.ts"],"sourcesContent":["import pc from \"picocolors\";\n\nexport const logger = {\n info: (msg: string) => console.log(pc.blue(\"ℹ \") + msg),\n success: (msg: string) => console.log(pc.green(\"✔ \") + pc.bold(msg)),\n warn: (msg: string) => console.warn(pc.yellow(\"⚠ \") + msg),\n error: (msg: string) => console.error(pc.red(\"✖ \") + pc.bold(msg)),\n log: (msg: string) => console.log(msg),\n};\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport fg from \"fast-glob\";\nimport chokidar from \"chokidar\";\nimport { resolveDialexConfig, generateDts } from \"dialexjs/scanner\";\nimport { logger } from \"../utils/logger.js\";\n\nexport interface GenerateOptions {\n cwd?: string;\n watch?: boolean;\n output?: string;\n config?: string;\n json?: boolean;\n}\n\nexport function generateDictionaries(\n root: string,\n options: GenerateOptions = {},\n): {\n files: string[];\n outputPath: string;\n dtsPath: string;\n} {\n const inlineConfig = options.config ? { configFile: options.config } : {};\n const config = resolveDialexConfig(root, inlineConfig);\n const include = config.include || \"**/*.content.ts\";\n\n const files = fg.sync(include, {\n cwd: root,\n absolute: true,\n ignore: [\"**/node_modules/**\", \"**/dist/**\", \"**/.next/**\"],\n });\n\n const srcDir = fs.existsSync(path.join(root, \"src\")) ? path.join(root, \"src\") : root;\n const targetOutput = options.output\n ? path.resolve(root, options.output)\n : path.join(srcDir, \"dialex.generated.ts\");\n\n const targetDir = path.dirname(targetOutput);\n\n // 1. Generate TypeScript environment declarations\n generateDts(root, files, config.locales);\n const dtsPath = path.join(srcDir, \"dialex-env.d.ts\");\n\n // 2. Build standalone generated module content\n const importLines: string[] = [];\n const dictIdentifiers: string[] = [];\n\n files.forEach((file, idx) => {\n let rel = path.relative(targetDir, file).replace(/\\\\/g, \"/\");\n rel = rel.replace(/\\.ts$/, \".js\");\n if (!rel.startsWith(\".\")) {\n rel = \"./\" + rel;\n }\n const id = `dict_${idx}`;\n importLines.push(`import ${id} from \"${rel}\";`);\n dictIdentifiers.push(id);\n });\n\n const dictList =\n dictIdentifiers.length <= 1\n ? `[${dictIdentifiers.join(\", \")}]`\n : `[\\n ${dictIdentifiers.join(\",\\n \")}\\n]`;\n\n const content = `// Auto-generated by dialex CLI. Do not edit directly.\n/* eslint-disable */\n// @ts-nocheck\n${importLines.join(\"\\n\")}\n\nexport const dictionaries = ${dictList};\n\nexport const dictionaryMap = {\n${dictIdentifiers.map((id) => ` [${id}.name]: ${id}.dictionary,`).join(\"\\n\")}\n};\n\nexport default dictionaries;\n`;\n\n fs.mkdirSync(targetDir, { recursive: true });\n const existing = fs.existsSync(targetOutput) ? fs.readFileSync(targetOutput, \"utf-8\") : \"\";\n if (existing !== content) {\n fs.writeFileSync(targetOutput, content, \"utf-8\");\n }\n\n return { files, outputPath: targetOutput, dtsPath };\n}\n\nexport async function runGenerate(options: GenerateOptions = {}) {\n const root = options.cwd || process.cwd();\n const quiet = options.json === true;\n\n const doGenerate = () => {\n try {\n const { files, outputPath, dtsPath } = generateDictionaries(root, options);\n if (quiet) {\n console.log(\n JSON.stringify(\n {\n success: true,\n files: files.map((f) => path.relative(root, f)),\n outputPath: path.relative(root, outputPath),\n dtsPath: path.relative(root, dtsPath),\n },\n null,\n 2,\n ),\n );\n } else {\n logger.success(\n `Generated dictionaries for ${files.length} file${files.length === 1 ? \"\" : \"s\"}:`,\n );\n logger.info(`→ ${path.relative(root, outputPath)}`);\n logger.info(`→ ${path.relative(root, dtsPath)}`);\n }\n return true;\n } catch (err: any) {\n if (quiet) {\n console.log(\n JSON.stringify(\n {\n success: false,\n error: err.message || String(err),\n },\n null,\n 2,\n ),\n );\n } else {\n logger.error(`Generation failed: ${err.message || String(err)}`);\n }\n return false;\n }\n };\n\n const ok = doGenerate();\n if (!ok && !options.watch) {\n process.exit(1);\n }\n\n if (options.watch) {\n logger.info(\"Watching for dictionary changes (-w, --watch)...\");\n const inlineConfig = options.config ? { configFile: options.config } : {};\n const config = resolveDialexConfig(root, inlineConfig);\n const pattern = config.include || \"**/*.content.ts\";\n\n const watcher = chokidar.watch(pattern, {\n cwd: root,\n ignoreInitial: true,\n ignored: [\"**/node_modules/**\", \"**/dist/**\", \"**/.next/**\"],\n });\n\n watcher.on(\"all\", (event, filePath) => {\n logger.info(`[${event}] ${filePath} changed, regenerating...`);\n doGenerate();\n });\n }\n}\n","import fs from \"node:fs\";\nimport { loadFile, writeFile, generateCode, parseExpression, parseModule } from \"magicast\";\n\n/**\n * AST-level helpers for reading and editing `.content.ts` dictionary files.\n *\n * Magicast's proxy layer cannot represent every value (for example template-literal\n * functions), so these helpers work on the underlying AST nodes and use Magicast only\n * to parse and print, which preserves the rest of the file's formatting.\n *\n * Supported shapes:\n * - `export default defineDictionary(\"name\", { en: {...}, tr: {...} })`\n * - `export default defineDictionary({ name: \"name\", dictionary: { ... } })`\n * - `export default { name: \"name\", dictionary: { ... } }`\n */\n\ntype Node = { type: string; [key: string]: any };\n\nexport const TODO_PREFIX = \"[TODO] \";\n\nconst IDENTIFIER = /^[A-Za-z_$][\\w$]*$/;\n\nexport interface DictionaryFile {\n file: string;\n /** Dictionary name from `defineDictionary(\"name\", ...)` or the `name` property, if literal. */\n name?: string;\n mod: Awaited<ReturnType<typeof loadFile>>;\n /** The object whose keys are locales. */\n localesObj: Node;\n /** Whether the file ended with a newline when loaded; restored on save. */\n endsWithNewline: boolean;\n /**\n * `false` when part of the dictionary cannot be read statically (spreads, computed keys, or a\n * locale whose content is not an object literal). Leaf lists and parity checks are unreliable\n * for such files.\n */\n complete: boolean;\n}\n\n/** A zero-based line/column range, as used by editors. */\nexport interface SourceRange {\n start: { line: number; column: number };\n end: { line: number; column: number };\n}\n\nexport type LeafKind = \"string\" | \"function\" | \"other\";\n\nexport interface Leaf {\n path: string[];\n kind: LeafKind;\n /** Present when `kind` is `\"string\"`. */\n value?: string;\n}\n\nfunction unwrap(node: Node): Node {\n while (\n node &&\n (node.type === \"TSAsExpression\" ||\n node.type === \"TSSatisfiesExpression\" ||\n node.type === \"ParenthesizedExpression\")\n ) {\n node = node.expression;\n }\n return node;\n}\n\nconst isObject = (node: Node) => node?.type === \"ObjectExpression\";\n\nfunction keyName(prop: Node): string | undefined {\n const key = prop?.key;\n if (!key || prop.computed) return undefined;\n if (key.type === \"Identifier\") return key.name;\n if (key.type === \"StringLiteral\" || (key.type === \"Literal\" && typeof key.value === \"string\")) {\n return key.value;\n }\n if (key.type === \"NumericLiteral\") return String(key.value);\n return undefined;\n}\n\nconst isPropLike = (p: Node) =>\n p?.type === \"ObjectProperty\" || p?.type === \"Property\" || p?.type === \"ObjectMethod\";\n\nfunction findProp(obj: Node, key: string): Node | undefined {\n return obj.properties.find((p: Node) => isPropLike(p) && keyName(p) === key);\n}\n\nfunction stringValue(node: Node): string | undefined {\n node = unwrap(node);\n if (node?.type === \"StringLiteral\") return node.value;\n if (node?.type === \"Literal\" && typeof node.value === \"string\") return node.value;\n if (node?.type === \"TemplateLiteral\" && node.expressions.length === 0) {\n return node.quasis[0]?.value?.cooked ?? undefined;\n }\n return undefined;\n}\n\nfunction leafKind(node: Node): LeafKind {\n node = unwrap(node);\n if (stringValue(node) !== undefined) return \"string\";\n if (\n node?.type === \"ArrowFunctionExpression\" ||\n node?.type === \"FunctionExpression\" ||\n node?.type === \"ObjectMethod\"\n ) {\n return \"function\";\n }\n return \"other\";\n}\n\nfunction dictionaryProp(obj: Node): Node | undefined {\n const prop = findProp(obj, \"dictionary\");\n const value = unwrap(prop?.value);\n return isObject(value) ? value : undefined;\n}\n\nfunction locateName(declaration: Node): string | undefined {\n const decl = unwrap(declaration);\n if (decl?.type === \"CallExpression\") {\n const first = unwrap(decl.arguments[0]);\n if (isObject(first)) return stringValue(findProp(first, \"name\")?.value);\n return stringValue(first);\n }\n if (isObject(decl)) return stringValue(findProp(decl, \"name\")?.value);\n return undefined;\n}\n\nfunction locateLocalesObject(declaration: Node): Node | undefined {\n const decl = unwrap(declaration);\n if (decl?.type === \"CallExpression\") {\n const first = unwrap(decl.arguments[0]);\n const second = unwrap(decl.arguments[1]);\n if (isObject(second)) return second;\n if (isObject(first)) return dictionaryProp(first);\n return undefined;\n }\n if (isObject(decl)) return dictionaryProp(decl);\n return undefined;\n}\n\n/** Quotes a property key only when it is not a valid identifier. */\nfunction keyCode(key: string): string {\n return IDENTIFIER.test(key) ? key : JSON.stringify(key);\n}\n\n/** Builds a detached `key: <value>` property node from source text. */\nfunction makeProp(key: string, valueCode: string): Node {\n const expr: Node = parseExpression(`({ ${keyCode(key)}: ${valueCode} })`);\n return expr.$ast.properties[0];\n}\n\nfunction makeStringNode(value: string): Node {\n return makeProp(\"_\", JSON.stringify(value)).value;\n}\n\n/**\n * A dictionary is statically readable when every locale is an object literal and no object on the\n * way down uses spreads or computed keys.\n */\nfunction isStaticallyComplete(localesObj: Node): boolean {\n const walk = (obj: Node): boolean =>\n obj.properties.every((prop: Node) => {\n if (!isPropLike(prop) || keyName(prop) === undefined) return false;\n if (prop.type === \"ObjectMethod\") return true;\n const value = unwrap(prop.value);\n return isObject(value) ? walk(value) : true;\n });\n\n return localesObj.properties.every((prop: Node) => {\n if (!isPropLike(prop) || keyName(prop) === undefined || prop.type === \"ObjectMethod\")\n return false;\n const value = unwrap(prop.value);\n return isObject(value) && walk(value);\n });\n}\n\n/**\n * Parses dictionary source text (for example an unsaved editor buffer). Returns `undefined` when\n * the file does not have an editable shape; throws on syntax errors.\n */\nexport function parseDictionaryText(file: string, text: string): DictionaryFile | undefined {\n const mod = parseModule(text);\n const exported: Node = (mod.exports as any).default;\n const ast: Node = exported?.$ast;\n if (!ast) return undefined;\n const declaration = ast.declaration ?? ast;\n const localesObj = locateLocalesObject(declaration);\n return localesObj\n ? {\n file,\n mod,\n localesObj,\n name: locateName(declaration),\n endsWithNewline: text.endsWith(\"\\n\"),\n complete: isStaticallyComplete(localesObj),\n }\n : undefined;\n}\n\n/** Loads a dictionary file; returns `undefined` when its shape is not editable. */\nexport async function loadDictionaryFile(file: string): Promise<DictionaryFile | undefined> {\n return parseDictionaryText(file, fs.readFileSync(file, \"utf-8\"));\n}\n\n/** The source text with all edits applied, without writing anything. */\nexport function renderDictionaryFile(df: DictionaryFile): string {\n const code = generateCode(df.mod as any).code;\n return df.endsWithNewline && !code.endsWith(\"\\n\") ? `${code}\\n` : code;\n}\n\nexport async function saveDictionaryFile(df: DictionaryFile): Promise<void> {\n await writeFile(df.mod, df.file);\n if (df.endsWithNewline) {\n const text = fs.readFileSync(df.file, \"utf-8\");\n if (!text.endsWith(\"\\n\")) fs.writeFileSync(df.file, text + \"\\n\", \"utf-8\");\n }\n}\n\nexport function listLocales(df: DictionaryFile): string[] {\n return df.localesObj.properties\n .filter(isPropLike)\n .map(keyName)\n .filter((k: string | undefined): k is string => k !== undefined);\n}\n\nfunction localeObject(df: DictionaryFile, locale: string): Node | undefined {\n const value = unwrap(findProp(df.localesObj, locale)?.value);\n return isObject(value) ? value : undefined;\n}\n\n/** Lists every leaf (string, function, or other value) of a locale, in source order. */\nexport function listLeaves(df: DictionaryFile, locale: string): Leaf[] {\n const root = localeObject(df, locale);\n if (!root) return [];\n\n const leaves: Leaf[] = [];\n const walk = (obj: Node, prefix: string[]) => {\n for (const prop of obj.properties) {\n if (!isPropLike(prop)) continue;\n const name = keyName(prop);\n if (name === undefined) continue;\n const path = [...prefix, name];\n const value = prop.type === \"ObjectMethod\" ? prop : unwrap(prop.value);\n if (isObject(value)) {\n walk(value, path);\n } else {\n const kind = leafKind(value);\n leaves.push({ path, kind, ...(kind === \"string\" ? { value: stringValue(value) } : {}) });\n }\n }\n };\n walk(root, []);\n return leaves;\n}\n\nfunction getProp(df: DictionaryFile, locale: string, path: string[]): Node | undefined {\n let obj = localeObject(df, locale);\n for (let i = 0; obj && i < path.length; i++) {\n const prop = findProp(obj, path[i]);\n if (!prop) return undefined;\n if (i === path.length - 1) return prop;\n const next = unwrap(prop.value);\n obj = isObject(next) ? next : undefined;\n }\n return undefined;\n}\n\nexport function hasPath(df: DictionaryFile, locale: string, path: string[]): boolean {\n return getProp(df, locale, path) !== undefined;\n}\n\nexport function getString(df: DictionaryFile, locale: string, path: string[]): string | undefined {\n const prop = getProp(df, locale, path);\n return prop && prop.type !== \"ObjectMethod\" ? stringValue(prop.value) : undefined;\n}\n\nfunction ensureLocale(df: DictionaryFile, locale: string): Node {\n let obj = localeObject(df, locale);\n if (!obj) {\n const prop = makeProp(locale, \"{}\");\n df.localesObj.properties.push(prop);\n obj = prop.value as Node;\n }\n return obj;\n}\n\n/** Returns the object that should contain the last path segment, creating objects as needed. */\nfunction ensureParent(df: DictionaryFile, locale: string, path: string[]): Node | undefined {\n let obj = ensureLocale(df, locale);\n for (const segment of path.slice(0, -1)) {\n let prop = findProp(obj, segment);\n if (!prop) {\n prop = makeProp(segment, \"{}\");\n obj.properties.push(prop);\n }\n const next = unwrap(prop.value);\n if (!isObject(next)) return undefined;\n obj = next;\n }\n return obj;\n}\n\nexport type SetResult = \"created\" | \"updated\" | \"skipped\";\n\n/**\n * Sets a string value at `path`. Existing function or non-string values are left alone\n * (`\"skipped\"`) because they cannot be translated as plain text.\n */\nexport function setString(\n df: DictionaryFile,\n locale: string,\n path: string[],\n value: string,\n): SetResult {\n const parent = ensureParent(df, locale, path);\n if (!parent) return \"skipped\";\n\n const last = path[path.length - 1];\n const existing = findProp(parent, last);\n if (existing) {\n if (existing.type === \"ObjectMethod\" || leafKind(existing.value) !== \"string\") {\n return \"skipped\";\n }\n existing.value = makeStringNode(value);\n return \"updated\";\n }\n parent.properties.push(makeProp(last, JSON.stringify(value)));\n return \"created\";\n}\n\n/**\n * Copies the leaf at `path` from one locale to another. String values can be rewritten with\n * `mapString` (for example to add a `[TODO]` marker); other values are copied verbatim.\n * Returns `false` when the source has no such leaf or the target already has one.\n */\nexport function copyLeaf(\n df: DictionaryFile,\n fromLocale: string,\n toLocale: string,\n path: string[],\n mapString?: (value: string) => string,\n): boolean {\n const source = getProp(df, fromLocale, path);\n if (!source || hasPath(df, toLocale, path)) return false;\n\n const parent = ensureParent(df, toLocale, path);\n if (!parent) return false;\n\n const last = path[path.length - 1];\n const text = source.type === \"ObjectMethod\" ? undefined : stringValue(source.value);\n if (text !== undefined && mapString) {\n parent.properties.push(makeProp(last, JSON.stringify(mapString(text))));\n } else {\n const code = generateCode(source as any).code;\n const expr: Node = parseExpression(`({ ${code} })`);\n parent.properties.push(expr.$ast.properties[0]);\n }\n return true;\n}\n\n/** Leaf paths of a runtime dictionary value (plain objects recurse; everything else is a leaf). */\nexport function flattenPaths(value: unknown, prefix: string[] = []): string[][] {\n if (value && typeof value === \"object\" && !Array.isArray(value)) {\n return Object.entries(value).flatMap(([k, v]) => flattenPaths(v, [...prefix, k]));\n }\n return prefix.length > 0 ? [prefix] : [];\n}\n\nconst toRange = (loc: Node | undefined): SourceRange | undefined =>\n loc\n ? {\n start: { line: loc.start.line - 1, column: loc.start.column },\n end: { line: loc.end.line - 1, column: loc.end.column },\n }\n : undefined;\n\n/**\n * Where a locale (no `path`) or a key within it is written. The range covers the property key, so\n * it is a good place to attach a diagnostic or jump to.\n */\nexport function locationOf(\n df: DictionaryFile,\n locale: string,\n path: string[] = [],\n): SourceRange | undefined {\n const prop = path.length === 0 ? findProp(df.localesObj, locale) : getProp(df, locale, path);\n return toRange((prop?.key ?? prop)?.loc);\n}\n\n/** The source text of the dictionary object itself (the object whose keys are locales). */\nexport function dictionaryLocation(df: DictionaryFile): SourceRange | undefined {\n return toRange(df.localesObj.loc);\n}\n\n/** The source code of a leaf's value (a function's source, or a string with its quotes). */\nexport function getLeafSource(\n df: DictionaryFile,\n locale: string,\n path: string[],\n): string | undefined {\n const prop = getProp(df, locale, path);\n if (!prop) return undefined;\n return generateCode((prop.type === \"ObjectMethod\" ? prop : prop.value) as any).code;\n}\n\n// AST helpers shared with the static config reader.\nexport {\n unwrap as unwrapNode,\n isObject as isObjectNode,\n keyName as propertyKeyName,\n findProp as findProperty,\n};\nexport type { Node as AstNode };\n","import {\n argumentSignature,\n findPlurals,\n getArguments,\n isIcuStructured,\n parseMessage,\n type IcuNode,\n} from \"dialexjs/icu\";\n\nexport interface IcuFinding {\n level: \"error\" | \"warning\";\n code: \"invalid-icu\" | \"icu-args-mismatch\" | \"icu-plural-categories\";\n locale: string;\n /** Dotted key including the dictionary name, e.g. `cart.items`. */\n key: string;\n message: string;\n}\n\n/** `locale -> dotted path within the dictionary -> string value` */\nexport type LocaleStrings = Map<string, Map<string, string>>;\n\n/** CLDR order. `resolvedOptions().pluralCategories` order differs between Node versions. */\nconst CATEGORY_ORDER = [\"zero\", \"one\", \"two\", \"few\", \"many\"];\n\nfunction requiredCategories(locale: string, ordinal: boolean): string[] {\n try {\n return new Intl.PluralRules(locale, { type: ordinal ? \"ordinal\" : \"cardinal\" })\n .resolvedOptions()\n .pluralCategories.filter((c) => c !== \"other\")\n .sort((a, b) => CATEGORY_ORDER.indexOf(a) - CATEGORY_ORDER.indexOf(b));\n } catch {\n return []; // not a valid BCP 47 tag; nothing to compare against\n }\n}\n\n/**\n * Validates ICU messages across the locales of one dictionary:\n *\n * - invalid syntax: an error for messages that clearly use ICU (plural/select/number/date/time),\n * a warning for plain `{placeholders}` that do not parse (they may not be meant as ICU);\n * - every locale must use the same arguments as the reference locale;\n * - plural options should cover the categories the locale's plural rules need.\n */\nexport function checkIcu(\n dictionary: string,\n strings: LocaleStrings,\n defaultLocale: string,\n): IcuFinding[] {\n const findings: IcuFinding[] = [];\n const parsed = new Map<string, Map<string, IcuNode[]>>();\n\n for (const [locale, entries] of strings) {\n const ok = new Map<string, IcuNode[]>();\n for (const [path, value] of entries) {\n if (!value.includes(\"{\")) continue;\n const key = `${dictionary}.${path}`;\n try {\n ok.set(path, parseMessage(value));\n } catch (error) {\n const structured = isIcuStructured(value);\n findings.push({\n level: structured ? \"error\" : \"warning\",\n code: \"invalid-icu\",\n locale,\n key,\n message: structured\n ? `Invalid ICU message \"${key}\" (${locale}): ${(error as Error).message}`\n : `\"${key}\" (${locale}) contains braces but is not valid ICU, so t() values cannot be applied: ${(error as Error).message}`,\n });\n }\n }\n parsed.set(locale, ok);\n }\n\n // Compare every locale against the reference (default locale first)\n const order = [defaultLocale, ...[...parsed.keys()].filter((l) => l !== defaultLocale)];\n const paths = new Set([...parsed.values()].flatMap((m) => [...m.keys()]));\n\n for (const path of paths) {\n const key = `${dictionary}.${path}`;\n const reference = order.find((l) => parsed.get(l)?.has(path));\n if (!reference) continue;\n const expected = argumentSignature(parsed.get(reference)!.get(path)!);\n\n for (const locale of order) {\n const nodes = parsed.get(locale)?.get(path);\n if (nodes && locale !== reference) {\n const found = argumentSignature(nodes);\n if (found !== expected) {\n findings.push({\n level: \"error\",\n code: \"icu-args-mismatch\",\n locale,\n key,\n message: `Locale \"${locale}\" uses different arguments than \"${reference}\" for \"${key}\" (expected ${expected || \"none\"}, found ${found || \"none\"})`,\n });\n }\n }\n if (!nodes) continue;\n\n for (const plural of findPlurals(nodes)) {\n const missing = requiredCategories(locale, plural.ordinal).filter(\n (c) => !(c in plural.options),\n );\n if (missing.length > 0) {\n findings.push({\n level: \"warning\",\n code: \"icu-plural-categories\",\n locale,\n key,\n message: `Locale \"${locale}\" plural \"${plural.name}\" in \"${key}\" has no ${missing.map((c) => `\"${c}\"`).join(\", \")} option (used by this language; \"other\" will be shown instead)`,\n });\n }\n }\n }\n }\n\n return findings;\n}\n\n/** Arguments of a message, or `undefined` when it does not parse. */\nexport function tryGetArguments(message: string) {\n try {\n return getArguments(parseMessage(message));\n } catch {\n return undefined;\n }\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport fg from \"fast-glob\";\nimport {\n TODO_PREFIX,\n dictionaryLocation,\n flattenPaths,\n listLeaves,\n listLocales,\n loadDictionaryFile,\n locationOf,\n type DictionaryFile,\n type SourceRange,\n} from \"./utils/dictionary-edit.js\";\nimport { checkIcu, type LocaleStrings } from \"./utils/icu-check.js\";\n\n/**\n * Project analysis shared by `dialex check` and the editor extension.\n *\n * It reads dictionaries from the syntax tree, so it never runs project code. Dictionaries that\n * cannot be read that way (spreads, computed keys, imported values) are skipped with an `info`\n * issue, unless `runtime: true` is passed, in which case they are imported and read from the\n * evaluated module (the CLI does this; editors must not).\n */\n\nexport type IssueLevel = \"error\" | \"warning\" | \"info\";\n\nexport type IssueCode =\n | \"invalid-dictionary\"\n | \"unanalyzable\"\n | \"missing-locale\"\n | \"missing-key\"\n | \"invalid-locale\"\n | \"todo-placeholder\"\n | \"invalid-icu\"\n | \"icu-args-mismatch\"\n | \"icu-plural-categories\"\n | \"unknown-dictionary\"\n | \"unknown-path\"\n | \"unused-key\"\n | \"unused-dictionary\";\n\nexport interface AnalysisIssue {\n /** Absolute path of the file the issue is in. */\n file: string;\n level: IssueLevel;\n code: IssueCode;\n message: string;\n /** Where to point, when known. Lines and columns are zero-based. */\n range?: SourceRange;\n /** The dictionary the issue is about, when it is about one. */\n dictionary?: string;\n locale?: string;\n /** Key path within the dictionary. */\n path?: string[];\n /** For `missing-key`: a locale that has the key, to copy it from. */\n sourceLocale?: string;\n}\n\nexport interface AnalysisConfig {\n defaultLocale?: string;\n locales?: string[];\n include?: string | string[];\n}\n\nexport interface AnalysisOptions {\n root: string;\n config: AnalysisConfig;\n /** Source globs to scan for dictionary references. Pass `[]` to skip scanning. */\n src?: string[];\n /** Import dictionaries the syntax tree cannot fully describe. Runs project code. */\n runtime?: boolean;\n /** Extra ignore globs, relative to `root`. */\n ignore?: string[];\n /** Report possibly unused keys and dictionaries. @default true */\n unused?: boolean;\n}\n\nexport interface LeafInfo {\n kind: \"string\" | \"function\" | \"other\";\n value?: string;\n}\n\nexport interface AnalyzedDictionary {\n name: string;\n /** Absolute path. */\n file: string;\n /** Locales in source order. */\n locales: string[];\n /** `locale -> dotted path -> leaf` */\n leaves: Map<string, Map<string, LeafInfo>>;\n /** Union of dotted leaf paths across locales, in order of first appearance. */\n paths: string[];\n /** The parsed file, present when it was read statically. */\n df?: DictionaryFile;\n}\n\nexport interface AnalysisResult {\n issues: AnalysisIssue[];\n dictionaries: AnalyzedDictionary[];\n /** Absolute paths of every dictionary file that matched. */\n files: string[];\n sourceFilesScanned: number;\n}\n\nconst DICTIONARY_IGNORE = [\"**/node_modules/**\", \"**/dist/**\", \"**/.next/**\"];\n\nexport const DEFAULT_SOURCE_GLOB = \"**/*.{ts,tsx,js,jsx,mjs,cjs,vue,svelte,astro,mdx}\";\nconst SOURCE_IGNORE = [\n ...DICTIONARY_IGNORE,\n \"**/.nuxt/**\",\n \"**/.output/**\",\n \"**/.svelte-kit/**\",\n \"**/.astro/**\",\n \"**/coverage/**\",\n \"**/graphify-out/**\",\n \"**/*.d.ts\",\n \"**/dialex.generated.*\",\n \"**/dialex.config.*\",\n \"**/i18n.config.*\",\n];\n\n/** `getDictionary(\"x\")`, `useDictionary(\"x\")`, `@DialexDictionary(\"x\")` */\nconst DICTIONARY_CALL =\n /\\b(?:getDictionary|useDictionary|DialexDictionary)\\(\\s*([\"'`])([^\"'`$\\n]+)\\1/dg;\n/** `t(\"dictionary.path.to.key\")` */\nconst T_CALL = /(?<![\\w$.])t\\(\\s*([\"'`])([\\w-]+(?:\\.[\\w-]+)+)\\1/dg;\n\nexport interface Reference {\n /** A dictionary name, or a full `dictionary.key.path`. */\n kind: \"dictionary\" | \"path\";\n value: string;\n /** Offsets of the string's contents (without the quotes) in the scanned text. */\n start: number;\n end: number;\n}\n\n/** Finds `getDictionary(\"x\")`-style and `t(\"x.y.z\")` references in source text. */\nexport function scanReferences(text: string): Reference[] {\n const references: Reference[] = [];\n const collect = (pattern: RegExp, kind: Reference[\"kind\"]) => {\n for (const match of text.matchAll(pattern)) {\n const [start, end] = match.indices![2] as [number, number];\n references.push({ kind, value: match[2], start, end });\n }\n };\n collect(DICTIONARY_CALL, \"dictionary\");\n collect(T_CALL, \"path\");\n return references.sort((a, b) => a.start - b.start);\n}\n\nfunction lineStarts(text: string): number[] {\n const starts = [0];\n for (let i = 0; i < text.length; i++) if (text.charCodeAt(i) === 10) starts.push(i + 1);\n return starts;\n}\n\nfunction positionAt(starts: number[], offset: number) {\n let low = 0;\n let high = starts.length - 1;\n while (low < high) {\n const mid = Math.ceil((low + high) / 2);\n if (starts[mid] <= offset) low = mid;\n else high = mid - 1;\n }\n return { line: low, column: offset - starts[low] };\n}\n\ninterface DictionaryData {\n name: string;\n locales: string[];\n leaves: Map<string, Map<string, LeafInfo>>;\n df?: DictionaryFile;\n}\n\ntype Loaded =\n | { ok: true; data: DictionaryData }\n | { ok: false; level: IssueLevel; code: IssueCode; message: string };\n\nfunction fromSyntaxTree(df: DictionaryFile): DictionaryData {\n const locales = listLocales(df);\n const leaves = new Map<string, Map<string, LeafInfo>>();\n for (const locale of locales) {\n const entries = new Map<string, LeafInfo>();\n for (const leaf of listLeaves(df, locale)) {\n entries.set(leaf.path.join(\".\"), { kind: leaf.kind, value: leaf.value });\n }\n leaves.set(locale, entries);\n }\n return { name: df.name!, locales, leaves, df };\n}\n\nasync function fromRuntime(file: string): Promise<Loaded> {\n try {\n const mod = await import(`${pathToFileURL(file).href}?t=${Date.now()}_${Math.random()}`);\n const definition = mod.default || mod;\n if (!definition || typeof definition !== \"object\" || !definition.dictionary) {\n return {\n ok: false,\n level: \"error\",\n code: \"invalid-dictionary\",\n message: \"Default export does not appear to be a valid defineDictionary output.\",\n };\n }\n\n const dictionary = definition.dictionary as Record<string, Record<string, any>>;\n const leaves = new Map<string, Map<string, LeafInfo>>();\n const invalid: string[] = [];\n\n for (const [locale, content] of Object.entries(dictionary)) {\n if (!content || typeof content !== \"object\") {\n invalid.push(locale);\n continue;\n }\n const entries = new Map<string, LeafInfo>();\n for (const leafPath of flattenPaths(content)) {\n let value: any = content;\n for (const segment of leafPath) value = value?.[segment];\n entries.set(\n leafPath.join(\".\"),\n typeof value === \"string\"\n ? { kind: \"string\", value }\n : { kind: typeof value === \"function\" ? \"function\" : \"other\" },\n );\n }\n leaves.set(locale, entries);\n }\n\n if (invalid.length > 0) {\n return {\n ok: false,\n level: \"error\",\n code: \"invalid-locale\",\n message: invalid.map((l) => `Locale \"${l}\" content is empty or invalid.`).join(\"\\n\"),\n };\n }\n\n return {\n ok: true,\n data: { name: String(definition.name ?? \"\"), locales: [...leaves.keys()], leaves },\n };\n } catch (error: any) {\n return {\n ok: false,\n level: \"error\",\n code: \"invalid-dictionary\",\n message: `Failed to import dictionary: ${error.message || String(error)}`,\n };\n }\n}\n\nasync function loadDictionaryData(file: string, runtime: boolean): Promise<Loaded> {\n let astError: Error | undefined;\n try {\n const df = await loadDictionaryFile(file);\n if (df?.complete && df.name) return { ok: true, data: fromSyntaxTree(df) };\n } catch (error) {\n astError = error as Error;\n }\n\n if (runtime) return fromRuntime(file);\n\n return astError\n ? {\n ok: false,\n level: \"error\",\n code: \"invalid-dictionary\",\n message: `Failed to parse dictionary: ${astError.message}`,\n }\n : {\n ok: false,\n level: \"info\",\n code: \"unanalyzable\",\n message:\n \"This dictionary uses spreads, computed keys, imported values, or a computed name, so it cannot be analyzed statically.\",\n };\n}\n\nexport async function analyzeProject(options: AnalysisOptions): Promise<AnalysisResult> {\n const { root, config } = options;\n const include = config.include || \"**/*.content.ts\";\n const configuredLocales = config.locales || [];\n const defaultLocale = config.defaultLocale || \"en\";\n const extraIgnore = options.ignore ?? [];\n\n const files = fg.sync(include, {\n cwd: root,\n absolute: true,\n ignore: [...DICTIONARY_IGNORE, ...extraIgnore],\n });\n\n const issues: AnalysisIssue[] = [];\n const dictionaries: AnalyzedDictionary[] = [];\n\n // 1. Dictionaries: parity, placeholders, ICU\n for (const file of files) {\n const loaded = await loadDictionaryData(file, options.runtime === true);\n if (!loaded.ok) {\n for (const message of loaded.message.split(\"\\n\")) {\n issues.push({ file, level: loaded.level, code: loaded.code, message });\n }\n continue;\n }\n\n const { data } = loaded;\n const { df } = data;\n const at = (locale?: string, keyPath?: string[]) =>\n df && locale ? locationOf(df, locale, keyPath) : undefined;\n const add = (issue: Omit<AnalysisIssue, \"file\" | \"dictionary\">) =>\n issues.push({ ...issue, file, dictionary: data.name });\n\n for (const required of configuredLocales) {\n if (!data.locales.includes(required)) {\n add({\n level: \"error\",\n code: \"missing-locale\",\n message: `Missing configured locale \"${required}\"`,\n range: df ? dictionaryLocation(df) : undefined,\n locale: required,\n });\n }\n }\n\n const paths: string[] = [];\n const seen = new Set<string>();\n for (const locale of data.locales) {\n for (const leafPath of data.leaves.get(locale)!.keys()) {\n if (!seen.has(leafPath)) {\n seen.add(leafPath);\n paths.push(leafPath);\n }\n }\n }\n\n for (const locale of data.locales) {\n const present = data.leaves.get(locale)!;\n for (const leafPath of paths) {\n if (present.has(leafPath)) continue;\n const sourceLocale = [defaultLocale, ...data.locales].find(\n (l) => l !== locale && data.leaves.get(l)?.has(leafPath),\n );\n add({\n level: \"error\",\n code: \"missing-key\",\n message: `Locale \"${locale}\" is missing key \"${leafPath}\"`,\n range: at(locale),\n locale,\n path: leafPath.split(\".\"),\n sourceLocale,\n });\n }\n }\n\n const strings: LocaleStrings = new Map();\n for (const locale of data.locales) {\n const entries = new Map<string, string>();\n strings.set(locale, entries);\n for (const [leafPath, leaf] of data.leaves.get(locale)!) {\n if (leaf.kind !== \"string\" || leaf.value === undefined) continue;\n entries.set(leafPath, leaf.value);\n if (leaf.value.startsWith(TODO_PREFIX)) {\n add({\n level: \"warning\",\n code: \"todo-placeholder\",\n message: `Locale \"${locale}\" key \"${leafPath}\" still has a ${TODO_PREFIX.trim()} placeholder`,\n range: at(locale, leafPath.split(\".\")),\n locale,\n path: leafPath.split(\".\"),\n });\n }\n }\n }\n\n for (const finding of checkIcu(data.name, strings, defaultLocale)) {\n const keyPath = finding.key.slice(data.name.length + 1).split(\".\");\n add({\n level: finding.level,\n code: finding.code,\n message: finding.message,\n range: at(finding.locale, keyPath),\n locale: finding.locale,\n path: keyPath,\n });\n }\n\n dictionaries.push({\n name: data.name,\n file,\n locales: data.locales,\n leaves: data.leaves,\n paths,\n df,\n });\n }\n\n // 2. Source code: references to dictionaries and keys\n const known = new Map(dictionaries.map((d) => [d.name, d]));\n const dictionaryFiles = new Set(files);\n const sourceGlobs = options.src ?? [DEFAULT_SOURCE_GLOB];\n const sourceFiles =\n sourceGlobs.length === 0\n ? []\n : fg\n .sync(sourceGlobs, {\n cwd: root,\n absolute: true,\n ignore: [...SOURCE_IGNORE, ...extraIgnore],\n })\n .filter((f) => !dictionaryFiles.has(f));\n\n if (sourceFiles.length > 0) {\n const tokens = new Set<string>();\n\n for (const file of sourceFiles) {\n let text: string;\n try {\n text = fs.readFileSync(file, \"utf-8\");\n } catch {\n continue;\n }\n for (const token of text.match(/[\\w$-]+/g) ?? []) tokens.add(token);\n\n const starts = lineStarts(text);\n const rangeOf = (start: number, end: number): SourceRange => ({\n start: positionAt(starts, start),\n end: positionAt(starts, end),\n });\n\n for (const ref of scanReferences(text)) {\n if (ref.kind === \"dictionary\") {\n if (!known.has(ref.value)) {\n issues.push({\n file,\n level: \"error\",\n code: \"unknown-dictionary\",\n message: `Unknown dictionary \"${ref.value}\"`,\n range: rangeOf(ref.start, ref.end),\n dictionary: ref.value,\n });\n }\n continue;\n }\n\n const [name, ...rest] = ref.value.split(\".\");\n const dictionary = known.get(name);\n if (!dictionary) continue; // `t(...)` may belong to another library\n const keyPath = rest.join(\".\");\n const exists = dictionary.paths.some((p) => p === keyPath || p.startsWith(`${keyPath}.`));\n if (!exists) {\n issues.push({\n file,\n level: \"error\",\n code: \"unknown-path\",\n message: `Unknown translation path \"${ref.value}\"`,\n range: rangeOf(ref.start, ref.end),\n dictionary: name,\n path: rest,\n });\n }\n }\n }\n\n // 3. Possibly unused dictionaries and keys (heuristic: warnings only)\n if (options.unused !== false) {\n for (const dictionary of dictionaries) {\n if (!tokens.has(dictionary.name)) {\n issues.push({\n file: dictionary.file,\n level: \"warning\",\n code: \"unused-dictionary\",\n message: `Dictionary \"${dictionary.name}\" is never referenced`,\n range: dictionary.df ? dictionaryLocation(dictionary.df) : undefined,\n dictionary: dictionary.name,\n });\n continue;\n }\n for (const keyPath of dictionary.paths) {\n const last = keyPath.split(\".\").pop()!;\n if (tokens.has(last)) continue;\n const holder = dictionary.locales.find((l) => dictionary.leaves.get(l)?.has(keyPath));\n issues.push({\n file: dictionary.file,\n level: \"warning\",\n code: \"unused-key\",\n message: `Key \"${keyPath}\" is possibly unused`,\n range:\n dictionary.df && holder\n ? locationOf(dictionary.df, holder, keyPath.split(\".\"))\n : undefined,\n dictionary: dictionary.name,\n path: keyPath.split(\".\"),\n });\n }\n }\n }\n }\n\n return { issues, dictionaries, files, sourceFilesScanned: sourceFiles.length };\n}\n\n/** Project root-relative path with forward slashes, for display. */\nexport function relativeFile(root: string, file: string): string {\n return path.relative(root, file);\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { parseModule } from \"magicast\";\nimport {\n findProperty,\n isObjectNode,\n propertyKeyName,\n unwrapNode,\n type AstNode,\n} from \"./dictionary-edit.js\";\n\n/**\n * The parts of `dialex.config` that tooling needs, read **without running the file**. Editors must\n * not execute workspace code (it may be untrusted), so values are read from the syntax tree and\n * only literals are understood.\n */\nexport interface StaticConfig {\n defaultLocale: string;\n locales: string[];\n include: string | string[];\n fallbacks: Record<string, string[]>;\n prefixDefault: boolean;\n lazy: boolean;\n}\n\nexport interface StaticConfigResult {\n config: StaticConfig;\n /** The file the values came from, if any. */\n file?: string;\n /** Things that could not be read statically, for example `locales: getLocales()`. */\n notes: string[];\n}\n\nconst CONFIG_NAMES = [\"dialex.config\", \"i18n.config\"];\nconst EXTENSIONS = [\"ts\", \"mts\", \"cts\", \"js\", \"mjs\", \"cjs\", \"json\"];\n\nexport const DEFAULT_STATIC_CONFIG: StaticConfig = {\n defaultLocale: \"en\",\n locales: [],\n include: \"**/*.content.ts\",\n fallbacks: {},\n prefixDefault: true,\n lazy: false,\n};\n\nconst NOT_LITERAL = Symbol(\"not literal\");\n\nfunction literal(node: AstNode | undefined): unknown {\n node = unwrapNode(node as AstNode);\n switch (node?.type) {\n case \"StringLiteral\":\n case \"NumericLiteral\":\n case \"BooleanLiteral\":\n return node.value;\n case \"Literal\":\n return node.value;\n case \"TemplateLiteral\":\n return node.expressions.length === 0 ? (node.quasis[0]?.value?.cooked ?? \"\") : NOT_LITERAL;\n case \"ArrayExpression\": {\n const items = node.elements.map((e: AstNode) => literal(e));\n return items.includes(NOT_LITERAL) ? NOT_LITERAL : items;\n }\n case \"ObjectExpression\": {\n const result: Record<string, unknown> = {};\n for (const prop of node.properties) {\n const key = propertyKeyName(prop);\n const value = key === undefined ? NOT_LITERAL : literal(prop.value);\n if (value === NOT_LITERAL) return NOT_LITERAL;\n result[key as string] = value;\n }\n return result;\n }\n default:\n return NOT_LITERAL;\n }\n}\n\n/** The object literal passed to `defineConfig({...})`, or exported directly. */\nfunction findConfigObject(declaration: AstNode): AstNode | undefined {\n const node = unwrapNode(declaration);\n if (node?.type === \"CallExpression\") return findConfigObject(node.arguments[0]);\n return isObjectNode(node) ? node : undefined;\n}\n\nconst isStringArray = (value: unknown): value is string[] =>\n Array.isArray(value) && value.every((v) => typeof v === \"string\");\n\nfunction apply(object: Record<string, unknown>, config: StaticConfig, notes: string[]) {\n const accept = <K extends keyof StaticConfig>(\n key: K,\n valid: (value: unknown) => boolean,\n expected: string,\n ) => {\n if (!(key in object)) return;\n const value = object[key];\n if (valid(value)) (config as any)[key] = value;\n else notes.push(`\"${key}\" could not be read statically (expected ${expected}).`);\n };\n\n accept(\"defaultLocale\", (v) => typeof v === \"string\" && v !== \"\", \"a string literal\");\n accept(\"locales\", isStringArray, \"an array of string literals\");\n accept(\n \"include\",\n (v) => typeof v === \"string\" || isStringArray(v),\n \"a string or array of strings\",\n );\n accept(\n \"fallbacks\",\n (v) =>\n typeof v === \"object\" && v !== null && Object.values(v).every((list) => isStringArray(list)),\n \"an object of string arrays\",\n );\n accept(\"prefixDefault\", (v) => typeof v === \"boolean\", \"true or false\");\n accept(\"lazy\", (v) => typeof v === \"boolean\", \"true or false\");\n}\n\n/** Reads a config file's source text. Exposed for tests and for unsaved buffers. */\nexport function parseStaticConfig(text: string, file = \"dialex.config.ts\"): StaticConfigResult {\n const notes: string[] = [];\n const config: StaticConfig = { ...DEFAULT_STATIC_CONFIG };\n\n if (file.endsWith(\".json\")) {\n try {\n const data = JSON.parse(text);\n if (data && typeof data === \"object\") apply(data, config, notes);\n } catch (error) {\n notes.push(`Could not parse ${path.basename(file)}: ${(error as Error).message}`);\n }\n return { config, file, notes };\n }\n\n try {\n const exported = (parseModule(text).exports as any).default;\n const object = findConfigObject(exported?.$ast?.declaration ?? exported?.$ast);\n if (!object) {\n notes.push(`${path.basename(file)} does not export a config object literal.`);\n } else {\n const values: Record<string, unknown> = {};\n for (const key of [\n \"defaultLocale\",\n \"locales\",\n \"include\",\n \"fallbacks\",\n \"prefixDefault\",\n \"lazy\",\n ]) {\n const prop = findProperty(object, key);\n if (!prop) continue;\n const value = literal(prop.value);\n if (value === NOT_LITERAL)\n notes.push(`\"${key}\" could not be read statically (not a literal).`);\n else values[key] = value;\n }\n apply(values, config, notes);\n }\n } catch (error) {\n notes.push(`Could not parse ${path.basename(file)}: ${(error as Error).message}`);\n }\n\n return { config, file, notes };\n}\n\n/** Reads `dialex.config.*` (or `i18n.config.*`) from `root`, or from `configFile` if given. */\nexport function readStaticConfig(root: string, configFile?: string): StaticConfigResult {\n const candidates = configFile\n ? [path.resolve(root, configFile)]\n : CONFIG_NAMES.flatMap((name) => EXTENSIONS.map((ext) => path.join(root, `${name}.${ext}`)));\n\n for (const file of candidates) {\n if (fs.existsSync(file)) return parseStaticConfig(fs.readFileSync(file, \"utf-8\"), file);\n }\n return { config: { ...DEFAULT_STATIC_CONFIG }, notes: [] };\n}\n","import path from \"node:path\";\nimport fg from \"fast-glob\";\nimport { resolveDialexConfig } from \"dialexjs/scanner\";\nimport type { DialexConfig } from \"dialexjs\";\nimport { loadDictionaryFile, type DictionaryFile } from \"./dictionary-edit.js\";\nimport { readStaticConfig } from \"./static-config.js\";\n\nexport interface ProjectDictionary {\n /** Path relative to the project root. */\n rel: string;\n name: string;\n df: DictionaryFile;\n}\n\nexport interface Project {\n root: string;\n config: DialexConfig;\n dictionaries: ProjectDictionary[];\n /** Dictionary files that could not be parsed into an editable shape. */\n unsupported: string[];\n /** Config values that could not be read statically (static loading only). */\n notes: string[];\n}\n\nasync function loadDictionaries(root: string, config: DialexConfig) {\n const include = config.include || \"**/*.content.ts\";\n const files = fg.sync(include, {\n cwd: root,\n absolute: true,\n ignore: [\"**/node_modules/**\", \"**/dist/**\", \"**/.next/**\"],\n });\n\n const dictionaries: ProjectDictionary[] = [];\n const unsupported: string[] = [];\n\n for (const file of files) {\n const rel = path.relative(root, file);\n try {\n const df = await loadDictionaryFile(file);\n if (!df || !df.name) unsupported.push(rel);\n else dictionaries.push({ rel, name: df.name, df });\n } catch {\n unsupported.push(rel); // syntax error: reported by the analysis, nothing to edit here\n }\n }\n\n return { dictionaries, unsupported };\n}\n\n/**\n * Resolves the config (running `dialex.config.*` through the loader, which executes it) and loads\n * every dictionary file for AST-level reading and editing.\n */\nexport async function loadProject(root: string, configFile?: string): Promise<Project> {\n const config = resolveDialexConfig(root, configFile ? { configFile } : {});\n return { root, config, notes: [], ...(await loadDictionaries(root, config)) };\n}\n\n/**\n * Like `loadProject`, but reads the config from the syntax tree without executing it. Use this in\n * editors and anywhere project code must not run.\n */\nexport async function loadStaticProject(root: string, configFile?: string): Promise<Project> {\n const { config, notes } = readStaticConfig(root, configFile);\n return { root, config, notes, ...(await loadDictionaries(root, config)) };\n}\n\n/** `home` + `[\"nav\", \"about\"]` -> `home.nav.about` */\nexport const toKey = (dictionary: string, keyPath: string[]) => [dictionary, ...keyPath].join(\".\");\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dialexjs/cli",
3
- "version": "0.2.3",
3
+ "version": "0.3.0",
4
4
  "description": "High-performance CLI tool for Dialex internationalization (codegen, scaffolding, CI parity checking)",
5
5
  "homepage": "https://github.com/awaiden/dialex#readme",
6
6
  "bugs": {
@@ -39,7 +39,7 @@
39
39
  "@clack/prompts": "^1.8.1",
40
40
  "chokidar": "^5.0.0",
41
41
  "commander": "^15.0.0",
42
- "dialexjs": "0.2.3",
42
+ "dialexjs": "0.3.0",
43
43
  "fast-glob": "^3.3.3",
44
44
  "magicast": "^0.5.5",
45
45
  "picocolors": "^1.1.1",
@@ -1 +0,0 @@
1
- {"version":3,"file":"project-BnG6V2I0.mjs","names":["unwrapNode","propertyKeyName","isObjectNode","findProperty"],"sources":["../src/utils/logger.ts","../src/commands/generate.ts","../src/utils/dictionary-edit.ts","../src/utils/icu-check.ts","../src/analysis.ts","../src/utils/static-config.ts","../src/utils/project.ts"],"sourcesContent":["import pc from \"picocolors\";\n\nexport const logger = {\n info: (msg: string) => console.log(pc.blue(\"ℹ \") + msg),\n success: (msg: string) => console.log(pc.green(\"✔ \") + pc.bold(msg)),\n warn: (msg: string) => console.warn(pc.yellow(\"⚠ \") + msg),\n error: (msg: string) => console.error(pc.red(\"✖ \") + pc.bold(msg)),\n log: (msg: string) => console.log(msg),\n};\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport fg from \"fast-glob\";\nimport chokidar from \"chokidar\";\nimport { resolveI18nConfig, generateDts } from \"dialexjs/scanner\";\nimport { logger } from \"../utils/logger.js\";\n\nexport interface GenerateOptions {\n cwd?: string;\n watch?: boolean;\n output?: string;\n config?: string;\n json?: boolean;\n}\n\nexport function generateDictionaries(\n root: string,\n options: GenerateOptions = {},\n): {\n files: string[];\n outputPath: string;\n dtsPath: string;\n} {\n const inlineConfig = options.config ? { configFile: options.config } : {};\n const config = resolveI18nConfig(root, inlineConfig);\n const include = config.include || \"**/*.content.ts\";\n\n const files = fg.sync(include, {\n cwd: root,\n absolute: true,\n ignore: [\"**/node_modules/**\", \"**/dist/**\", \"**/.next/**\"],\n });\n\n const srcDir = fs.existsSync(path.join(root, \"src\")) ? path.join(root, \"src\") : root;\n const targetOutput = options.output\n ? path.resolve(root, options.output)\n : path.join(srcDir, \"dialex.generated.ts\");\n\n const targetDir = path.dirname(targetOutput);\n\n // 1. Generate TypeScript environment declarations\n generateDts(root, files, config.locales);\n const dtsPath = path.join(srcDir, \"dialex-env.d.ts\");\n\n // 2. Build standalone generated module content\n const importLines: string[] = [];\n const dictIdentifiers: string[] = [];\n\n files.forEach((file, idx) => {\n let rel = path.relative(targetDir, file).replace(/\\\\/g, \"/\");\n rel = rel.replace(/\\.ts$/, \".js\");\n if (!rel.startsWith(\".\")) {\n rel = \"./\" + rel;\n }\n const id = `dict_${idx}`;\n importLines.push(`import ${id} from \"${rel}\";`);\n dictIdentifiers.push(id);\n });\n\n const dictList =\n dictIdentifiers.length <= 1\n ? `[${dictIdentifiers.join(\", \")}]`\n : `[\\n ${dictIdentifiers.join(\",\\n \")}\\n]`;\n\n const content = `// Auto-generated by dialex CLI. Do not edit directly.\n/* eslint-disable */\n// @ts-nocheck\n${importLines.join(\"\\n\")}\n\nexport const dictionaries = ${dictList};\n\nexport const dictionaryMap = {\n${dictIdentifiers.map((id) => ` [${id}.name]: ${id}.dictionary,`).join(\"\\n\")}\n};\n\nexport default dictionaries;\n`;\n\n fs.mkdirSync(targetDir, { recursive: true });\n const existing = fs.existsSync(targetOutput) ? fs.readFileSync(targetOutput, \"utf-8\") : \"\";\n if (existing !== content) {\n fs.writeFileSync(targetOutput, content, \"utf-8\");\n }\n\n return { files, outputPath: targetOutput, dtsPath };\n}\n\nexport async function runGenerate(options: GenerateOptions = {}) {\n const root = options.cwd || process.cwd();\n const quiet = options.json === true;\n\n const doGenerate = () => {\n try {\n const { files, outputPath, dtsPath } = generateDictionaries(root, options);\n if (quiet) {\n console.log(\n JSON.stringify(\n {\n success: true,\n files: files.map((f) => path.relative(root, f)),\n outputPath: path.relative(root, outputPath),\n dtsPath: path.relative(root, dtsPath),\n },\n null,\n 2,\n ),\n );\n } else {\n logger.success(\n `Generated dictionaries for ${files.length} file${files.length === 1 ? \"\" : \"s\"}:`,\n );\n logger.info(`→ ${path.relative(root, outputPath)}`);\n logger.info(`→ ${path.relative(root, dtsPath)}`);\n }\n return true;\n } catch (err: any) {\n if (quiet) {\n console.log(\n JSON.stringify(\n {\n success: false,\n error: err.message || String(err),\n },\n null,\n 2,\n ),\n );\n } else {\n logger.error(`Generation failed: ${err.message || String(err)}`);\n }\n return false;\n }\n };\n\n const ok = doGenerate();\n if (!ok && !options.watch) {\n process.exit(1);\n }\n\n if (options.watch) {\n logger.info(\"Watching for dictionary changes (-w, --watch)...\");\n const inlineConfig = options.config ? { configFile: options.config } : {};\n const config = resolveI18nConfig(root, inlineConfig);\n const pattern = config.include || \"**/*.content.ts\";\n\n const watcher = chokidar.watch(pattern, {\n cwd: root,\n ignoreInitial: true,\n ignored: [\"**/node_modules/**\", \"**/dist/**\", \"**/.next/**\"],\n });\n\n watcher.on(\"all\", (event, filePath) => {\n logger.info(`[${event}] ${filePath} changed, regenerating...`);\n doGenerate();\n });\n }\n}\n","import fs from \"node:fs\";\nimport { loadFile, writeFile, generateCode, parseExpression, parseModule } from \"magicast\";\n\n/**\n * AST-level helpers for reading and editing `.content.ts` dictionary files.\n *\n * Magicast's proxy layer cannot represent every value (for example template-literal\n * functions), so these helpers work on the underlying AST nodes and use Magicast only\n * to parse and print, which preserves the rest of the file's formatting.\n *\n * Supported shapes:\n * - `export default defineDictionary(\"name\", { en: {...}, tr: {...} })`\n * - `export default defineDictionary({ name: \"name\", dictionary: { ... } })`\n * - `export default { name: \"name\", dictionary: { ... } }`\n */\n\ntype Node = { type: string; [key: string]: any };\n\nexport const TODO_PREFIX = \"[TODO] \";\n\nconst IDENTIFIER = /^[A-Za-z_$][\\w$]*$/;\n\nexport interface DictionaryFile {\n file: string;\n /** Dictionary name from `defineDictionary(\"name\", ...)` or the `name` property, if literal. */\n name?: string;\n mod: Awaited<ReturnType<typeof loadFile>>;\n /** The object whose keys are locales. */\n localesObj: Node;\n /** Whether the file ended with a newline when loaded; restored on save. */\n endsWithNewline: boolean;\n /**\n * `false` when part of the dictionary cannot be read statically (spreads, computed keys, or a\n * locale whose content is not an object literal). Leaf lists and parity checks are unreliable\n * for such files.\n */\n complete: boolean;\n}\n\n/** A zero-based line/column range, as used by editors. */\nexport interface SourceRange {\n start: { line: number; column: number };\n end: { line: number; column: number };\n}\n\nexport type LeafKind = \"string\" | \"function\" | \"other\";\n\nexport interface Leaf {\n path: string[];\n kind: LeafKind;\n /** Present when `kind` is `\"string\"`. */\n value?: string;\n}\n\nfunction unwrap(node: Node): Node {\n while (\n node &&\n (node.type === \"TSAsExpression\" ||\n node.type === \"TSSatisfiesExpression\" ||\n node.type === \"ParenthesizedExpression\")\n ) {\n node = node.expression;\n }\n return node;\n}\n\nconst isObject = (node: Node) => node?.type === \"ObjectExpression\";\n\nfunction keyName(prop: Node): string | undefined {\n const key = prop?.key;\n if (!key || prop.computed) return undefined;\n if (key.type === \"Identifier\") return key.name;\n if (key.type === \"StringLiteral\" || (key.type === \"Literal\" && typeof key.value === \"string\")) {\n return key.value;\n }\n if (key.type === \"NumericLiteral\") return String(key.value);\n return undefined;\n}\n\nconst isPropLike = (p: Node) =>\n p?.type === \"ObjectProperty\" || p?.type === \"Property\" || p?.type === \"ObjectMethod\";\n\nfunction findProp(obj: Node, key: string): Node | undefined {\n return obj.properties.find((p: Node) => isPropLike(p) && keyName(p) === key);\n}\n\nfunction stringValue(node: Node): string | undefined {\n node = unwrap(node);\n if (node?.type === \"StringLiteral\") return node.value;\n if (node?.type === \"Literal\" && typeof node.value === \"string\") return node.value;\n if (node?.type === \"TemplateLiteral\" && node.expressions.length === 0) {\n return node.quasis[0]?.value?.cooked ?? undefined;\n }\n return undefined;\n}\n\nfunction leafKind(node: Node): LeafKind {\n node = unwrap(node);\n if (stringValue(node) !== undefined) return \"string\";\n if (\n node?.type === \"ArrowFunctionExpression\" ||\n node?.type === \"FunctionExpression\" ||\n node?.type === \"ObjectMethod\"\n ) {\n return \"function\";\n }\n return \"other\";\n}\n\nfunction dictionaryProp(obj: Node): Node | undefined {\n const prop = findProp(obj, \"dictionary\");\n const value = unwrap(prop?.value);\n return isObject(value) ? value : undefined;\n}\n\nfunction locateName(declaration: Node): string | undefined {\n const decl = unwrap(declaration);\n if (decl?.type === \"CallExpression\") {\n const first = unwrap(decl.arguments[0]);\n if (isObject(first)) return stringValue(findProp(first, \"name\")?.value);\n return stringValue(first);\n }\n if (isObject(decl)) return stringValue(findProp(decl, \"name\")?.value);\n return undefined;\n}\n\nfunction locateLocalesObject(declaration: Node): Node | undefined {\n const decl = unwrap(declaration);\n if (decl?.type === \"CallExpression\") {\n const first = unwrap(decl.arguments[0]);\n const second = unwrap(decl.arguments[1]);\n if (isObject(second)) return second;\n if (isObject(first)) return dictionaryProp(first);\n return undefined;\n }\n if (isObject(decl)) return dictionaryProp(decl);\n return undefined;\n}\n\n/** Quotes a property key only when it is not a valid identifier. */\nfunction keyCode(key: string): string {\n return IDENTIFIER.test(key) ? key : JSON.stringify(key);\n}\n\n/** Builds a detached `key: <value>` property node from source text. */\nfunction makeProp(key: string, valueCode: string): Node {\n const expr: Node = parseExpression(`({ ${keyCode(key)}: ${valueCode} })`);\n return expr.$ast.properties[0];\n}\n\nfunction makeStringNode(value: string): Node {\n return makeProp(\"_\", JSON.stringify(value)).value;\n}\n\n/**\n * A dictionary is statically readable when every locale is an object literal and no object on the\n * way down uses spreads or computed keys.\n */\nfunction isStaticallyComplete(localesObj: Node): boolean {\n const walk = (obj: Node): boolean =>\n obj.properties.every((prop: Node) => {\n if (!isPropLike(prop) || keyName(prop) === undefined) return false;\n if (prop.type === \"ObjectMethod\") return true;\n const value = unwrap(prop.value);\n return isObject(value) ? walk(value) : true;\n });\n\n return localesObj.properties.every((prop: Node) => {\n if (!isPropLike(prop) || keyName(prop) === undefined || prop.type === \"ObjectMethod\")\n return false;\n const value = unwrap(prop.value);\n return isObject(value) && walk(value);\n });\n}\n\n/**\n * Parses dictionary source text (for example an unsaved editor buffer). Returns `undefined` when\n * the file does not have an editable shape; throws on syntax errors.\n */\nexport function parseDictionaryText(file: string, text: string): DictionaryFile | undefined {\n const mod = parseModule(text);\n const exported: Node = (mod.exports as any).default;\n const ast: Node = exported?.$ast;\n if (!ast) return undefined;\n const declaration = ast.declaration ?? ast;\n const localesObj = locateLocalesObject(declaration);\n return localesObj\n ? {\n file,\n mod,\n localesObj,\n name: locateName(declaration),\n endsWithNewline: text.endsWith(\"\\n\"),\n complete: isStaticallyComplete(localesObj),\n }\n : undefined;\n}\n\n/** Loads a dictionary file; returns `undefined` when its shape is not editable. */\nexport async function loadDictionaryFile(file: string): Promise<DictionaryFile | undefined> {\n return parseDictionaryText(file, fs.readFileSync(file, \"utf-8\"));\n}\n\n/** The source text with all edits applied, without writing anything. */\nexport function renderDictionaryFile(df: DictionaryFile): string {\n const code = generateCode(df.mod as any).code;\n return df.endsWithNewline && !code.endsWith(\"\\n\") ? `${code}\\n` : code;\n}\n\nexport async function saveDictionaryFile(df: DictionaryFile): Promise<void> {\n await writeFile(df.mod, df.file);\n if (df.endsWithNewline) {\n const text = fs.readFileSync(df.file, \"utf-8\");\n if (!text.endsWith(\"\\n\")) fs.writeFileSync(df.file, text + \"\\n\", \"utf-8\");\n }\n}\n\nexport function listLocales(df: DictionaryFile): string[] {\n return df.localesObj.properties\n .filter(isPropLike)\n .map(keyName)\n .filter((k: string | undefined): k is string => k !== undefined);\n}\n\nfunction localeObject(df: DictionaryFile, locale: string): Node | undefined {\n const value = unwrap(findProp(df.localesObj, locale)?.value);\n return isObject(value) ? value : undefined;\n}\n\n/** Lists every leaf (string, function, or other value) of a locale, in source order. */\nexport function listLeaves(df: DictionaryFile, locale: string): Leaf[] {\n const root = localeObject(df, locale);\n if (!root) return [];\n\n const leaves: Leaf[] = [];\n const walk = (obj: Node, prefix: string[]) => {\n for (const prop of obj.properties) {\n if (!isPropLike(prop)) continue;\n const name = keyName(prop);\n if (name === undefined) continue;\n const path = [...prefix, name];\n const value = prop.type === \"ObjectMethod\" ? prop : unwrap(prop.value);\n if (isObject(value)) {\n walk(value, path);\n } else {\n const kind = leafKind(value);\n leaves.push({ path, kind, ...(kind === \"string\" ? { value: stringValue(value) } : {}) });\n }\n }\n };\n walk(root, []);\n return leaves;\n}\n\nfunction getProp(df: DictionaryFile, locale: string, path: string[]): Node | undefined {\n let obj = localeObject(df, locale);\n for (let i = 0; obj && i < path.length; i++) {\n const prop = findProp(obj, path[i]);\n if (!prop) return undefined;\n if (i === path.length - 1) return prop;\n const next = unwrap(prop.value);\n obj = isObject(next) ? next : undefined;\n }\n return undefined;\n}\n\nexport function hasPath(df: DictionaryFile, locale: string, path: string[]): boolean {\n return getProp(df, locale, path) !== undefined;\n}\n\nexport function getString(df: DictionaryFile, locale: string, path: string[]): string | undefined {\n const prop = getProp(df, locale, path);\n return prop && prop.type !== \"ObjectMethod\" ? stringValue(prop.value) : undefined;\n}\n\nfunction ensureLocale(df: DictionaryFile, locale: string): Node {\n let obj = localeObject(df, locale);\n if (!obj) {\n const prop = makeProp(locale, \"{}\");\n df.localesObj.properties.push(prop);\n obj = prop.value as Node;\n }\n return obj;\n}\n\n/** Returns the object that should contain the last path segment, creating objects as needed. */\nfunction ensureParent(df: DictionaryFile, locale: string, path: string[]): Node | undefined {\n let obj = ensureLocale(df, locale);\n for (const segment of path.slice(0, -1)) {\n let prop = findProp(obj, segment);\n if (!prop) {\n prop = makeProp(segment, \"{}\");\n obj.properties.push(prop);\n }\n const next = unwrap(prop.value);\n if (!isObject(next)) return undefined;\n obj = next;\n }\n return obj;\n}\n\nexport type SetResult = \"created\" | \"updated\" | \"skipped\";\n\n/**\n * Sets a string value at `path`. Existing function or non-string values are left alone\n * (`\"skipped\"`) because they cannot be translated as plain text.\n */\nexport function setString(\n df: DictionaryFile,\n locale: string,\n path: string[],\n value: string,\n): SetResult {\n const parent = ensureParent(df, locale, path);\n if (!parent) return \"skipped\";\n\n const last = path[path.length - 1];\n const existing = findProp(parent, last);\n if (existing) {\n if (existing.type === \"ObjectMethod\" || leafKind(existing.value) !== \"string\") {\n return \"skipped\";\n }\n existing.value = makeStringNode(value);\n return \"updated\";\n }\n parent.properties.push(makeProp(last, JSON.stringify(value)));\n return \"created\";\n}\n\n/**\n * Copies the leaf at `path` from one locale to another. String values can be rewritten with\n * `mapString` (for example to add a `[TODO]` marker); other values are copied verbatim.\n * Returns `false` when the source has no such leaf or the target already has one.\n */\nexport function copyLeaf(\n df: DictionaryFile,\n fromLocale: string,\n toLocale: string,\n path: string[],\n mapString?: (value: string) => string,\n): boolean {\n const source = getProp(df, fromLocale, path);\n if (!source || hasPath(df, toLocale, path)) return false;\n\n const parent = ensureParent(df, toLocale, path);\n if (!parent) return false;\n\n const last = path[path.length - 1];\n const text = source.type === \"ObjectMethod\" ? undefined : stringValue(source.value);\n if (text !== undefined && mapString) {\n parent.properties.push(makeProp(last, JSON.stringify(mapString(text))));\n } else {\n const code = generateCode(source as any).code;\n const expr: Node = parseExpression(`({ ${code} })`);\n parent.properties.push(expr.$ast.properties[0]);\n }\n return true;\n}\n\n/** Leaf paths of a runtime dictionary value (plain objects recurse; everything else is a leaf). */\nexport function flattenPaths(value: unknown, prefix: string[] = []): string[][] {\n if (value && typeof value === \"object\" && !Array.isArray(value)) {\n return Object.entries(value).flatMap(([k, v]) => flattenPaths(v, [...prefix, k]));\n }\n return prefix.length > 0 ? [prefix] : [];\n}\n\nconst toRange = (loc: Node | undefined): SourceRange | undefined =>\n loc\n ? {\n start: { line: loc.start.line - 1, column: loc.start.column },\n end: { line: loc.end.line - 1, column: loc.end.column },\n }\n : undefined;\n\n/**\n * Where a locale (no `path`) or a key within it is written. The range covers the property key, so\n * it is a good place to attach a diagnostic or jump to.\n */\nexport function locationOf(\n df: DictionaryFile,\n locale: string,\n path: string[] = [],\n): SourceRange | undefined {\n const prop = path.length === 0 ? findProp(df.localesObj, locale) : getProp(df, locale, path);\n return toRange((prop?.key ?? prop)?.loc);\n}\n\n/** The source text of the dictionary object itself (the object whose keys are locales). */\nexport function dictionaryLocation(df: DictionaryFile): SourceRange | undefined {\n return toRange(df.localesObj.loc);\n}\n\n/** The source code of a leaf's value (a function's source, or a string with its quotes). */\nexport function getLeafSource(\n df: DictionaryFile,\n locale: string,\n path: string[],\n): string | undefined {\n const prop = getProp(df, locale, path);\n if (!prop) return undefined;\n return generateCode((prop.type === \"ObjectMethod\" ? prop : prop.value) as any).code;\n}\n\n// AST helpers shared with the static config reader.\nexport {\n unwrap as unwrapNode,\n isObject as isObjectNode,\n keyName as propertyKeyName,\n findProp as findProperty,\n};\nexport type { Node as AstNode };\n","import {\n argumentSignature,\n findPlurals,\n getArguments,\n isIcuStructured,\n parseMessage,\n type IcuNode,\n} from \"dialexjs/icu\";\n\nexport interface IcuFinding {\n level: \"error\" | \"warning\";\n code: \"invalid-icu\" | \"icu-args-mismatch\" | \"icu-plural-categories\";\n locale: string;\n /** Dotted key including the dictionary name, e.g. `cart.items`. */\n key: string;\n message: string;\n}\n\n/** `locale -> dotted path within the dictionary -> string value` */\nexport type LocaleStrings = Map<string, Map<string, string>>;\n\n/** CLDR order. `resolvedOptions().pluralCategories` order differs between Node versions. */\nconst CATEGORY_ORDER = [\"zero\", \"one\", \"two\", \"few\", \"many\"];\n\nfunction requiredCategories(locale: string, ordinal: boolean): string[] {\n try {\n return new Intl.PluralRules(locale, { type: ordinal ? \"ordinal\" : \"cardinal\" })\n .resolvedOptions()\n .pluralCategories.filter((c) => c !== \"other\")\n .sort((a, b) => CATEGORY_ORDER.indexOf(a) - CATEGORY_ORDER.indexOf(b));\n } catch {\n return []; // not a valid BCP 47 tag; nothing to compare against\n }\n}\n\n/**\n * Validates ICU messages across the locales of one dictionary:\n *\n * - invalid syntax: an error for messages that clearly use ICU (plural/select/number/date/time),\n * a warning for plain `{placeholders}` that do not parse (they may not be meant as ICU);\n * - every locale must use the same arguments as the reference locale;\n * - plural options should cover the categories the locale's plural rules need.\n */\nexport function checkIcu(\n dictionary: string,\n strings: LocaleStrings,\n defaultLocale: string,\n): IcuFinding[] {\n const findings: IcuFinding[] = [];\n const parsed = new Map<string, Map<string, IcuNode[]>>();\n\n for (const [locale, entries] of strings) {\n const ok = new Map<string, IcuNode[]>();\n for (const [path, value] of entries) {\n if (!value.includes(\"{\")) continue;\n const key = `${dictionary}.${path}`;\n try {\n ok.set(path, parseMessage(value));\n } catch (error) {\n const structured = isIcuStructured(value);\n findings.push({\n level: structured ? \"error\" : \"warning\",\n code: \"invalid-icu\",\n locale,\n key,\n message: structured\n ? `Invalid ICU message \"${key}\" (${locale}): ${(error as Error).message}`\n : `\"${key}\" (${locale}) contains braces but is not valid ICU, so t() values cannot be applied: ${(error as Error).message}`,\n });\n }\n }\n parsed.set(locale, ok);\n }\n\n // Compare every locale against the reference (default locale first)\n const order = [defaultLocale, ...[...parsed.keys()].filter((l) => l !== defaultLocale)];\n const paths = new Set([...parsed.values()].flatMap((m) => [...m.keys()]));\n\n for (const path of paths) {\n const key = `${dictionary}.${path}`;\n const reference = order.find((l) => parsed.get(l)?.has(path));\n if (!reference) continue;\n const expected = argumentSignature(parsed.get(reference)!.get(path)!);\n\n for (const locale of order) {\n const nodes = parsed.get(locale)?.get(path);\n if (nodes && locale !== reference) {\n const found = argumentSignature(nodes);\n if (found !== expected) {\n findings.push({\n level: \"error\",\n code: \"icu-args-mismatch\",\n locale,\n key,\n message: `Locale \"${locale}\" uses different arguments than \"${reference}\" for \"${key}\" (expected ${expected || \"none\"}, found ${found || \"none\"})`,\n });\n }\n }\n if (!nodes) continue;\n\n for (const plural of findPlurals(nodes)) {\n const missing = requiredCategories(locale, plural.ordinal).filter(\n (c) => !(c in plural.options),\n );\n if (missing.length > 0) {\n findings.push({\n level: \"warning\",\n code: \"icu-plural-categories\",\n locale,\n key,\n message: `Locale \"${locale}\" plural \"${plural.name}\" in \"${key}\" has no ${missing.map((c) => `\"${c}\"`).join(\", \")} option (used by this language; \"other\" will be shown instead)`,\n });\n }\n }\n }\n }\n\n return findings;\n}\n\n/** Arguments of a message, or `undefined` when it does not parse. */\nexport function tryGetArguments(message: string) {\n try {\n return getArguments(parseMessage(message));\n } catch {\n return undefined;\n }\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport fg from \"fast-glob\";\nimport {\n TODO_PREFIX,\n dictionaryLocation,\n flattenPaths,\n listLeaves,\n listLocales,\n loadDictionaryFile,\n locationOf,\n type DictionaryFile,\n type SourceRange,\n} from \"./utils/dictionary-edit.js\";\nimport { checkIcu, type LocaleStrings } from \"./utils/icu-check.js\";\n\n/**\n * Project analysis shared by `dialex check` and the editor extension.\n *\n * It reads dictionaries from the syntax tree, so it never runs project code. Dictionaries that\n * cannot be read that way (spreads, computed keys, imported values) are skipped with an `info`\n * issue, unless `runtime: true` is passed, in which case they are imported and read from the\n * evaluated module (the CLI does this; editors must not).\n */\n\nexport type IssueLevel = \"error\" | \"warning\" | \"info\";\n\nexport type IssueCode =\n | \"invalid-dictionary\"\n | \"unanalyzable\"\n | \"missing-locale\"\n | \"missing-key\"\n | \"invalid-locale\"\n | \"todo-placeholder\"\n | \"invalid-icu\"\n | \"icu-args-mismatch\"\n | \"icu-plural-categories\"\n | \"unknown-dictionary\"\n | \"unknown-path\"\n | \"unused-key\"\n | \"unused-dictionary\";\n\nexport interface AnalysisIssue {\n /** Absolute path of the file the issue is in. */\n file: string;\n level: IssueLevel;\n code: IssueCode;\n message: string;\n /** Where to point, when known. Lines and columns are zero-based. */\n range?: SourceRange;\n /** The dictionary the issue is about, when it is about one. */\n dictionary?: string;\n locale?: string;\n /** Key path within the dictionary. */\n path?: string[];\n /** For `missing-key`: a locale that has the key, to copy it from. */\n sourceLocale?: string;\n}\n\nexport interface AnalysisConfig {\n defaultLocale?: string;\n locales?: string[];\n include?: string | string[];\n}\n\nexport interface AnalysisOptions {\n root: string;\n config: AnalysisConfig;\n /** Source globs to scan for dictionary references. Pass `[]` to skip scanning. */\n src?: string[];\n /** Import dictionaries the syntax tree cannot fully describe. Runs project code. */\n runtime?: boolean;\n /** Extra ignore globs, relative to `root`. */\n ignore?: string[];\n /** Report possibly unused keys and dictionaries. @default true */\n unused?: boolean;\n}\n\nexport interface LeafInfo {\n kind: \"string\" | \"function\" | \"other\";\n value?: string;\n}\n\nexport interface AnalyzedDictionary {\n name: string;\n /** Absolute path. */\n file: string;\n /** Locales in source order. */\n locales: string[];\n /** `locale -> dotted path -> leaf` */\n leaves: Map<string, Map<string, LeafInfo>>;\n /** Union of dotted leaf paths across locales, in order of first appearance. */\n paths: string[];\n /** The parsed file, present when it was read statically. */\n df?: DictionaryFile;\n}\n\nexport interface AnalysisResult {\n issues: AnalysisIssue[];\n dictionaries: AnalyzedDictionary[];\n /** Absolute paths of every dictionary file that matched. */\n files: string[];\n sourceFilesScanned: number;\n}\n\nconst DICTIONARY_IGNORE = [\"**/node_modules/**\", \"**/dist/**\", \"**/.next/**\"];\n\nexport const DEFAULT_SOURCE_GLOB = \"**/*.{ts,tsx,js,jsx,mjs,cjs,vue,svelte,astro,mdx}\";\nconst SOURCE_IGNORE = [\n ...DICTIONARY_IGNORE,\n \"**/.nuxt/**\",\n \"**/.output/**\",\n \"**/.svelte-kit/**\",\n \"**/.astro/**\",\n \"**/coverage/**\",\n \"**/graphify-out/**\",\n \"**/*.d.ts\",\n \"**/dialex.generated.*\",\n \"**/dialex.config.*\",\n \"**/i18n.config.*\",\n];\n\n/** `getDictionary(\"x\")`, `useDictionary(\"x\")`, `@I18nDictionary(\"x\")` */\nconst DICTIONARY_CALL =\n /\\b(?:getDictionary|useDictionary|I18nDictionary)\\(\\s*([\"'`])([^\"'`$\\n]+)\\1/dg;\n/** `t(\"dictionary.path.to.key\")` */\nconst T_CALL = /(?<![\\w$.])t\\(\\s*([\"'`])([\\w-]+(?:\\.[\\w-]+)+)\\1/dg;\n\nexport interface Reference {\n /** A dictionary name, or a full `dictionary.key.path`. */\n kind: \"dictionary\" | \"path\";\n value: string;\n /** Offsets of the string's contents (without the quotes) in the scanned text. */\n start: number;\n end: number;\n}\n\n/** Finds `getDictionary(\"x\")`-style and `t(\"x.y.z\")` references in source text. */\nexport function scanReferences(text: string): Reference[] {\n const references: Reference[] = [];\n const collect = (pattern: RegExp, kind: Reference[\"kind\"]) => {\n for (const match of text.matchAll(pattern)) {\n const [start, end] = match.indices![2] as [number, number];\n references.push({ kind, value: match[2], start, end });\n }\n };\n collect(DICTIONARY_CALL, \"dictionary\");\n collect(T_CALL, \"path\");\n return references.sort((a, b) => a.start - b.start);\n}\n\nfunction lineStarts(text: string): number[] {\n const starts = [0];\n for (let i = 0; i < text.length; i++) if (text.charCodeAt(i) === 10) starts.push(i + 1);\n return starts;\n}\n\nfunction positionAt(starts: number[], offset: number) {\n let low = 0;\n let high = starts.length - 1;\n while (low < high) {\n const mid = Math.ceil((low + high) / 2);\n if (starts[mid] <= offset) low = mid;\n else high = mid - 1;\n }\n return { line: low, column: offset - starts[low] };\n}\n\ninterface DictionaryData {\n name: string;\n locales: string[];\n leaves: Map<string, Map<string, LeafInfo>>;\n df?: DictionaryFile;\n}\n\ntype Loaded =\n | { ok: true; data: DictionaryData }\n | { ok: false; level: IssueLevel; code: IssueCode; message: string };\n\nfunction fromSyntaxTree(df: DictionaryFile): DictionaryData {\n const locales = listLocales(df);\n const leaves = new Map<string, Map<string, LeafInfo>>();\n for (const locale of locales) {\n const entries = new Map<string, LeafInfo>();\n for (const leaf of listLeaves(df, locale)) {\n entries.set(leaf.path.join(\".\"), { kind: leaf.kind, value: leaf.value });\n }\n leaves.set(locale, entries);\n }\n return { name: df.name!, locales, leaves, df };\n}\n\nasync function fromRuntime(file: string): Promise<Loaded> {\n try {\n const mod = await import(`${pathToFileURL(file).href}?t=${Date.now()}_${Math.random()}`);\n const definition = mod.default || mod;\n if (!definition || typeof definition !== \"object\" || !definition.dictionary) {\n return {\n ok: false,\n level: \"error\",\n code: \"invalid-dictionary\",\n message: \"Default export does not appear to be a valid defineDictionary output.\",\n };\n }\n\n const dictionary = definition.dictionary as Record<string, Record<string, any>>;\n const leaves = new Map<string, Map<string, LeafInfo>>();\n const invalid: string[] = [];\n\n for (const [locale, content] of Object.entries(dictionary)) {\n if (!content || typeof content !== \"object\") {\n invalid.push(locale);\n continue;\n }\n const entries = new Map<string, LeafInfo>();\n for (const leafPath of flattenPaths(content)) {\n let value: any = content;\n for (const segment of leafPath) value = value?.[segment];\n entries.set(\n leafPath.join(\".\"),\n typeof value === \"string\"\n ? { kind: \"string\", value }\n : { kind: typeof value === \"function\" ? \"function\" : \"other\" },\n );\n }\n leaves.set(locale, entries);\n }\n\n if (invalid.length > 0) {\n return {\n ok: false,\n level: \"error\",\n code: \"invalid-locale\",\n message: invalid.map((l) => `Locale \"${l}\" content is empty or invalid.`).join(\"\\n\"),\n };\n }\n\n return {\n ok: true,\n data: { name: String(definition.name ?? \"\"), locales: [...leaves.keys()], leaves },\n };\n } catch (error: any) {\n return {\n ok: false,\n level: \"error\",\n code: \"invalid-dictionary\",\n message: `Failed to import dictionary: ${error.message || String(error)}`,\n };\n }\n}\n\nasync function loadDictionaryData(file: string, runtime: boolean): Promise<Loaded> {\n let astError: Error | undefined;\n try {\n const df = await loadDictionaryFile(file);\n if (df?.complete && df.name) return { ok: true, data: fromSyntaxTree(df) };\n } catch (error) {\n astError = error as Error;\n }\n\n if (runtime) return fromRuntime(file);\n\n return astError\n ? {\n ok: false,\n level: \"error\",\n code: \"invalid-dictionary\",\n message: `Failed to parse dictionary: ${astError.message}`,\n }\n : {\n ok: false,\n level: \"info\",\n code: \"unanalyzable\",\n message:\n \"This dictionary uses spreads, computed keys, imported values, or a computed name, so it cannot be analyzed statically.\",\n };\n}\n\nexport async function analyzeProject(options: AnalysisOptions): Promise<AnalysisResult> {\n const { root, config } = options;\n const include = config.include || \"**/*.content.ts\";\n const configuredLocales = config.locales || [];\n const defaultLocale = config.defaultLocale || \"en\";\n const extraIgnore = options.ignore ?? [];\n\n const files = fg.sync(include, {\n cwd: root,\n absolute: true,\n ignore: [...DICTIONARY_IGNORE, ...extraIgnore],\n });\n\n const issues: AnalysisIssue[] = [];\n const dictionaries: AnalyzedDictionary[] = [];\n\n // 1. Dictionaries: parity, placeholders, ICU\n for (const file of files) {\n const loaded = await loadDictionaryData(file, options.runtime === true);\n if (!loaded.ok) {\n for (const message of loaded.message.split(\"\\n\")) {\n issues.push({ file, level: loaded.level, code: loaded.code, message });\n }\n continue;\n }\n\n const { data } = loaded;\n const { df } = data;\n const at = (locale?: string, keyPath?: string[]) =>\n df && locale ? locationOf(df, locale, keyPath) : undefined;\n const add = (issue: Omit<AnalysisIssue, \"file\" | \"dictionary\">) =>\n issues.push({ ...issue, file, dictionary: data.name });\n\n for (const required of configuredLocales) {\n if (!data.locales.includes(required)) {\n add({\n level: \"error\",\n code: \"missing-locale\",\n message: `Missing configured locale \"${required}\"`,\n range: df ? dictionaryLocation(df) : undefined,\n locale: required,\n });\n }\n }\n\n const paths: string[] = [];\n const seen = new Set<string>();\n for (const locale of data.locales) {\n for (const leafPath of data.leaves.get(locale)!.keys()) {\n if (!seen.has(leafPath)) {\n seen.add(leafPath);\n paths.push(leafPath);\n }\n }\n }\n\n for (const locale of data.locales) {\n const present = data.leaves.get(locale)!;\n for (const leafPath of paths) {\n if (present.has(leafPath)) continue;\n const sourceLocale = [defaultLocale, ...data.locales].find(\n (l) => l !== locale && data.leaves.get(l)?.has(leafPath),\n );\n add({\n level: \"error\",\n code: \"missing-key\",\n message: `Locale \"${locale}\" is missing key \"${leafPath}\"`,\n range: at(locale),\n locale,\n path: leafPath.split(\".\"),\n sourceLocale,\n });\n }\n }\n\n const strings: LocaleStrings = new Map();\n for (const locale of data.locales) {\n const entries = new Map<string, string>();\n strings.set(locale, entries);\n for (const [leafPath, leaf] of data.leaves.get(locale)!) {\n if (leaf.kind !== \"string\" || leaf.value === undefined) continue;\n entries.set(leafPath, leaf.value);\n if (leaf.value.startsWith(TODO_PREFIX)) {\n add({\n level: \"warning\",\n code: \"todo-placeholder\",\n message: `Locale \"${locale}\" key \"${leafPath}\" still has a ${TODO_PREFIX.trim()} placeholder`,\n range: at(locale, leafPath.split(\".\")),\n locale,\n path: leafPath.split(\".\"),\n });\n }\n }\n }\n\n for (const finding of checkIcu(data.name, strings, defaultLocale)) {\n const keyPath = finding.key.slice(data.name.length + 1).split(\".\");\n add({\n level: finding.level,\n code: finding.code,\n message: finding.message,\n range: at(finding.locale, keyPath),\n locale: finding.locale,\n path: keyPath,\n });\n }\n\n dictionaries.push({\n name: data.name,\n file,\n locales: data.locales,\n leaves: data.leaves,\n paths,\n df,\n });\n }\n\n // 2. Source code: references to dictionaries and keys\n const known = new Map(dictionaries.map((d) => [d.name, d]));\n const dictionaryFiles = new Set(files);\n const sourceGlobs = options.src ?? [DEFAULT_SOURCE_GLOB];\n const sourceFiles =\n sourceGlobs.length === 0\n ? []\n : fg\n .sync(sourceGlobs, {\n cwd: root,\n absolute: true,\n ignore: [...SOURCE_IGNORE, ...extraIgnore],\n })\n .filter((f) => !dictionaryFiles.has(f));\n\n if (sourceFiles.length > 0) {\n const tokens = new Set<string>();\n\n for (const file of sourceFiles) {\n let text: string;\n try {\n text = fs.readFileSync(file, \"utf-8\");\n } catch {\n continue;\n }\n for (const token of text.match(/[\\w$-]+/g) ?? []) tokens.add(token);\n\n const starts = lineStarts(text);\n const rangeOf = (start: number, end: number): SourceRange => ({\n start: positionAt(starts, start),\n end: positionAt(starts, end),\n });\n\n for (const ref of scanReferences(text)) {\n if (ref.kind === \"dictionary\") {\n if (!known.has(ref.value)) {\n issues.push({\n file,\n level: \"error\",\n code: \"unknown-dictionary\",\n message: `Unknown dictionary \"${ref.value}\"`,\n range: rangeOf(ref.start, ref.end),\n dictionary: ref.value,\n });\n }\n continue;\n }\n\n const [name, ...rest] = ref.value.split(\".\");\n const dictionary = known.get(name);\n if (!dictionary) continue; // `t(...)` may belong to another library\n const keyPath = rest.join(\".\");\n const exists = dictionary.paths.some((p) => p === keyPath || p.startsWith(`${keyPath}.`));\n if (!exists) {\n issues.push({\n file,\n level: \"error\",\n code: \"unknown-path\",\n message: `Unknown translation path \"${ref.value}\"`,\n range: rangeOf(ref.start, ref.end),\n dictionary: name,\n path: rest,\n });\n }\n }\n }\n\n // 3. Possibly unused dictionaries and keys (heuristic: warnings only)\n if (options.unused !== false) {\n for (const dictionary of dictionaries) {\n if (!tokens.has(dictionary.name)) {\n issues.push({\n file: dictionary.file,\n level: \"warning\",\n code: \"unused-dictionary\",\n message: `Dictionary \"${dictionary.name}\" is never referenced`,\n range: dictionary.df ? dictionaryLocation(dictionary.df) : undefined,\n dictionary: dictionary.name,\n });\n continue;\n }\n for (const keyPath of dictionary.paths) {\n const last = keyPath.split(\".\").pop()!;\n if (tokens.has(last)) continue;\n const holder = dictionary.locales.find((l) => dictionary.leaves.get(l)?.has(keyPath));\n issues.push({\n file: dictionary.file,\n level: \"warning\",\n code: \"unused-key\",\n message: `Key \"${keyPath}\" is possibly unused`,\n range:\n dictionary.df && holder\n ? locationOf(dictionary.df, holder, keyPath.split(\".\"))\n : undefined,\n dictionary: dictionary.name,\n path: keyPath.split(\".\"),\n });\n }\n }\n }\n }\n\n return { issues, dictionaries, files, sourceFilesScanned: sourceFiles.length };\n}\n\n/** Project root-relative path with forward slashes, for display. */\nexport function relativeFile(root: string, file: string): string {\n return path.relative(root, file);\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { parseModule } from \"magicast\";\nimport {\n findProperty,\n isObjectNode,\n propertyKeyName,\n unwrapNode,\n type AstNode,\n} from \"./dictionary-edit.js\";\n\n/**\n * The parts of `dialex.config` that tooling needs, read **without running the file**. Editors must\n * not execute workspace code (it may be untrusted), so values are read from the syntax tree and\n * only literals are understood.\n */\nexport interface StaticConfig {\n defaultLocale: string;\n locales: string[];\n include: string | string[];\n fallbacks: Record<string, string[]>;\n prefixDefault: boolean;\n lazy: boolean;\n}\n\nexport interface StaticConfigResult {\n config: StaticConfig;\n /** The file the values came from, if any. */\n file?: string;\n /** Things that could not be read statically, for example `locales: getLocales()`. */\n notes: string[];\n}\n\nconst CONFIG_NAMES = [\"dialex.config\", \"i18n.config\"];\nconst EXTENSIONS = [\"ts\", \"mts\", \"cts\", \"js\", \"mjs\", \"cjs\", \"json\"];\n\nexport const DEFAULT_STATIC_CONFIG: StaticConfig = {\n defaultLocale: \"en\",\n locales: [],\n include: \"**/*.content.ts\",\n fallbacks: {},\n prefixDefault: true,\n lazy: false,\n};\n\nconst NOT_LITERAL = Symbol(\"not literal\");\n\nfunction literal(node: AstNode | undefined): unknown {\n node = unwrapNode(node as AstNode);\n switch (node?.type) {\n case \"StringLiteral\":\n case \"NumericLiteral\":\n case \"BooleanLiteral\":\n return node.value;\n case \"Literal\":\n return node.value;\n case \"TemplateLiteral\":\n return node.expressions.length === 0 ? (node.quasis[0]?.value?.cooked ?? \"\") : NOT_LITERAL;\n case \"ArrayExpression\": {\n const items = node.elements.map((e: AstNode) => literal(e));\n return items.includes(NOT_LITERAL) ? NOT_LITERAL : items;\n }\n case \"ObjectExpression\": {\n const result: Record<string, unknown> = {};\n for (const prop of node.properties) {\n const key = propertyKeyName(prop);\n const value = key === undefined ? NOT_LITERAL : literal(prop.value);\n if (value === NOT_LITERAL) return NOT_LITERAL;\n result[key as string] = value;\n }\n return result;\n }\n default:\n return NOT_LITERAL;\n }\n}\n\n/** The object literal passed to `defineConfig({...})`, or exported directly. */\nfunction findConfigObject(declaration: AstNode): AstNode | undefined {\n const node = unwrapNode(declaration);\n if (node?.type === \"CallExpression\") return findConfigObject(node.arguments[0]);\n return isObjectNode(node) ? node : undefined;\n}\n\nconst isStringArray = (value: unknown): value is string[] =>\n Array.isArray(value) && value.every((v) => typeof v === \"string\");\n\nfunction apply(object: Record<string, unknown>, config: StaticConfig, notes: string[]) {\n const accept = <K extends keyof StaticConfig>(\n key: K,\n valid: (value: unknown) => boolean,\n expected: string,\n ) => {\n if (!(key in object)) return;\n const value = object[key];\n if (valid(value)) (config as any)[key] = value;\n else notes.push(`\"${key}\" could not be read statically (expected ${expected}).`);\n };\n\n accept(\"defaultLocale\", (v) => typeof v === \"string\" && v !== \"\", \"a string literal\");\n accept(\"locales\", isStringArray, \"an array of string literals\");\n accept(\n \"include\",\n (v) => typeof v === \"string\" || isStringArray(v),\n \"a string or array of strings\",\n );\n accept(\n \"fallbacks\",\n (v) =>\n typeof v === \"object\" && v !== null && Object.values(v).every((list) => isStringArray(list)),\n \"an object of string arrays\",\n );\n accept(\"prefixDefault\", (v) => typeof v === \"boolean\", \"true or false\");\n accept(\"lazy\", (v) => typeof v === \"boolean\", \"true or false\");\n}\n\n/** Reads a config file's source text. Exposed for tests and for unsaved buffers. */\nexport function parseStaticConfig(text: string, file = \"dialex.config.ts\"): StaticConfigResult {\n const notes: string[] = [];\n const config: StaticConfig = { ...DEFAULT_STATIC_CONFIG };\n\n if (file.endsWith(\".json\")) {\n try {\n const data = JSON.parse(text);\n if (data && typeof data === \"object\") apply(data, config, notes);\n } catch (error) {\n notes.push(`Could not parse ${path.basename(file)}: ${(error as Error).message}`);\n }\n return { config, file, notes };\n }\n\n try {\n const exported = (parseModule(text).exports as any).default;\n const object = findConfigObject(exported?.$ast?.declaration ?? exported?.$ast);\n if (!object) {\n notes.push(`${path.basename(file)} does not export a config object literal.`);\n } else {\n const values: Record<string, unknown> = {};\n for (const key of [\n \"defaultLocale\",\n \"locales\",\n \"include\",\n \"fallbacks\",\n \"prefixDefault\",\n \"lazy\",\n ]) {\n const prop = findProperty(object, key);\n if (!prop) continue;\n const value = literal(prop.value);\n if (value === NOT_LITERAL)\n notes.push(`\"${key}\" could not be read statically (not a literal).`);\n else values[key] = value;\n }\n apply(values, config, notes);\n }\n } catch (error) {\n notes.push(`Could not parse ${path.basename(file)}: ${(error as Error).message}`);\n }\n\n return { config, file, notes };\n}\n\n/** Reads `dialex.config.*` (or `i18n.config.*`) from `root`, or from `configFile` if given. */\nexport function readStaticConfig(root: string, configFile?: string): StaticConfigResult {\n const candidates = configFile\n ? [path.resolve(root, configFile)]\n : CONFIG_NAMES.flatMap((name) => EXTENSIONS.map((ext) => path.join(root, `${name}.${ext}`)));\n\n for (const file of candidates) {\n if (fs.existsSync(file)) return parseStaticConfig(fs.readFileSync(file, \"utf-8\"), file);\n }\n return { config: { ...DEFAULT_STATIC_CONFIG }, notes: [] };\n}\n","import path from \"node:path\";\nimport fg from \"fast-glob\";\nimport { resolveI18nConfig } from \"dialexjs/scanner\";\nimport type { I18nConfig } from \"dialexjs\";\nimport { loadDictionaryFile, type DictionaryFile } from \"./dictionary-edit.js\";\nimport { readStaticConfig } from \"./static-config.js\";\n\nexport interface ProjectDictionary {\n /** Path relative to the project root. */\n rel: string;\n name: string;\n df: DictionaryFile;\n}\n\nexport interface Project {\n root: string;\n config: I18nConfig;\n dictionaries: ProjectDictionary[];\n /** Dictionary files that could not be parsed into an editable shape. */\n unsupported: string[];\n /** Config values that could not be read statically (static loading only). */\n notes: string[];\n}\n\nasync function loadDictionaries(root: string, config: I18nConfig) {\n const include = config.include || \"**/*.content.ts\";\n const files = fg.sync(include, {\n cwd: root,\n absolute: true,\n ignore: [\"**/node_modules/**\", \"**/dist/**\", \"**/.next/**\"],\n });\n\n const dictionaries: ProjectDictionary[] = [];\n const unsupported: string[] = [];\n\n for (const file of files) {\n const rel = path.relative(root, file);\n try {\n const df = await loadDictionaryFile(file);\n if (!df || !df.name) unsupported.push(rel);\n else dictionaries.push({ rel, name: df.name, df });\n } catch {\n unsupported.push(rel); // syntax error: reported by the analysis, nothing to edit here\n }\n }\n\n return { dictionaries, unsupported };\n}\n\n/**\n * Resolves the config (running `dialex.config.*` through the loader, which executes it) and loads\n * every dictionary file for AST-level reading and editing.\n */\nexport async function loadProject(root: string, configFile?: string): Promise<Project> {\n const config = resolveI18nConfig(root, configFile ? { configFile } : {});\n return { root, config, notes: [], ...(await loadDictionaries(root, config)) };\n}\n\n/**\n * Like `loadProject`, but reads the config from the syntax tree without executing it. Use this in\n * editors and anywhere project code must not run.\n */\nexport async function loadStaticProject(root: string, configFile?: string): Promise<Project> {\n const { config, notes } = readStaticConfig(root, configFile);\n return { root, config, notes, ...(await loadDictionaries(root, config)) };\n}\n\n/** `home` + `[\"nav\", \"about\"]` -> `home.nav.about` */\nexport const toKey = (dictionary: string, keyPath: string[]) => [dictionary, ...keyPath].join(\".\");\n"],"mappings":"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"}