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.
- package/dist/config/index.cjs +4 -8
- package/dist/config/index.d.cts +3 -3
- package/dist/config/index.d.ts +3 -3
- package/dist/config/index.js +4 -8
- package/dist/index.cjs +142 -132
- package/dist/index.d.cts +119 -28
- package/dist/index.d.ts +119 -28
- package/dist/index.js +142 -132
- package/dist/next/index.cjs +292 -188
- package/dist/next/index.d.cts +101 -31
- package/dist/next/index.d.ts +101 -31
- package/dist/next/index.js +292 -189
- package/dist/next/middleware/index.cjs +28 -37
- package/dist/next/middleware/index.d.cts +6 -6
- package/dist/next/middleware/index.d.ts +6 -6
- package/dist/next/middleware/index.js +28 -37
- package/dist/next/server/index.cjs +133 -154
- package/dist/next/server/index.d.cts +77 -18
- package/dist/next/server/index.d.ts +77 -18
- package/dist/next/server/index.js +132 -152
- package/package.json +14 -10
package/dist/config/index.cjs
CHANGED
|
@@ -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.
|
|
90
|
-
while (end >= start && rawPathname.
|
|
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
|
-
|
|
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
|
};
|
package/dist/config/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Level, NormalizerConfig, FormatterConfig, LoggerPreset } from 'logry/edge';
|
|
2
|
-
import { Locale,
|
|
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?:
|
|
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?:
|
|
123
|
+
readonly messages?: LocaleMessages;
|
|
124
124
|
readonly defaultLocale: Locale;
|
|
125
125
|
readonly fallbackLocales: FallbackLocalesMap;
|
|
126
126
|
readonly translator?: TranslatorOptions;
|
package/dist/config/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Level, NormalizerConfig, FormatterConfig, LoggerPreset } from 'logry/edge';
|
|
2
|
-
import { Locale,
|
|
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?:
|
|
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?:
|
|
123
|
+
readonly messages?: LocaleMessages;
|
|
124
124
|
readonly defaultLocale: Locale;
|
|
125
125
|
readonly fallbackLocales: FallbackLocalesMap;
|
|
126
126
|
readonly translator?: TranslatorOptions;
|
package/dist/config/index.js
CHANGED
|
@@ -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.
|
|
88
|
-
while (end >= start && rawPathname.
|
|
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
|
-
|
|
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
|
|
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({
|
|
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 =
|
|
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
|
|
116
|
-
|
|
117
|
-
|
|
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 =
|
|
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
|
|
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
|
-
|
|
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
|
|
351
|
-
for (const locale of
|
|
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:
|
|
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 (
|
|
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
|
-
|
|
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
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
}).
|
|
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.
|
|
525
|
-
while (end >= start && rawPathname.
|
|
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
|
-
|
|
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
|
|
565
|
-
const maybeLocale =
|
|
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("/").
|
|
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
|
-
|
|
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
|
-
|
|
635
|
-
|
|
622
|
+
(fallbackLocales ?? []).toSorted().join(","),
|
|
623
|
+
(namespaces ?? []).toSorted().join(",")
|
|
636
624
|
]);
|
|
637
625
|
if (cache.enabled && key) {
|
|
638
|
-
const cached = await pool
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
778
|
-
|
|
768
|
+
(fallbackLocales ?? []).toSorted().join(","),
|
|
769
|
+
(namespaces ?? []).toSorted().join(",")
|
|
779
770
|
]);
|
|
780
771
|
if (cache.enabled && key) {
|
|
781
|
-
const cached = await pool
|
|
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
|
|
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
|
|
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/
|
|
827
|
-
var
|
|
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
|
-
|
|
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:
|
|
837
|
+
logger.debug("Loader type selected.", { loaderType: loader.type });
|
|
841
838
|
let loadedMessages;
|
|
842
|
-
if (
|
|
843
|
-
const loadLocalMessages2 = createLoadLocalMessages(
|
|
839
|
+
if (loader.type === "import") {
|
|
840
|
+
const loadLocalMessages2 = createLoadLocalMessages(loader.basePath);
|
|
844
841
|
loadedMessages = await loadLocalMessages2({
|
|
845
|
-
...
|
|
842
|
+
...loader,
|
|
846
843
|
locale,
|
|
847
844
|
fallbackLocales,
|
|
848
845
|
namespaces,
|
|
849
|
-
cache
|
|
850
|
-
logger: { id
|
|
846
|
+
cache,
|
|
847
|
+
logger: { id }
|
|
851
848
|
});
|
|
852
|
-
} else if (
|
|
849
|
+
} else if (loader.type === "api") {
|
|
853
850
|
loadedMessages = await loadApiMessages({
|
|
854
|
-
...
|
|
851
|
+
...loader,
|
|
855
852
|
locale,
|
|
856
853
|
fallbackLocales,
|
|
857
854
|
namespaces,
|
|
858
|
-
logger: { 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
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
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
|
|
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.
|
|
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;
|