@fluenti/cli 0.3.0 → 0.3.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/cli.js CHANGED
@@ -1,33 +1,34 @@
1
1
  #!/usr/bin/env node
2
- import { i as e, n as t, r as n, t as r } from "./compile-BZGNcCK1.js";
2
+ import { i as e, n as t, r as n, t as r } from "./compile-jumIhf8m.js";
3
3
  import { t as i } from "./tsx-extractor-B9fnGNTG.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-1XVokN31.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-CmnwPMdA.js";
5
5
  import { resolveLocaleCodes as p } from "@fluenti/core/internal";
6
6
  import { appendFileSync as m, existsSync as h, mkdirSync as g, readFileSync as _, writeFileSync as v } from "node:fs";
7
7
  import { dirname as y, extname as b, join as x, resolve as S } from "node:path";
8
- import C from "fast-glob";
9
- import { createHash as w } from "node:crypto";
10
- import { defineCommand as T, runMain as E } from "citty";
11
- import D from "consola";
12
- import { execFile as O } from "node:child_process";
13
- import { promisify as k } from "node:util";
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";
14
15
  //#region src/stats-format.ts
15
- var A = "█", ee = "░";
16
- function j(e, t = 20) {
16
+ var ee = "█", te = "░";
17
+ function ne(e, t = 20) {
17
18
  let n = Math.max(0, Math.min(100, e)), r = Math.round(n / 100 * t);
18
- return A.repeat(r) + ee.repeat(t - r);
19
+ return ee.repeat(r) + te.repeat(t - r);
19
20
  }
20
- function te(e) {
21
+ function re(e) {
21
22
  let t = e.toFixed(1) + "%";
22
23
  return e >= 90 ? `\x1b[32m${t}\x1b[0m` : e >= 70 ? `\x1b[33m${t}\x1b[0m` : `\x1b[31m${t}\x1b[0m`;
23
24
  }
24
- function ne(e, t, n) {
25
- let r = t > 0 ? n / t * 100 : 0, i = t > 0 ? te(r) : "—", a = t > 0 ? j(r) : "";
25
+ function ie(e, t, n) {
26
+ let r = t > 0 ? n / t * 100 : 0, i = t > 0 ? re(r) : "—", a = t > 0 ? ne(r) : "";
26
27
  return ` ${e.padEnd(8)}│ ${String(t).padStart(5)} │ ${String(n).padStart(10)} │ ${a} ${i}`;
27
28
  }
28
29
  //#endregion
29
30
  //#region src/lint.ts
30
- function M(e, t) {
31
+ function j(e, t) {
31
32
  let n = [], { sourceLocale: r } = t, i = t.locales ?? Object.keys(e), a = e[r];
32
33
  if (!a) return n.push({
33
34
  rule: "missing-source",
@@ -59,7 +60,7 @@ function M(e, t) {
59
60
  });
60
61
  continue;
61
62
  }
62
- let s = N(r.message ?? e), c = N(o.translation), l = s.filter((e) => !c.includes(e)), u = c.filter((e) => !s.includes(e));
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));
63
64
  l.length > 0 && n.push({
64
65
  rule: "inconsistent-placeholders",
65
66
  severity: "error",
@@ -102,7 +103,7 @@ function M(e, t) {
102
103
  });
103
104
  return n;
104
105
  }
105
- function N(e) {
106
+ function M(e) {
106
107
  let t = [], n = /\{(\w+)(?:\s*,\s*(?:plural|select|selectordinal|number|date|time))?/g, r;
107
108
  for (; (r = n.exec(e)) !== null;) {
108
109
  let e = r[1];
@@ -110,9 +111,9 @@ function N(e) {
110
111
  }
111
112
  return t.sort();
112
113
  }
113
- function P(e) {
114
+ function ae(e) {
114
115
  if (e.length === 0) return " ✓ All checks passed";
115
- let t = [], n = re(e, (e) => e.rule);
116
+ let t = [], n = N(e, (e) => e.rule);
116
117
  for (let [e, r] of Object.entries(n)) {
117
118
  t.push(` ${e} (${r.length}):`);
118
119
  for (let e of r) {
@@ -123,7 +124,7 @@ function P(e) {
123
124
  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;
124
125
  return t.push(""), t.push(` Summary: ${r} errors, ${i} warnings, ${a} info`), t.join("\n");
125
126
  }
126
- function re(e, t) {
127
+ function N(e, t) {
127
128
  let n = {};
128
129
  for (let r of e) {
129
130
  let e = t(r);
@@ -133,7 +134,7 @@ function re(e, t) {
133
134
  }
134
135
  //#endregion
135
136
  //#region src/check.ts
136
- function ie(e, t) {
137
+ function P(e, t) {
137
138
  let { sourceLocale: n, minCoverage: r, locale: i } = t, a = e[n];
138
139
  if (!a) return {
139
140
  results: [],
@@ -181,10 +182,10 @@ function ie(e, t) {
181
182
  passed: p,
182
183
  minCoverage: r,
183
184
  actualCoverage: f,
184
- diagnostics: M(e, m)
185
+ diagnostics: j(e, m)
185
186
  };
186
187
  }
187
- function ae(e) {
188
+ function oe(e) {
188
189
  let t = [];
189
190
  for (let n of e.results) {
190
191
  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` : "";
@@ -194,7 +195,7 @@ function ae(e) {
194
195
  let n = e.actualCoverage.toFixed(1), r = e.passed ? "PASSED" : "FAILED";
195
196
  return t.push(`Coverage: ${n}% (min: ${e.minCoverage}%) — ${r}`), t.join("\n");
196
197
  }
197
- function oe(e, t, n) {
198
+ function se(e, t, n) {
198
199
  let r = [], i = n === "json" ? ".json" : ".po";
199
200
  for (let n of e.results) if (n.coverage < e.minCoverage) {
200
201
  let a = `${t}/${n.locale}${i}`;
@@ -207,7 +208,7 @@ function oe(e, t, n) {
207
208
  }
208
209
  return r.join("\n");
209
210
  }
210
- function se(e) {
211
+ function ce(e) {
211
212
  return JSON.stringify({
212
213
  results: e.results,
213
214
  passed: e.passed,
@@ -217,7 +218,7 @@ function se(e) {
217
218
  }
218
219
  //#endregion
219
220
  //#region src/compile-cache.ts
220
- var F = "1", ce = class {
221
+ var F = "1", le = class {
221
222
  data;
222
223
  cachePath;
223
224
  dirty = !1;
@@ -250,11 +251,11 @@ var F = "1", ce = class {
250
251
  }
251
252
  };
252
253
  function I(e) {
253
- return w("md5").update(e).digest("hex");
254
+ return T("md5").update(e).digest("hex");
254
255
  }
255
256
  //#endregion
256
257
  //#region src/translate.ts
257
- var L = k(O);
258
+ var L = A(k);
258
259
  function R(e, t, n, r) {
259
260
  let i = JSON.stringify(n, null, 2);
260
261
  return [
@@ -321,16 +322,16 @@ async function U(e) {
321
322
  catalog: { ...i },
322
323
  translated: 0
323
324
  };
324
- D.info(` ${c} untranslated messages, translating with ${t}...`);
325
+ O.info(` ${c} untranslated messages, translating with ${t}...`);
325
326
  let l = { ...i }, u = H(s, a), d = 0;
326
327
  for (let e = 0; e < u.length; e++) {
327
328
  let i = u[e], a = Object.keys(i);
328
- u.length > 1 && D.info(` Batch ${e + 1}/${u.length} (${a.length} messages)`);
329
+ u.length > 1 && O.info(` Batch ${e + 1}/${u.length} (${a.length} messages)`);
329
330
  let s = B(await z(t, R(n, r, i, o)));
330
331
  for (let e of a) s[e] && typeof s[e] == "string" ? (l[e] = {
331
332
  ...l[e],
332
333
  translation: s[e]
333
- }, d++) : D.warn(` Missing translation for key: ${e}`);
334
+ }, d++) : O.warn(` Missing translation for key: ${e}`);
334
335
  }
335
336
  return {
336
337
  catalog: l,
@@ -339,7 +340,7 @@ async function U(e) {
339
340
  }
340
341
  //#endregion
341
342
  //#region src/migrate.ts
342
- var W = k(O), G = {
343
+ var W = A(k), G = {
343
344
  "vue-i18n": {
344
345
  name: "vue-i18n",
345
346
  framework: "Vue",
@@ -480,7 +481,7 @@ var W = k(O), G = {
480
481
  migrationGuide: "react/llms-migration.txt"
481
482
  }
482
483
  }, K = Object.keys(G);
483
- function le(e) {
484
+ function q(e) {
484
485
  let t = e.toLowerCase().replace(/^@nuxtjs\//, "nuxt-").replace(/^@/, "");
485
486
  return K.find((e) => e === t);
486
487
  }
@@ -499,7 +500,7 @@ async function ue(e) {
499
500
  content: _(e, "utf-8")
500
501
  });
501
502
  }
502
- let r = await C(e.localePatterns, { absolute: !1 });
503
+ let r = await w(e.localePatterns, { absolute: !1 });
503
504
  for (let e of r.slice(0, 10)) {
504
505
  let n = _(S(e), "utf-8");
505
506
  t.localeFiles.push({
@@ -507,7 +508,7 @@ async function ue(e) {
507
508
  content: n.length > 5e3 ? n.slice(0, 5e3) + "\n... (truncated)" : n
508
509
  });
509
510
  }
510
- let i = await C(e.sourcePatterns, { absolute: !1 });
511
+ let i = await w(e.sourcePatterns, { absolute: !1 });
511
512
  for (let e of i.slice(0, 5)) {
512
513
  let n = _(S(e), "utf-8");
513
514
  t.sampleSources.push({
@@ -518,12 +519,12 @@ async function ue(e) {
518
519
  return t;
519
520
  }
520
521
  function de(e) {
521
- let t = [
522
+ let t = typeof __dirname < "u" ? __dirname : y(C(import.meta.url)), n = [
522
523
  S("node_modules", "@fluenti", "cli", "..", "..", e),
523
- x(__dirname, "..", "..", "..", e),
524
- x(__dirname, "..", "..", e)
524
+ x(t, "..", "..", "..", e),
525
+ x(t, "..", "..", e)
525
526
  ];
526
- for (let e of t) if (h(e)) return _(e, "utf-8");
527
+ for (let e of n) if (h(e)) return _(e, "utf-8");
527
528
  return "";
528
529
  }
529
530
  function fe(e, t, n) {
@@ -557,7 +558,8 @@ async function pe(e, t) {
557
558
  return e;
558
559
  }
559
560
  } catch (t) {
560
- 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;
561
+ let n = t;
562
+ 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;
561
563
  }
562
564
  }
563
565
  function me(e) {
@@ -582,30 +584,30 @@ function me(e) {
582
584
  return a && (t.installCommands = a[1].trim()), t;
583
585
  }
584
586
  async function he(e) {
585
- let { from: t, provider: n, write: r } = e, i = le(t);
587
+ let { from: t, provider: n, write: r } = e, i = q(t);
586
588
  if (!i) {
587
- D.error(`Unsupported library "${t}". Supported libraries:`);
588
- for (let e of K) D.log(` - ${e}`);
589
+ O.error(`Unsupported library "${t}". Supported libraries:`);
590
+ for (let e of K) O.log(` - ${e}`);
589
591
  return;
590
592
  }
591
593
  let a = G[i];
592
- D.info(`Migrating from ${a.name} (${a.framework}) to Fluenti`), D.info("Scanning project for existing i18n files...");
594
+ O.info(`Migrating from ${a.name} (${a.framework}) to Fluenti`), O.info("Scanning project for existing i18n files...");
593
595
  let o = await ue(a);
594
596
  if (o.configFiles.length === 0 && o.localeFiles.length === 0) {
595
- D.warn(`No ${a.name} configuration or locale files found.`), D.info("Make sure you are running this command from the project root directory.");
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.");
596
598
  return;
597
599
  }
598
- D.info(`Found: ${o.configFiles.length} config file(s), ${o.localeFiles.length} locale file(s), ${o.sampleSources.length} source file(s)`);
600
+ O.info(`Found: ${o.configFiles.length} config file(s), ${o.localeFiles.length} locale file(s), ${o.sampleSources.length} source file(s)`);
599
601
  let s = de(a.migrationGuide);
600
- D.info(`Generating migration plan with ${n}...`);
602
+ O.info(`Generating migration plan with ${n}...`);
601
603
  let c = me(await pe(n, fe(a, o, s)));
602
- if (c.installCommands && (D.log(""), D.box({
604
+ if (c.installCommands && (O.log(""), O.box({
603
605
  title: "Install Commands",
604
606
  message: c.installCommands
605
607
  })), c.config) if (r) {
606
608
  let { writeFileSync: e } = await import("node:fs"), t = S("fluenti.config.ts");
607
- e(t, c.config, "utf-8"), D.success(`Written: ${t}`);
608
- } else D.log(""), D.box({
609
+ e(t, c.config, "utf-8"), O.success(`Written: ${t}`);
610
+ } else O.log(""), O.box({
609
611
  title: "fluenti.config.ts",
610
612
  message: c.config
611
613
  });
@@ -614,21 +616,21 @@ async function he(e) {
614
616
  t(S(n), { recursive: !0 });
615
617
  for (let t of c.localeFiles) {
616
618
  let r = S(n, `${t.locale}.po`);
617
- e(r, t.content, "utf-8"), D.success(`Written: ${r}`);
619
+ e(r, t.content, "utf-8"), O.success(`Written: ${r}`);
618
620
  }
619
- } else for (let e of c.localeFiles) D.log(""), D.box({
621
+ } else for (let e of c.localeFiles) O.log(""), O.box({
620
622
  title: `locales/${e.locale}.po`,
621
623
  message: e.content.length > 500 ? e.content.slice(0, 500) + "\n... (use --write to save full file)" : e.content
622
624
  });
623
- c.steps && (D.log(""), D.box({
625
+ c.steps && (O.log(""), O.box({
624
626
  title: "Migration Steps",
625
627
  message: c.steps
626
- })), !r && (c.config || c.localeFiles.length > 0) && (D.log(""), D.info("Run with --write to save generated files to disk:"), D.log(` fluenti migrate --from ${t} --write`));
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`));
627
629
  }
628
630
  //#endregion
629
631
  //#region src/init.ts
630
632
  var ge = /^[a-zA-Z]{2,3}(-[a-zA-Z0-9]{1,8})*$/;
631
- function q(e) {
633
+ function J(e) {
632
634
  if (!ge.test(e)) throw Error(`Invalid locale format: "${e}"`);
633
635
  return e;
634
636
  }
@@ -691,47 +693,47 @@ export default defineConfig({
691
693
  async function be(e) {
692
694
  let t = S(e.cwd, "package.json");
693
695
  if (!h(t)) {
694
- D.error("No package.json found in current directory.");
696
+ O.error("No package.json found in current directory.");
695
697
  return;
696
698
  }
697
699
  let n = JSON.parse(_(t, "utf-8")), r = ve({
698
700
  ...n.dependencies,
699
701
  ...n.devDependencies
700
702
  });
701
- D.info(`Detected framework: ${r.name}`), r.pluginPackage && D.info(`Recommended plugin: ${r.pluginPackage}`);
703
+ O.info(`Detected framework: ${r.name}`), r.pluginPackage && O.info(`Recommended plugin: ${r.pluginPackage}`);
702
704
  let i = S(e.cwd, "fluenti.config.ts");
703
705
  if (h(i)) {
704
- D.warn("fluenti.config.ts already exists. Skipping config generation.");
706
+ O.warn("fluenti.config.ts already exists. Skipping config generation.");
705
707
  return;
706
708
  }
707
- let a = await D.prompt("Source locale?", {
709
+ let a = await O.prompt("Source locale?", {
708
710
  type: "text",
709
711
  default: "en",
710
712
  placeholder: "en"
711
713
  });
712
714
  if (typeof a == "symbol") return;
713
- let o = await D.prompt("Target locales (comma-separated)?", {
715
+ let o = await O.prompt("Target locales (comma-separated)?", {
714
716
  type: "text",
715
717
  default: "ja,zh-CN",
716
718
  placeholder: "ja,zh-CN"
717
719
  });
718
720
  if (typeof o == "symbol") return;
719
- let s = await D.prompt("Catalog format?", {
721
+ let s = await O.prompt("Catalog format?", {
720
722
  type: "select",
721
723
  options: ["po", "json"],
722
724
  initial: "po"
723
725
  });
724
726
  if (typeof s == "symbol") return;
725
727
  let c = o.split(",").map((e) => e.trim()).filter(Boolean);
726
- q(a);
727
- for (let e of c) q(e);
728
+ J(a);
729
+ for (let e of c) J(e);
728
730
  v(i, ye({
729
731
  sourceLocale: a,
730
732
  locales: [a, ...c.filter((e) => e !== a)],
731
733
  format: s
732
- }), "utf-8"), D.success("Created fluenti.config.ts");
734
+ }), "utf-8"), O.success("Created fluenti.config.ts");
733
735
  let l = S(e.cwd, ".gitignore"), u = "src/locales/compiled/";
734
- h(l) ? _(l, "utf-8").includes(u) || (m(l, `\n# Fluenti compiled catalogs\n${u}\n`), D.success("Updated .gitignore")) : (v(l, `# Fluenti compiled catalogs\n${u}\n`), D.success("Created .gitignore"));
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"));
735
737
  let d = n.scripts ?? {}, f = {}, p = !1;
736
738
  if (d["i18n:extract"] || (f["i18n:extract"] = "fluenti extract", p = !0), d["i18n:compile"] || (f["i18n:compile"] = "fluenti compile", p = !0), p) {
737
739
  let e = {
@@ -741,9 +743,9 @@ async function be(e) {
741
743
  ...f
742
744
  }
743
745
  };
744
- v(t, JSON.stringify(e, null, 2) + "\n", "utf-8"), D.success("Added i18n:extract and i18n:compile scripts to package.json");
746
+ v(t, JSON.stringify(e, null, 2) + "\n", "utf-8"), O.success("Added i18n:extract and i18n:compile scripts to package.json");
745
747
  }
746
- D.log(""), D.box({
748
+ O.log(""), O.box({
747
749
  title: "Next steps",
748
750
  message: [
749
751
  r.pluginPackage ? `1. Install: pnpm add -D ${r.pluginPackage} @fluenti/cli` : "1. Install: pnpm add -D @fluenti/cli",
@@ -756,15 +758,15 @@ async function be(e) {
756
758
  }
757
759
  //#endregion
758
760
  //#region src/cli.ts
759
- function J(e) {
760
- return w("md5").update(e).digest("hex").slice(0, 8);
761
+ function Y(e) {
762
+ return T("md5").update(e).digest("hex").slice(0, 8);
761
763
  }
762
- function Y(e, t) {
764
+ function X(e, t) {
763
765
  if (!h(e)) return {};
764
766
  let n = _(e, "utf-8");
765
767
  return t === "json" ? l(n) : s(n);
766
768
  }
767
- function X(e, t, n) {
769
+ function Z(e, t, n) {
768
770
  g(y(e), { recursive: !0 }), v(e, n === "json" ? d(t) : a(t), "utf-8");
769
771
  }
770
772
  async function xe(e, t, n) {
@@ -772,11 +774,11 @@ async function xe(e, t, n) {
772
774
  let { extractFromVue: r } = await import("./vue-extractor.js");
773
775
  return r(t, e, n);
774
776
  } catch {
775
- return D.warn(`Skipping ${e}: install @vue/compiler-sfc to extract from .vue files`), [];
777
+ return O.warn(`Skipping ${e}: install @vue/compiler-sfc to extract from .vue files`), [];
776
778
  }
777
779
  return i(t, e, n);
778
780
  }
779
- var Se = T({
781
+ var Se = E({
780
782
  meta: {
781
783
  name: "extract",
782
784
  description: "Extract messages from source files"
@@ -804,8 +806,8 @@ var Se = T({
804
806
  },
805
807
  async run({ args: e }) {
806
808
  let t = await u(e.config), n = p(t.locales);
807
- D.info(`Extracting messages from ${t.include.join(", ")}`);
808
- let r = await C(t.include, { ignore: t.exclude ?? [] }), i = [], a = e["no-cache"] ?? !1 ? null : new f(t.catalogDir, J(process.cwd())), s = 0;
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;
809
811
  for (let e of r) {
810
812
  if (a) {
811
813
  let t = a.get(e);
@@ -817,13 +819,13 @@ var Se = T({
817
819
  let n = await xe(e, _(e, "utf-8"), t.idGenerator);
818
820
  i.push(...n), a && a.set(e, n);
819
821
  }
820
- a && (a.prune(new Set(r)), a.save()), s > 0 ? D.info(`Found ${i.length} messages in ${r.length} files (${s} cached)`) : D.info(`Found ${i.length} messages in ${r.length} files`);
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`);
821
823
  let c = t.format === "json" ? ".json" : ".po", l = e.clean ?? !1, d = e["no-fuzzy"] ?? !1;
822
824
  for (let e of n) {
823
- let n = S(t.catalogDir, `${e}${c}`), { catalog: r, result: a } = o(Y(n, t.format), i, { stripFuzzy: d });
824
- X(n, l ? Object.fromEntries(Object.entries(r).filter(([, e]) => !e.obsolete)) : r, t.format);
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);
825
827
  let s = l ? `${a.obsolete} removed` : `${a.obsolete} obsolete`;
826
- D.success(`${e}: ${a.added} added, ${a.unchanged} unchanged, ${s}`);
828
+ O.success(`${e}: ${a.added} added, ${a.unchanged} unchanged, ${s}`);
827
829
  }
828
830
  for (let e of t.plugins ?? []) await e.onAfterExtract?.({
829
831
  messages: new Map(i.map((e) => [e.id, e])),
@@ -838,7 +840,7 @@ function Ce(e) {
838
840
  for (let [n, r] of Object.entries(e)) r.translation && r.translation.length > 0 ? t[n] = r.translation : r.message && (t[n] = r.message);
839
841
  return t;
840
842
  }
841
- async function Z(e, t, n) {
843
+ async function Q(e, t, n) {
842
844
  let r = Ce(e);
843
845
  for (let e of n) e.transformMessages && (r = await e.transformMessages(r, t));
844
846
  let i = {};
@@ -851,7 +853,7 @@ async function Z(e, t, n) {
851
853
  }
852
854
  return i;
853
855
  }
854
- function Q(e, t, n, r) {
856
+ function $(e, t, n, r) {
855
857
  let i = {};
856
858
  for (let [e, n] of Object.entries(t)) n.translation && n.translation.length > 0 ? i[e] = n.translation : n.message && (i[e] = n.message);
857
859
  return {
@@ -861,7 +863,7 @@ function Q(e, t, n, r) {
861
863
  config: r
862
864
  };
863
865
  }
864
- var $ = T({
866
+ var we = E({
865
867
  meta: {
866
868
  name: "compile",
867
869
  description: "Compile message catalogs to JS modules"
@@ -903,27 +905,27 @@ var $ = T({
903
905
  } else m[e] = "", f[e] = {};
904
906
  }
905
907
  let y = r(f);
906
- D.info(`Compiling ${y.length} messages across ${o.length} locales`);
907
- let b = i["skip-fuzzy"] ?? !1, x = i["no-cache"] ?? !1 ? null : new ce(a.catalogDir, J(process.cwd())), C = i.parallel ?? !1, w = i.concurrency ? parseInt(i.concurrency, 10) : void 0;
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;
908
910
  if (w !== void 0 && (isNaN(w) || w < 1)) {
909
- D.error("Invalid --concurrency. Must be a positive integer."), process.exitCode = 1;
911
+ O.error("Invalid --concurrency. Must be a positive integer."), process.exitCode = 1;
910
912
  return;
911
913
  }
912
- let T = 0, E = !1, O = [];
914
+ let T = 0, E = !1, D = [];
913
915
  for (let e of o) {
914
916
  if (x && x.isUpToDate(e, m[e]) && h(S(a.compileOutDir, `${e}.js`))) {
915
917
  T++;
916
918
  continue;
917
919
  }
918
- O.push(e);
920
+ D.push(e);
919
921
  }
920
- if (O.length > 0 && (E = !0), C && O.length > 1) {
922
+ if (D.length > 0 && (E = !0), C && D.length > 1) {
921
923
  let e = a.plugins ?? [], t = {};
922
- for (let n of O) {
923
- for (let t of e) await t.onBeforeCompile?.(Q(n, f[n], a.compileOutDir, a));
924
- t[n] = e.length > 0 ? await Z(f[n], n, e) : f[n];
924
+ 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];
925
927
  }
926
- let n = await c(O.map((e) => ({
928
+ let n = await c(D.map((e) => ({
927
929
  locale: e,
928
930
  catalog: t[e],
929
931
  allIds: y,
@@ -933,29 +935,29 @@ var $ = T({
933
935
  for (let e of n) {
934
936
  let t = S(a.compileOutDir, `${e.locale}.js`);
935
937
  if (v(t, e.code, "utf-8"), x && x.set(e.locale, m[e.locale]), e.stats.missing.length > 0) {
936
- D.warn(`${e.locale}: ${e.stats.compiled} compiled, ${e.stats.missing.length} missing translations`);
937
- for (let t of e.stats.missing) D.warn(` ⤷ ${t}`);
938
- } else D.success(`Compiled ${e.locale}: ${e.stats.compiled} messages → ${t}`);
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}`);
939
941
  }
940
- for (let n of O) for (let r of e) await r.onAfterCompile?.(Q(n, t[n], a.compileOutDir, a));
942
+ for (let n of D) for (let r of e) await r.onAfterCompile?.($(n, t[n], a.compileOutDir, a));
941
943
  } else {
942
944
  let e = a.plugins ?? [];
943
- for (let n of O) {
945
+ for (let n of D) {
944
946
  let r = S(a.compileOutDir, `${n}.js`);
945
- for (let t of e) await t.onBeforeCompile?.(Q(n, f[n], a.compileOutDir, a));
946
- let i = e.length > 0 ? await Z(f[n], n, e) : f[n], { code: o, stats: s } = t(i, n, y, a.sourceLocale, { skipFuzzy: b });
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 });
947
949
  if (v(r, o, "utf-8"), x && x.set(n, m[n]), s.missing.length > 0) {
948
- D.warn(`${n}: ${s.compiled} compiled, ${s.missing.length} missing translations`);
949
- for (let e of s.missing) D.warn(` ⤷ ${e}`);
950
- } else D.success(`Compiled ${n}: ${s.compiled} messages → ${r}`);
951
- for (let t of e) await t.onAfterCompile?.(Q(n, i, a.compileOutDir, a));
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));
952
954
  }
953
955
  }
954
- T > 0 && D.info(`${T} locale(s) unchanged — skipped`), x && x.save();
956
+ T > 0 && O.info(`${T} locale(s) unchanged — skipped`), x && x.save();
955
957
  let k = S(a.compileOutDir, "index.js"), A = S(a.compileOutDir, "messages.d.ts");
956
- (E || !h(k)) && (v(k, n(o, a.compileOutDir), "utf-8"), D.success(`Generated index → ${k}`)), (E || !h(A)) && (v(A, e(y, f, a.sourceLocale), "utf-8"), D.success(`Generated types → ${A}`));
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}`));
957
959
  }
958
- }), we = T({
960
+ }), Te = E({
959
961
  meta: {
960
962
  name: "stats",
961
963
  description: "Show translation progress"
@@ -967,7 +969,7 @@ var $ = T({
967
969
  async run({ args: e }) {
968
970
  let t = await u(e.config), n = p(t.locales), r = t.format === "json" ? ".json" : ".po", i = [];
969
971
  for (let e of n) {
970
- let n = Y(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) + "%" : "—";
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) + "%" : "—";
971
973
  i.push({
972
974
  locale: e,
973
975
  total: o,
@@ -975,11 +977,11 @@ var $ = T({
975
977
  pct: c
976
978
  });
977
979
  }
978
- D.log(""), D.log(" Locale │ Total │ Translated │ Progress"), D.log(" ────────┼───────┼────────────┼─────────────────────────────");
979
- for (let e of i) D.log(ne(e.locale, e.total, e.translated));
980
- D.log("");
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("");
981
983
  }
982
- }), Te = T({
984
+ }), Ee = E({
983
985
  meta: {
984
986
  name: "lint",
985
987
  description: "Check translation quality (missing, inconsistent placeholders, fuzzy)"
@@ -1001,20 +1003,20 @@ var $ = T({
1001
1003
  },
1002
1004
  async run({ args: e }) {
1003
1005
  let t = await u(e.config), n = p(t.locales), r = t.format === "json" ? ".json" : ".po", i = {};
1004
- for (let e of n) i[e] = Y(S(t.catalogDir, `${e}${r}`), t.format);
1006
+ for (let e of n) i[e] = X(S(t.catalogDir, `${e}${r}`), t.format);
1005
1007
  let a = e.locale ? [e.locale] : void 0;
1006
- D.info(`Linting ${a ? a.join(", ") : "all locales"} (source: ${t.sourceLocale})`);
1008
+ O.info(`Linting ${a ? a.join(", ") : "all locales"} (source: ${t.sourceLocale})`);
1007
1009
  let o = {
1008
1010
  sourceLocale: t.sourceLocale,
1009
1011
  strict: e.strict ?? !1
1010
1012
  };
1011
1013
  a && (o.locales = a);
1012
- let s = M(i, o);
1013
- D.log(""), D.log(P(s)), D.log("");
1014
+ let s = j(i, o);
1015
+ O.log(""), O.log(ae(s)), O.log("");
1014
1016
  let c = s.filter((e) => e.severity === "error"), l = s.filter((e) => e.severity === "warning");
1015
1017
  (c.length > 0 || e.strict && l.length > 0) && (process.exitCode = 1);
1016
1018
  }
1017
- }), Ee = T({
1019
+ }), De = E({
1018
1020
  meta: {
1019
1021
  name: "check",
1020
1022
  description: "Check translation coverage for CI"
@@ -1045,10 +1047,10 @@ var $ = T({
1045
1047
  },
1046
1048
  async run({ args: e }) {
1047
1049
  let t = await u(e.config), n = p(t.locales), r = t.format === "json" ? ".json" : ".po", i = {};
1048
- for (let e of n) i[e] = Y(S(t.catalogDir, `${e}${r}`), t.format);
1050
+ for (let e of n) i[e] = X(S(t.catalogDir, `${e}${r}`), t.format);
1049
1051
  let a = parseFloat(e["min-coverage"] ?? "100");
1050
1052
  if (isNaN(a) || a < 0 || a > 100) {
1051
- D.error("Invalid --min-coverage. Must be a number between 0 and 100."), process.exitCode = 1;
1053
+ O.error("Invalid --min-coverage. Must be a number between 0 and 100."), process.exitCode = 1;
1052
1054
  return;
1053
1055
  }
1054
1056
  let o = e.format ?? (e.ci ? "github" : "text"), s = {
@@ -1057,21 +1059,21 @@ var $ = T({
1057
1059
  format: o
1058
1060
  };
1059
1061
  e.locale && (s.locale = e.locale);
1060
- let c = ie(i, s);
1062
+ let c = P(i, s);
1061
1063
  switch (o) {
1062
1064
  case "json":
1063
- D.log(se(c));
1065
+ O.log(ce(c));
1064
1066
  break;
1065
1067
  case "github":
1066
- D.log(oe(c, t.catalogDir, t.format));
1068
+ O.log(se(c, t.catalogDir, t.format));
1067
1069
  break;
1068
1070
  default:
1069
- D.log(""), D.log(ae(c)), D.log("");
1071
+ O.log(""), O.log(oe(c)), O.log("");
1070
1072
  break;
1071
1073
  }
1072
1074
  c.passed || (process.exitCode = 1);
1073
1075
  }
1074
- }), De = T({
1076
+ }), Oe = E({
1075
1077
  meta: {
1076
1078
  name: "translate",
1077
1079
  description: "Translate messages using AI (Claude Code or Codex CLI)"
@@ -1108,30 +1110,30 @@ var $ = T({
1108
1110
  async run({ args: e }) {
1109
1111
  let t = await u(e.config), n = p(t.locales), r = e.provider;
1110
1112
  if (r !== "claude" && r !== "codex") {
1111
- D.error(`Invalid provider "${r}". Use "claude" or "codex".`);
1113
+ O.error(`Invalid provider "${r}". Use "claude" or "codex".`);
1112
1114
  return;
1113
1115
  }
1114
1116
  let i = parseInt(e["batch-size"] ?? "50", 10);
1115
1117
  if (isNaN(i) || i < 1) {
1116
- D.error("Invalid batch-size. Must be a positive integer.");
1118
+ O.error("Invalid batch-size. Must be a positive integer.");
1117
1119
  return;
1118
1120
  }
1119
1121
  let a = e.locale ? [e.locale] : n.filter((e) => e !== t.sourceLocale);
1120
1122
  if (a.length === 0) {
1121
- D.warn("No target locales to translate.");
1123
+ O.warn("No target locales to translate.");
1122
1124
  return;
1123
1125
  }
1124
- D.info(`Translating with ${r} (batch size: ${i})`);
1126
+ O.info(`Translating with ${r} (batch size: ${i})`);
1125
1127
  let o = t.format === "json" ? ".json" : ".po";
1126
1128
  for (let n of a) {
1127
- D.info(`\n[${n}]`);
1128
- let a = S(t.catalogDir, `${n}${o}`), s = Y(a, t.format);
1129
+ O.info(`\n[${n}]`);
1130
+ let a = S(t.catalogDir, `${n}${o}`), s = X(a, t.format);
1129
1131
  if (e["dry-run"]) {
1130
1132
  let e = Object.entries(s).filter(([, e]) => !e.obsolete && (!e.translation || e.translation.length === 0));
1131
1133
  if (e.length > 0) {
1132
- for (let [t, n] of e) D.log(` ${t}: ${n.message ?? t}`);
1133
- D.success(` ${n}: ${e.length} messages would be translated (dry-run)`);
1134
- } else D.success(` ${n}: already fully translated`);
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`);
1135
1137
  continue;
1136
1138
  }
1137
1139
  let { catalog: c, translated: l } = await U({
@@ -1142,10 +1144,10 @@ var $ = T({
1142
1144
  batchSize: i,
1143
1145
  ...e.context ? { context: e.context } : {}
1144
1146
  });
1145
- l > 0 ? (X(a, c, t.format), D.success(` ${n}: ${l} messages translated`)) : D.success(` ${n}: already fully translated`);
1147
+ l > 0 ? (Z(a, c, t.format), O.success(` ${n}: ${l} messages translated`)) : O.success(` ${n}: already fully translated`);
1146
1148
  }
1147
1149
  }
1148
- }), Oe = T({
1150
+ }), ke = E({
1149
1151
  meta: {
1150
1152
  name: "migrate",
1151
1153
  description: "Migrate from another i18n library using AI"
@@ -1170,7 +1172,7 @@ var $ = T({
1170
1172
  async run({ args: e }) {
1171
1173
  let t = e.provider;
1172
1174
  if (t !== "claude" && t !== "codex") {
1173
- D.error(`Invalid provider "${t}". Use "claude" or "codex".`);
1175
+ O.error(`Invalid provider "${t}". Use "claude" or "codex".`);
1174
1176
  return;
1175
1177
  }
1176
1178
  await he({
@@ -1180,14 +1182,14 @@ var $ = T({
1180
1182
  });
1181
1183
  }
1182
1184
  });
1183
- E(T({
1185
+ D(E({
1184
1186
  meta: {
1185
1187
  name: "fluenti",
1186
1188
  version: "0.0.1",
1187
1189
  description: "Compile-time i18n for modern frameworks"
1188
1190
  },
1189
1191
  subCommands: {
1190
- init: T({
1192
+ init: E({
1191
1193
  meta: {
1192
1194
  name: "init",
1193
1195
  description: "Initialize Fluenti in your project"
@@ -1198,12 +1200,12 @@ E(T({
1198
1200
  }
1199
1201
  }),
1200
1202
  extract: Se,
1201
- compile: $,
1202
- stats: we,
1203
- lint: Te,
1204
- check: Ee,
1205
- translate: De,
1206
- migrate: Oe
1203
+ compile: we,
1204
+ stats: Te,
1205
+ lint: Ee,
1206
+ check: De,
1207
+ translate: Oe,
1208
+ migrate: ke
1207
1209
  }
1208
1210
  }));
1209
1211
  //#endregion