@let-value/translate-extract 1.2.3 → 1.2.5

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/bin/cli.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- const require_run = require("../run-Bcz92fEY.cjs");
2
+ const require_run = require("../run-CFFMFcbP.cjs");
3
3
  let node_util = require("node:util");
4
4
  let chalk = require("chalk");
5
5
  chalk = require_run.__toESM(chalk, 1);
package/dist/bin/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as run } from "../run-CzeTVOug.mjs";
2
+ import { t as run } from "../run-Cpimgi_3.mjs";
3
3
  import { parseArgs } from "node:util";
4
4
  import chalk from "chalk";
5
5
  import log from "loglevel";
@@ -233,7 +233,11 @@ interface UserConfig {
233
233
  */
234
234
  walk?: boolean;
235
235
  /**
236
- * Paths or patterns to exclude from extraction, applied to all entrypoints
236
+ * Paths or patterns to exclude from extraction, applied to all entrypoints.
237
+ * Also matched against the specifier of an import that could not be
238
+ * resolved, so it doubles as an ignore list for such imports — a matching
239
+ * specifier is skipped without a warning. Bundler-virtual specifiers
240
+ * (`virtual:…`, `\0…`, URL schemes) are skipped without configuration.
237
241
  * @default [/node_modules/, /dist/, /build/]
238
242
  * @see Can be overridden per entrypoint via `exclude` in {@link EntrypointConfig}.
239
243
  */
@@ -265,4 +269,4 @@ interface ResolvedConfig {
265
269
  declare function defineConfig(config: UserConfig): ResolvedConfig;
266
270
  //#endregion
267
271
  export { po as A, ProcessHook as C, StaticPlugin as D, UniversalPlugin as E, cleanup$1 as F, Logger as I, react$1 as M, po$1 as N, cleanup as O, core$1 as P, ProcessArgs as S, SourceArgs as T, LoadArgs as _, ExcludeFn as a, OutputsHook as b, ResolvedEntrypoint as c, Build as d, CollectedArgs as f, ImportReference as g, FileTranslations as h, ExcludeConfig as i, react as j, core as k, UserConfig as l, Context as m, EntrypointConfig as n, ObsoleteStrategy as o, CollectedHook as p, Exclude as r, ResolvedConfig as s, DestinationFn as t, defineConfig as u, LoadHook as v, ResolveArgs as w, Plugin as x, OutputsArgs as y };
268
- //# sourceMappingURL=configuration-DLSMbmU5.d.cts.map
272
+ //# sourceMappingURL=configuration-CoElcSHz.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"configuration-Bwtek7Fh.d.mts","names":[],"sources":["../src/logger.ts","../src/plugins/core/queries/types.ts","../src/plugins/cleanup/cleanup.ts","../src/plugins/core/core.ts","../src/plugins/po/po.ts","../src/plugins/react/react.ts","../src/static.ts","../src/plugin.ts","../src/exclude.ts","../src/configuration.ts"],"mappings":";;;;KAIY,SAAS,IAAI;KACb,gBAAgB,IAAI;KACpB,WAAW;;;UCHN;EACb;EACA;EACA;EACA;EACA;;UAGa;EACb;EACA;EACA;EACA;EACA,WAAW;EACX;;;;iBCVY,aAAW;;;iBCEX,UAAQ;;;iBCCR,QAAM;;;iBCLN,WAAS;;;iBCAT,QAAQ,OAAO,kBAAkB;;;;;;iBASjC,SAAS,OAAO,kBAAkB;;;;;;iBAQlC,MAAM,OAAO,kBAAkB;;;;;;iBAS/B,WAAW,OAAO,kBAAkB;;;;;;KASxC,eACN,kBAAkB,QAClB,kBAAkB,SAClB,kBAAkB,MAClB,kBAAkB;;;KCvCnB,aAAa,KAAK,IAAI,QAAQ;UAElB;EACb,QAAQ;EACR,aAAa;;EAEb,OAAO;EACP,SAAS;;UAGI;EACb;EACA;EACA;;;UAIa,YAAY;EACzB;EACA;EACA;EACA,SAAS;EACT,OAAO;;UAGM;EACb;EACA;EACA,SAAS;;UAGI;EACb;EACA;;;KAIQ,YAAY,MAAM,aAAa;UAE1B;EACb;EACA;EACA;;EAEA,KAAK,cAAc;;;KAIX,eAAe,MAAM,gBAAgB;UAEhC;EACb;EACA,cAAc;;UAGD;EACb;;EAEA,OAAO;;;;;;;EAOP,OAAO,cAAc,eAAe;;;KAI5B,iBAAiB,MAAM,kBAAkB;UAEpC;;EAEb;;;KAIQ,eAAe,MAAM,gBAAgB;UAEhC;EACb,SAAS;;;;;;;EAOT,OAAO,MAAM;EACb,OAAO,QAAQ,QAAQ,MAAM;EAC7B,UAAU,QAAQ,QAAQ,MAAM;EAChC,YAAY,MAAM;EAClB,UAAU,MAAM;;UAGH;EACb;EACA,MAAM,OAAO;;KAGL,kBAAkB,SAAS;;;cC3F1B;WACW,YAAA,QAAA;WACH,SAAA,QAAA;WACC,UAAA,QAAA;WACO,UAAA,QAAA,OAAA;;KAGjB,wBAAwB;;;KCZxB,iBAAiB;EAAQ;EAAgB;EAAoB;;KAC7D,aAAa,MAAM;KACnB,UAAU,SAAS;KACnB,gBAAgB,SAAS,cAAc,gBAAgB,mBAAmB;cAEhF;;;;;KACD,wBAAwB;;;;;;KAOjB;UAEK;EACb;EACA,cAAc;EACd,WAAW;EACX;EACA,UAAU;;UAGG;;;;;;EAMb,gBAAgB;;;;;;EAMhB,UAAU;;;;;;EAMV,UAAU,sBAAsB,gBAAgB,mBAAmB;;;;;;;;EAQnE,sBAAsB,mBAAmB,eAAe;;;;;;;EAOxD,cAAc;;;;;;;EAOd,WAAW;;;;;;EAMX;;;;;;EAMA,UAAU;;;;;EAKV,WAAW;;UAGE,2BAA2B,KAAK;EAC7C,UAAU;;UAGG;EACb,SAAS;EACT,aAAa;EACb;EACA;EACA,aAAa;EACb,UAAU;EACV;EACA,UAAU;EACV,SAAS;;;;;;iBA+CG,aAAa,QAAQ,aAAa"}
1
+ {"version":3,"file":"configuration-CoElcSHz.d.cts","names":[],"sources":["../src/logger.ts","../src/plugins/core/queries/types.ts","../src/plugins/cleanup/cleanup.ts","../src/plugins/core/core.ts","../src/plugins/po/po.ts","../src/plugins/react/react.ts","../src/static.ts","../src/plugin.ts","../src/exclude.ts","../src/configuration.ts"],"mappings":";;;;KAIY,SAAS,IAAI;KACb,gBAAgB,IAAI;KACpB,WAAW;;;UCHN;EACb;EACA;EACA;EACA;EACA;;UAGa;EACb;EACA;EACA;EACA;EACA,WAAW;EACX;;;;iBCVY,aAAW;;;iBCEX,UAAQ;;;iBCCR,QAAM;;;iBCLN,WAAS;;;iBCAT,QAAQ,OAAO,kBAAkB;;;;;;iBASjC,SAAS,OAAO,kBAAkB;;;;;;iBAQlC,MAAM,OAAO,kBAAkB;;;;;;iBAS/B,WAAW,OAAO,kBAAkB;;;;;;KASxC,eACN,kBAAkB,QAClB,kBAAkB,SAClB,kBAAkB,MAClB,kBAAkB;;;KCvCnB,aAAa,KAAK,IAAI,QAAQ;UAElB;EACb,QAAQ;EACR,aAAa;;EAEb,OAAO;EACP,SAAS;;UAGI;EACb;EACA;EACA;;;UAIa,YAAY;EACzB;EACA;EACA;EACA,SAAS;EACT,OAAO;;UAGM;EACb;EACA;EACA,SAAS;;UAGI;EACb;EACA;;;KAIQ,YAAY,MAAM,aAAa;UAE1B;EACb;EACA;EACA;;EAEA,KAAK,cAAc;;;KAIX,eAAe,MAAM,gBAAgB;UAEhC;EACb;EACA,cAAc;;UAGD;EACb;;EAEA,OAAO;;;;;;;EAOP,OAAO,cAAc,eAAe;;;KAI5B,iBAAiB,MAAM,kBAAkB;UAEpC;;EAEb;;;KAIQ,eAAe,MAAM,gBAAgB;UAEhC;EACb,SAAS;;;;;;;EAOT,OAAO,MAAM;EACb,OAAO,QAAQ,QAAQ,MAAM;EAC7B,UAAU,QAAQ,QAAQ,MAAM;EAChC,YAAY,MAAM;EAClB,UAAU,MAAM;;UAGH;EACb;EACA,MAAM,OAAO;;KAGL,kBAAkB,SAAS;;;cC3F1B;WACW,YAAA,QAAA;WACH,SAAA,QAAA;WACC,UAAA,QAAA;WACO,UAAA,QAAA,OAAA;;KAGjB,wBAAwB;;;KCZxB,iBAAiB;EAAQ;EAAgB;EAAoB;;KAC7D,aAAa,MAAM;KACnB,UAAU,SAAS;KACnB,gBAAgB,SAAS,cAAc,gBAAgB,mBAAmB;cAEhF;;;;;KACD,wBAAwB;;;;;;KAOjB;UAEK;EACb;EACA,cAAc;EACd,WAAW;EACX;EACA,UAAU;;UAGG;;;;;;EAMb,gBAAgB;;;;;;EAMhB,UAAU;;;;;;EAMV,UAAU,sBAAsB,gBAAgB,mBAAmB;;;;;;;;EAQnE,sBAAsB,mBAAmB,eAAe;;;;;;;EAOxD,cAAc;;;;;;;EAOd,WAAW;;;;;;EAMX;;;;;;;;;;EAUA,UAAU;;;;;EAKV,WAAW;;UAGE,2BAA2B,KAAK;EAC7C,UAAU;;UAGG;EACb,SAAS;EACT,aAAa;EACb;EACA;EACA,aAAa;EACb,UAAU;EACV;EACA,UAAU;EACV,SAAS;;;;;;iBA+CG,aAAa,QAAQ,aAAa"}
@@ -233,7 +233,11 @@ interface UserConfig {
233
233
  */
234
234
  walk?: boolean;
235
235
  /**
236
- * Paths or patterns to exclude from extraction, applied to all entrypoints
236
+ * Paths or patterns to exclude from extraction, applied to all entrypoints.
237
+ * Also matched against the specifier of an import that could not be
238
+ * resolved, so it doubles as an ignore list for such imports — a matching
239
+ * specifier is skipped without a warning. Bundler-virtual specifiers
240
+ * (`virtual:…`, `\0…`, URL schemes) are skipped without configuration.
237
241
  * @default [/node_modules/, /dist/, /build/]
238
242
  * @see Can be overridden per entrypoint via `exclude` in {@link EntrypointConfig}.
239
243
  */
@@ -265,4 +269,4 @@ interface ResolvedConfig {
265
269
  declare function defineConfig(config: UserConfig): ResolvedConfig;
266
270
  //#endregion
267
271
  export { po as A, ProcessHook as C, StaticPlugin as D, UniversalPlugin as E, cleanup$1 as F, Logger as I, react$1 as M, po$1 as N, cleanup as O, core$1 as P, ProcessArgs as S, SourceArgs as T, LoadArgs as _, ExcludeFn as a, OutputsHook as b, ResolvedEntrypoint as c, Build as d, CollectedArgs as f, ImportReference as g, FileTranslations as h, ExcludeConfig as i, react as j, core as k, UserConfig as l, Context as m, EntrypointConfig as n, ObsoleteStrategy as o, CollectedHook as p, Exclude as r, ResolvedConfig as s, DestinationFn as t, defineConfig as u, LoadHook as v, ResolveArgs as w, Plugin as x, OutputsArgs as y };
268
- //# sourceMappingURL=configuration-Bwtek7Fh.d.mts.map
272
+ //# sourceMappingURL=configuration-s7zv58Wf.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"configuration-DLSMbmU5.d.cts","names":[],"sources":["../src/logger.ts","../src/plugins/core/queries/types.ts","../src/plugins/cleanup/cleanup.ts","../src/plugins/core/core.ts","../src/plugins/po/po.ts","../src/plugins/react/react.ts","../src/static.ts","../src/plugin.ts","../src/exclude.ts","../src/configuration.ts"],"mappings":";;;;KAIY,SAAS,IAAI;KACb,gBAAgB,IAAI;KACpB,WAAW;;;UCHN;EACb;EACA;EACA;EACA;EACA;;UAGa;EACb;EACA;EACA;EACA;EACA,WAAW;EACX;;;;iBCVY,aAAW;;;iBCEX,UAAQ;;;iBCCR,QAAM;;;iBCLN,WAAS;;;iBCAT,QAAQ,OAAO,kBAAkB;;;;;;iBASjC,SAAS,OAAO,kBAAkB;;;;;;iBAQlC,MAAM,OAAO,kBAAkB;;;;;;iBAS/B,WAAW,OAAO,kBAAkB;;;;;;KASxC,eACN,kBAAkB,QAClB,kBAAkB,SAClB,kBAAkB,MAClB,kBAAkB;;;KCvCnB,aAAa,KAAK,IAAI,QAAQ;UAElB;EACb,QAAQ;EACR,aAAa;;EAEb,OAAO;EACP,SAAS;;UAGI;EACb;EACA;EACA;;;UAIa,YAAY;EACzB;EACA;EACA;EACA,SAAS;EACT,OAAO;;UAGM;EACb;EACA;EACA,SAAS;;UAGI;EACb;EACA;;;KAIQ,YAAY,MAAM,aAAa;UAE1B;EACb;EACA;EACA;;EAEA,KAAK,cAAc;;;KAIX,eAAe,MAAM,gBAAgB;UAEhC;EACb;EACA,cAAc;;UAGD;EACb;;EAEA,OAAO;;;;;;;EAOP,OAAO,cAAc,eAAe;;;KAI5B,iBAAiB,MAAM,kBAAkB;UAEpC;;EAEb;;;KAIQ,eAAe,MAAM,gBAAgB;UAEhC;EACb,SAAS;;;;;;;EAOT,OAAO,MAAM;EACb,OAAO,QAAQ,QAAQ,MAAM;EAC7B,UAAU,QAAQ,QAAQ,MAAM;EAChC,YAAY,MAAM;EAClB,UAAU,MAAM;;UAGH;EACb;EACA,MAAM,OAAO;;KAGL,kBAAkB,SAAS;;;cC3F1B;WACW,YAAA,QAAA;WACH,SAAA,QAAA;WACC,UAAA,QAAA;WACO,UAAA,QAAA,OAAA;;KAGjB,wBAAwB;;;KCZxB,iBAAiB;EAAQ;EAAgB;EAAoB;;KAC7D,aAAa,MAAM;KACnB,UAAU,SAAS;KACnB,gBAAgB,SAAS,cAAc,gBAAgB,mBAAmB;cAEhF;;;;;KACD,wBAAwB;;;;;;KAOjB;UAEK;EACb;EACA,cAAc;EACd,WAAW;EACX;EACA,UAAU;;UAGG;;;;;;EAMb,gBAAgB;;;;;;EAMhB,UAAU;;;;;;EAMV,UAAU,sBAAsB,gBAAgB,mBAAmB;;;;;;;;EAQnE,sBAAsB,mBAAmB,eAAe;;;;;;;EAOxD,cAAc;;;;;;;EAOd,WAAW;;;;;;EAMX;;;;;;EAMA,UAAU;;;;;EAKV,WAAW;;UAGE,2BAA2B,KAAK;EAC7C,UAAU;;UAGG;EACb,SAAS;EACT,aAAa;EACb;EACA;EACA,aAAa;EACb,UAAU;EACV;EACA,UAAU;EACV,SAAS;;;;;;iBA+CG,aAAa,QAAQ,aAAa"}
1
+ {"version":3,"file":"configuration-s7zv58Wf.d.mts","names":[],"sources":["../src/logger.ts","../src/plugins/core/queries/types.ts","../src/plugins/cleanup/cleanup.ts","../src/plugins/core/core.ts","../src/plugins/po/po.ts","../src/plugins/react/react.ts","../src/static.ts","../src/plugin.ts","../src/exclude.ts","../src/configuration.ts"],"mappings":";;;;KAIY,SAAS,IAAI;KACb,gBAAgB,IAAI;KACpB,WAAW;;;UCHN;EACb;EACA;EACA;EACA;EACA;;UAGa;EACb;EACA;EACA;EACA;EACA,WAAW;EACX;;;;iBCVY,aAAW;;;iBCEX,UAAQ;;;iBCCR,QAAM;;;iBCLN,WAAS;;;iBCAT,QAAQ,OAAO,kBAAkB;;;;;;iBASjC,SAAS,OAAO,kBAAkB;;;;;;iBAQlC,MAAM,OAAO,kBAAkB;;;;;;iBAS/B,WAAW,OAAO,kBAAkB;;;;;;KASxC,eACN,kBAAkB,QAClB,kBAAkB,SAClB,kBAAkB,MAClB,kBAAkB;;;KCvCnB,aAAa,KAAK,IAAI,QAAQ;UAElB;EACb,QAAQ;EACR,aAAa;;EAEb,OAAO;EACP,SAAS;;UAGI;EACb;EACA;EACA;;;UAIa,YAAY;EACzB;EACA;EACA;EACA,SAAS;EACT,OAAO;;UAGM;EACb;EACA;EACA,SAAS;;UAGI;EACb;EACA;;;KAIQ,YAAY,MAAM,aAAa;UAE1B;EACb;EACA;EACA;;EAEA,KAAK,cAAc;;;KAIX,eAAe,MAAM,gBAAgB;UAEhC;EACb;EACA,cAAc;;UAGD;EACb;;EAEA,OAAO;;;;;;;EAOP,OAAO,cAAc,eAAe;;;KAI5B,iBAAiB,MAAM,kBAAkB;UAEpC;;EAEb;;;KAIQ,eAAe,MAAM,gBAAgB;UAEhC;EACb,SAAS;;;;;;;EAOT,OAAO,MAAM;EACb,OAAO,QAAQ,QAAQ,MAAM;EAC7B,UAAU,QAAQ,QAAQ,MAAM;EAChC,YAAY,MAAM;EAClB,UAAU,MAAM;;UAGH;EACb;EACA,MAAM,OAAO;;KAGL,kBAAkB,SAAS;;;cC3F1B;WACW,YAAA,QAAA;WACH,SAAA,QAAA;WACC,UAAA,QAAA;WACO,UAAA,QAAA,OAAA;;KAGjB,wBAAwB;;;KCZxB,iBAAiB;EAAQ;EAAgB;EAAoB;;KAC7D,aAAa,MAAM;KACnB,UAAU,SAAS;KACnB,gBAAgB,SAAS,cAAc,gBAAgB,mBAAmB;cAEhF;;;;;KACD,wBAAwB;;;;;;KAOjB;UAEK;EACb;EACA,cAAc;EACd,WAAW;EACX;EACA,UAAU;;UAGG;;;;;;EAMb,gBAAgB;;;;;;EAMhB,UAAU;;;;;;EAMV,UAAU,sBAAsB,gBAAgB,mBAAmB;;;;;;;;EAQnE,sBAAsB,mBAAmB,eAAe;;;;;;;EAOxD,cAAc;;;;;;;EAOd,WAAW;;;;;;EAMX;;;;;;;;;;EAUA,UAAU;;;;;EAKV,WAAW;;UAGE,2BAA2B,KAAK;EAC7C,UAAU;;UAGG;EACb,SAAS;EACT,aAAa;EACb;EACA;EACA,aAAa;EACb,UAAU;EACV;EACA,UAAU;EACV,SAAS;;;;;;iBA+CG,aAAa,QAAQ,aAAa"}
@@ -582,6 +582,16 @@ function isBuiltin(spec) {
582
582
  const [base, subpath] = (spec.startsWith("node:") ? spec.slice(5) : spec).split("/", 2);
583
583
  return subpath !== void 0 && builtins.has(base);
584
584
  }
585
+ const schemePattern = /^[a-z][a-z\d+\-.]+:/i;
586
+ /**
587
+ * Specifiers that exist only inside a bundler's plugin pipeline — Vite virtual
588
+ * modules (`virtual:pwa-register`), their resolved `\0` form, and URL schemes.
589
+ * Extraction runs without that pipeline, so they can never resolve on disk and
590
+ * reporting them as unresolved is noise.
591
+ */
592
+ function isExternal(spec) {
593
+ return spec.startsWith("\0") || schemePattern.test(spec);
594
+ }
585
595
  function getResolver(dir) {
586
596
  const tsconfig = findTsconfig(dir);
587
597
  const key = tsconfig ?? "__default__";
@@ -621,10 +631,15 @@ function resolveImportResults(file, imports) {
621
631
  const resolver = getResolver(dir);
622
632
  const resolved = [];
623
633
  const unresolved = [];
634
+ const external = [];
624
635
  for (const imp of imports) {
625
636
  const ref = normalizeImportReference(imp);
626
637
  const { spec } = ref;
627
638
  if (isBuiltin(spec)) continue;
639
+ if (isExternal(spec)) {
640
+ external.push(spec);
641
+ continue;
642
+ }
628
643
  try {
629
644
  const res = resolver.sync(dir, spec);
630
645
  if (res.path) resolved.push({
@@ -647,7 +662,8 @@ function resolveImportResults(file, imports) {
647
662
  }
648
663
  return {
649
664
  resolved,
650
- unresolved
665
+ unresolved,
666
+ external
651
667
  };
652
668
  }
653
669
  //#endregion
@@ -658,6 +674,12 @@ function core() {
658
674
  name: "core",
659
675
  setup(build) {
660
676
  build.context.logger?.debug("core plugin initialized");
677
+ const reported = /* @__PURE__ */ new Set();
678
+ const warnOnce = (message) => {
679
+ if (reported.has(message)) return;
680
+ reported.add(message);
681
+ build.context.logger?.warn(message);
682
+ };
661
683
  build.onLoad(filter$1, ({ path }) => (0, node_fs_promises.readFile)(path, "utf8"));
662
684
  build.onProcess(filter$1, ({ entrypoint, path, contents, emit }) => {
663
685
  const result = parseSource$1(contents, path);
@@ -670,7 +692,11 @@ function core() {
670
692
  }
671
693
  const { translations, imports, warnings } = result;
672
694
  if (build.context.config.walk) {
673
- const { resolved, unresolved } = resolveImportResults(path, imports);
695
+ const { resolved, unresolved, external } = resolveImportResults(path, imports);
696
+ for (const spec of external) build.context.logger?.debug({
697
+ path,
698
+ spec
699
+ }, "skipping external import");
674
700
  for (const result of resolved) {
675
701
  if (build.context.paths.has(result.path)) continue;
676
702
  build.source({
@@ -687,20 +713,62 @@ function core() {
687
713
  namespace: "source",
688
714
  import: imp
689
715
  }, build.context.config.exclude)) continue;
690
- build.context.logger?.warn(`Unable to resolve import "${spec}" from ${path}${error ? `: ${error}` : ""}`);
716
+ warnOnce(`Unable to resolve import "${spec}" from ${path}${error ? `: ${error}` : ""}`);
691
717
  }
692
718
  }
693
- for (const warning of warnings) build.context.logger?.warn(`${warning.error} at ${warning.reference}`);
719
+ for (const warning of warnings) warnOnce(`${warning.error} at ${warning.reference}`);
694
720
  emit(translations);
695
721
  });
696
722
  }
697
723
  };
698
724
  }
699
725
  //#endregion
726
+ //#region src/plugins/po/references.ts
727
+ const referencePattern = /^(.*?):(\d+)(?::(\d+))?$/;
728
+ function parseReference(reference) {
729
+ const match = referencePattern.exec(reference);
730
+ if (!match) return {
731
+ path: reference,
732
+ line: -1,
733
+ column: -1
734
+ };
735
+ return {
736
+ path: match[1],
737
+ line: Number(match[2]),
738
+ column: match[3] ? Number(match[3]) : -1
739
+ };
740
+ }
741
+ function comparePaths(left, right) {
742
+ if (left === right) return 0;
743
+ return left < right ? -1 : 1;
744
+ }
745
+ /**
746
+ * Orders reference comments canonically — by file path, then line, then column —
747
+ * so that a catalog does not record the order in which the module graph happened
748
+ * to be walked.
749
+ */
750
+ function sortReferences(references) {
751
+ return [...references].map((reference) => ({
752
+ reference,
753
+ parsed: parseReference(reference)
754
+ })).sort((left, right) => {
755
+ const byPath = comparePaths(left.parsed.path, right.parsed.path);
756
+ if (byPath !== 0) return byPath;
757
+ if (left.parsed.line !== right.parsed.line) return left.parsed.line - right.parsed.line;
758
+ if (left.parsed.column !== right.parsed.column) return left.parsed.column - right.parsed.column;
759
+ return comparePaths(left.reference, right.reference);
760
+ }).map(({ reference }) => reference);
761
+ }
762
+ /** Orders message keys (contexts and msgids) canonically. */
763
+ function sortKeys(keys) {
764
+ return [...keys].sort(comparePaths);
765
+ }
766
+ //#endregion
700
767
  //#region src/plugins/po/collect.ts
701
- function collect(source, locale) {
768
+ function collect(source, locale, defaultLocale) {
702
769
  const translations = { "": {} };
703
770
  const nplurals = locale ? Number((0, plural_forms.getNPlurals)(locale)) : void 0;
771
+ const isDefaultLocale = locale !== void 0 && locale === defaultLocale;
704
772
  for (const { context, id, message, comments, obsolete, plural } of source) {
705
773
  const ctx = context || "";
706
774
  if (!translations[ctx]) translations[ctx] = {};
@@ -713,7 +781,7 @@ function collect(source, locale) {
713
781
  if (comments?.reference) comments.reference.split(/\r?\n|\r/).forEach((r) => {
714
782
  refs.add(r);
715
783
  });
716
- const msgstr = existing?.msgstr ? existing.msgstr.slice(0, length) : Array.from({ length }, () => "");
784
+ const msgstr = existing?.msgstr ? existing.msgstr.slice(0, length) : Array.from({ length }, (_, i) => isDefaultLocale ? message[i] ?? "" : "");
717
785
  while (msgstr.length < length) msgstr.push("");
718
786
  translations[ctx][id] = {
719
787
  msgctxt: context || void 0,
@@ -723,7 +791,7 @@ function collect(source, locale) {
723
791
  comments: {
724
792
  ...existing?.comments,
725
793
  ...comments,
726
- reference: refs.size ? Array.from(refs).join("\n") : void 0
794
+ reference: refs.size ? sortReferences(refs).join("\n") : void 0
727
795
  },
728
796
  obsolete: existing?.obsolete ?? obsolete
729
797
  };
@@ -810,14 +878,16 @@ function merge(sources, existing, obsolete, locale, generatedAt) {
810
878
  comments: {
811
879
  ...existing?.comments,
812
880
  ...entry.comments,
813
- reference: refs.size ? Array.from(refs).join("\n") : void 0
881
+ reference: refs.size ? sortReferences(refs).join("\n") : void 0
814
882
  }
815
883
  };
816
884
  }
817
885
  }
818
- for (const [ctx, msgs] of Object.entries(collected)) {
886
+ for (const ctx of sortKeys(Object.keys(collected))) {
887
+ const msgs = collected[ctx];
819
888
  if (!translations[ctx]) translations[ctx] = {};
820
- for (const [id, entry] of Object.entries(msgs)) {
889
+ for (const id of sortKeys(Object.keys(msgs))) {
890
+ const entry = msgs[id];
821
891
  const existingEntry = translations[ctx][id] ?? obsoleteTranslations[ctx]?.[id];
822
892
  if (existingEntry) {
823
893
  entry.msgstr = existingEntry.msgstr;
@@ -887,7 +957,7 @@ function po() {
887
957
  output(destination, async () => {
888
958
  const contents = await node_fs_promises.default.readFile(destination).catch(() => void 0);
889
959
  const existing = contents ? gettext_parser.po.parse(contents) : void 0;
890
- const out = merge([{ translations: collect(created.translations, created.locale) }], existing, build.context.config.obsolete, created.locale, build.context.generatedAt);
960
+ const out = merge([{ translations: collect(created.translations, created.locale, build.context.config.defaultLocale) }], existing, build.context.config.obsolete, created.locale, build.context.generatedAt);
891
961
  if (hasChanges(out, existing)) {
892
962
  await node_fs_promises.default.mkdir((0, node_path.dirname)(destination), { recursive: true });
893
963
  await node_fs_promises.default.writeFile(destination, gettext_parser.po.compile(out));
@@ -1194,9 +1264,15 @@ function react() {
1194
1264
  name: "react",
1195
1265
  setup(build) {
1196
1266
  build.context.logger?.debug("react plugin initialized");
1267
+ const reported = /* @__PURE__ */ new Set();
1197
1268
  build.onProcess(filter, ({ path, contents, emit }) => {
1198
1269
  const { translations, warnings } = parseSource(contents, path);
1199
- for (const warning of warnings) build.context.logger?.warn(`${warning.error} at ${warning.reference}`);
1270
+ for (const warning of warnings) {
1271
+ const message = `${warning.error} at ${warning.reference}`;
1272
+ if (reported.has(message)) continue;
1273
+ reported.add(message);
1274
+ build.context.logger?.warn(message);
1275
+ }
1200
1276
  emit(translations);
1201
1277
  });
1202
1278
  }
@@ -552,6 +552,16 @@ function isBuiltin(spec) {
552
552
  const [base, subpath] = (spec.startsWith("node:") ? spec.slice(5) : spec).split("/", 2);
553
553
  return subpath !== void 0 && builtins.has(base);
554
554
  }
555
+ const schemePattern = /^[a-z][a-z\d+\-.]+:/i;
556
+ /**
557
+ * Specifiers that exist only inside a bundler's plugin pipeline — Vite virtual
558
+ * modules (`virtual:pwa-register`), their resolved `\0` form, and URL schemes.
559
+ * Extraction runs without that pipeline, so they can never resolve on disk and
560
+ * reporting them as unresolved is noise.
561
+ */
562
+ function isExternal(spec) {
563
+ return spec.startsWith("\0") || schemePattern.test(spec);
564
+ }
555
565
  function getResolver(dir) {
556
566
  const tsconfig = findTsconfig(dir);
557
567
  const key = tsconfig ?? "__default__";
@@ -591,10 +601,15 @@ function resolveImportResults(file, imports) {
591
601
  const resolver = getResolver(dir);
592
602
  const resolved = [];
593
603
  const unresolved = [];
604
+ const external = [];
594
605
  for (const imp of imports) {
595
606
  const ref = normalizeImportReference(imp);
596
607
  const { spec } = ref;
597
608
  if (isBuiltin(spec)) continue;
609
+ if (isExternal(spec)) {
610
+ external.push(spec);
611
+ continue;
612
+ }
598
613
  try {
599
614
  const res = resolver.sync(dir, spec);
600
615
  if (res.path) resolved.push({
@@ -617,7 +632,8 @@ function resolveImportResults(file, imports) {
617
632
  }
618
633
  return {
619
634
  resolved,
620
- unresolved
635
+ unresolved,
636
+ external
621
637
  };
622
638
  }
623
639
  //#endregion
@@ -628,6 +644,12 @@ function core() {
628
644
  name: "core",
629
645
  setup(build) {
630
646
  build.context.logger?.debug("core plugin initialized");
647
+ const reported = /* @__PURE__ */ new Set();
648
+ const warnOnce = (message) => {
649
+ if (reported.has(message)) return;
650
+ reported.add(message);
651
+ build.context.logger?.warn(message);
652
+ };
631
653
  build.onLoad(filter$1, ({ path }) => readFile(path, "utf8"));
632
654
  build.onProcess(filter$1, ({ entrypoint, path, contents, emit }) => {
633
655
  const result = parseSource$1(contents, path);
@@ -640,7 +662,11 @@ function core() {
640
662
  }
641
663
  const { translations, imports, warnings } = result;
642
664
  if (build.context.config.walk) {
643
- const { resolved, unresolved } = resolveImportResults(path, imports);
665
+ const { resolved, unresolved, external } = resolveImportResults(path, imports);
666
+ for (const spec of external) build.context.logger?.debug({
667
+ path,
668
+ spec
669
+ }, "skipping external import");
644
670
  for (const result of resolved) {
645
671
  if (build.context.paths.has(result.path)) continue;
646
672
  build.source({
@@ -657,20 +683,62 @@ function core() {
657
683
  namespace: "source",
658
684
  import: imp
659
685
  }, build.context.config.exclude)) continue;
660
- build.context.logger?.warn(`Unable to resolve import "${spec}" from ${path}${error ? `: ${error}` : ""}`);
686
+ warnOnce(`Unable to resolve import "${spec}" from ${path}${error ? `: ${error}` : ""}`);
661
687
  }
662
688
  }
663
- for (const warning of warnings) build.context.logger?.warn(`${warning.error} at ${warning.reference}`);
689
+ for (const warning of warnings) warnOnce(`${warning.error} at ${warning.reference}`);
664
690
  emit(translations);
665
691
  });
666
692
  }
667
693
  };
668
694
  }
669
695
  //#endregion
696
+ //#region src/plugins/po/references.ts
697
+ const referencePattern = /^(.*?):(\d+)(?::(\d+))?$/;
698
+ function parseReference(reference) {
699
+ const match = referencePattern.exec(reference);
700
+ if (!match) return {
701
+ path: reference,
702
+ line: -1,
703
+ column: -1
704
+ };
705
+ return {
706
+ path: match[1],
707
+ line: Number(match[2]),
708
+ column: match[3] ? Number(match[3]) : -1
709
+ };
710
+ }
711
+ function comparePaths(left, right) {
712
+ if (left === right) return 0;
713
+ return left < right ? -1 : 1;
714
+ }
715
+ /**
716
+ * Orders reference comments canonically — by file path, then line, then column —
717
+ * so that a catalog does not record the order in which the module graph happened
718
+ * to be walked.
719
+ */
720
+ function sortReferences(references) {
721
+ return [...references].map((reference) => ({
722
+ reference,
723
+ parsed: parseReference(reference)
724
+ })).sort((left, right) => {
725
+ const byPath = comparePaths(left.parsed.path, right.parsed.path);
726
+ if (byPath !== 0) return byPath;
727
+ if (left.parsed.line !== right.parsed.line) return left.parsed.line - right.parsed.line;
728
+ if (left.parsed.column !== right.parsed.column) return left.parsed.column - right.parsed.column;
729
+ return comparePaths(left.reference, right.reference);
730
+ }).map(({ reference }) => reference);
731
+ }
732
+ /** Orders message keys (contexts and msgids) canonically. */
733
+ function sortKeys(keys) {
734
+ return [...keys].sort(comparePaths);
735
+ }
736
+ //#endregion
670
737
  //#region src/plugins/po/collect.ts
671
- function collect(source, locale) {
738
+ function collect(source, locale, defaultLocale) {
672
739
  const translations = { "": {} };
673
740
  const nplurals = locale ? Number(getNPlurals(locale)) : void 0;
741
+ const isDefaultLocale = locale !== void 0 && locale === defaultLocale;
674
742
  for (const { context, id, message, comments, obsolete, plural } of source) {
675
743
  const ctx = context || "";
676
744
  if (!translations[ctx]) translations[ctx] = {};
@@ -683,7 +751,7 @@ function collect(source, locale) {
683
751
  if (comments?.reference) comments.reference.split(/\r?\n|\r/).forEach((r) => {
684
752
  refs.add(r);
685
753
  });
686
- const msgstr = existing?.msgstr ? existing.msgstr.slice(0, length) : Array.from({ length }, () => "");
754
+ const msgstr = existing?.msgstr ? existing.msgstr.slice(0, length) : Array.from({ length }, (_, i) => isDefaultLocale ? message[i] ?? "" : "");
687
755
  while (msgstr.length < length) msgstr.push("");
688
756
  translations[ctx][id] = {
689
757
  msgctxt: context || void 0,
@@ -693,7 +761,7 @@ function collect(source, locale) {
693
761
  comments: {
694
762
  ...existing?.comments,
695
763
  ...comments,
696
- reference: refs.size ? Array.from(refs).join("\n") : void 0
764
+ reference: refs.size ? sortReferences(refs).join("\n") : void 0
697
765
  },
698
766
  obsolete: existing?.obsolete ?? obsolete
699
767
  };
@@ -780,14 +848,16 @@ function merge(sources, existing, obsolete, locale, generatedAt) {
780
848
  comments: {
781
849
  ...existing?.comments,
782
850
  ...entry.comments,
783
- reference: refs.size ? Array.from(refs).join("\n") : void 0
851
+ reference: refs.size ? sortReferences(refs).join("\n") : void 0
784
852
  }
785
853
  };
786
854
  }
787
855
  }
788
- for (const [ctx, msgs] of Object.entries(collected)) {
856
+ for (const ctx of sortKeys(Object.keys(collected))) {
857
+ const msgs = collected[ctx];
789
858
  if (!translations[ctx]) translations[ctx] = {};
790
- for (const [id, entry] of Object.entries(msgs)) {
859
+ for (const id of sortKeys(Object.keys(msgs))) {
860
+ const entry = msgs[id];
791
861
  const existingEntry = translations[ctx][id] ?? obsoleteTranslations[ctx]?.[id];
792
862
  if (existingEntry) {
793
863
  entry.msgstr = existingEntry.msgstr;
@@ -857,7 +927,7 @@ function po() {
857
927
  output(destination, async () => {
858
928
  const contents = await fs.readFile(destination).catch(() => void 0);
859
929
  const existing = contents ? gettextParser.po.parse(contents) : void 0;
860
- const out = merge([{ translations: collect(created.translations, created.locale) }], existing, build.context.config.obsolete, created.locale, build.context.generatedAt);
930
+ const out = merge([{ translations: collect(created.translations, created.locale, build.context.config.defaultLocale) }], existing, build.context.config.obsolete, created.locale, build.context.generatedAt);
861
931
  if (hasChanges(out, existing)) {
862
932
  await fs.mkdir(dirname(destination), { recursive: true });
863
933
  await fs.writeFile(destination, gettextParser.po.compile(out));
@@ -1164,9 +1234,15 @@ function react() {
1164
1234
  name: "react",
1165
1235
  setup(build) {
1166
1236
  build.context.logger?.debug("react plugin initialized");
1237
+ const reported = /* @__PURE__ */ new Set();
1167
1238
  build.onProcess(filter, ({ path, contents, emit }) => {
1168
1239
  const { translations, warnings } = parseSource(contents, path);
1169
- for (const warning of warnings) build.context.logger?.warn(`${warning.error} at ${warning.reference}`);
1240
+ for (const warning of warnings) {
1241
+ const message = `${warning.error} at ${warning.reference}`;
1242
+ if (reported.has(message)) continue;
1243
+ reported.add(message);
1244
+ build.context.logger?.warn(message);
1245
+ }
1170
1246
  emit(translations);
1171
1247
  });
1172
1248
  }
@@ -1982,4 +2058,4 @@ async function run(entrypoint, { config, logger }) {
1982
2058
  //#endregion
1983
2059
  export { cleanup as a, core as i, react as n, po as r, run as t };
1984
2060
 
1985
- //# sourceMappingURL=run-CzeTVOug.mjs.map
2061
+ //# sourceMappingURL=run-Cpimgi_3.mjs.map