intor 2.0.3 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -86,8 +86,8 @@ var normalizePathname = (rawPathname, options = {}) => {
86
86
  const length = rawPathname.length;
87
87
  let start = 0;
88
88
  let end = length - 1;
89
- while (start <= end && rawPathname.charCodeAt(start) <= 32) start++;
90
- while (end >= start && rawPathname.charCodeAt(end) <= 32) end--;
89
+ while (start <= end && (rawPathname.codePointAt(start) ?? 0) <= 32) start++;
90
+ while (end >= start && (rawPathname.codePointAt(end) ?? 0) <= 32) end--;
91
91
  if (start > end) return "/";
92
92
  let result = "";
93
93
  let hasSlash = false;
@@ -98,11 +98,7 @@ var normalizePathname = (rawPathname, options = {}) => {
98
98
  hasSlash = true;
99
99
  }
100
100
  } else {
101
- if (hasSlash || result === "") {
102
- result += "/" + char;
103
- } else {
104
- result += char;
105
- }
101
+ result += hasSlash || result === "" ? "/" + char : char;
106
102
  hasSlash = false;
107
103
  }
108
104
  }
@@ -119,7 +115,7 @@ var resolveRoutingOptions = (routing = {}) => {
119
115
  ...routing,
120
116
  firstVisit: {
121
117
  ...DEFAULT_ROUTING_OPTIONS.firstVisit,
122
- ...routing.firstVisit || {}
118
+ ...routing.firstVisit
123
119
  },
124
120
  basePath: normalizePathname(routing?.basePath || "")
125
121
  };
@@ -1,5 +1,5 @@
1
1
  import { Level, NormalizerConfig, FormatterConfig, LoggerPreset } from 'logry/edge';
2
- import { Locale, LocaleNamespaceMessages, FallbackLocalesMap } from 'intor-translator';
2
+ import { Locale, LocaleMessages, FallbackLocalesMap } from 'intor-translator';
3
3
 
4
4
  type CookieRawOptions = {
5
5
  /** Completely disable cookie usage (no read, no write, no lookup by name) - default: false */
@@ -109,7 +109,7 @@ type WithLoader = {
109
109
  };
110
110
  type IntorRawConfig = (WithLoader | WithoutLoader) & {
111
111
  readonly id?: string;
112
- readonly messages?: LocaleNamespaceMessages;
112
+ readonly messages?: LocaleMessages;
113
113
  readonly defaultLocale: Locale;
114
114
  readonly fallbackLocales?: FallbackLocalesMap;
115
115
  readonly translator?: TranslatorOptions;
@@ -120,7 +120,7 @@ type IntorRawConfig = (WithLoader | WithoutLoader) & {
120
120
  };
121
121
  type IntorResolvedConfig = (WithLoader | WithoutLoader) & {
122
122
  readonly id: string;
123
- readonly messages?: LocaleNamespaceMessages;
123
+ readonly messages?: LocaleMessages;
124
124
  readonly defaultLocale: Locale;
125
125
  readonly fallbackLocales: FallbackLocalesMap;
126
126
  readonly translator?: TranslatorOptions;
@@ -1,5 +1,5 @@
1
1
  import { Level, NormalizerConfig, FormatterConfig, LoggerPreset } from 'logry/edge';
2
- import { Locale, LocaleNamespaceMessages, FallbackLocalesMap } from 'intor-translator';
2
+ import { Locale, LocaleMessages, FallbackLocalesMap } from 'intor-translator';
3
3
 
4
4
  type CookieRawOptions = {
5
5
  /** Completely disable cookie usage (no read, no write, no lookup by name) - default: false */
@@ -109,7 +109,7 @@ type WithLoader = {
109
109
  };
110
110
  type IntorRawConfig = (WithLoader | WithoutLoader) & {
111
111
  readonly id?: string;
112
- readonly messages?: LocaleNamespaceMessages;
112
+ readonly messages?: LocaleMessages;
113
113
  readonly defaultLocale: Locale;
114
114
  readonly fallbackLocales?: FallbackLocalesMap;
115
115
  readonly translator?: TranslatorOptions;
@@ -120,7 +120,7 @@ type IntorRawConfig = (WithLoader | WithoutLoader) & {
120
120
  };
121
121
  type IntorResolvedConfig = (WithLoader | WithoutLoader) & {
122
122
  readonly id: string;
123
- readonly messages?: LocaleNamespaceMessages;
123
+ readonly messages?: LocaleMessages;
124
124
  readonly defaultLocale: Locale;
125
125
  readonly fallbackLocales: FallbackLocalesMap;
126
126
  readonly translator?: TranslatorOptions;
@@ -84,8 +84,8 @@ var normalizePathname = (rawPathname, options = {}) => {
84
84
  const length = rawPathname.length;
85
85
  let start = 0;
86
86
  let end = length - 1;
87
- while (start <= end && rawPathname.charCodeAt(start) <= 32) start++;
88
- while (end >= start && rawPathname.charCodeAt(end) <= 32) end--;
87
+ while (start <= end && (rawPathname.codePointAt(start) ?? 0) <= 32) start++;
88
+ while (end >= start && (rawPathname.codePointAt(end) ?? 0) <= 32) end--;
89
89
  if (start > end) return "/";
90
90
  let result = "";
91
91
  let hasSlash = false;
@@ -96,11 +96,7 @@ var normalizePathname = (rawPathname, options = {}) => {
96
96
  hasSlash = true;
97
97
  }
98
98
  } else {
99
- if (hasSlash || result === "") {
100
- result += "/" + char;
101
- } else {
102
- result += char;
103
- }
99
+ result += hasSlash || result === "" ? "/" + char : char;
104
100
  hasSlash = false;
105
101
  }
106
102
  }
@@ -117,7 +113,7 @@ var resolveRoutingOptions = (routing = {}) => {
117
113
  ...routing,
118
114
  firstVisit: {
119
115
  ...DEFAULT_ROUTING_OPTIONS.firstVisit,
120
- ...routing.firstVisit || {}
116
+ ...routing.firstVisit
121
117
  },
122
118
  basePath: normalizePathname(routing?.basePath || "")
123
119
  };
package/dist/index.cjs CHANGED
@@ -31,33 +31,6 @@ var DEFAULT_CACHE_OPTIONS = {
31
31
  // 1 hour
32
32
  };
33
33
 
34
- // src/shared/error/intor-error.ts
35
- var IntorError = class extends Error {
36
- constructor({ message, code, id }) {
37
- const fullMessage = id ? `[${id}] ${message}` : message;
38
- super(fullMessage);
39
- this.name = "IntorError";
40
- this.id = id;
41
- this.code = code;
42
- Object.setPrototypeOf(this, new.target.prototype);
43
- }
44
- };
45
-
46
- // src/modules/messages/load-local-messages/utils/read-message-record-file.ts
47
- var readMessageRecordFile = async (filePath, loggerOptions) => {
48
- const fileName = path__default.default.basename(filePath, ".json");
49
- const content = await fs__default.default.readFile(filePath, "utf-8");
50
- const parsed = JSON.parse(content);
51
- if (typeof parsed !== "object" || parsed === null) {
52
- throw new IntorError({
53
- id: loggerOptions.id,
54
- code: "INTOR_INVALID_MESSAGE_FORMAT" /* INVALID_MESSAGE_FORMAT */,
55
- message: "Invalid message format"
56
- });
57
- }
58
- return { fileName, content: parsed };
59
- };
60
-
61
34
  // src/shared/logger/global-logger-pool.ts
62
35
  function getGlobalLoggerPool() {
63
36
  if (!globalThis.__INTOR_LOGGER_POOL__) {
@@ -76,22 +49,40 @@ var DEFAULT_FORMATTER_CONFIG = {
76
49
  };
77
50
  function getLogger({
78
51
  id,
79
- formatterConfig = DEFAULT_FORMATTER_CONFIG,
52
+ formatterConfig,
53
+ preset,
80
54
  ...options
81
55
  }) {
82
56
  const pool = getGlobalLoggerPool();
83
57
  let logger = pool.get(id);
84
58
  if (!logger) {
85
- logger = logry.logry({ id, formatterConfig, ...options });
59
+ logger = logry.logry({
60
+ id,
61
+ formatterConfig: !formatterConfig && !preset ? DEFAULT_FORMATTER_CONFIG : formatterConfig,
62
+ preset,
63
+ ...options
64
+ });
86
65
  pool.set(id, logger);
87
66
  if (pool.size > 1e3) {
88
- const keys = Array.from(pool.keys());
67
+ const keys = [...pool.keys()];
89
68
  for (const key of keys.slice(0, 200)) pool.delete(key);
90
69
  }
91
70
  }
92
71
  return logger;
93
72
  }
94
73
 
74
+ // src/shared/error/intor-error.ts
75
+ var IntorError = class extends Error {
76
+ constructor({ message, code, id }) {
77
+ const fullMessage = id ? `[${id}] ${message}` : message;
78
+ super(fullMessage);
79
+ this.name = "IntorError";
80
+ this.id = id;
81
+ this.code = code;
82
+ Object.setPrototypeOf(this, new.target.prototype);
83
+ }
84
+ };
85
+
95
86
  // src/modules/messages/load-local-messages/load-namespace-group/parse-message-file.ts
96
87
  var MAX_PATH_LENGTH = 260;
97
88
  var parseMessageFile = async (filePath, loggerOptions) => {
@@ -112,9 +103,17 @@ var parseMessageFile = async (filePath, loggerOptions) => {
112
103
  return null;
113
104
  }
114
105
  try {
115
- const { content } = await readMessageRecordFile(trimmedPath, loggerOptions);
116
- logger.trace(`Message file loaded.`, { filePath: trimmedPath });
117
- return content;
106
+ const content = await fs__default.default.readFile(trimmedPath, "utf8");
107
+ const parsed = JSON.parse(content);
108
+ if (typeof parsed !== "object" || parsed === null) {
109
+ throw new IntorError({
110
+ id: loggerOptions.id,
111
+ code: "INTOR_INVALID_MESSAGE_FORMAT" /* INVALID_MESSAGE_FORMAT */,
112
+ message: "Invalid message format"
113
+ });
114
+ }
115
+ logger.trace("Message file loaded.", { filePath: trimmedPath });
116
+ return parsed;
118
117
  } catch (error) {
119
118
  logger.warn("Failed to parse message file.", {
120
119
  filePath: trimmedPath,
@@ -208,7 +207,7 @@ var addToNamespaceGroup = ({
208
207
  const filePathsSet = new Set(group.filePaths);
209
208
  if (!filePathsSet.has(filePath)) {
210
209
  filePathsSet.add(filePath);
211
- group.filePaths = Array.from(filePathsSet);
210
+ group.filePaths = [...filePathsSet];
212
211
  namespaceGroups.set(nsKey, group);
213
212
  }
214
213
  };
@@ -218,14 +217,15 @@ var traverseDirectory = async ({
218
217
  options,
219
218
  currentDirPath,
220
219
  namespaceGroups,
221
- namespacePathSegments
220
+ namespacePathSegments,
221
+ readdir = fs__default.default.readdir
222
222
  }) => {
223
223
  const { limit } = options;
224
224
  const loggerOptions = options.logger || { id: "default" };
225
225
  const baseLogger = getLogger({ ...loggerOptions });
226
226
  const logger = baseLogger.child({ scope: "traverse-directory" });
227
227
  try {
228
- const dirents = await fs__default.default.readdir(currentDirPath, { withFileTypes: true });
228
+ const dirents = await readdir(currentDirPath, { withFileTypes: true });
229
229
  const dirPromises = dirents.map(
230
230
  (dirent) => limit(async () => {
231
231
  const filePath = path__default.default.join(currentDirPath, dirent.name);
@@ -241,7 +241,8 @@ var traverseDirectory = async ({
241
241
  namespaceGroups,
242
242
  currentDirPath: filePath,
243
243
  namespacePathSegments: [...namespacePathSegments, dirent.name],
244
- options
244
+ options,
245
+ readdir
245
246
  });
246
247
  }
247
248
  }).catch((error) => {
@@ -316,7 +317,7 @@ var loadSingleLocale = async ({
316
317
  namespaceGroups: [...namespaceGroups.entries()].map(([ns, val]) => ({
317
318
  namespace: ns,
318
319
  isAtRoot: val.isAtRoot,
319
- fileCounts: val.filePaths.length
320
+ fileCount: val.filePaths.length
320
321
  }))
321
322
  });
322
323
  const namespaceGroupTasks = [...namespaceGroups.entries()].filter(
@@ -347,8 +348,8 @@ var loadLocaleWithFallback = async ({
347
348
  }) => {
348
349
  const baseLogger = getLogger({ ...loggerOptions });
349
350
  const logger = baseLogger.child({ scope: "load-locale-with-fallback" });
350
- const localesToTry = [targetLocale, ...fallbackLocales];
351
- for (const locale of localesToTry) {
351
+ const candidateLocales = [targetLocale, ...fallbackLocales];
352
+ for (const locale of candidateLocales) {
352
353
  try {
353
354
  const validNamespaces = await loadSingleLocale({
354
355
  basePath,
@@ -367,7 +368,7 @@ var loadLocaleWithFallback = async ({
367
368
  }
368
369
  }
369
370
  logger.warn("All fallback locales failed.", {
370
- attemptedLocales: localesToTry
371
+ attemptedLocales: candidateLocales
371
372
  });
372
373
  return;
373
374
  };
@@ -384,7 +385,7 @@ function clearMessagesPool() {
384
385
 
385
386
  // src/shared/utils/merge-messages.ts
386
387
  var mergeMessages = (staticMessages = {}, loadedMessages = {}) => {
387
- const result = Object.keys(staticMessages).length ? { ...staticMessages } : {};
388
+ const result = Object.keys(staticMessages).length > 0 ? { ...staticMessages } : {};
388
389
  for (const locale in loadedMessages) {
389
390
  const loaded = loadedMessages[locale];
390
391
  if (!result[locale]) {
@@ -403,7 +404,7 @@ var mergeMessages = (staticMessages = {}, loadedMessages = {}) => {
403
404
  var CACHE_KEY_DELIMITER = "|";
404
405
  var sanitize = (k) => k.replaceAll(/[\u200B-\u200D\uFEFF]/g, "").replaceAll(/[\r\n]/g, "").trim();
405
406
  var normalizeCacheKey = (key, delimiter = CACHE_KEY_DELIMITER) => {
406
- if (!key) return null;
407
+ if (key === null || key === void 0) return null;
407
408
  if (Array.isArray(key)) {
408
409
  if (key.length === 0) return null;
409
410
  const normalized = key.map((k) => {
@@ -427,56 +428,44 @@ var resolveNamespaces = ({
427
428
  pathname
428
429
  }) => {
429
430
  const { loader } = config;
430
- const {
431
- routeNamespaces = {},
432
- namespaces: fallbackNamespaces
433
- } = loader;
434
- const { unprefixedPathname } = extractPathname({ config, pathname });
435
- const standardizedPathname = standardizePathname({
436
- config,
437
- pathname: unprefixedPathname
438
- });
431
+ const { routeNamespaces = {}, namespaces } = loader || {};
432
+ const standardizedPathname = standardizePathname({ config, pathname });
439
433
  const placeholderRemovedPathname = standardizedPathname.replace(
440
434
  `/${PREFIX_PLACEHOLDER}`,
441
435
  ""
442
436
  );
443
- const defaultNamespaces = routeNamespaces.default ?? [];
444
- const exactMatchNamespaces = routeNamespaces[standardizedPathname] ?? routeNamespaces[placeholderRemovedPathname];
445
- if (exactMatchNamespaces) {
446
- return [...defaultNamespaces, ...exactMatchNamespaces];
447
- }
448
- let bestMatch = "";
449
- let bestNamespaces;
437
+ const collected = [
438
+ ...routeNamespaces.default || [],
439
+ // default
440
+ ...namespaces || [],
441
+ // default
442
+ ...routeNamespaces[standardizedPathname] || [],
443
+ // exact match
444
+ ...routeNamespaces[placeholderRemovedPathname] || []
445
+ // exact match
446
+ ];
450
447
  const prefixPatterns = Object.keys(routeNamespaces).filter(
451
448
  (pattern) => pattern.endsWith("/*")
452
449
  );
453
450
  for (const pattern of prefixPatterns) {
454
451
  const basePath = pattern.replace(/\/\*$/, "");
455
- if (standardizedPathname.startsWith(basePath)) {
456
- if (basePath.length > bestMatch.length) {
457
- bestMatch = basePath;
458
- bestNamespaces = routeNamespaces[pattern];
459
- }
452
+ if (standardizedPathname.startsWith(basePath) || placeholderRemovedPathname.startsWith(basePath)) {
453
+ collected.push(...routeNamespaces[pattern] || []);
460
454
  }
461
455
  }
462
- const matchedNamespaces = bestNamespaces ?? routeNamespaces["/*"] ?? fallbackNamespaces ?? [];
463
- if (matchedNamespaces.length > 0) {
464
- return [...defaultNamespaces, ...matchedNamespaces];
465
- } else {
466
- return [...defaultNamespaces];
467
- }
456
+ return [...new Set(collected)];
468
457
  };
469
458
 
470
459
  // src/shared/utils/locale/normalize-locale.ts
460
+ var toCanonical = (input) => {
461
+ try {
462
+ return Intl.getCanonicalLocales(input)[0]?.toLowerCase();
463
+ } catch {
464
+ return;
465
+ }
466
+ };
471
467
  var normalizeLocale = (locale = "", supportedLocales = []) => {
472
468
  if (!locale || supportedLocales.length === 0) return;
473
- const toCanonical = (input) => {
474
- try {
475
- return Intl.getCanonicalLocales(input)[0]?.toLowerCase();
476
- } catch {
477
- return;
478
- }
479
- };
480
469
  const canonicalLocale = toCanonical(locale);
481
470
  if (!canonicalLocale) return;
482
471
  const supportedCanonicalMap = /* @__PURE__ */ new Map();
@@ -507,12 +496,12 @@ var resolvePreferredLocale = (acceptLanguageHeader, supportedLocales) => {
507
496
  const supportedLocalesSet = new Set(supportedLocales);
508
497
  const preferred = acceptLanguageHeader.split(",").map((part) => {
509
498
  const [lang, qValue] = part.split(";");
510
- const q = qValue ? parseFloat(qValue.split("=")[1]) : 1;
511
- if (isNaN(q)) {
499
+ const q = qValue ? Number.parseFloat(qValue.split("=")[1]) : 1;
500
+ if (Number.isNaN(q)) {
512
501
  return { lang: lang.trim(), q: 0 };
513
502
  }
514
503
  return { lang: lang.trim(), q };
515
- }).sort((a, b) => b.q - a.q).find(({ lang }) => supportedLocalesSet.has(lang))?.lang;
504
+ }).toSorted((a, b) => b.q - a.q).find(({ lang }) => supportedLocalesSet.has(lang))?.lang;
516
505
  return preferred;
517
506
  };
518
507
 
@@ -521,8 +510,8 @@ var normalizePathname = (rawPathname, options = {}) => {
521
510
  const length = rawPathname.length;
522
511
  let start = 0;
523
512
  let end = length - 1;
524
- while (start <= end && rawPathname.charCodeAt(start) <= 32) start++;
525
- while (end >= start && rawPathname.charCodeAt(end) <= 32) end--;
513
+ while (start <= end && (rawPathname.codePointAt(start) ?? 0) <= 32) start++;
514
+ while (end >= start && (rawPathname.codePointAt(end) ?? 0) <= 32) end--;
526
515
  if (start > end) return "/";
527
516
  let result = "";
528
517
  let hasSlash = false;
@@ -533,11 +522,7 @@ var normalizePathname = (rawPathname, options = {}) => {
533
522
  hasSlash = true;
534
523
  }
535
524
  } else {
536
- if (hasSlash || result === "") {
537
- result += "/" + char;
538
- } else {
539
- result += char;
540
- }
525
+ result += hasSlash || result === "" ? "/" + char : char;
541
526
  hasSlash = false;
542
527
  }
543
528
  }
@@ -561,8 +546,8 @@ var extractPathname = ({
561
546
  } else if (basePath && normalizedPathname === basePath) {
562
547
  prefixedPathname = "/";
563
548
  }
564
- const pathParts = prefixedPathname.split("/").filter(Boolean);
565
- const maybeLocale = pathParts[0] || "";
549
+ const pathPart = prefixedPathname.split("/").find(Boolean);
550
+ const maybeLocale = pathPart || "";
566
551
  const isLocalePrefixed = config.supportedLocales?.includes(maybeLocale);
567
552
  let unprefixedPathname = prefixedPathname;
568
553
  if (prefix === "all") {
@@ -595,7 +580,7 @@ var standardizePathname = ({
595
580
  PREFIX_PLACEHOLDER,
596
581
  normalizePathname(pathname)
597
582
  ];
598
- const standardizedPathname = parts.join("/").replace(/\/{2,}/g, "/");
583
+ const standardizedPathname = parts.join("/").replaceAll(/\/{2,}/g, "/");
599
584
  return normalizePathname(standardizedPathname);
600
585
  };
601
586
 
@@ -626,16 +611,19 @@ var loadLocalMessages = async ({
626
611
  namespaces: namespaces && namespaces.length > 0 ? { count: namespaces?.length, list: [...namespaces] } : "All Namespaces",
627
612
  concurrency
628
613
  });
629
- const pool = getGlobalMessagesPool();
614
+ let pool;
615
+ if (cache.enabled) {
616
+ pool = getGlobalMessagesPool();
617
+ }
630
618
  const key = normalizeCacheKey([
631
619
  loggerOptions.id,
632
620
  resolvedBasePath,
633
621
  locale,
634
- [...fallbackLocales ?? []].sort().join(","),
635
- [...namespaces ?? []].sort().join(",")
622
+ (fallbackLocales ?? []).toSorted().join(","),
623
+ (namespaces ?? []).toSorted().join(",")
636
624
  ]);
637
625
  if (cache.enabled && key) {
638
- const cached = await pool.get(key);
626
+ const cached = await pool?.get(key);
639
627
  if (cached) {
640
628
  logger.debug("Messages cache hit.", { key });
641
629
  return cached;
@@ -652,7 +640,7 @@ var loadLocalMessages = async ({
652
640
  logger: loggerOptions
653
641
  });
654
642
  if (cache.enabled && key) {
655
- await pool.set(key, messages, cache.ttl);
643
+ await pool?.set(key, messages, cache.ttl);
656
644
  }
657
645
  const end = perf_hooks.performance.now();
658
646
  const duration = Math.round(end - start);
@@ -769,16 +757,19 @@ var loadApiMessages = async ({
769
757
  logger.warn("No apiUrl provided. Skipping fetch.");
770
758
  return;
771
759
  }
772
- const pool = getGlobalMessagesPool();
760
+ let pool;
761
+ if (cache.enabled) {
762
+ pool = getGlobalMessagesPool();
763
+ }
773
764
  const key = normalizeCacheKey([
774
765
  loggerOptions.id,
775
766
  basePath,
776
767
  locale,
777
- [...fallbackLocales ?? []].sort().join(","),
778
- [...namespaces ?? []].sort().join(",")
768
+ (fallbackLocales ?? []).toSorted().join(","),
769
+ (namespaces ?? []).toSorted().join(",")
779
770
  ]);
780
771
  if (cache.enabled && key) {
781
- const cached = await pool.get(key);
772
+ const cached = await pool?.get(key);
782
773
  if (cached) {
783
774
  logger.debug("Messages cache hit.", { key });
784
775
  return cached;
@@ -794,7 +785,7 @@ var loadApiMessages = async ({
794
785
  });
795
786
  if (messages) {
796
787
  if (cache.enabled && key) {
797
- await pool.set(key, messages, cache.ttl);
788
+ await pool?.set(key, messages, cache.ttl);
798
789
  }
799
790
  return messages;
800
791
  }
@@ -812,7 +803,7 @@ var loadApiMessages = async ({
812
803
  searchParams: decodeURIComponent(searchParams.toString())
813
804
  });
814
805
  if (cache.enabled && key) {
815
- await pool.set(key, fallbackResult.messages, cache.ttl);
806
+ await pool?.set(key, fallbackResult.messages, cache.ttl);
816
807
  }
817
808
  return fallbackResult.messages;
818
809
  }
@@ -823,39 +814,45 @@ var loadApiMessages = async ({
823
814
  return;
824
815
  };
825
816
 
826
- // src/modules/messages/get-messages.ts
827
- var getMessages = async ({
817
+ // src/modules/messages/load-messages.ts
818
+ var loadMessages = async ({
828
819
  config,
829
820
  locale,
830
821
  pathname
831
822
  }) => {
832
- const baseLogger = getLogger({ id: config.id });
823
+ const baseLogger = getLogger({ id: config.id, ...config.logger });
833
824
  const logger = baseLogger.child({ scope: "messages-loader" });
834
- const loaderOptions = config.loader;
825
+ if (!config.loader) {
826
+ logger.warn(
827
+ "No loader options have been configured in the current config."
828
+ );
829
+ return;
830
+ }
831
+ const { id, loader, cache } = config;
835
832
  const fallbackLocales = config.fallbackLocales[locale] || [];
836
833
  const namespaces = resolveNamespaces({ config, pathname });
837
834
  logger.debug("Namespaces ready for loading.", {
838
835
  namespaces: namespaces.length > 0 ? { count: namespaces.length, list: [...namespaces] } : "All Namespaces"
839
836
  });
840
- logger.debug("Loader type selected.", { loaderType: loaderOptions.type });
837
+ logger.debug("Loader type selected.", { loaderType: loader.type });
841
838
  let loadedMessages;
842
- if (loaderOptions.type === "import") {
843
- const loadLocalMessages2 = createLoadLocalMessages(loaderOptions.basePath);
839
+ if (loader.type === "import") {
840
+ const loadLocalMessages2 = createLoadLocalMessages(loader.basePath);
844
841
  loadedMessages = await loadLocalMessages2({
845
- ...loaderOptions,
842
+ ...loader,
846
843
  locale,
847
844
  fallbackLocales,
848
845
  namespaces,
849
- cache: config.cache,
850
- logger: { id: config.id }
846
+ cache,
847
+ logger: { id }
851
848
  });
852
- } else if (loaderOptions.type === "api") {
849
+ } else if (loader.type === "api") {
853
850
  loadedMessages = await loadApiMessages({
854
- ...loaderOptions,
851
+ ...loader,
855
852
  locale,
856
853
  fallbackLocales,
857
854
  namespaces,
858
- logger: { id: config.id }
855
+ logger: { id }
859
856
  });
860
857
  }
861
858
  if (!loadedMessages || Object.keys(loadedMessages).length === 0) {
@@ -865,29 +862,22 @@ var getMessages = async ({
865
862
  };
866
863
 
867
864
  // src/modules/intor/intor.ts
868
- var intor = async ({
869
- config,
870
- adapter,
871
- adapterRuntime
872
- }) => {
865
+ var intor = async (config, i18nContext) => {
873
866
  const baseLogger = getLogger({ id: config.id, ...config.logger });
874
867
  const logger = baseLogger.child({ scope: "intor" });
875
868
  logger.info("Start Intor initialization.");
876
869
  const { messages, loader } = config;
877
- let runtime;
878
- if (adapter) {
879
- runtime = await adapter(config);
880
- } else {
881
- runtime = {
882
- locale: adapterRuntime?.locale || config.defaultLocale,
883
- pathname: adapterRuntime?.pathname || ""
884
- };
885
- }
886
- const { locale, pathname } = runtime;
887
- logger.debug("Runtime resolved via adapter/fallback", runtime);
870
+ const isI18nContextFunction = typeof i18nContext === "function";
871
+ const context = isI18nContextFunction ? await i18nContext(config) : {
872
+ locale: i18nContext?.locale || config.defaultLocale,
873
+ pathname: i18nContext?.pathname || ""
874
+ };
875
+ const { locale, pathname } = context;
876
+ const source = isI18nContextFunction ? "[function]" : "[static object]";
877
+ logger.debug(`Context resolved via ${source}.`, context);
888
878
  let loadedMessages;
889
879
  if (shouldLoadMessages(loader)) {
890
- loadedMessages = await getMessages({ config, locale, pathname });
880
+ loadedMessages = await loadMessages({ config, locale, pathname });
891
881
  }
892
882
  const mergedMessages = mergeMessages(messages, loadedMessages);
893
883
  logger.info("Messages initialized.", {
@@ -905,6 +895,25 @@ var intor = async ({
905
895
  messages: mergedMessages
906
896
  };
907
897
  };
898
+ async function getTranslator(opts) {
899
+ const { config, locale, pathname = "", preKey, handlers } = opts;
900
+ const messages = await loadMessages({ config, locale, pathname });
901
+ const translator = new intorTranslator.Translator({
902
+ locale,
903
+ messages,
904
+ fallbackLocales: config.fallbackLocales,
905
+ loadingMessage: config.translator?.loadingMessage,
906
+ placeholder: config.translator?.placeholder,
907
+ handlers
908
+ });
909
+ const props = { messages, locale };
910
+ const scoped = translator.scoped(preKey);
911
+ return {
912
+ ...props,
913
+ hasKey: preKey ? scoped.hasKey : translator.hasKey,
914
+ t: preKey ? scoped.t : translator.t
915
+ };
916
+ }
908
917
 
909
918
  Object.defineProperty(exports, "Translator", {
910
919
  enumerable: true,
@@ -914,10 +923,11 @@ exports.PREFIX_PLACEHOLDER = PREFIX_PLACEHOLDER;
914
923
  exports.clearLoggerPool = clearLoggerPool;
915
924
  exports.clearMessagesPool = clearMessagesPool;
916
925
  exports.extractPathname = extractPathname;
917
- exports.getMessages = getMessages;
926
+ exports.getTranslator = getTranslator;
918
927
  exports.intor = intor;
919
928
  exports.loadApiMessages = loadApiMessages;
920
929
  exports.loadLocalMessages = loadLocalMessages;
930
+ exports.loadMessages = loadMessages;
921
931
  exports.mergeMessages = mergeMessages;
922
932
  exports.normalizeCacheKey = normalizeCacheKey;
923
933
  exports.normalizeLocale = normalizeLocale;