@dialexjs/cli 0.7.2 → 0.9.1

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/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { A as scanFiles, C as lockPath, E as writeLock, F as getString, I as hasPath, L as listLeaves, M as copyLeaf, R as listLocales, S as lockFor, T as record, U as saveDictionaryFile, W as setString, a as renderGenerated, d as resolveDialexConfig, f as logger, i as generateDictionaries, j as TODO_PREFIX, m as analyzeProject, o as runGenerate, r as toKey, t as loadProject, w as readLock, x as isStale, y as LOCK_FILE, z as loadDictionaryFile } from "./project-Dz0FbydQ.mjs";
2
+ import { B as listLocales, C as isStale, D as record, E as readLock, G as saveDictionaryFile, K as setString, L as getString, M as scanFiles, N as TODO_PREFIX, O as writeLock, P as copyLeaf, R as hasPath, T as lockPath, V as loadDictionaryFile, a as renderGenerated, d as resolveDialexConfig, f as logger, i as generateDictionaries, m as analyzeProject, o as runGenerate, r as toKey, t as loadProject, w as lockFor, x as LOCK_FILE, z as listLeaves } from "./project-B27699T2.mjs";
3
3
  import { Command } from "commander";
4
4
  import fs from "node:fs";
5
5
  import path from "node:path";
@@ -10,7 +10,7 @@ import { argumentSignature, getArguments, isIcuStructured, parseMessage } from "
10
10
  import * as p from "@clack/prompts";
11
11
  import { addNuxtModule } from "magicast/helpers";
12
12
  //#region package.json
13
- var version = "0.7.2";
13
+ var version = "0.9.1";
14
14
  //#endregion
15
15
  //#region src/commands/check.ts
16
16
  function addIssue(diag, issue) {
@@ -510,6 +510,16 @@ function detectFramework(root) {
510
510
  confidence: "high",
511
511
  matchedRule: "package.json dependencies (@nestjs/core)"
512
512
  };
513
+ if ("@adonisjs/core" in allDeps) return {
514
+ framework: "adonis",
515
+ confidence: "high",
516
+ matchedRule: "package.json dependencies (@adonisjs/core)"
517
+ };
518
+ if ("@hapi/hapi" in allDeps) return {
519
+ framework: "hapi",
520
+ confidence: "high",
521
+ matchedRule: "package.json dependencies (@hapi/hapi)"
522
+ };
513
523
  if ("fastify" in allDeps) return {
514
524
  framework: "fastify",
515
525
  confidence: "high",
@@ -535,11 +545,51 @@ function detectFramework(root) {
535
545
  confidence: "high",
536
546
  matchedRule: "package.json dependencies (hono)"
537
547
  };
548
+ if ("@trpc/server" in allDeps) return {
549
+ framework: "trpc",
550
+ confidence: "high",
551
+ matchedRule: "package.json dependencies (@trpc/server)"
552
+ };
553
+ if ("@builder.io/qwik" in allDeps) return {
554
+ framework: "qwik",
555
+ confidence: "high",
556
+ matchedRule: "package.json dependencies (@builder.io/qwik)"
557
+ };
558
+ if ("react-native" in allDeps || "expo" in allDeps) return {
559
+ framework: "react-native",
560
+ confidence: "high",
561
+ matchedRule: "package.json dependencies (react-native/expo)"
562
+ };
563
+ if ("@react-router/dev" in allDeps) return {
564
+ framework: "react-router",
565
+ confidence: "high",
566
+ matchedRule: "package.json dependencies (@react-router/dev)"
567
+ };
568
+ if ("solid-js" in allDeps) return {
569
+ framework: "solid",
570
+ confidence: "high",
571
+ matchedRule: "package.json dependencies (solid-js)"
572
+ };
573
+ if ("svelte" in allDeps) return {
574
+ framework: "svelte",
575
+ confidence: "high",
576
+ matchedRule: "package.json dependencies (svelte)"
577
+ };
538
578
  if ("vue" in allDeps && !("react" in allDeps)) return {
539
579
  framework: "vue",
540
580
  confidence: "high",
541
581
  matchedRule: "package.json dependencies (vue)"
542
582
  };
583
+ if ("preact" in allDeps) return {
584
+ framework: "preact",
585
+ confidence: "high",
586
+ matchedRule: "package.json dependencies (preact)"
587
+ };
588
+ if ("lit" in allDeps && !("react" in allDeps)) return {
589
+ framework: "lit",
590
+ confidence: "high",
591
+ matchedRule: "package.json dependencies (lit)"
592
+ };
543
593
  if ("react" in allDeps || "vite" in allDeps) return {
544
594
  framework: "react",
545
595
  confidence: "high",
@@ -554,7 +604,8 @@ function detectFramework(root) {
554
604
  for (const [framework, base] of [
555
605
  ["nuxt", "nuxt.config"],
556
606
  ["sveltekit", "svelte.config"],
557
- ["astro", "astro.config"]
607
+ ["astro", "astro.config"],
608
+ ["react-router", "react-router.config"]
558
609
  ]) if ([
559
610
  "js",
560
611
  "mjs",
@@ -697,6 +748,56 @@ async function runInit(options = {}) {
697
748
  value: "nuxt",
698
749
  label: "Nuxt",
699
750
  hint: detected.framework === "nuxt" ? "detected" : void 0
751
+ },
752
+ {
753
+ value: "svelte",
754
+ label: "Svelte / Vite",
755
+ hint: detected.framework === "svelte" ? "detected" : void 0
756
+ },
757
+ {
758
+ value: "solid",
759
+ label: "Solid / Vite",
760
+ hint: detected.framework === "solid" ? "detected" : void 0
761
+ },
762
+ {
763
+ value: "react-router",
764
+ label: "React Router",
765
+ hint: detected.framework === "react-router" ? "detected" : void 0
766
+ },
767
+ {
768
+ value: "react-native",
769
+ label: "React Native / Expo",
770
+ hint: detected.framework === "react-native" ? "detected" : void 0
771
+ },
772
+ {
773
+ value: "preact",
774
+ label: "Preact / Vite",
775
+ hint: detected.framework === "preact" ? "detected" : void 0
776
+ },
777
+ {
778
+ value: "qwik",
779
+ label: "Qwik",
780
+ hint: detected.framework === "qwik" ? "detected" : void 0
781
+ },
782
+ {
783
+ value: "lit",
784
+ label: "Lit / Web Components",
785
+ hint: detected.framework === "lit" ? "detected" : void 0
786
+ },
787
+ {
788
+ value: "hapi",
789
+ label: "Hapi",
790
+ hint: detected.framework === "hapi" ? "detected" : void 0
791
+ },
792
+ {
793
+ value: "adonis",
794
+ label: "AdonisJS",
795
+ hint: detected.framework === "adonis" ? "detected" : void 0
796
+ },
797
+ {
798
+ value: "trpc",
799
+ label: "tRPC",
800
+ hint: detected.framework === "trpc" ? "detected" : void 0
700
801
  }
701
802
  ];
702
803
  const selectedFramework = await p.select({
@@ -740,6 +841,7 @@ async function runInit(options = {}) {
740
841
  const localeList = Array.from(/* @__PURE__ */ new Set([defaultLocale, ...localesInput.split(",").map((s) => s.trim()).filter(Boolean)]));
741
842
  const configPath = fs.existsSync(path.join(root, "dialex.config.ts")) ? path.join(root, "dialex.config.ts") : fs.existsSync(path.join(root, "i18n.config.ts")) ? path.join(root, "i18n.config.ts") : path.join(root, "dialex.config.ts");
742
843
  const configFileName = path.basename(configPath);
844
+ const generatedOutput = framework === "react-router" ? "app/dialex.generated.ts" : framework === "adonis" ? "start/dialex.generated.ts" : void 0;
743
845
  try {
744
846
  if (fs.existsSync(configPath)) {
745
847
  const mod = await loadFile(configPath);
@@ -747,6 +849,7 @@ async function runInit(options = {}) {
747
849
  if (mod.exports.default.$args && mod.exports.default.$args[0]) {
748
850
  mod.exports.default.$args[0].defaultLocale = defaultLocale;
749
851
  mod.exports.default.$args[0].locales = localeList;
852
+ if (generatedOutput) mod.exports.default.$args[0].output = generatedOutput;
750
853
  }
751
854
  await writeFile(mod, configPath);
752
855
  logger.success(`Updated ${pc.bold(configFileName)} via Magicast`);
@@ -758,6 +861,7 @@ export default defineConfig({});
758
861
  `);
759
862
  mod.exports.default.$args[0].defaultLocale = defaultLocale;
760
863
  mod.exports.default.$args[0].locales = localeList;
864
+ if (generatedOutput) mod.exports.default.$args[0].output = generatedOutput;
761
865
  await writeFile(mod, configPath);
762
866
  logger.success(`Created ${pc.bold(configFileName)} via Magicast`);
763
867
  }
@@ -767,7 +871,7 @@ export default defineConfig({});
767
871
 
768
872
  export default defineConfig({
769
873
  defaultLocale: "${defaultLocale}",
770
- locales: [${localeList.map((l) => `"${l}"`).join(", ")}],
874
+ locales: [${localeList.map((l) => `"${l}"`).join(", ")}],${generatedOutput ? `\n output: "${generatedOutput}",` : ""}
771
875
  });
772
876
  `;
773
877
  fs.writeFileSync(configPath, fallback, "utf-8");
@@ -787,7 +891,7 @@ export default defineConfig({
787
891
  logger.warn("Could not update the Nuxt config; add the dialexjs/nuxt module manually.");
788
892
  }
789
893
  }
790
- const targetDir = fs.existsSync(path.join(root, "src")) ? path.join(root, "src") : root;
894
+ const targetDir = (framework === "react-router" || framework === "adonis") && fs.existsSync(path.join(root, "app")) ? path.join(root, "app") : fs.existsSync(path.join(root, "src")) ? path.join(root, "src") : root;
791
895
  const dictPath = path.join(targetDir, "home.content.ts");
792
896
  if (!fs.existsSync(dictPath)) {
793
897
  const dictContent = `import { defineDictionary } from "dialexjs";
@@ -803,7 +907,7 @@ ${localeList.map((loc) => ` ${loc}: {
803
907
  fs.writeFileSync(dictPath, dictContent, "utf-8");
804
908
  logger.success(`Created starter dictionary at ${pc.bold(path.relative(root, dictPath))}`);
805
909
  } else logger.info("home.content.ts already exists, skipping creation.");
806
- generateDictionaries(root);
910
+ generateDictionaries(root, { static: true });
807
911
  logger.success("Generated types and standalone dictionary registry!");
808
912
  const pkgPath = path.join(root, "package.json");
809
913
  if (fs.existsSync(pkgPath)) try {
@@ -884,11 +988,11 @@ This project uses [Dialex](https://github.com/awaiden/dialex) for type-safe inte
884
988
  case "hono":
885
989
  logger.log(`
886
990
  import { Hono } from "hono";
887
- import { dialex } from "dialexjs/hono";
888
- import dictionaries from "./src/dialex.generated.js";
991
+ import { dialexHono } from "dialexjs/hono";
992
+ import { dialex } from "./src/dialex.generated.js";
889
993
 
890
994
  const app = new Hono();
891
- app.use("*", dialex({ dictionaries }));
995
+ app.use("*", dialexHono({ ...dialex }));
892
996
 
893
997
  app.get("/", (c) => {
894
998
  const dict = c.var.getDictionary("home");
@@ -900,10 +1004,10 @@ app.get("/", (c) => {
900
1004
  logger.log(`
901
1005
  import Fastify from "fastify";
902
1006
  import { dialexPlugin } from "dialexjs/fastify";
903
- import dictionaries from "./src/dialex.generated.js";
1007
+ import { dialex } from "./src/dialex.generated.js";
904
1008
 
905
1009
  const app = Fastify();
906
- await app.register(dialexPlugin, { dictionaries });
1010
+ await app.register(dialexPlugin, { ...dialex });
907
1011
 
908
1012
  app.get("/", (req) => {
909
1013
  const dict = req.getDictionary("home");
@@ -914,11 +1018,11 @@ app.get("/", (req) => {
914
1018
  case "express":
915
1019
  logger.log(`
916
1020
  import express from "express";
917
- import { dialex } from "dialexjs/express";
918
- import dictionaries from "./src/dialex.generated.js";
1021
+ import { dialexExpress } from "dialexjs/express";
1022
+ import { dialex } from "./src/dialex.generated.js";
919
1023
 
920
1024
  const app = express();
921
- app.use(dialex({ dictionaries }));
1025
+ app.use(dialexExpress({ ...dialex }));
922
1026
 
923
1027
  app.get("/", (req, res) => {
924
1028
  const dict = req.getDictionary("home");
@@ -929,11 +1033,11 @@ app.get("/", (req, res) => {
929
1033
  case "koa":
930
1034
  logger.log(`
931
1035
  import Koa from "koa";
932
- import { dialex } from "dialexjs/koa";
933
- import dictionaries from "./src/dialex.generated.js";
1036
+ import { dialexKoa } from "dialexjs/koa";
1037
+ import { dialex } from "./src/dialex.generated.js";
934
1038
 
935
1039
  const app = new Koa();
936
- app.use(dialex({ dictionaries }));
1040
+ app.use(dialexKoa({ ...dialex }));
937
1041
 
938
1042
  app.use((ctx) => {
939
1043
  const dict = ctx.getDictionary("home");
@@ -945,10 +1049,10 @@ app.use((ctx) => {
945
1049
  logger.log(`
946
1050
  import { Module } from "@nestjs/common";
947
1051
  import { DialexModule } from "dialexjs/nestjs";
948
- import dictionaries from "./src/dialex.generated.js";
1052
+ import { dialex } from "./src/dialex.generated.js";
949
1053
 
950
1054
  @Module({
951
- imports: [DialexModule.forRoot({ dictionaries })],
1055
+ imports: [DialexModule.forRoot({ ...dialex })],
952
1056
  })
953
1057
  export class AppModule {}
954
1058
  `);
@@ -997,11 +1101,11 @@ createRoot(document.getElementById("root")!).render(
997
1101
  case "elysia":
998
1102
  logger.log(`
999
1103
  import { Elysia } from "elysia";
1000
- import { dialex } from "dialexjs/elysia";
1001
- import dictionaries from "./src/dialex.generated.js";
1104
+ import { dialexElysia } from "dialexjs/elysia";
1105
+ import { dialex } from "./src/dialex.generated.js";
1002
1106
 
1003
1107
  new Elysia()
1004
- .use(dialex({ dictionaries }))
1108
+ .use(dialexElysia({ ...dialex }))
1005
1109
  .get("/", ({ getDictionary }) => ({ title: getDictionary("home").title }))
1006
1110
  .listen(3000);
1007
1111
  `);
@@ -1010,9 +1114,9 @@ new Elysia()
1010
1114
  logger.log(`
1011
1115
  // src/hooks.server.ts
1012
1116
  import { dialexHandle } from "dialexjs/sveltekit";
1013
- import dictionaries from "./dialex.generated.js";
1117
+ import { dialex } from "./dialex.generated.js";
1014
1118
 
1015
- export const handle = dialexHandle({ dictionaries });
1119
+ export const handle = dialexHandle({ ...dialex });
1016
1120
 
1017
1121
  // src/app.html: <html lang="%dialex.lang%">
1018
1122
  // In load functions: locals.getDictionary("home")
@@ -1021,10 +1125,10 @@ export const handle = dialexHandle({ dictionaries });
1021
1125
  case "astro":
1022
1126
  logger.log(`
1023
1127
  // src/middleware.ts
1024
- import { dialex } from "dialexjs/astro";
1025
- import dictionaries from "./dialex.generated.js";
1128
+ import { dialexAstro } from "dialexjs/astro";
1129
+ import { dialex } from "./dialex.generated.js";
1026
1130
 
1027
- export const onRequest = dialex({ dictionaries });
1131
+ export const onRequest = dialexAstro({ ...dialex });
1028
1132
 
1029
1133
  // In pages: Astro.locals.getDictionary("home")
1030
1134
  `);
@@ -1040,6 +1144,199 @@ import App from "./App.vue";
1040
1144
  createApp(App).use(createDialex({ ...dialex })).mount("#app");
1041
1145
 
1042
1146
  // In components: const dict = useDictionary("home")
1147
+ `);
1148
+ break;
1149
+ case "svelte":
1150
+ logger.log(`
1151
+ <!-- src/App.svelte -->
1152
+ <script lang="ts">
1153
+ import { provideDialex, useDictionary } from "dialexjs/svelte";
1154
+ import { dialex } from "./dialex.generated";
1155
+
1156
+ const { locale, setLocale } = provideDialex({ ...dialex });
1157
+ const home = useDictionary("home");
1158
+ <\/script>
1159
+
1160
+ <h1>{$home.title}</h1>
1161
+ <button onclick={() => setLocale("tr")}>TR</button>
1162
+ `);
1163
+ break;
1164
+ case "solid":
1165
+ logger.log(`
1166
+ // src/index.tsx
1167
+ import { render } from "solid-js/web";
1168
+ import { DialexProvider } from "dialexjs/solid";
1169
+ import { dialex } from "./dialex.generated";
1170
+ import App from "./App";
1171
+
1172
+ render(
1173
+ () => (
1174
+ <DialexProvider {...dialex}>
1175
+ <App />
1176
+ </DialexProvider>
1177
+ ),
1178
+ document.getElementById("root")!,
1179
+ );
1180
+
1181
+ // In components: const home = useDictionary("home"); then {home().title}
1182
+ `);
1183
+ break;
1184
+ case "react-router":
1185
+ logger.log(`
1186
+ // app/dialex.server.ts
1187
+ import { createDialexHandler } from "dialexjs/web";
1188
+ import { dialex } from "./dialex.generated";
1189
+
1190
+ export const resolveDialex = createDialexHandler({ ...dialex });
1191
+
1192
+ // app/root.tsx
1193
+ import { DialexProvider } from "dialexjs/react";
1194
+ import { useLoaderData } from "react-router";
1195
+ import { dialex } from "./dialex.generated";
1196
+ import { resolveDialex } from "./dialex.server";
1197
+
1198
+ export async function loader({ request }: Route.LoaderArgs) {
1199
+ const { locale } = await resolveDialex(request);
1200
+ return { locale };
1201
+ }
1202
+
1203
+ export default function App() {
1204
+ const { locale } = useLoaderData<typeof loader>();
1205
+ return (
1206
+ <DialexProvider {...dialex} initialLocale={locale}>
1207
+ <Outlet />
1208
+ </DialexProvider>
1209
+ );
1210
+ }
1211
+ `);
1212
+ break;
1213
+ case "preact":
1214
+ logger.log(`
1215
+ // src/index.tsx
1216
+ import { render } from "preact";
1217
+ import { DialexProvider } from "dialexjs/preact";
1218
+ import { dialex } from "./dialex.generated";
1219
+ import { App } from "./app";
1220
+
1221
+ render(
1222
+ <DialexProvider {...dialex}>
1223
+ <App />
1224
+ </DialexProvider>,
1225
+ document.getElementById("app")!,
1226
+ );
1227
+
1228
+ // In components: const dict = useDictionary("home")
1229
+ `);
1230
+ break;
1231
+ case "qwik":
1232
+ logger.log(`
1233
+ // src/i18n.ts
1234
+ import { createDialexQwik } from "dialexjs/qwik";
1235
+ import { dialex } from "./dialex.generated";
1236
+
1237
+ export const { useDialexProvider, useDialex, setLocale, useDictionary, useT } =
1238
+ createDialexQwik({ ...dialex });
1239
+
1240
+ // src/routes/layout.tsx
1241
+ export default component$(() => {
1242
+ useDialexProvider();
1243
+ return <Slot />;
1244
+ });
1245
+
1246
+ // In components: const home = useDictionary("home"); then {home().title}
1247
+ `);
1248
+ break;
1249
+ case "lit":
1250
+ logger.log(`
1251
+ // src/i18n.ts
1252
+ import { createDialex } from "dialexjs/lit";
1253
+ import { dialex } from "./dialex.generated";
1254
+
1255
+ export const i18n = createDialex({ ...dialex });
1256
+
1257
+ // src/my-element.ts
1258
+ import { LitElement, html } from "lit";
1259
+ import { DialexController } from "dialexjs/lit";
1260
+ import { i18n } from "./i18n";
1261
+
1262
+ class MyElement extends LitElement {
1263
+ private dx = new DialexController(this, i18n);
1264
+
1265
+ render() {
1266
+ return html\`<h1>\${this.dx.dictionary("home").title}</h1>\`;
1267
+ }
1268
+ }
1269
+ `);
1270
+ break;
1271
+ case "react-native":
1272
+ logger.log(`
1273
+ // App.tsx
1274
+ import AsyncStorage from "@react-native-async-storage/async-storage";
1275
+ import { getLocales } from "expo-localization";
1276
+ import { DialexProvider } from "dialexjs/react-native";
1277
+ import { dialex } from "./src/dialex.generated";
1278
+
1279
+ export default function App() {
1280
+ return (
1281
+ <DialexProvider
1282
+ {...dialex}
1283
+ deviceLocales={getLocales().map((locale) => locale.languageTag)}
1284
+ storage={AsyncStorage}
1285
+ >
1286
+ <Home />
1287
+ </DialexProvider>
1288
+ );
1289
+ }
1290
+
1291
+ // In components: const dict = useDictionary("home")
1292
+ `);
1293
+ break;
1294
+ case "hapi":
1295
+ logger.log(`
1296
+ import Hapi from "@hapi/hapi";
1297
+ import { dialexPlugin } from "dialexjs/hapi";
1298
+ import { dialex } from "./src/dialex.generated.js";
1299
+
1300
+ const server = Hapi.server({ port: 3000 });
1301
+ await server.register({ plugin: dialexPlugin, options: { ...dialex } });
1302
+
1303
+ server.route({
1304
+ method: "GET",
1305
+ path: "/",
1306
+ handler: (request) => ({ title: request.getDictionary("home").title }),
1307
+ });
1308
+ `);
1309
+ break;
1310
+ case "adonis":
1311
+ logger.log(`
1312
+ // app/middleware/dialex_middleware.ts
1313
+ import { createDialexMiddleware } from "dialexjs/adonis";
1314
+ import { dialex } from "#start/dialex.generated";
1315
+
1316
+ export default createDialexMiddleware({ ...dialex });
1317
+
1318
+ // start/kernel.ts
1319
+ router.use([() => import("#middleware/dialex_middleware")]);
1320
+
1321
+ // In handlers: ctx.locale, ctx.getDictionary("home")
1322
+ `);
1323
+ break;
1324
+ case "trpc":
1325
+ logger.log(`
1326
+ // src/trpc.ts
1327
+ import { initTRPC } from "@trpc/server";
1328
+ import { createDialexContext } from "dialexjs/trpc";
1329
+ import { dialex } from "./dialex.generated.js";
1330
+
1331
+ const resolveDialex = createDialexContext({ ...dialex });
1332
+
1333
+ export const createContext = ({ req }: { req: Request }) => ({ ...resolveDialex(req) });
1334
+
1335
+ const t = initTRPC.context<Awaited<ReturnType<typeof createContext>>>().create();
1336
+
1337
+ export const appRouter = t.router({
1338
+ greeting: t.procedure.query(({ ctx }) => ctx.getDictionary("home").title),
1339
+ });
1043
1340
  `);
1044
1341
  break;
1045
1342
  case "nuxt":
@@ -1150,6 +1447,13 @@ function preservesPlaceholders(source, translated) {
1150
1447
  }
1151
1448
  //#endregion
1152
1449
  //#region src/commands/translate.ts
1450
+ /**
1451
+ * The JSON of a result. Tasks carry the parsed dictionary and the key path for the writing step;
1452
+ * those are not part of the output (the parsed file is large and not meant to be read).
1453
+ */
1454
+ function printable(result) {
1455
+ return JSON.stringify(result, (key, value) => key === "dict" || key === "path" ? void 0 : value, 2);
1456
+ }
1153
1457
  async function runTranslate(options = {}) {
1154
1458
  const root = options.cwd || process.cwd();
1155
1459
  const project = await loadProject(root, options.config);
@@ -1193,12 +1497,12 @@ async function runTranslate(options = {}) {
1193
1497
  rejected: []
1194
1498
  };
1195
1499
  if (tasks.length === 0) {
1196
- if (quiet) console.log(JSON.stringify(result, null, 2));
1500
+ if (quiet) console.log(printable(result));
1197
1501
  else logger.success(`Nothing to translate from "${source}".`);
1198
1502
  return result;
1199
1503
  }
1200
1504
  if (options.dryRun) {
1201
- if (quiet) console.log(JSON.stringify(result, null, 2));
1505
+ if (quiet) console.log(printable(result));
1202
1506
  else {
1203
1507
  logger.info(`Would translate ${tasks.length} string${tasks.length === 1 ? "" : "s"} from "${source}":`);
1204
1508
  for (const t of tasks) logger.log(` ${pc.dim(t.locale)} ${t.key} ${pc.dim(JSON.stringify(t.source))}${t.stale ? pc.yellow(" (out of date)") : ""}`);
@@ -1243,7 +1547,7 @@ async function runTranslate(options = {}) {
1243
1547
  for (const dict of touched) await saveDictionaryFile(dict.df);
1244
1548
  if (result.translated > 0) writeLock(root, lock);
1245
1549
  if (result.rejected.length > 0) result.success = false;
1246
- if (quiet) console.log(JSON.stringify(result, null, 2));
1550
+ if (quiet) console.log(printable(result));
1247
1551
  else {
1248
1552
  logger.success(`Translated ${result.translated} of ${tasks.length} string${tasks.length === 1 ? "" : "s"}.`);
1249
1553
  if (result.rejected.length > 0) logger.warn(`${result.rejected.length} left unchanged: ${result.rejected.slice(0, 5).join("; ")}${result.rejected.length > 5 ? "; ..." : ""}`);
@@ -1257,7 +1561,7 @@ program.name("dialex").description("Dialex CLI - High-performance, type-safe int
1257
1561
  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) => {
1258
1562
  await runGenerate(opts);
1259
1563
  });
1260
- program.command("init").description("Initialize Dialex in the current project").option("-f, --framework <framework>", "Target framework (hono, express, fastify, koa, nestjs, next, react)").option("-d, --default-locale <locale>", "Default locale (e.g. en)").option("-l, --locales <locales>", "Comma-separated supported locales (e.g. en,tr)").option("-y, --yes", "Skip prompts and use defaults").option("--ai", "Configure AI agent support (.agents/skills, .mcp.json, AGENTS.md)").option("--no-ai", "Skip AI agent configuration").action(async (opts) => {
1564
+ program.command("init").description("Initialize Dialex in the current project").option("-f, --framework <framework>", "Target framework (hono, express, fastify, koa, nestjs, elysia, sveltekit, astro, vue, nuxt, next, react, react-router, svelte, solid, preact, qwik, lit, react-native, hapi, adonis, trpc)").option("-d, --default-locale <locale>", "Default locale (e.g. en)").option("-l, --locales <locales>", "Comma-separated supported locales (e.g. en,tr)").option("-y, --yes", "Skip prompts and use defaults").option("--ai", "Configure AI agent support (.agents/skills, .mcp.json, AGENTS.md)").option("--no-ai", "Skip AI agent configuration").action(async (opts) => {
1261
1565
  await runInit(opts);
1262
1566
  });
1263
1567
  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("--fail-on-stale", "Treat translations whose source text changed as errors").option("--src <globs...>", "Source globs to scan for dictionary references").action(async (opts) => {