@fluenti/cli 0.3.3 → 0.3.4

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.
Files changed (51) hide show
  1. package/dist/cli.cjs +9 -9
  2. package/dist/cli.cjs.map +1 -1
  3. package/dist/cli.js +290 -251
  4. package/dist/cli.js.map +1 -1
  5. package/dist/compile-CX1b_JVQ.cjs +8 -0
  6. package/dist/compile-CX1b_JVQ.cjs.map +1 -0
  7. package/dist/{compile-B4y2UPsX.js → compile-CXReVuTG.js} +35 -32
  8. package/dist/compile-CXReVuTG.js.map +1 -0
  9. package/dist/compile-cache.d.ts.map +1 -1
  10. package/dist/compile-worker.cjs +1 -1
  11. package/dist/compile-worker.cjs.map +1 -1
  12. package/dist/compile-worker.d.ts +1 -0
  13. package/dist/compile-worker.d.ts.map +1 -1
  14. package/dist/compile-worker.js +19 -7
  15. package/dist/compile-worker.js.map +1 -1
  16. package/dist/compile.d.ts.map +1 -1
  17. package/dist/{extract-cache-DYoHe5P-.js → extract-cache-BTxWgic2.js} +57 -44
  18. package/dist/extract-cache-BTxWgic2.js.map +1 -0
  19. package/dist/{extract-cache-idNfsd7n.cjs → extract-cache-CGSKwh76.cjs} +5 -5
  20. package/dist/extract-cache-CGSKwh76.cjs.map +1 -0
  21. package/dist/extract-cache.d.ts.map +1 -1
  22. package/dist/extract-runner.d.ts.map +1 -1
  23. package/dist/index.cjs +1 -1
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.js +10 -4
  26. package/dist/index.js.map +1 -1
  27. package/dist/lint.d.ts.map +1 -1
  28. package/dist/parallel-compile.d.ts.map +1 -1
  29. package/dist/po-format.d.ts.map +1 -1
  30. package/dist/translate.d.ts +2 -1
  31. package/dist/translate.d.ts.map +1 -1
  32. package/dist/{tsx-extractor-C-9_TnCW.cjs → tsx-extractor-BOD7JJQK.cjs} +2 -2
  33. package/dist/tsx-extractor-BOD7JJQK.cjs.map +1 -0
  34. package/dist/{tsx-extractor-CjQIMvKo.js → tsx-extractor-C-HZNobu.js} +2 -2
  35. package/dist/tsx-extractor-C-HZNobu.js.map +1 -0
  36. package/dist/tsx-extractor.d.ts.map +1 -1
  37. package/dist/validation.d.ts +4 -1
  38. package/dist/validation.d.ts.map +1 -1
  39. package/dist/vue-extractor.cjs +2 -2
  40. package/dist/vue-extractor.cjs.map +1 -1
  41. package/dist/vue-extractor.d.ts.map +1 -1
  42. package/dist/vue-extractor.js +3 -3
  43. package/dist/vue-extractor.js.map +1 -1
  44. package/package.json +2 -2
  45. package/dist/compile-B4y2UPsX.js.map +0 -1
  46. package/dist/compile-Brygn0bn.cjs +0 -8
  47. package/dist/compile-Brygn0bn.cjs.map +0 -1
  48. package/dist/extract-cache-DYoHe5P-.js.map +0 -1
  49. package/dist/extract-cache-idNfsd7n.cjs.map +0 -1
  50. package/dist/tsx-extractor-C-9_TnCW.cjs.map +0 -1
  51. package/dist/tsx-extractor-CjQIMvKo.js.map +0 -1
package/dist/cli.js CHANGED
@@ -1,34 +1,65 @@
1
1
  #!/usr/bin/env node
2
- import { i as e, n as t, r as n, t as r } from "./compile-B4y2UPsX.js";
3
- import { t as i } from "./tsx-extractor-CjQIMvKo.js";
4
- import { a, c as o, i as s, n as c, o as l, r as u, s as d, t as f } from "./extract-cache-DYoHe5P-.js";
5
- import { resolveLocaleCodes as p } from "@fluenti/core/internal";
6
- import { appendFileSync as m, existsSync as h, mkdirSync as g, readFileSync as _, writeFileSync as v } from "node:fs";
7
- import { dirname as y, extname as b, join as x, resolve as S } from "node:path";
8
- import { fileURLToPath as C } from "node:url";
9
- import w from "fast-glob";
10
- import { createHash as T } from "node:crypto";
11
- import { defineCommand as E, runMain as D } from "citty";
12
- import O from "consola";
13
- import { execFile as k } from "node:child_process";
14
- import { promisify as A } from "node:util";
2
+ import { i as e, n as t, r as n, t as r } from "./compile-CXReVuTG.js";
3
+ import { t as i } from "./tsx-extractor-C-HZNobu.js";
4
+ import { a, c as o, i as s, n as c, o as l, r as u, s as d, t as f } from "./extract-cache-BTxWgic2.js";
5
+ import { parse as p, resolveLocaleCodes as m } from "@fluenti/core/internal";
6
+ import { appendFileSync as h, existsSync as g, mkdirSync as _, readFileSync as v, writeFileSync as y } from "node:fs";
7
+ import { dirname as b, extname as x, join as S, resolve as C } from "node:path";
8
+ import { fileURLToPath as w } from "node:url";
9
+ import T from "fast-glob";
10
+ import { createHash as E } from "node:crypto";
11
+ import { defineCommand as D, runMain as O } from "citty";
12
+ import k from "consola";
13
+ import { execFile as A } from "node:child_process";
14
+ import { promisify as j } from "node:util";
15
+ import { setTimeout as ee } from "node:timers/promises";
15
16
  //#region src/stats-format.ts
16
- var ee = "█", te = "░";
17
- function ne(e, t = 20) {
17
+ var te = "█", ne = "░";
18
+ function re(e, t = 20) {
18
19
  let n = Math.round(Math.max(0, Math.min(100, e)) / 100 * t);
19
- return ee.repeat(n) + te.repeat(t - n);
20
+ return te.repeat(n) + ne.repeat(t - n);
20
21
  }
21
- function re(e) {
22
+ function M(e) {
22
23
  let t = e.toFixed(1) + "%";
23
24
  return e >= 90 ? `\x1b[32m${t}\x1b[0m` : e >= 70 ? `\x1b[33m${t}\x1b[0m` : `\x1b[31m${t}\x1b[0m`;
24
25
  }
25
26
  function ie(e, t, n) {
26
- let r = t > 0 ? n / t * 100 : 0, i = t > 0 ? re(r) : "—", a = t > 0 ? ne(r) : "";
27
+ let r = t > 0 ? n / t * 100 : 0, i = t > 0 ? M(r) : "—", a = t > 0 ? re(r) : "";
27
28
  return ` ${e.padEnd(8)}│ ${String(t).padStart(5)} │ ${String(n).padStart(10)} │ ${a} ${i}`;
28
29
  }
29
30
  //#endregion
31
+ //#region src/validation.ts
32
+ function N(e) {
33
+ try {
34
+ let t = p(e), n = /* @__PURE__ */ new Set();
35
+ return P(t, n), [...n].sort();
36
+ } catch {
37
+ let t = /* @__PURE__ */ new Set(), n = 0, r = 0;
38
+ for (; r < e.length;) {
39
+ if (e[r] === "{") {
40
+ if (n++, n === 1) {
41
+ let n = e.indexOf("}", r + 1);
42
+ if (n !== -1) {
43
+ let i = e.slice(r + 1, n).trim(), a = /^(\w+)/.exec(i);
44
+ a && t.add(a[1]);
45
+ }
46
+ }
47
+ } else e[r] === "}" && n--;
48
+ r++;
49
+ }
50
+ return [...t].sort();
51
+ }
52
+ }
53
+ function P(e, t) {
54
+ for (let n of e) if (n.type === "variable" && n.name !== "#") t.add(n.name);
55
+ else if (n.type === "plural" || n.type === "select") {
56
+ t.add(n.variable);
57
+ for (let e of Object.values(n.options)) P(e, t);
58
+ } else n.type === "function" && t.add(n.variable);
59
+ }
60
+ //#endregion
30
61
  //#region src/lint.ts
31
- function j(e, t) {
62
+ function F(e, t) {
32
63
  let n = [], { sourceLocale: r } = t, i = t.locales ?? Object.keys(e), a = e[r];
33
64
  if (!a) return n.push({
34
65
  rule: "missing-source",
@@ -60,7 +91,7 @@ function j(e, t) {
60
91
  });
61
92
  continue;
62
93
  }
63
- let s = M(r.message ?? e), c = M(o.translation), l = s.filter((e) => !c.includes(e)), u = c.filter((e) => !s.includes(e));
94
+ let s = N(r.message ?? e), c = N(o.translation), l = s.filter((e) => !c.includes(e)), u = c.filter((e) => !s.includes(e));
64
95
  l.length > 0 && n.push({
65
96
  rule: "inconsistent-placeholders",
66
97
  severity: "error",
@@ -103,17 +134,9 @@ function j(e, t) {
103
134
  });
104
135
  return n;
105
136
  }
106
- function M(e) {
107
- let t = [], n = /\{(\w+)(?:\s*,\s*(?:plural|select|selectordinal|number|date|time))?/g, r;
108
- for (; (r = n.exec(e)) !== null;) {
109
- let e = r[1];
110
- t.includes(e) || t.push(e);
111
- }
112
- return t.sort();
113
- }
114
137
  function ae(e) {
115
138
  if (e.length === 0) return " ✓ All checks passed";
116
- let t = [], n = N(e, (e) => e.rule);
139
+ let t = [], n = oe(e, (e) => e.rule);
117
140
  for (let [e, r] of Object.entries(n)) {
118
141
  t.push(` ${e} (${r.length}):`);
119
142
  for (let e of r) {
@@ -124,7 +147,7 @@ function ae(e) {
124
147
  let r = e.filter((e) => e.severity === "error").length, i = e.filter((e) => e.severity === "warning").length, a = e.filter((e) => e.severity === "info").length;
125
148
  return t.push(""), t.push(` Summary: ${r} errors, ${i} warnings, ${a} info`), t.join("\n");
126
149
  }
127
- function N(e, t) {
150
+ function oe(e, t) {
128
151
  let n = {};
129
152
  for (let r of e) {
130
153
  let e = t(r);
@@ -134,7 +157,7 @@ function N(e, t) {
134
157
  }
135
158
  //#endregion
136
159
  //#region src/check.ts
137
- function P(e, t) {
160
+ function se(e, t) {
138
161
  let { sourceLocale: n, minCoverage: r, locale: i } = t, a = e[n];
139
162
  if (!a) return {
140
163
  results: [],
@@ -182,10 +205,10 @@ function P(e, t) {
182
205
  passed: p,
183
206
  minCoverage: r,
184
207
  actualCoverage: f,
185
- diagnostics: j(e, m)
208
+ diagnostics: F(e, m)
186
209
  };
187
210
  }
188
- function oe(e) {
211
+ function ce(e) {
189
212
  let t = [];
190
213
  for (let n of e.results) {
191
214
  let r = n.coverage >= e.minCoverage ? "✓" : "✗", i = n.coverage.toFixed(1), a = n.missing > 0 ? ` — ${n.missing} missing` : "", o = n.fuzzy > 0 ? `, ${n.fuzzy} fuzzy` : "";
@@ -195,7 +218,7 @@ function oe(e) {
195
218
  let n = e.actualCoverage.toFixed(1), r = e.passed ? "PASSED" : "FAILED";
196
219
  return t.push(`Coverage: ${n}% (min: ${e.minCoverage}%) — ${r}`), t.join("\n");
197
220
  }
198
- function se(e, t, n) {
221
+ function le(e, t, n) {
199
222
  let r = [], i = n === "json" ? ".json" : ".po";
200
223
  for (let n of e.results) if (n.coverage < e.minCoverage) {
201
224
  let a = `${t}/${n.locale}${i}`;
@@ -208,7 +231,7 @@ function se(e, t, n) {
208
231
  }
209
232
  return r.join("\n");
210
233
  }
211
- function ce(e) {
234
+ function ue(e) {
212
235
  return JSON.stringify({
213
236
  results: e.results,
214
237
  passed: e.passed,
@@ -218,45 +241,76 @@ function ce(e) {
218
241
  }
219
242
  //#endregion
220
243
  //#region src/compile-cache.ts
221
- var F = "1", le = class {
244
+ var I = "1", L = class {
222
245
  data;
223
246
  cachePath;
224
247
  dirty = !1;
225
248
  constructor(e, t) {
226
- this.cachePath = S(t ? S(e, ".cache", t) : S(e, ".cache"), "compile-cache.json"), this.data = this.load();
249
+ this.cachePath = C(t ? C(e, ".cache", t) : C(e, ".cache"), "compile-cache.json"), this.data = this.load();
227
250
  }
228
251
  isUpToDate(e, t) {
229
252
  let n = this.data.entries[e];
230
253
  if (!n) return !1;
231
- let r = I(t);
254
+ let r = R(t);
232
255
  return n.inputHash === r;
233
256
  }
234
257
  set(e, t) {
235
- this.data.entries[e] = { inputHash: I(t) }, this.dirty = !0;
258
+ this.data.entries[e] = { inputHash: R(t) }, this.dirty = !0;
236
259
  }
237
260
  save() {
238
- this.dirty &&= (g(y(this.cachePath), { recursive: !0 }), v(this.cachePath, JSON.stringify(this.data), "utf-8"), !1);
261
+ if (this.dirty) try {
262
+ _(b(this.cachePath), { recursive: !0 }), y(this.cachePath, JSON.stringify(this.data), "utf-8"), this.dirty = !1;
263
+ } catch {}
239
264
  }
240
265
  load() {
241
266
  try {
242
- if (h(this.cachePath)) {
243
- let e = _(this.cachePath, "utf-8"), t = JSON.parse(e);
244
- if (t.version === F) return t;
267
+ if (g(this.cachePath)) {
268
+ let e = v(this.cachePath, "utf-8"), t = JSON.parse(e);
269
+ if (t.version === I) return t;
245
270
  }
246
271
  } catch {}
247
272
  return {
248
- version: F,
273
+ version: I,
249
274
  entries: {}
250
275
  };
251
276
  }
252
277
  };
253
- function I(e) {
254
- return T("md5").update(e).digest("hex");
278
+ function R(e) {
279
+ return E("md5").update(e).digest("hex");
280
+ }
281
+ //#endregion
282
+ //#region src/ai-provider.ts
283
+ var z = j(A), B = {
284
+ claude: "npm install -g @anthropic-ai/claude-code",
285
+ codex: "npm install -g @openai/codex"
286
+ };
287
+ function V(e, t) {
288
+ return e === "claude" ? ["-p", t] : [
289
+ "-p",
290
+ t,
291
+ "--full-auto"
292
+ ];
293
+ }
294
+ function H(e) {
295
+ return e.code === "ENOENT";
296
+ }
297
+ async function U(e) {
298
+ let { provider: t, prompt: n, maxRetries: r = 3, initialDelayMs: i = 1e3, maxBuffer: a = 10 * 1024 * 1024 } = e, o = V(t, n), s = t === "claude" ? "claude" : "codex", c;
299
+ for (let e = 0; e <= r; e++) try {
300
+ let { stdout: t } = await z(s, [...o], { maxBuffer: a });
301
+ return {
302
+ stdout: t,
303
+ attempts: e + 1
304
+ };
305
+ } catch (n) {
306
+ if (H(n)) throw Error(`"${t}" CLI not found. Please install it first:\n ${B[t]}`);
307
+ c = n, e < r && await ee(i * 2 ** e);
308
+ }
309
+ throw c;
255
310
  }
256
311
  //#endregion
257
312
  //#region src/translate.ts
258
- var L = A(k);
259
- function R(e, t, n, r) {
313
+ function de(e, t, n, r) {
260
314
  let i = JSON.stringify(n, null, 2);
261
315
  return [
262
316
  `You are a professional translator. Translate the following messages from "${e}" to "${t}".`,
@@ -272,25 +326,7 @@ function R(e, t, n, r) {
272
326
  "- Do not add any explanation or markdown formatting, output raw JSON only."
273
327
  ].join("\n");
274
328
  }
275
- async function z(e, t) {
276
- let n = 10 * 1024 * 1024;
277
- try {
278
- if (e === "claude") {
279
- let { stdout: e } = await L("claude", ["-p", t], { maxBuffer: n });
280
- return e;
281
- } else {
282
- let { stdout: e } = await L("codex", [
283
- "-p",
284
- t,
285
- "--full-auto"
286
- ], { maxBuffer: n });
287
- return e;
288
- }
289
- } catch (t) {
290
- 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;
291
- }
292
- }
293
- function B(e) {
329
+ function fe(e) {
294
330
  let t = e.match(/\{[\s\S]*\}/);
295
331
  if (!t) throw Error("No JSON object found in AI response");
296
332
  let n;
@@ -302,12 +338,12 @@ function B(e) {
302
338
  if (typeof n != "object" || !n || Array.isArray(n)) throw Error("AI response is not a valid JSON object");
303
339
  return n;
304
340
  }
305
- function V(e) {
341
+ function pe(e) {
306
342
  let t = {};
307
343
  for (let [n, r] of Object.entries(e)) r.obsolete || (!r.translation || r.translation.length === 0) && (t[n] = r.message ?? n);
308
344
  return t;
309
345
  }
310
- function H(e, t) {
346
+ function me(e, t) {
311
347
  let n = Object.keys(e), r = [];
312
348
  for (let i = 0; i < n.length; i += t) {
313
349
  let a = {};
@@ -316,22 +352,25 @@ function H(e, t) {
316
352
  }
317
353
  return r;
318
354
  }
319
- async function U(e) {
320
- let { provider: t, sourceLocale: n, targetLocale: r, catalog: i, batchSize: a, context: o } = e, s = V(i), c = Object.keys(s).length;
355
+ async function he(e) {
356
+ let { provider: t, sourceLocale: n, targetLocale: r, catalog: i, batchSize: a, context: o } = e, s = pe(i), c = Object.keys(s).length;
321
357
  if (c === 0) return {
322
358
  catalog: { ...i },
323
359
  translated: 0
324
360
  };
325
- O.info(` ${c} untranslated messages, translating with ${t}...`);
326
- let l = { ...i }, u = H(s, a), d = 0;
361
+ k.info(` ${c} untranslated messages, translating with ${t}...`);
362
+ let l = { ...i }, u = me(s, a), d = 0;
327
363
  for (let e = 0; e < u.length; e++) {
328
364
  let i = u[e], a = Object.keys(i);
329
- u.length > 1 && O.info(` Batch ${e + 1}/${u.length} (${a.length} messages)`);
330
- let s = B(await z(t, R(n, r, i, o)));
331
- for (let e of a) s[e] && typeof s[e] == "string" ? (l[e] = {
365
+ u.length > 1 && k.info(` Batch ${e + 1}/${u.length} (${a.length} messages)`);
366
+ let { stdout: s } = await U({
367
+ provider: t,
368
+ prompt: de(n, r, i, o)
369
+ }), c = fe(s);
370
+ for (let e of a) c[e] && typeof c[e] == "string" ? (l[e] = {
332
371
  ...l[e],
333
- translation: s[e]
334
- }, d++) : O.warn(` Missing translation for key: ${e}`);
372
+ translation: c[e]
373
+ }, d++) : k.warn(` Missing translation for key: ${e}`);
335
374
  }
336
375
  return {
337
376
  catalog: l,
@@ -340,7 +379,7 @@ async function U(e) {
340
379
  }
341
380
  //#endregion
342
381
  //#region src/migrate.ts
343
- var W = A(k), G = {
382
+ var W = j(A), G = {
344
383
  "vue-i18n": {
345
384
  name: "vue-i18n",
346
385
  framework: "Vue",
@@ -481,36 +520,36 @@ var W = A(k), G = {
481
520
  migrationGuide: "react/llms-migration.txt"
482
521
  }
483
522
  }, K = Object.keys(G);
484
- function q(e) {
523
+ function ge(e) {
485
524
  let t = e.toLowerCase().replace(/^@nuxtjs\//, "nuxt-").replace(/^@/, "");
486
525
  return K.find((e) => e === t);
487
526
  }
488
- async function ue(e) {
527
+ async function _e(e) {
489
528
  let t = {
490
529
  configFiles: [],
491
530
  localeFiles: [],
492
531
  sampleSources: [],
493
532
  packageJson: void 0
494
- }, n = S("package.json");
495
- h(n) && (t.packageJson = _(n, "utf-8"));
533
+ }, n = C("package.json");
534
+ g(n) && (t.packageJson = v(n, "utf-8"));
496
535
  for (let n of e.configPatterns) {
497
- let e = S(n);
498
- h(e) && t.configFiles.push({
536
+ let e = C(n);
537
+ g(e) && t.configFiles.push({
499
538
  path: n,
500
- content: _(e, "utf-8")
539
+ content: v(e, "utf-8")
501
540
  });
502
541
  }
503
- let r = await w(e.localePatterns, { absolute: !1 });
542
+ let r = await T(e.localePatterns, { absolute: !1 });
504
543
  for (let e of r.slice(0, 10)) {
505
- let n = _(S(e), "utf-8");
544
+ let n = v(C(e), "utf-8");
506
545
  t.localeFiles.push({
507
546
  path: e,
508
547
  content: n.length > 5e3 ? n.slice(0, 5e3) + "\n... (truncated)" : n
509
548
  });
510
549
  }
511
- let i = await w(e.sourcePatterns, { absolute: !1 });
550
+ let i = await T(e.sourcePatterns, { absolute: !1 });
512
551
  for (let e of i.slice(0, 5)) {
513
- let n = _(S(e), "utf-8");
552
+ let n = v(C(e), "utf-8");
514
553
  t.sampleSources.push({
515
554
  path: e,
516
555
  content: n.length > 3e3 ? n.slice(0, 3e3) + "\n... (truncated)" : n
@@ -518,16 +557,16 @@ async function ue(e) {
518
557
  }
519
558
  return t;
520
559
  }
521
- function de(e) {
522
- let t = typeof __dirname < "u" ? __dirname : y(C(import.meta.url)), n = [
523
- S("node_modules", "@fluenti", "cli", "..", "..", e),
524
- x(t, "..", "..", "..", e),
525
- x(t, "..", "..", e)
560
+ function ve(e) {
561
+ let t = typeof __dirname < "u" ? __dirname : b(w(import.meta.url)), n = [
562
+ C("node_modules", "@fluenti", "cli", "..", "..", e),
563
+ S(t, "..", "..", "..", e),
564
+ S(t, "..", "..", e)
526
565
  ];
527
- for (let e of n) if (h(e)) return _(e, "utf-8");
566
+ for (let e of n) if (g(e)) return v(e, "utf-8");
528
567
  return "";
529
568
  }
530
- function fe(e, t, n) {
569
+ function ye(e, t, n) {
531
570
  let r = [];
532
571
  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) {
533
572
  r.push("=== EXISTING CONFIG FILES ===");
@@ -543,7 +582,7 @@ function fe(e, t, n) {
543
582
  }
544
583
  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");
545
584
  }
546
- async function pe(e, t) {
585
+ async function be(e, t) {
547
586
  let n = 10 * 1024 * 1024;
548
587
  try {
549
588
  if (e === "claude") {
@@ -562,7 +601,7 @@ async function pe(e, t) {
562
601
  throw n.code === "ENOENT" || n.code === "EPERM" || n.code === "EACCES" ? Error(`"${e}" CLI not found or not executable. Please install it first:\n` + (e === "claude" ? " npm install -g @anthropic-ai/claude-code" : " npm install -g @openai/codex")) : t;
563
602
  }
564
603
  }
565
- function me(e) {
604
+ function xe(e) {
566
605
  let t = {
567
606
  config: void 0,
568
607
  localeFiles: [],
@@ -583,58 +622,58 @@ function me(e) {
583
622
  let a = e.match(/### INSTALL_COMMANDS[\s\S]*?```(?:bash|sh)?\n([\s\S]*?)```/);
584
623
  return a && (t.installCommands = a[1].trim()), t;
585
624
  }
586
- async function he(e) {
587
- let { from: t, provider: n, write: r } = e, i = q(t);
625
+ async function Se(e) {
626
+ let { from: t, provider: n, write: r } = e, i = ge(t);
588
627
  if (!i) {
589
- O.error(`Unsupported library "${t}". Supported libraries:`);
590
- for (let e of K) O.log(` - ${e}`);
628
+ k.error(`Unsupported library "${t}". Supported libraries:`);
629
+ for (let e of K) k.log(` - ${e}`);
591
630
  return;
592
631
  }
593
632
  let a = G[i];
594
- O.info(`Migrating from ${a.name} (${a.framework}) to Fluenti`), O.info("Scanning project for existing i18n files...");
595
- let o = await ue(a);
633
+ k.info(`Migrating from ${a.name} (${a.framework}) to Fluenti`), k.info("Scanning project for existing i18n files...");
634
+ let o = await _e(a);
596
635
  if (o.configFiles.length === 0 && o.localeFiles.length === 0) {
597
- O.warn(`No ${a.name} configuration or locale files found.`), O.info("Make sure you are running this command from the project root directory.");
636
+ k.warn(`No ${a.name} configuration or locale files found.`), k.info("Make sure you are running this command from the project root directory.");
598
637
  return;
599
638
  }
600
- O.info(`Found: ${o.configFiles.length} config file(s), ${o.localeFiles.length} locale file(s), ${o.sampleSources.length} source file(s)`);
601
- let s = de(a.migrationGuide);
602
- O.info(`Generating migration plan with ${n}...`);
603
- let c = me(await pe(n, fe(a, o, s)));
604
- if (c.installCommands && (O.log(""), O.box({
639
+ k.info(`Found: ${o.configFiles.length} config file(s), ${o.localeFiles.length} locale file(s), ${o.sampleSources.length} source file(s)`);
640
+ let s = ve(a.migrationGuide);
641
+ k.info(`Generating migration plan with ${n}...`);
642
+ let c = xe(await be(n, ye(a, o, s)));
643
+ if (c.installCommands && (k.log(""), k.box({
605
644
  title: "Install Commands",
606
645
  message: c.installCommands
607
646
  })), c.config) if (r) {
608
- let { writeFileSync: e } = await import("node:fs"), t = S("fluenti.config.ts");
609
- e(t, c.config, "utf-8"), O.success(`Written: ${t}`);
610
- } else O.log(""), O.box({
647
+ let { writeFileSync: e } = await import("node:fs"), t = C("fluenti.config.ts");
648
+ e(t, c.config, "utf-8"), k.success(`Written: ${t}`);
649
+ } else k.log(""), k.box({
611
650
  title: "fluenti.config.ts",
612
651
  message: c.config
613
652
  });
614
653
  if (c.localeFiles.length > 0) if (r) {
615
654
  let { writeFileSync: e, mkdirSync: t } = await import("node:fs"), n = "./locales";
616
- t(S(n), { recursive: !0 });
655
+ t(C(n), { recursive: !0 });
617
656
  for (let t of c.localeFiles) {
618
- let r = S(n, `${t.locale}.po`);
619
- e(r, t.content, "utf-8"), O.success(`Written: ${r}`);
657
+ let r = C(n, `${t.locale}.po`);
658
+ e(r, t.content, "utf-8"), k.success(`Written: ${r}`);
620
659
  }
621
- } else for (let e of c.localeFiles) O.log(""), O.box({
660
+ } else for (let e of c.localeFiles) k.log(""), k.box({
622
661
  title: `locales/${e.locale}.po`,
623
662
  message: e.content.length > 500 ? e.content.slice(0, 500) + "\n... (use --write to save full file)" : e.content
624
663
  });
625
- c.steps && (O.log(""), O.box({
664
+ c.steps && (k.log(""), k.box({
626
665
  title: "Migration Steps",
627
666
  message: c.steps
628
- })), !r && (c.config || c.localeFiles.length > 0) && (O.log(""), O.info("Run with --write to save generated files to disk:"), O.log(` fluenti migrate --from ${t} --write`));
667
+ })), !r && (c.config || c.localeFiles.length > 0) && (k.log(""), k.info("Run with --write to save generated files to disk:"), k.log(` fluenti migrate --from ${t} --write`));
629
668
  }
630
669
  //#endregion
631
670
  //#region src/init.ts
632
- var ge = /^[a-zA-Z]{2,3}(-[a-zA-Z0-9]{1,8})*$/;
633
- function J(e) {
634
- if (!ge.test(e)) throw Error(`Invalid locale format: "${e}"`);
671
+ var Ce = /^[a-zA-Z]{2,3}(-[a-zA-Z0-9]{1,8})*$/;
672
+ function q(e) {
673
+ if (!Ce.test(e)) throw Error(`Invalid locale format: "${e}"`);
635
674
  return e;
636
675
  }
637
- var _e = [
676
+ var we = [
638
677
  {
639
678
  dep: "next",
640
679
  name: "nextjs",
@@ -666,8 +705,8 @@ var _e = [
666
705
  pluginPackage: "@fluenti/react"
667
706
  }
668
707
  ];
669
- function ve(e) {
670
- for (let t of _e) if (t.dep in e) return {
708
+ function Te(e) {
709
+ for (let t of we) if (t.dep in e) return {
671
710
  name: t.name,
672
711
  pluginPackage: t.pluginPackage
673
712
  };
@@ -676,7 +715,7 @@ function ve(e) {
676
715
  pluginPackage: null
677
716
  };
678
717
  }
679
- function ye(e) {
718
+ function Ee(e) {
680
719
  let t = e.locales.map((e) => `'${e}'`).join(", ");
681
720
  return `import { defineConfig } from '@fluenti/cli'
682
721
 
@@ -690,50 +729,50 @@ export default defineConfig({
690
729
  })
691
730
  `;
692
731
  }
693
- async function be(e) {
694
- let t = S(e.cwd, "package.json");
695
- if (!h(t)) {
696
- O.error("No package.json found in current directory.");
732
+ async function De(e) {
733
+ let t = C(e.cwd, "package.json");
734
+ if (!g(t)) {
735
+ k.error("No package.json found in current directory.");
697
736
  return;
698
737
  }
699
- let n = JSON.parse(_(t, "utf-8")), r = ve({
738
+ let n = JSON.parse(v(t, "utf-8")), r = Te({
700
739
  ...n.dependencies,
701
740
  ...n.devDependencies
702
741
  });
703
- O.info(`Detected framework: ${r.name}`), r.pluginPackage && O.info(`Recommended plugin: ${r.pluginPackage}`);
704
- let i = S(e.cwd, "fluenti.config.ts");
705
- if (h(i)) {
706
- O.warn("fluenti.config.ts already exists. Skipping config generation.");
742
+ k.info(`Detected framework: ${r.name}`), r.pluginPackage && k.info(`Recommended plugin: ${r.pluginPackage}`);
743
+ let i = C(e.cwd, "fluenti.config.ts");
744
+ if (g(i)) {
745
+ k.warn("fluenti.config.ts already exists. Skipping config generation.");
707
746
  return;
708
747
  }
709
- let a = await O.prompt("Source locale?", {
748
+ let a = await k.prompt("Source locale?", {
710
749
  type: "text",
711
750
  default: "en",
712
751
  placeholder: "en"
713
752
  });
714
753
  if (typeof a == "symbol") return;
715
- let o = await O.prompt("Target locales (comma-separated)?", {
754
+ let o = await k.prompt("Target locales (comma-separated)?", {
716
755
  type: "text",
717
756
  default: "ja,zh-CN",
718
757
  placeholder: "ja,zh-CN"
719
758
  });
720
759
  if (typeof o == "symbol") return;
721
- let s = await O.prompt("Catalog format?", {
760
+ let s = await k.prompt("Catalog format?", {
722
761
  type: "select",
723
762
  options: ["po", "json"],
724
763
  initial: "po"
725
764
  });
726
765
  if (typeof s == "symbol") return;
727
766
  let c = o.split(",").map((e) => e.trim()).filter(Boolean);
728
- J(a);
729
- for (let e of c) J(e);
730
- v(i, ye({
767
+ q(a);
768
+ for (let e of c) q(e);
769
+ y(i, Ee({
731
770
  sourceLocale: a,
732
771
  locales: [a, ...c.filter((e) => e !== a)],
733
772
  format: s
734
- }), "utf-8"), O.success("Created fluenti.config.ts");
735
- let l = S(e.cwd, ".gitignore"), u = "src/locales/compiled/";
736
- h(l) ? _(l, "utf-8").includes(u) || (m(l, `\n# Fluenti compiled catalogs\n${u}\n`), O.success("Updated .gitignore")) : (v(l, `# Fluenti compiled catalogs\n${u}\n`), O.success("Created .gitignore"));
773
+ }), "utf-8"), k.success("Created fluenti.config.ts");
774
+ let l = C(e.cwd, ".gitignore"), u = "src/locales/compiled/";
775
+ g(l) ? v(l, "utf-8").includes(u) || (h(l, `\n# Fluenti compiled catalogs\n${u}\n`), k.success("Updated .gitignore")) : (y(l, `# Fluenti compiled catalogs\n${u}\n`), k.success("Created .gitignore"));
737
776
  let d = n.scripts ?? {}, f = {}, p = !1;
738
777
  if (d["i18n:extract"] || (f["i18n:extract"] = "fluenti extract", p = !0), d["i18n:compile"] || (f["i18n:compile"] = "fluenti compile", p = !0), p) {
739
778
  let e = {
@@ -743,9 +782,9 @@ async function be(e) {
743
782
  ...f
744
783
  }
745
784
  };
746
- v(t, JSON.stringify(e, null, 2) + "\n", "utf-8"), O.success("Added i18n:extract and i18n:compile scripts to package.json");
785
+ y(t, JSON.stringify(e, null, 2) + "\n", "utf-8"), k.success("Added i18n:extract and i18n:compile scripts to package.json");
747
786
  }
748
- O.log(""), O.box({
787
+ k.log(""), k.box({
749
788
  title: "Next steps",
750
789
  message: [
751
790
  r.pluginPackage ? `1. Install: pnpm add -D ${r.pluginPackage} @fluenti/cli` : "1. Install: pnpm add -D @fluenti/cli",
@@ -758,27 +797,27 @@ async function be(e) {
758
797
  }
759
798
  //#endregion
760
799
  //#region src/cli.ts
761
- function Y(e) {
762
- return T("md5").update(e).digest("hex").slice(0, 8);
800
+ function J(e) {
801
+ return E("md5").update(e).digest("hex").slice(0, 8);
763
802
  }
764
- function X(e, t) {
765
- if (!h(e)) return {};
766
- let n = _(e, "utf-8");
803
+ function Y(e, t) {
804
+ if (!g(e)) return {};
805
+ let n = v(e, "utf-8");
767
806
  return t === "json" ? l(n) : s(n);
768
807
  }
769
- function Z(e, t, n) {
770
- g(y(e), { recursive: !0 }), v(e, n === "json" ? d(t) : a(t), "utf-8");
808
+ function X(e, t, n) {
809
+ _(b(e), { recursive: !0 }), y(e, n === "json" ? d(t) : a(t), "utf-8");
771
810
  }
772
- async function xe(e, t, n) {
773
- if (b(e) === ".vue") try {
811
+ async function Oe(e, t, n) {
812
+ if (x(e) === ".vue") try {
774
813
  let { extractFromVue: r } = await import("./vue-extractor.js");
775
814
  return r(t, e, n);
776
815
  } catch {
777
- return O.warn(`Skipping ${e}: install @vue/compiler-sfc to extract from .vue files`), [];
816
+ return k.warn(`Skipping ${e}: install @vue/compiler-sfc to extract from .vue files`), [];
778
817
  }
779
818
  return i(t, e, n);
780
819
  }
781
- var Se = E({
820
+ var ke = D({
782
821
  meta: {
783
822
  name: "extract",
784
823
  description: "Extract messages from source files"
@@ -805,9 +844,9 @@ var Se = E({
805
844
  }
806
845
  },
807
846
  async run({ args: e }) {
808
- let t = await u(e.config), n = p(t.locales);
809
- O.info(`Extracting messages from ${t.include.join(", ")}`);
810
- let r = await w(t.include, { ignore: t.exclude ?? [] }), i = [], a = e["no-cache"] ?? !1 ? null : new f(t.catalogDir, Y(process.cwd())), s = 0;
847
+ let t = await u(e.config), n = m(t.locales);
848
+ k.info(`Extracting messages from ${t.include.join(", ")}`);
849
+ let r = await T(t.include, { ignore: t.exclude ?? [] }), i = [], a = e["no-cache"] ?? !1 ? null : new f(t.catalogDir, J(process.cwd())), s = 0;
811
850
  for (let e of r) {
812
851
  if (a) {
813
852
  let t = a.get(e);
@@ -816,16 +855,16 @@ var Se = E({
816
855
  continue;
817
856
  }
818
857
  }
819
- let n = await xe(e, _(e, "utf-8"), t.idGenerator);
858
+ let n = await Oe(e, v(e, "utf-8"), t.idGenerator);
820
859
  i.push(...n), a && a.set(e, n);
821
860
  }
822
- a && (a.prune(new Set(r)), a.save()), s > 0 ? O.info(`Found ${i.length} messages in ${r.length} files (${s} cached)`) : O.info(`Found ${i.length} messages in ${r.length} files`);
861
+ a && (a.prune(new Set(r)), a.save()), s > 0 ? k.info(`Found ${i.length} messages in ${r.length} files (${s} cached)`) : k.info(`Found ${i.length} messages in ${r.length} files`);
823
862
  let c = t.format === "json" ? ".json" : ".po", l = e.clean ?? !1, d = e["no-fuzzy"] ?? !1;
824
863
  for (let e of n) {
825
- let n = S(t.catalogDir, `${e}${c}`), { catalog: r, result: a } = o(X(n, t.format), i, { stripFuzzy: d });
826
- Z(n, l ? Object.fromEntries(Object.entries(r).filter(([, e]) => !e.obsolete)) : r, t.format);
864
+ let n = C(t.catalogDir, `${e}${c}`), { catalog: r, result: a } = o(Y(n, t.format), i, { stripFuzzy: d });
865
+ X(n, l ? Object.fromEntries(Object.entries(r).filter(([, e]) => !e.obsolete)) : r, t.format);
827
866
  let s = l ? `${a.obsolete} removed` : `${a.obsolete} obsolete`;
828
- O.success(`${e}: ${a.added} added, ${a.unchanged} unchanged, ${s}`);
867
+ k.success(`${e}: ${a.added} added, ${a.unchanged} unchanged, ${s}`);
829
868
  }
830
869
  for (let e of t.plugins ?? []) await e.onAfterExtract?.({
831
870
  messages: new Map(i.map((e) => [e.id, e])),
@@ -835,13 +874,13 @@ var Se = E({
835
874
  });
836
875
  }
837
876
  });
838
- function Ce(e) {
877
+ function Ae(e) {
839
878
  let t = {};
840
879
  for (let [n, r] of Object.entries(e)) r.translation && r.translation.length > 0 ? t[n] = r.translation : r.message && (t[n] = r.message);
841
880
  return t;
842
881
  }
843
- async function Q(e, t, n) {
844
- let r = Ce(e);
882
+ async function Z(e, t, n) {
883
+ let r = Ae(e);
845
884
  for (let e of n) e.transformMessages && (r = await e.transformMessages(r, t));
846
885
  let i = {};
847
886
  for (let [t, n] of Object.entries(e)) {
@@ -853,7 +892,7 @@ async function Q(e, t, n) {
853
892
  }
854
893
  return i;
855
894
  }
856
- function $(e, t, n, r) {
895
+ function Q(e, t, n, r) {
857
896
  let i = {};
858
897
  for (let [e, n] of Object.entries(t)) n.translation && n.translation.length > 0 ? i[e] = n.translation : n.message && (i[e] = n.message);
859
898
  return {
@@ -863,7 +902,7 @@ function $(e, t, n, r) {
863
902
  config: r
864
903
  };
865
904
  }
866
- var we = E({
905
+ var $ = D({
867
906
  meta: {
868
907
  name: "compile",
869
908
  description: "Compile message catalogs to JS modules"
@@ -894,70 +933,70 @@ var we = E({
894
933
  }
895
934
  },
896
935
  async run({ args: i }) {
897
- let a = await u(i.config), o = p(a.locales), d = a.format === "json" ? ".json" : ".po";
898
- g(a.compileOutDir, { recursive: !0 });
899
- let f = {}, m = {};
936
+ let a = await u(i.config), o = m(a.locales), d = a.format === "json" ? ".json" : ".po";
937
+ _(a.compileOutDir, { recursive: !0 });
938
+ let f = {}, p = {};
900
939
  for (let e of o) {
901
- let t = S(a.catalogDir, `${e}${d}`);
902
- if (h(t)) {
903
- let n = _(t, "utf-8");
904
- m[e] = n, f[e] = a.format === "json" ? l(n) : s(n);
905
- } else m[e] = "", f[e] = {};
940
+ let t = C(a.catalogDir, `${e}${d}`);
941
+ if (g(t)) {
942
+ let n = v(t, "utf-8");
943
+ p[e] = n, f[e] = a.format === "json" ? l(n) : s(n);
944
+ } else p[e] = "", f[e] = {};
906
945
  }
907
- let y = r(f);
908
- O.info(`Compiling ${y.length} messages across ${o.length} locales`);
909
- let b = i["skip-fuzzy"] ?? !1, x = i["no-cache"] ?? !1 ? null : new le(a.catalogDir, Y(process.cwd())), C = i.parallel ?? !1, w = i.concurrency ? parseInt(i.concurrency, 10) : void 0;
946
+ let h = r(f);
947
+ k.info(`Compiling ${h.length} messages across ${o.length} locales`);
948
+ let b = i["skip-fuzzy"] ?? !1, x = i["no-cache"] ?? !1 ? null : new L(a.catalogDir, J(process.cwd())), S = i.parallel ?? !1, w = i.concurrency ? parseInt(i.concurrency, 10) : void 0;
910
949
  if (w !== void 0 && (isNaN(w) || w < 1)) {
911
- O.error("Invalid --concurrency. Must be a positive integer."), process.exitCode = 1;
950
+ k.error("Invalid --concurrency. Must be a positive integer."), process.exitCode = 1;
912
951
  return;
913
952
  }
914
953
  let T = 0, E = !1, D = [];
915
954
  for (let e of o) {
916
- if (x && x.isUpToDate(e, m[e]) && h(S(a.compileOutDir, `${e}.js`))) {
955
+ if (x && x.isUpToDate(e, p[e]) && g(C(a.compileOutDir, `${e}.js`))) {
917
956
  T++;
918
957
  continue;
919
958
  }
920
959
  D.push(e);
921
960
  }
922
- if (D.length > 0 && (E = !0), C && D.length > 1) {
961
+ if (D.length > 0 && (E = !0), S && D.length > 1) {
923
962
  let e = a.plugins ?? [], t = {};
924
963
  for (let n of D) {
925
- for (let t of e) await t.onBeforeCompile?.($(n, f[n], a.compileOutDir, a));
926
- t[n] = e.length > 0 ? await Q(f[n], n, e) : f[n];
964
+ for (let t of e) await t.onBeforeCompile?.(Q(n, f[n], a.compileOutDir, a));
965
+ t[n] = e.length > 0 ? await Z(f[n], n, e) : f[n];
927
966
  }
928
967
  let n = await c(D.map((e) => ({
929
968
  locale: e,
930
969
  catalog: t[e],
931
- allIds: y,
970
+ allIds: h,
932
971
  sourceLocale: a.sourceLocale,
933
972
  options: { skipFuzzy: b }
934
973
  })), w);
935
974
  for (let e of n) {
936
- let t = S(a.compileOutDir, `${e.locale}.js`);
937
- if (v(t, e.code, "utf-8"), x && x.set(e.locale, m[e.locale]), e.stats.missing.length > 0) {
938
- O.warn(`${e.locale}: ${e.stats.compiled} compiled, ${e.stats.missing.length} missing translations`);
939
- for (let t of e.stats.missing) O.warn(` ⤷ ${t}`);
940
- } else O.success(`Compiled ${e.locale}: ${e.stats.compiled} messages → ${t}`);
975
+ let t = C(a.compileOutDir, `${e.locale}.js`);
976
+ if (y(t, e.code, "utf-8"), x && x.set(e.locale, p[e.locale]), e.stats.missing.length > 0) {
977
+ k.warn(`${e.locale}: ${e.stats.compiled} compiled, ${e.stats.missing.length} missing translations`);
978
+ for (let t of e.stats.missing) k.warn(` ⤷ ${t}`);
979
+ } else k.success(`Compiled ${e.locale}: ${e.stats.compiled} messages → ${t}`);
941
980
  }
942
- for (let n of D) for (let r of e) await r.onAfterCompile?.($(n, t[n], a.compileOutDir, a));
981
+ for (let n of D) for (let r of e) await r.onAfterCompile?.(Q(n, t[n], a.compileOutDir, a));
943
982
  } else {
944
983
  let e = a.plugins ?? [];
945
984
  for (let n of D) {
946
- let r = S(a.compileOutDir, `${n}.js`);
947
- for (let t of e) await t.onBeforeCompile?.($(n, f[n], a.compileOutDir, a));
948
- let i = e.length > 0 ? await Q(f[n], n, e) : f[n], { code: o, stats: s } = t(i, n, y, a.sourceLocale, { skipFuzzy: b });
949
- if (v(r, o, "utf-8"), x && x.set(n, m[n]), s.missing.length > 0) {
950
- O.warn(`${n}: ${s.compiled} compiled, ${s.missing.length} missing translations`);
951
- for (let e of s.missing) O.warn(` ⤷ ${e}`);
952
- } else O.success(`Compiled ${n}: ${s.compiled} messages → ${r}`);
953
- for (let t of e) await t.onAfterCompile?.($(n, i, a.compileOutDir, a));
985
+ let r = C(a.compileOutDir, `${n}.js`);
986
+ for (let t of e) await t.onBeforeCompile?.(Q(n, f[n], a.compileOutDir, a));
987
+ let i = e.length > 0 ? await Z(f[n], n, e) : f[n], { code: o, stats: s } = t(i, n, h, a.sourceLocale, { skipFuzzy: b });
988
+ if (y(r, o, "utf-8"), x && x.set(n, p[n]), s.missing.length > 0) {
989
+ k.warn(`${n}: ${s.compiled} compiled, ${s.missing.length} missing translations`);
990
+ for (let e of s.missing) k.warn(` ⤷ ${e}`);
991
+ } else k.success(`Compiled ${n}: ${s.compiled} messages → ${r}`);
992
+ for (let t of e) await t.onAfterCompile?.(Q(n, i, a.compileOutDir, a));
954
993
  }
955
994
  }
956
- T > 0 && O.info(`${T} locale(s) unchanged — skipped`), x && x.save();
957
- let k = S(a.compileOutDir, "index.js"), A = S(a.compileOutDir, "messages.d.ts");
958
- (E || !h(k)) && (v(k, n(o, a.compileOutDir), "utf-8"), O.success(`Generated index → ${k}`)), (E || !h(A)) && (v(A, e(y, f, a.sourceLocale), "utf-8"), O.success(`Generated types → ${A}`));
995
+ T > 0 && k.info(`${T} locale(s) unchanged — skipped`), x && x.save();
996
+ let O = C(a.compileOutDir, "index.js"), A = C(a.compileOutDir, "messages.d.ts");
997
+ (E || !g(O)) && (y(O, n(o, a.compileOutDir), "utf-8"), k.success(`Generated index → ${O}`)), (E || !g(A)) && (y(A, e(h, f, a.sourceLocale), "utf-8"), k.success(`Generated types → ${A}`));
959
998
  }
960
- }), Te = E({
999
+ }), je = D({
961
1000
  meta: {
962
1001
  name: "stats",
963
1002
  description: "Show translation progress"
@@ -967,9 +1006,9 @@ var we = E({
967
1006
  description: "Path to config file"
968
1007
  } },
969
1008
  async run({ args: e }) {
970
- let t = await u(e.config), n = p(t.locales), r = t.format === "json" ? ".json" : ".po", i = [];
1009
+ let t = await u(e.config), n = m(t.locales), r = t.format === "json" ? ".json" : ".po", i = [];
971
1010
  for (let e of n) {
972
- let n = X(S(t.catalogDir, `${e}${r}`), t.format), a = Object.values(n).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) + "%" : "—";
1011
+ let n = Y(C(t.catalogDir, `${e}${r}`), t.format), a = Object.values(n).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) + "%" : "—";
973
1012
  i.push({
974
1013
  locale: e,
975
1014
  total: o,
@@ -977,11 +1016,11 @@ var we = E({
977
1016
  pct: c
978
1017
  });
979
1018
  }
980
- O.log(""), O.log(" Locale │ Total │ Translated │ Progress"), O.log(" ────────┼───────┼────────────┼─────────────────────────────");
981
- for (let e of i) O.log(ie(e.locale, e.total, e.translated));
982
- O.log("");
1019
+ k.log(""), k.log(" Locale │ Total │ Translated │ Progress"), k.log(" ────────┼───────┼────────────┼─────────────────────────────");
1020
+ for (let e of i) k.log(ie(e.locale, e.total, e.translated));
1021
+ k.log("");
983
1022
  }
984
- }), Ee = E({
1023
+ }), Me = D({
985
1024
  meta: {
986
1025
  name: "lint",
987
1026
  description: "Check translation quality (missing, inconsistent placeholders, fuzzy)"
@@ -1002,21 +1041,21 @@ var we = E({
1002
1041
  }
1003
1042
  },
1004
1043
  async run({ args: e }) {
1005
- let t = await u(e.config), n = p(t.locales), r = t.format === "json" ? ".json" : ".po", i = {};
1006
- for (let e of n) i[e] = X(S(t.catalogDir, `${e}${r}`), t.format);
1044
+ let t = await u(e.config), n = m(t.locales), r = t.format === "json" ? ".json" : ".po", i = {};
1045
+ for (let e of n) i[e] = Y(C(t.catalogDir, `${e}${r}`), t.format);
1007
1046
  let a = e.locale ? [e.locale] : void 0;
1008
- O.info(`Linting ${a ? a.join(", ") : "all locales"} (source: ${t.sourceLocale})`);
1047
+ k.info(`Linting ${a ? a.join(", ") : "all locales"} (source: ${t.sourceLocale})`);
1009
1048
  let o = {
1010
1049
  sourceLocale: t.sourceLocale,
1011
1050
  strict: e.strict ?? !1
1012
1051
  };
1013
1052
  a && (o.locales = a);
1014
- let s = j(i, o);
1015
- O.log(""), O.log(ae(s)), O.log("");
1053
+ let s = F(i, o);
1054
+ k.log(""), k.log(ae(s)), k.log("");
1016
1055
  let c = s.filter((e) => e.severity === "error"), l = s.filter((e) => e.severity === "warning");
1017
1056
  (c.length > 0 || e.strict && l.length > 0) && (process.exitCode = 1);
1018
1057
  }
1019
- }), De = E({
1058
+ }), Ne = D({
1020
1059
  meta: {
1021
1060
  name: "check",
1022
1061
  description: "Check translation coverage for CI"
@@ -1046,11 +1085,11 @@ var we = E({
1046
1085
  }
1047
1086
  },
1048
1087
  async run({ args: e }) {
1049
- let t = await u(e.config), n = p(t.locales), r = t.format === "json" ? ".json" : ".po", i = {};
1050
- for (let e of n) i[e] = X(S(t.catalogDir, `${e}${r}`), t.format);
1088
+ let t = await u(e.config), n = m(t.locales), r = t.format === "json" ? ".json" : ".po", i = {};
1089
+ for (let e of n) i[e] = Y(C(t.catalogDir, `${e}${r}`), t.format);
1051
1090
  let a = parseFloat(e["min-coverage"] ?? "100");
1052
1091
  if (isNaN(a) || a < 0 || a > 100) {
1053
- O.error("Invalid --min-coverage. Must be a number between 0 and 100."), process.exitCode = 1;
1092
+ k.error("Invalid --min-coverage. Must be a number between 0 and 100."), process.exitCode = 1;
1054
1093
  return;
1055
1094
  }
1056
1095
  let o = e.format ?? (e.ci ? "github" : "text"), s = {
@@ -1059,21 +1098,21 @@ var we = E({
1059
1098
  format: o
1060
1099
  };
1061
1100
  e.locale && (s.locale = e.locale);
1062
- let c = P(i, s);
1101
+ let c = se(i, s);
1063
1102
  switch (o) {
1064
1103
  case "json":
1065
- O.log(ce(c));
1104
+ k.log(ue(c));
1066
1105
  break;
1067
1106
  case "github":
1068
- O.log(se(c, t.catalogDir, t.format));
1107
+ k.log(le(c, t.catalogDir, t.format));
1069
1108
  break;
1070
1109
  default:
1071
- O.log(""), O.log(oe(c)), O.log("");
1110
+ k.log(""), k.log(ce(c)), k.log("");
1072
1111
  break;
1073
1112
  }
1074
1113
  c.passed || (process.exitCode = 1);
1075
1114
  }
1076
- }), Oe = E({
1115
+ }), Pe = D({
1077
1116
  meta: {
1078
1117
  name: "translate",
1079
1118
  description: "Translate messages using AI (Claude Code or Codex CLI)"
@@ -1108,35 +1147,35 @@ var we = E({
1108
1147
  }
1109
1148
  },
1110
1149
  async run({ args: e }) {
1111
- let t = await u(e.config), n = p(t.locales), r = e.provider;
1150
+ let t = await u(e.config), n = m(t.locales), r = e.provider;
1112
1151
  if (r !== "claude" && r !== "codex") {
1113
- O.error(`Invalid provider "${r}". Use "claude" or "codex".`);
1152
+ k.error(`Invalid provider "${r}". Use "claude" or "codex".`);
1114
1153
  return;
1115
1154
  }
1116
1155
  let i = parseInt(e["batch-size"] ?? "50", 10);
1117
1156
  if (isNaN(i) || i < 1) {
1118
- O.error("Invalid batch-size. Must be a positive integer.");
1157
+ k.error("Invalid batch-size. Must be a positive integer.");
1119
1158
  return;
1120
1159
  }
1121
1160
  let a = e.locale ? [e.locale] : n.filter((e) => e !== t.sourceLocale);
1122
1161
  if (a.length === 0) {
1123
- O.warn("No target locales to translate.");
1162
+ k.warn("No target locales to translate.");
1124
1163
  return;
1125
1164
  }
1126
- O.info(`Translating with ${r} (batch size: ${i})`);
1165
+ k.info(`Translating with ${r} (batch size: ${i})`);
1127
1166
  let o = t.format === "json" ? ".json" : ".po";
1128
1167
  for (let n of a) {
1129
- O.info(`\n[${n}]`);
1130
- let a = S(t.catalogDir, `${n}${o}`), s = X(a, t.format);
1168
+ k.info(`\n[${n}]`);
1169
+ let a = C(t.catalogDir, `${n}${o}`), s = Y(a, t.format);
1131
1170
  if (e["dry-run"]) {
1132
1171
  let e = Object.entries(s).filter(([, e]) => !e.obsolete && (!e.translation || e.translation.length === 0));
1133
1172
  if (e.length > 0) {
1134
- for (let [t, n] of e) O.log(` ${t}: ${n.message ?? t}`);
1135
- O.success(` ${n}: ${e.length} messages would be translated (dry-run)`);
1136
- } else O.success(` ${n}: already fully translated`);
1173
+ for (let [t, n] of e) k.log(` ${t}: ${n.message ?? t}`);
1174
+ k.success(` ${n}: ${e.length} messages would be translated (dry-run)`);
1175
+ } else k.success(` ${n}: already fully translated`);
1137
1176
  continue;
1138
1177
  }
1139
- let { catalog: c, translated: l } = await U({
1178
+ let { catalog: c, translated: l } = await he({
1140
1179
  provider: r,
1141
1180
  sourceLocale: t.sourceLocale,
1142
1181
  targetLocale: n,
@@ -1144,10 +1183,10 @@ var we = E({
1144
1183
  batchSize: i,
1145
1184
  ...e.context ? { context: e.context } : {}
1146
1185
  });
1147
- l > 0 ? (Z(a, c, t.format), O.success(` ${n}: ${l} messages translated`)) : O.success(` ${n}: already fully translated`);
1186
+ l > 0 ? (X(a, c, t.format), k.success(` ${n}: ${l} messages translated`)) : k.success(` ${n}: already fully translated`);
1148
1187
  }
1149
1188
  }
1150
- }), ke = E({
1189
+ }), Fe = D({
1151
1190
  meta: {
1152
1191
  name: "migrate",
1153
1192
  description: "Migrate from another i18n library using AI"
@@ -1172,40 +1211,40 @@ var we = E({
1172
1211
  async run({ args: e }) {
1173
1212
  let t = e.provider;
1174
1213
  if (t !== "claude" && t !== "codex") {
1175
- O.error(`Invalid provider "${t}". Use "claude" or "codex".`);
1214
+ k.error(`Invalid provider "${t}". Use "claude" or "codex".`);
1176
1215
  return;
1177
1216
  }
1178
- await he({
1217
+ await Se({
1179
1218
  from: e.from,
1180
1219
  provider: t,
1181
1220
  write: e.write ?? !1
1182
1221
  });
1183
1222
  }
1184
1223
  });
1185
- D(E({
1224
+ O(D({
1186
1225
  meta: {
1187
1226
  name: "fluenti",
1188
1227
  version: "0.0.1",
1189
1228
  description: "Compile-time i18n for modern frameworks"
1190
1229
  },
1191
1230
  subCommands: {
1192
- init: E({
1231
+ init: D({
1193
1232
  meta: {
1194
1233
  name: "init",
1195
1234
  description: "Initialize Fluenti in your project"
1196
1235
  },
1197
1236
  args: {},
1198
1237
  async run() {
1199
- await be({ cwd: process.cwd() });
1238
+ await De({ cwd: process.cwd() });
1200
1239
  }
1201
1240
  }),
1202
- extract: Se,
1203
- compile: we,
1204
- stats: Te,
1205
- lint: Ee,
1206
- check: De,
1207
- translate: Oe,
1208
- migrate: ke
1241
+ extract: ke,
1242
+ compile: $,
1243
+ stats: je,
1244
+ lint: Me,
1245
+ check: Ne,
1246
+ translate: Pe,
1247
+ migrate: Fe
1209
1248
  }
1210
1249
  }));
1211
1250
  //#endregion