@fluenti/cli 0.1.3 → 0.2.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/cli.js CHANGED
@@ -1,31 +1,31 @@
1
1
  #!/usr/bin/env node
2
2
  import { t as e } from "./tsx-extractor-DZrY1LMS.js";
3
- import { a as t, c as n, i as r, l as i, n as a, o, r as s, s as c, t as l } from "./compile-BJdEF9QX.js";
4
- import { defineCommand as u, runMain as d } from "citty";
5
- import f from "consola";
6
- import p from "fast-glob";
7
- import { appendFileSync as m, existsSync as h, mkdirSync as g, readFileSync as _, writeFileSync as v } from "node:fs";
8
- import { dirname as ee, extname as y, join as b, resolve as x } from "node:path";
9
- import { execFile as S } from "node:child_process";
10
- import { promisify as C } from "node:util";
3
+ import { a as t, c as n, i as r, l as i, n as a, o, r as s, s as c, t as l, u } from "./config-loader-CcqRnMzw.js";
4
+ import { appendFileSync as d, existsSync as f, mkdirSync as p, readFileSync as m, writeFileSync as h } from "node:fs";
5
+ import { dirname as g, extname as _, join as v, resolve as y } from "node:path";
6
+ import { defineCommand as b, runMain as x } from "citty";
7
+ import S from "consola";
8
+ import C from "fast-glob";
9
+ import { execFile as w } from "node:child_process";
10
+ import { promisify as T } from "node:util";
11
11
  //#region src/stats-format.ts
12
- var w = "█", T = "░";
13
- function E(e, t = 20) {
12
+ var ee = "█", E = "░";
13
+ function D(e, t = 20) {
14
14
  let n = Math.max(0, Math.min(100, e)), r = Math.round(n / 100 * t);
15
- return w.repeat(r) + T.repeat(t - r);
15
+ return ee.repeat(r) + E.repeat(t - r);
16
16
  }
17
- function D(e) {
17
+ function O(e) {
18
18
  let t = e.toFixed(1) + "%";
19
19
  return e >= 90 ? `\x1b[32m${t}\x1b[0m` : e >= 70 ? `\x1b[33m${t}\x1b[0m` : `\x1b[31m${t}\x1b[0m`;
20
20
  }
21
- function O(e, t, n) {
22
- let r = t > 0 ? n / t * 100 : 0, i = t > 0 ? D(r) : "—", a = t > 0 ? E(r) : "";
21
+ function te(e, t, n) {
22
+ let r = t > 0 ? n / t * 100 : 0, i = t > 0 ? O(r) : "—", a = t > 0 ? D(r) : "";
23
23
  return ` ${e.padEnd(8)}│ ${String(t).padStart(5)} │ ${String(n).padStart(10)} │ ${a} ${i}`;
24
24
  }
25
25
  //#endregion
26
26
  //#region src/translate.ts
27
- var k = C(S);
28
- function te(e, t, n) {
27
+ var k = T(w);
28
+ function A(e, t, n) {
29
29
  let r = JSON.stringify(n, null, 2);
30
30
  return [
31
31
  `You are a professional translator. Translate the following messages from "${e}" to "${t}".`,
@@ -40,7 +40,7 @@ function te(e, t, n) {
40
40
  "- Do not add any explanation or markdown formatting, output raw JSON only."
41
41
  ].join("\n");
42
42
  }
43
- async function ne(e, t) {
43
+ async function j(e, t) {
44
44
  let n = 10 * 1024 * 1024;
45
45
  try {
46
46
  if (e === "claude") {
@@ -58,19 +58,19 @@ async function ne(e, t) {
58
58
  throw t.code === "ENOENT" ? Error(`"${e}" CLI not found. Please install it first:\n` + (e === "claude" ? " npm install -g @anthropic-ai/claude-code" : " npm install -g @openai/codex")) : t;
59
59
  }
60
60
  }
61
- function A(e) {
61
+ function M(e) {
62
62
  let t = e.match(/\{[\s\S]*\}/);
63
63
  if (!t) throw Error("No JSON object found in AI response");
64
64
  let n = JSON.parse(t[0]);
65
65
  if (typeof n != "object" || !n || Array.isArray(n)) throw Error("AI response is not a valid JSON object");
66
66
  return n;
67
67
  }
68
- function j(e) {
68
+ function N(e) {
69
69
  let t = {};
70
70
  for (let [n, r] of Object.entries(e)) r.obsolete || (!r.translation || r.translation.length === 0) && (t[n] = r.message ?? n);
71
71
  return t;
72
72
  }
73
- function M(e, t) {
73
+ function P(e, t) {
74
74
  let n = Object.keys(e), r = [];
75
75
  for (let i = 0; i < n.length; i += t) {
76
76
  let a = {};
@@ -79,22 +79,22 @@ function M(e, t) {
79
79
  }
80
80
  return r;
81
81
  }
82
- async function N(e) {
83
- let { provider: t, sourceLocale: n, targetLocale: r, catalog: i, batchSize: a } = e, o = j(i), s = Object.keys(o).length;
82
+ async function F(e) {
83
+ let { provider: t, sourceLocale: n, targetLocale: r, catalog: i, batchSize: a } = e, o = N(i), s = Object.keys(o).length;
84
84
  if (s === 0) return {
85
85
  catalog: { ...i },
86
86
  translated: 0
87
87
  };
88
- f.info(` ${s} untranslated messages, translating with ${t}...`);
89
- let c = { ...i }, l = M(o, a), u = 0;
88
+ S.info(` ${s} untranslated messages, translating with ${t}...`);
89
+ let c = { ...i }, l = P(o, a), u = 0;
90
90
  for (let e = 0; e < l.length; e++) {
91
91
  let i = l[e], a = Object.keys(i);
92
- l.length > 1 && f.info(` Batch ${e + 1}/${l.length} (${a.length} messages)`);
93
- let o = A(await ne(t, te(n, r, i)));
92
+ l.length > 1 && S.info(` Batch ${e + 1}/${l.length} (${a.length} messages)`);
93
+ let o = M(await j(t, A(n, r, i)));
94
94
  for (let e of a) o[e] && typeof o[e] == "string" ? (c[e] = {
95
95
  ...c[e],
96
96
  translation: o[e]
97
- }, u++) : f.warn(` Missing translation for key: ${e}`);
97
+ }, u++) : S.warn(` Missing translation for key: ${e}`);
98
98
  }
99
99
  return {
100
100
  catalog: c,
@@ -103,7 +103,7 @@ async function N(e) {
103
103
  }
104
104
  //#endregion
105
105
  //#region src/migrate.ts
106
- var P = C(S), F = {
106
+ var I = T(w), L = {
107
107
  "vue-i18n": {
108
108
  name: "vue-i18n",
109
109
  framework: "Vue",
@@ -243,37 +243,37 @@ var P = C(S), F = {
243
243
  ],
244
244
  migrationGuide: "react/llms-migration.txt"
245
245
  }
246
- }, I = Object.keys(F);
247
- function L(e) {
246
+ }, R = Object.keys(L);
247
+ function z(e) {
248
248
  let t = e.toLowerCase().replace(/^@nuxtjs\//, "nuxt-").replace(/^@/, "");
249
- return I.find((e) => e === t);
249
+ return R.find((e) => e === t);
250
250
  }
251
- async function R(e) {
251
+ async function B(e) {
252
252
  let t = {
253
253
  configFiles: [],
254
254
  localeFiles: [],
255
255
  sampleSources: [],
256
256
  packageJson: void 0
257
- }, n = x("package.json");
258
- h(n) && (t.packageJson = _(n, "utf-8"));
257
+ }, n = y("package.json");
258
+ f(n) && (t.packageJson = m(n, "utf-8"));
259
259
  for (let n of e.configPatterns) {
260
- let e = x(n);
261
- h(e) && t.configFiles.push({
260
+ let e = y(n);
261
+ f(e) && t.configFiles.push({
262
262
  path: n,
263
- content: _(e, "utf-8")
263
+ content: m(e, "utf-8")
264
264
  });
265
265
  }
266
- let r = await p(e.localePatterns, { absolute: !1 });
266
+ let r = await C(e.localePatterns, { absolute: !1 });
267
267
  for (let e of r.slice(0, 10)) {
268
- let n = _(x(e), "utf-8");
268
+ let n = m(y(e), "utf-8");
269
269
  t.localeFiles.push({
270
270
  path: e,
271
271
  content: n.length > 5e3 ? n.slice(0, 5e3) + "\n... (truncated)" : n
272
272
  });
273
273
  }
274
- let i = await p(e.sourcePatterns, { absolute: !1 });
274
+ let i = await C(e.sourcePatterns, { absolute: !1 });
275
275
  for (let e of i.slice(0, 5)) {
276
- let n = _(x(e), "utf-8");
276
+ let n = m(y(e), "utf-8");
277
277
  t.sampleSources.push({
278
278
  path: e,
279
279
  content: n.length > 3e3 ? n.slice(0, 3e3) + "\n... (truncated)" : n
@@ -281,16 +281,16 @@ async function R(e) {
281
281
  }
282
282
  return t;
283
283
  }
284
- function z(e) {
284
+ function V(e) {
285
285
  let t = [
286
- x("node_modules", "@fluenti", "cli", "..", "..", e),
287
- b(__dirname, "..", "..", "..", e),
288
- b(__dirname, "..", "..", e)
286
+ y("node_modules", "@fluenti", "cli", "..", "..", e),
287
+ v(__dirname, "..", "..", "..", e),
288
+ v(__dirname, "..", "..", e)
289
289
  ];
290
- for (let e of t) if (h(e)) return _(e, "utf-8");
290
+ for (let e of t) if (f(e)) return m(e, "utf-8");
291
291
  return "";
292
292
  }
293
- function B(e, t, n) {
293
+ function H(e, t, n) {
294
294
  let r = [];
295
295
  if (r.push(`You are a migration assistant helping convert a ${e.framework} project from "${e.name}" to Fluenti (@fluenti).`, "", "Your task:", "1. Generate a `fluenti.config.ts` file based on the existing i18n configuration", "2. Convert each locale/translation file to Fluenti PO format", "3. List the code changes needed (file by file) to migrate source code from the old API to Fluenti API", ""), n && r.push("=== MIGRATION GUIDE ===", n, ""), t.packageJson && r.push("=== package.json ===", t.packageJson, ""), t.configFiles.length > 0) {
296
296
  r.push("=== EXISTING CONFIG FILES ===");
@@ -306,14 +306,14 @@ function B(e, t, n) {
306
306
  }
307
307
  return r.push("", "=== OUTPUT FORMAT ===", "Respond with the following sections, each starting with the exact header shown:", "", "### FLUENTI_CONFIG", "```ts", "// The fluenti.config.ts content", "```", "", "### LOCALE_FILES", "For each locale file, output:", "#### LOCALE: {locale_code}", "```po", "// The PO file content", "```", "", "### MIGRATION_STEPS", "A numbered checklist of specific code changes needed, with before/after examples.", "", "### INSTALL_COMMANDS", "```bash", "// The install and uninstall commands", "```"), r.join("\n");
308
308
  }
309
- async function V(e, t) {
309
+ async function U(e, t) {
310
310
  let n = 10 * 1024 * 1024;
311
311
  try {
312
312
  if (e === "claude") {
313
- let { stdout: e } = await P("claude", ["-p", t], { maxBuffer: n });
313
+ let { stdout: e } = await I("claude", ["-p", t], { maxBuffer: n });
314
314
  return e;
315
315
  } else {
316
- let { stdout: e } = await P("codex", [
316
+ let { stdout: e } = await I("codex", [
317
317
  "-p",
318
318
  t,
319
319
  "--full-auto"
@@ -324,7 +324,7 @@ async function V(e, t) {
324
324
  throw t.code === "ENOENT" ? Error(`"${e}" CLI not found. Please install it first:\n` + (e === "claude" ? " npm install -g @anthropic-ai/claude-code" : " npm install -g @openai/codex")) : t;
325
325
  }
326
326
  }
327
- function H(e) {
327
+ function W(e) {
328
328
  let t = {
329
329
  config: void 0,
330
330
  localeFiles: [],
@@ -345,58 +345,58 @@ function H(e) {
345
345
  let a = e.match(/### INSTALL_COMMANDS[\s\S]*?```(?:bash|sh)?\n([\s\S]*?)```/);
346
346
  return a && (t.installCommands = a[1].trim()), t;
347
347
  }
348
- async function U(e) {
349
- let { from: t, provider: n, write: r } = e, i = L(t);
348
+ async function G(e) {
349
+ let { from: t, provider: n, write: r } = e, i = z(t);
350
350
  if (!i) {
351
- f.error(`Unsupported library "${t}". Supported libraries:`);
352
- for (let e of I) f.log(` - ${e}`);
351
+ S.error(`Unsupported library "${t}". Supported libraries:`);
352
+ for (let e of R) S.log(` - ${e}`);
353
353
  return;
354
354
  }
355
- let a = F[i];
356
- f.info(`Migrating from ${a.name} (${a.framework}) to Fluenti`), f.info("Scanning project for existing i18n files...");
357
- let o = await R(a);
355
+ let a = L[i];
356
+ S.info(`Migrating from ${a.name} (${a.framework}) to Fluenti`), S.info("Scanning project for existing i18n files...");
357
+ let o = await B(a);
358
358
  if (o.configFiles.length === 0 && o.localeFiles.length === 0) {
359
- f.warn(`No ${a.name} configuration or locale files found.`), f.info("Make sure you are running this command from the project root directory.");
359
+ S.warn(`No ${a.name} configuration or locale files found.`), S.info("Make sure you are running this command from the project root directory.");
360
360
  return;
361
361
  }
362
- f.info(`Found: ${o.configFiles.length} config file(s), ${o.localeFiles.length} locale file(s), ${o.sampleSources.length} source file(s)`);
363
- let s = z(a.migrationGuide);
364
- f.info(`Generating migration plan with ${n}...`);
365
- let c = H(await V(n, B(a, o, s)));
366
- if (c.installCommands && (f.log(""), f.box({
362
+ S.info(`Found: ${o.configFiles.length} config file(s), ${o.localeFiles.length} locale file(s), ${o.sampleSources.length} source file(s)`);
363
+ let s = V(a.migrationGuide);
364
+ S.info(`Generating migration plan with ${n}...`);
365
+ let c = W(await U(n, H(a, o, s)));
366
+ if (c.installCommands && (S.log(""), S.box({
367
367
  title: "Install Commands",
368
368
  message: c.installCommands
369
369
  })), c.config) if (r) {
370
- let { writeFileSync: e } = await import("node:fs"), t = x("fluenti.config.ts");
371
- e(t, c.config, "utf-8"), f.success(`Written: ${t}`);
372
- } else f.log(""), f.box({
370
+ let { writeFileSync: e } = await import("node:fs"), t = y("fluenti.config.ts");
371
+ e(t, c.config, "utf-8"), S.success(`Written: ${t}`);
372
+ } else S.log(""), S.box({
373
373
  title: "fluenti.config.ts",
374
374
  message: c.config
375
375
  });
376
376
  if (c.localeFiles.length > 0) if (r) {
377
377
  let { writeFileSync: e, mkdirSync: t } = await import("node:fs"), n = "./locales";
378
- t(x(n), { recursive: !0 });
378
+ t(y(n), { recursive: !0 });
379
379
  for (let t of c.localeFiles) {
380
- let r = x(n, `${t.locale}.po`);
381
- e(r, t.content, "utf-8"), f.success(`Written: ${r}`);
380
+ let r = y(n, `${t.locale}.po`);
381
+ e(r, t.content, "utf-8"), S.success(`Written: ${r}`);
382
382
  }
383
- } else for (let e of c.localeFiles) f.log(""), f.box({
383
+ } else for (let e of c.localeFiles) S.log(""), S.box({
384
384
  title: `locales/${e.locale}.po`,
385
385
  message: e.content.length > 500 ? e.content.slice(0, 500) + "\n... (use --write to save full file)" : e.content
386
386
  });
387
- c.steps && (f.log(""), f.box({
387
+ c.steps && (S.log(""), S.box({
388
388
  title: "Migration Steps",
389
389
  message: c.steps
390
- })), !r && (c.config || c.localeFiles.length > 0) && (f.log(""), f.info("Run with --write to save generated files to disk:"), f.log(` fluenti migrate --from ${t} --write`));
390
+ })), !r && (c.config || c.localeFiles.length > 0) && (S.log(""), S.info("Run with --write to save generated files to disk:"), S.log(` fluenti migrate --from ${t} --write`));
391
391
  }
392
392
  //#endregion
393
393
  //#region src/init.ts
394
- var W = /^[a-zA-Z]{2,3}(-[a-zA-Z0-9]{1,8})*$/;
395
- function G(e) {
396
- if (!W.test(e)) throw Error(`Invalid locale format: "${e}"`);
394
+ var K = /^[a-zA-Z]{2,3}(-[a-zA-Z0-9]{1,8})*$/;
395
+ function q(e) {
396
+ if (!K.test(e)) throw Error(`Invalid locale format: "${e}"`);
397
397
  return e;
398
398
  }
399
- var K = [
399
+ var J = [
400
400
  {
401
401
  dep: "next",
402
402
  name: "nextjs",
@@ -410,26 +410,26 @@ var K = [
410
410
  {
411
411
  dep: "@solidjs/start",
412
412
  name: "solidstart",
413
- pluginPackage: "@fluenti/vite-plugin"
413
+ pluginPackage: "@fluenti/solid"
414
414
  },
415
415
  {
416
416
  dep: "vue",
417
417
  name: "vue",
418
- pluginPackage: "@fluenti/vite-plugin"
418
+ pluginPackage: "@fluenti/vue"
419
419
  },
420
420
  {
421
421
  dep: "solid-js",
422
422
  name: "solid",
423
- pluginPackage: "@fluenti/vite-plugin"
423
+ pluginPackage: "@fluenti/solid"
424
424
  },
425
425
  {
426
426
  dep: "react",
427
427
  name: "react",
428
- pluginPackage: "@fluenti/vite-plugin"
428
+ pluginPackage: "@fluenti/react"
429
429
  }
430
430
  ];
431
- function q(e) {
432
- for (let t of K) if (t.dep in e) return {
431
+ function Y(e) {
432
+ for (let t of J) if (t.dep in e) return {
433
433
  name: t.name,
434
434
  pluginPackage: t.pluginPackage
435
435
  };
@@ -438,7 +438,7 @@ function q(e) {
438
438
  pluginPackage: null
439
439
  };
440
440
  }
441
- function J(e) {
441
+ function X(e) {
442
442
  let t = e.locales.map((e) => `'${e}'`).join(", ");
443
443
  return `import { defineConfig } from '@fluenti/cli'
444
444
 
@@ -452,66 +452,66 @@ export default defineConfig({
452
452
  })
453
453
  `;
454
454
  }
455
- async function Y(e) {
456
- let t = x(e.cwd, "package.json");
457
- if (!h(t)) {
458
- f.error("No package.json found in current directory.");
455
+ async function Z(e) {
456
+ let t = y(e.cwd, "package.json");
457
+ if (!f(t)) {
458
+ S.error("No package.json found in current directory.");
459
459
  return;
460
460
  }
461
- let n = JSON.parse(_(t, "utf-8")), r = q({
461
+ let n = JSON.parse(m(t, "utf-8")), r = Y({
462
462
  ...n.dependencies,
463
463
  ...n.devDependencies
464
464
  });
465
- f.info(`Detected framework: ${r.name}`), r.pluginPackage && f.info(`Recommended plugin: ${r.pluginPackage}`);
466
- let i = x(e.cwd, "fluenti.config.ts");
467
- if (h(i)) {
468
- f.warn("fluenti.config.ts already exists. Skipping config generation.");
465
+ S.info(`Detected framework: ${r.name}`), r.pluginPackage && S.info(`Recommended plugin: ${r.pluginPackage}`);
466
+ let i = y(e.cwd, "fluenti.config.ts");
467
+ if (f(i)) {
468
+ S.warn("fluenti.config.ts already exists. Skipping config generation.");
469
469
  return;
470
470
  }
471
- let a = await f.prompt("Source locale?", {
471
+ let a = await S.prompt("Source locale?", {
472
472
  type: "text",
473
473
  default: "en",
474
474
  placeholder: "en"
475
475
  });
476
476
  if (typeof a == "symbol") return;
477
- let o = await f.prompt("Target locales (comma-separated)?", {
477
+ let o = await S.prompt("Target locales (comma-separated)?", {
478
478
  type: "text",
479
479
  default: "ja,zh-CN",
480
480
  placeholder: "ja,zh-CN"
481
481
  });
482
482
  if (typeof o == "symbol") return;
483
- let s = await f.prompt("Catalog format?", {
483
+ let s = await S.prompt("Catalog format?", {
484
484
  type: "select",
485
485
  options: ["po", "json"],
486
486
  initial: "po"
487
487
  });
488
488
  if (typeof s == "symbol") return;
489
489
  let c = o.split(",").map((e) => e.trim()).filter(Boolean);
490
- G(a);
491
- for (let e of c) G(e);
492
- v(i, J({
490
+ q(a);
491
+ for (let e of c) q(e);
492
+ h(i, X({
493
493
  sourceLocale: a,
494
494
  locales: [a, ...c.filter((e) => e !== a)],
495
495
  format: s
496
- }), "utf-8"), f.success("Created fluenti.config.ts");
497
- let l = x(e.cwd, ".gitignore"), u = "src/locales/compiled/";
498
- h(l) ? _(l, "utf-8").includes(u) || (m(l, `\n# Fluenti compiled catalogs\n${u}\n`), f.success("Updated .gitignore")) : (v(l, `# Fluenti compiled catalogs\n${u}\n`), f.success("Created .gitignore"));
499
- let d = n.scripts ?? {}, p = {}, g = !1;
500
- if (d["i18n:extract"] || (p["i18n:extract"] = "fluenti extract", g = !0), d["i18n:compile"] || (p["i18n:compile"] = "fluenti compile", g = !0), g) {
496
+ }), "utf-8"), S.success("Created fluenti.config.ts");
497
+ let l = y(e.cwd, ".gitignore"), u = "src/locales/compiled/";
498
+ f(l) ? m(l, "utf-8").includes(u) || (d(l, `\n# Fluenti compiled catalogs\n${u}\n`), S.success("Updated .gitignore")) : (h(l, `# Fluenti compiled catalogs\n${u}\n`), S.success("Created .gitignore"));
499
+ let p = n.scripts ?? {}, g = {}, _ = !1;
500
+ if (p["i18n:extract"] || (g["i18n:extract"] = "fluenti extract", _ = !0), p["i18n:compile"] || (g["i18n:compile"] = "fluenti compile", _ = !0), _) {
501
501
  let e = {
502
502
  ...n,
503
503
  scripts: {
504
- ...d,
505
- ...p
504
+ ...p,
505
+ ...g
506
506
  }
507
507
  };
508
- v(t, JSON.stringify(e, null, 2) + "\n", "utf-8"), f.success("Added i18n:extract and i18n:compile scripts to package.json");
508
+ h(t, JSON.stringify(e, null, 2) + "\n", "utf-8"), S.success("Added i18n:extract and i18n:compile scripts to package.json");
509
509
  }
510
- f.log(""), f.box({
510
+ S.log(""), S.box({
511
511
  title: "Next steps",
512
512
  message: [
513
513
  r.pluginPackage ? `1. Install: pnpm add -D ${r.pluginPackage} @fluenti/cli` : "1. Install: pnpm add -D @fluenti/cli",
514
- r.name === "nextjs" ? "2. Add withFluenti() to your next.config.ts" : r.name === "unknown" ? "2. Configure your build tool to use @fluenti/vite-plugin or @fluenti/next" : "2. Add fluentiPlugin() to your vite.config.ts",
514
+ r.name === "nextjs" ? "2. Add withFluenti() to your next.config.ts" : r.name === "unknown" ? "2. Configure your build tool with the framework Vite plugin or @fluenti/next" : "2. Add the Vite plugin to your vite.config.ts (e.g. fluentiVue() from @fluenti/vue/vite-plugin)",
515
515
  "3. Run: npx fluenti extract",
516
516
  "4. Translate your messages",
517
517
  "5. Run: npx fluenti compile"
@@ -520,47 +520,24 @@ async function Y(e) {
520
520
  }
521
521
  //#endregion
522
522
  //#region src/cli.ts
523
- var X = {
524
- sourceLocale: "en",
525
- locales: ["en"],
526
- catalogDir: "./locales",
527
- format: "po",
528
- include: ["./src/**/*.{vue,tsx,jsx,ts,js}"],
529
- compileOutDir: "./src/locales/compiled"
530
- };
531
- async function Z(e) {
532
- let t = e ? [x(e)] : [
533
- x("fluenti.config.ts"),
534
- x("fluenti.config.js"),
535
- x("fluenti.config.mjs")
536
- ];
537
- for (let e of t) if (h(e)) try {
538
- let { createJiti: t } = await import("jiti"), n = await t(import.meta.url).import(e), r = n.default ?? n;
539
- return {
540
- ...X,
541
- ...r
542
- };
543
- } catch {
544
- f.warn(`Failed to load config from ${e}, using defaults`);
545
- }
546
- return X;
547
- }
548
- function Q(e, n) {
549
- if (!h(e)) return {};
550
- let r = _(e, "utf-8");
551
- return n === "json" ? c(r) : t(r);
523
+ function Q(e, t) {
524
+ if (!f(e)) return {};
525
+ let r = m(e, "utf-8");
526
+ return t === "json" ? n(r) : o(r);
552
527
  }
553
- function $(e, t, r) {
554
- g(ee(e), { recursive: !0 }), v(e, r === "json" ? n(t) : o(t), "utf-8");
528
+ function $(e, t, n) {
529
+ p(g(e), { recursive: !0 }), h(e, n === "json" ? i(t) : c(t), "utf-8");
555
530
  }
556
- async function re(t, n) {
557
- if (y(t) === ".vue") {
531
+ async function ne(t, n) {
532
+ if (_(t) === ".vue") try {
558
533
  let { extractFromVue: e } = await import("./vue-extractor-iUl6SUkv.js").then((e) => e.n);
559
534
  return e(n, t);
535
+ } catch {
536
+ return S.warn(`Skipping ${t}: install @vue/compiler-sfc to extract from .vue files`), [];
560
537
  }
561
538
  return e(n, t);
562
539
  }
563
- var ie = u({
540
+ var re = b({
564
541
  meta: {
565
542
  name: "extract",
566
543
  description: "Extract messages from source files"
@@ -582,23 +559,23 @@ var ie = u({
582
559
  }
583
560
  },
584
561
  async run({ args: e }) {
585
- let t = await Z(e.config);
586
- f.info(`Extracting messages from ${t.include.join(", ")}`);
587
- let n = await p(t.include), r = [];
562
+ let t = await l(e.config);
563
+ S.info(`Extracting messages from ${t.include.join(", ")}`);
564
+ let n = await C(t.include), r = [];
588
565
  for (let e of n) {
589
- let t = await re(e, _(e, "utf-8"));
566
+ let t = await ne(e, m(e, "utf-8"));
590
567
  r.push(...t);
591
568
  }
592
- f.info(`Found ${r.length} messages in ${n.length} files`);
593
- let a = t.format === "json" ? ".json" : ".po", o = e.clean ?? !1, s = e["no-fuzzy"] ?? !1;
569
+ S.info(`Found ${r.length} messages in ${n.length} files`);
570
+ let i = t.format === "json" ? ".json" : ".po", a = e.clean ?? !1, o = e["no-fuzzy"] ?? !1;
594
571
  for (let e of t.locales) {
595
- let n = x(t.catalogDir, `${e}${a}`), { catalog: c, result: l } = i(Q(n, t.format), r, { stripFuzzy: s });
596
- $(n, o ? Object.fromEntries(Object.entries(c).filter(([, e]) => !e.obsolete)) : c, t.format);
597
- let u = o ? `${l.obsolete} removed` : `${l.obsolete} obsolete`;
598
- f.success(`${e}: ${l.added} added, ${l.unchanged} unchanged, ${u}`);
572
+ let n = y(t.catalogDir, `${e}${i}`), { catalog: s, result: c } = u(Q(n, t.format), r, { stripFuzzy: o });
573
+ $(n, a ? Object.fromEntries(Object.entries(s).filter(([, e]) => !e.obsolete)) : s, t.format);
574
+ let l = a ? `${c.obsolete} removed` : `${c.obsolete} obsolete`;
575
+ S.success(`${e}: ${c.added} added, ${c.unchanged} unchanged, ${l}`);
599
576
  }
600
577
  }
601
- }), ae = u({
578
+ }), ie = b({
602
579
  meta: {
603
580
  name: "compile",
604
581
  description: "Compile message catalogs to JS modules"
@@ -615,26 +592,26 @@ var ie = u({
615
592
  }
616
593
  },
617
594
  async run({ args: e }) {
618
- let t = await Z(e.config), n = t.format === "json" ? ".json" : ".po";
619
- g(t.compileOutDir, { recursive: !0 });
620
- let i = {};
621
- for (let e of t.locales) i[e] = Q(x(t.catalogDir, `${e}${n}`), t.format);
622
- let o = l(i);
623
- f.info(`Compiling ${o.length} messages across ${t.locales.length} locales`);
624
- let c = e["skip-fuzzy"] ?? !1;
625
- for (let e of t.locales) {
626
- let { code: n, stats: r } = a(i[e], e, o, t.sourceLocale, { skipFuzzy: c }), s = x(t.compileOutDir, `${e}.js`);
627
- if (v(s, n, "utf-8"), r.missing.length > 0) {
628
- f.warn(`${e}: ${r.compiled} compiled, ${r.missing.length} missing translations`);
629
- for (let e of r.missing) f.warn(` ⤷ ${e}`);
630
- } else f.success(`Compiled ${e}: ${r.compiled} messages → ${s}`);
595
+ let n = await l(e.config), i = n.format === "json" ? ".json" : ".po";
596
+ p(n.compileOutDir, { recursive: !0 });
597
+ let o = {};
598
+ for (let e of n.locales) o[e] = Q(y(n.catalogDir, `${e}${i}`), n.format);
599
+ let c = a(o);
600
+ S.info(`Compiling ${c.length} messages across ${n.locales.length} locales`);
601
+ let u = e["skip-fuzzy"] ?? !1;
602
+ for (let e of n.locales) {
603
+ let { code: t, stats: r } = s(o[e], e, c, n.sourceLocale, { skipFuzzy: u }), i = y(n.compileOutDir, `${e}.js`);
604
+ if (h(i, t, "utf-8"), r.missing.length > 0) {
605
+ S.warn(`${e}: ${r.compiled} compiled, ${r.missing.length} missing translations`);
606
+ for (let e of r.missing) S.warn(` ⤷ ${e}`);
607
+ } else S.success(`Compiled ${e}: ${r.compiled} messages → ${i}`);
631
608
  }
632
- let u = s(t.locales, t.compileOutDir), d = x(t.compileOutDir, "index.js");
633
- v(d, u, "utf-8"), f.success(`Generated index → ${d}`);
634
- let p = r(o, i, t.sourceLocale), m = x(t.compileOutDir, "messages.d.ts");
635
- v(m, p, "utf-8"), f.success(`Generated types → ${m}`);
609
+ let d = r(n.locales, n.compileOutDir), f = y(n.compileOutDir, "index.js");
610
+ h(f, d, "utf-8"), S.success(`Generated index → ${f}`);
611
+ let m = t(c, o, n.sourceLocale), g = y(n.compileOutDir, "messages.d.ts");
612
+ h(g, m, "utf-8"), S.success(`Generated types → ${g}`);
636
613
  }
637
- }), oe = u({
614
+ }), ae = b({
638
615
  meta: {
639
616
  name: "stats",
640
617
  description: "Show translation progress"
@@ -644,9 +621,9 @@ var ie = u({
644
621
  description: "Path to config file"
645
622
  } },
646
623
  async run({ args: e }) {
647
- let t = await Z(e.config), n = t.format === "json" ? ".json" : ".po", r = [];
624
+ let t = await l(e.config), n = t.format === "json" ? ".json" : ".po", r = [];
648
625
  for (let e of t.locales) {
649
- let i = Q(x(t.catalogDir, `${e}${n}`), t.format), a = Object.values(i).filter((e) => !e.obsolete), o = a.length, s = a.filter((e) => e.translation && e.translation.length > 0).length, c = o > 0 ? (s / o * 100).toFixed(1) + "%" : "—";
626
+ let i = Q(y(t.catalogDir, `${e}${n}`), t.format), a = Object.values(i).filter((e) => !e.obsolete), o = a.length, s = a.filter((e) => e.translation && e.translation.length > 0).length, c = o > 0 ? (s / o * 100).toFixed(1) + "%" : "—";
650
627
  r.push({
651
628
  locale: e,
652
629
  total: o,
@@ -654,11 +631,11 @@ var ie = u({
654
631
  pct: c
655
632
  });
656
633
  }
657
- f.log(""), f.log(" Locale │ Total │ Translated │ Progress"), f.log(" ────────┼───────┼────────────┼─────────────────────────────");
658
- for (let e of r) f.log(O(e.locale, e.total, e.translated));
659
- f.log("");
634
+ S.log(""), S.log(" Locale │ Total │ Translated │ Progress"), S.log(" ────────┼───────┼────────────┼─────────────────────────────");
635
+ for (let e of r) S.log(te(e.locale, e.total, e.translated));
636
+ S.log("");
660
637
  }
661
- }), se = u({
638
+ }), oe = b({
662
639
  meta: {
663
640
  name: "translate",
664
641
  description: "Translate messages using AI (Claude Code or Codex CLI)"
@@ -684,36 +661,36 @@ var ie = u({
684
661
  }
685
662
  },
686
663
  async run({ args: e }) {
687
- let t = await Z(e.config), n = e.provider;
664
+ let t = await l(e.config), n = e.provider;
688
665
  if (n !== "claude" && n !== "codex") {
689
- f.error(`Invalid provider "${n}". Use "claude" or "codex".`);
666
+ S.error(`Invalid provider "${n}". Use "claude" or "codex".`);
690
667
  return;
691
668
  }
692
669
  let r = parseInt(e["batch-size"] ?? "50", 10);
693
670
  if (isNaN(r) || r < 1) {
694
- f.error("Invalid batch-size. Must be a positive integer.");
671
+ S.error("Invalid batch-size. Must be a positive integer.");
695
672
  return;
696
673
  }
697
674
  let i = e.locale ? [e.locale] : t.locales.filter((e) => e !== t.sourceLocale);
698
675
  if (i.length === 0) {
699
- f.warn("No target locales to translate.");
676
+ S.warn("No target locales to translate.");
700
677
  return;
701
678
  }
702
- f.info(`Translating with ${n} (batch size: ${r})`);
679
+ S.info(`Translating with ${n} (batch size: ${r})`);
703
680
  let a = t.format === "json" ? ".json" : ".po";
704
681
  for (let e of i) {
705
- f.info(`\n[${e}]`);
706
- let i = x(t.catalogDir, `${e}${a}`), o = Q(i, t.format), { catalog: s, translated: c } = await N({
682
+ S.info(`\n[${e}]`);
683
+ let i = y(t.catalogDir, `${e}${a}`), o = Q(i, t.format), { catalog: s, translated: c } = await F({
707
684
  provider: n,
708
685
  sourceLocale: t.sourceLocale,
709
686
  targetLocale: e,
710
687
  catalog: o,
711
688
  batchSize: r
712
689
  });
713
- c > 0 ? ($(i, s, t.format), f.success(` ${e}: ${c} messages translated`)) : f.success(` ${e}: already fully translated`);
690
+ c > 0 ? ($(i, s, t.format), S.success(` ${e}: ${c} messages translated`)) : S.success(` ${e}: already fully translated`);
714
691
  }
715
692
  }
716
- }), ce = u({
693
+ }), se = b({
717
694
  meta: {
718
695
  name: "migrate",
719
696
  description: "Migrate from another i18n library using AI"
@@ -738,38 +715,38 @@ var ie = u({
738
715
  async run({ args: e }) {
739
716
  let t = e.provider;
740
717
  if (t !== "claude" && t !== "codex") {
741
- f.error(`Invalid provider "${t}". Use "claude" or "codex".`);
718
+ S.error(`Invalid provider "${t}". Use "claude" or "codex".`);
742
719
  return;
743
720
  }
744
- await U({
721
+ await G({
745
722
  from: e.from,
746
723
  provider: t,
747
724
  write: e.write ?? !1
748
725
  });
749
726
  }
750
727
  });
751
- d(u({
728
+ x(b({
752
729
  meta: {
753
730
  name: "fluenti",
754
731
  version: "0.0.1",
755
732
  description: "Compile-time i18n for modern frameworks"
756
733
  },
757
734
  subCommands: {
758
- init: u({
735
+ init: b({
759
736
  meta: {
760
737
  name: "init",
761
738
  description: "Initialize Fluenti in your project"
762
739
  },
763
740
  args: {},
764
741
  async run() {
765
- await Y({ cwd: process.cwd() });
742
+ await Z({ cwd: process.cwd() });
766
743
  }
767
744
  }),
768
- extract: ie,
769
- compile: ae,
770
- stats: oe,
771
- translate: se,
772
- migrate: ce
745
+ extract: re,
746
+ compile: ie,
747
+ stats: ae,
748
+ translate: oe,
749
+ migrate: se
773
750
  }
774
751
  }));
775
752
  //#endregion