intor 2.1.0 → 2.2.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/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 +88 -120
- package/dist/index.d.cts +65 -39
- package/dist/index.d.ts +65 -39
- package/dist/index.js +88 -120
- package/dist/next/index.cjs +112 -131
- package/dist/next/index.d.cts +54 -27
- package/dist/next/index.d.ts +54 -27
- package/dist/next/index.js +112 -131
- package/dist/next/middleware/index.cjs +31 -55
- package/dist/next/middleware/index.d.cts +4 -8
- package/dist/next/middleware/index.d.ts +4 -8
- package/dist/next/middleware/index.js +31 -55
- package/dist/next/server/index.cjs +69 -132
- package/dist/next/server/index.d.cts +52 -25
- package/dist/next/server/index.d.ts +52 -25
- package/dist/next/server/index.js +69 -132
- package/package.json +13 -9
package/dist/next/index.js
CHANGED
|
@@ -2,8 +2,8 @@ import * as React7 from 'react';
|
|
|
2
2
|
import { logry } from 'logry';
|
|
3
3
|
import Keyv from 'keyv';
|
|
4
4
|
import { Translator } from 'intor-translator';
|
|
5
|
-
import NextLink from 'next/link';
|
|
6
5
|
import { formatUrl } from 'next/dist/shared/lib/router/utils/format-url';
|
|
6
|
+
import NextLink from 'next/link';
|
|
7
7
|
import { usePathname as usePathname$1, useRouter as useRouter$1, redirect as redirect$1 } from 'next/navigation';
|
|
8
8
|
import { cookies, headers } from 'next/headers';
|
|
9
9
|
|
|
@@ -22,66 +22,6 @@ function useConfig() {
|
|
|
22
22
|
return context;
|
|
23
23
|
}
|
|
24
24
|
var LocaleContext = React7.createContext(void 0);
|
|
25
|
-
|
|
26
|
-
// src/adapters/next/shared/utils/build-cookie-string.ts
|
|
27
|
-
var buildCookieString = (cookie, locale) => {
|
|
28
|
-
const parts = [];
|
|
29
|
-
parts.push(`${cookie.name}=${encodeURIComponent(locale)}`);
|
|
30
|
-
if (cookie.maxAge) {
|
|
31
|
-
const expires = new Date(Date.now() + cookie.maxAge * 1e3).toUTCString();
|
|
32
|
-
parts.push(`expires=${expires}`);
|
|
33
|
-
parts.push(`max-age=${cookie.maxAge}`);
|
|
34
|
-
}
|
|
35
|
-
parts.push(`path=${cookie.path ?? "/"}`);
|
|
36
|
-
if (cookie.domain) {
|
|
37
|
-
parts.push(`domain=${cookie.domain}`);
|
|
38
|
-
}
|
|
39
|
-
if (cookie.sameSite) {
|
|
40
|
-
parts.push(
|
|
41
|
-
`SameSite=${cookie.sameSite[0].toUpperCase()}${cookie.sameSite.slice(1).toLowerCase()}`
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
if (cookie.secure !== false) {
|
|
45
|
-
parts.push(`Secure`);
|
|
46
|
-
}
|
|
47
|
-
return parts.join("; ");
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
// src/adapters/next/shared/utils/set-locale-cookie-browser.ts
|
|
51
|
-
var setLocaleCookieBrowser = ({
|
|
52
|
-
cookie,
|
|
53
|
-
locale
|
|
54
|
-
}) => {
|
|
55
|
-
if (typeof window === "undefined") return;
|
|
56
|
-
if (cookie.disabled || !cookie.autoSetCookie) return;
|
|
57
|
-
const cookieString = buildCookieString(cookie, locale);
|
|
58
|
-
document.cookie = cookieString;
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
// src/adapters/next/contexts/locale/utils/change-locale.ts
|
|
62
|
-
var changeLocale = ({
|
|
63
|
-
currentLocale,
|
|
64
|
-
newLocale,
|
|
65
|
-
loaderOptions,
|
|
66
|
-
cookie,
|
|
67
|
-
setLocale,
|
|
68
|
-
refetchMessages
|
|
69
|
-
}) => {
|
|
70
|
-
if (typeof document === "undefined") return;
|
|
71
|
-
const loaderType = loaderOptions?.type;
|
|
72
|
-
if (newLocale === currentLocale) return;
|
|
73
|
-
if (loaderType === "import") {
|
|
74
|
-
console.warn(
|
|
75
|
-
`[Intor] You are using dynamic import to switch languages. Please make sure to use the wrapped <Link> component to trigger a page reload, ensuring that the translation data is dynamically updated.`
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
setLocale(newLocale);
|
|
79
|
-
setLocaleCookieBrowser({ cookie, locale: newLocale });
|
|
80
|
-
document.documentElement.lang = newLocale;
|
|
81
|
-
if (loaderType === "api" && refetchMessages) {
|
|
82
|
-
void refetchMessages(newLocale);
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
25
|
var MessagesContext = React7.createContext(void 0);
|
|
86
26
|
|
|
87
27
|
// src/modules/config/constants/cache.constants.ts
|
|
@@ -120,7 +60,7 @@ function getLogger({
|
|
|
120
60
|
});
|
|
121
61
|
pool.set(id, logger);
|
|
122
62
|
if (pool.size > 1e3) {
|
|
123
|
-
const keys =
|
|
63
|
+
const keys = [...pool.keys()];
|
|
124
64
|
for (const key of keys.slice(0, 200)) pool.delete(key);
|
|
125
65
|
}
|
|
126
66
|
}
|
|
@@ -135,7 +75,7 @@ function getGlobalMessagesPool() {
|
|
|
135
75
|
|
|
136
76
|
// src/shared/utils/merge-messages.ts
|
|
137
77
|
var mergeMessages = (staticMessages = {}, loadedMessages = {}) => {
|
|
138
|
-
const result = Object.keys(staticMessages).length ? { ...staticMessages } : {};
|
|
78
|
+
const result = Object.keys(staticMessages).length > 0 ? { ...staticMessages } : {};
|
|
139
79
|
for (const locale in loadedMessages) {
|
|
140
80
|
const loaded = loadedMessages[locale];
|
|
141
81
|
if (!result[locale]) {
|
|
@@ -154,7 +94,7 @@ var mergeMessages = (staticMessages = {}, loadedMessages = {}) => {
|
|
|
154
94
|
var CACHE_KEY_DELIMITER = "|";
|
|
155
95
|
var sanitize = (k) => k.replaceAll(/[\u200B-\u200D\uFEFF]/g, "").replaceAll(/[\r\n]/g, "").trim();
|
|
156
96
|
var normalizeCacheKey = (key, delimiter = CACHE_KEY_DELIMITER) => {
|
|
157
|
-
if (
|
|
97
|
+
if (key === null || key === void 0) return null;
|
|
158
98
|
if (Array.isArray(key)) {
|
|
159
99
|
if (key.length === 0) return null;
|
|
160
100
|
const normalized = key.map((k) => {
|
|
@@ -178,56 +118,44 @@ var resolveNamespaces = ({
|
|
|
178
118
|
pathname
|
|
179
119
|
}) => {
|
|
180
120
|
const { loader } = config;
|
|
181
|
-
const {
|
|
182
|
-
|
|
183
|
-
namespaces: fallbackNamespaces
|
|
184
|
-
} = loader;
|
|
185
|
-
const { unprefixedPathname } = extractPathname({ config, pathname });
|
|
186
|
-
const standardizedPathname = standardizePathname({
|
|
187
|
-
config,
|
|
188
|
-
pathname: unprefixedPathname
|
|
189
|
-
});
|
|
121
|
+
const { routeNamespaces = {}, namespaces } = loader || {};
|
|
122
|
+
const standardizedPathname = standardizePathname({ config, pathname });
|
|
190
123
|
const placeholderRemovedPathname = standardizedPathname.replace(
|
|
191
124
|
`/${PREFIX_PLACEHOLDER}`,
|
|
192
125
|
""
|
|
193
126
|
);
|
|
194
|
-
const
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
127
|
+
const collected = [
|
|
128
|
+
...routeNamespaces.default || [],
|
|
129
|
+
// default
|
|
130
|
+
...namespaces || [],
|
|
131
|
+
// default
|
|
132
|
+
...routeNamespaces[standardizedPathname] || [],
|
|
133
|
+
// exact match
|
|
134
|
+
...routeNamespaces[placeholderRemovedPathname] || []
|
|
135
|
+
// exact match
|
|
136
|
+
];
|
|
201
137
|
const prefixPatterns = Object.keys(routeNamespaces).filter(
|
|
202
138
|
(pattern) => pattern.endsWith("/*")
|
|
203
139
|
);
|
|
204
140
|
for (const pattern of prefixPatterns) {
|
|
205
141
|
const basePath = pattern.replace(/\/\*$/, "");
|
|
206
|
-
if (standardizedPathname.startsWith(basePath)) {
|
|
207
|
-
|
|
208
|
-
bestMatch = basePath;
|
|
209
|
-
bestNamespaces = routeNamespaces[pattern];
|
|
210
|
-
}
|
|
142
|
+
if (standardizedPathname.startsWith(basePath) || placeholderRemovedPathname.startsWith(basePath)) {
|
|
143
|
+
collected.push(...routeNamespaces[pattern] || []);
|
|
211
144
|
}
|
|
212
145
|
}
|
|
213
|
-
|
|
214
|
-
if (matchedNamespaces.length > 0) {
|
|
215
|
-
return [...defaultNamespaces, ...matchedNamespaces];
|
|
216
|
-
} else {
|
|
217
|
-
return [...defaultNamespaces];
|
|
218
|
-
}
|
|
146
|
+
return [...new Set(collected)];
|
|
219
147
|
};
|
|
220
148
|
|
|
221
149
|
// src/shared/utils/locale/normalize-locale.ts
|
|
150
|
+
var toCanonical = (input) => {
|
|
151
|
+
try {
|
|
152
|
+
return Intl.getCanonicalLocales(input)[0]?.toLowerCase();
|
|
153
|
+
} catch {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
};
|
|
222
157
|
var normalizeLocale = (locale = "", supportedLocales = []) => {
|
|
223
158
|
if (!locale || supportedLocales.length === 0) return;
|
|
224
|
-
const toCanonical = (input) => {
|
|
225
|
-
try {
|
|
226
|
-
return Intl.getCanonicalLocales(input)[0]?.toLowerCase();
|
|
227
|
-
} catch {
|
|
228
|
-
return;
|
|
229
|
-
}
|
|
230
|
-
};
|
|
231
159
|
const canonicalLocale = toCanonical(locale);
|
|
232
160
|
if (!canonicalLocale) return;
|
|
233
161
|
const supportedCanonicalMap = /* @__PURE__ */ new Map();
|
|
@@ -258,12 +186,12 @@ var resolvePreferredLocale = (acceptLanguageHeader, supportedLocales) => {
|
|
|
258
186
|
const supportedLocalesSet = new Set(supportedLocales);
|
|
259
187
|
const preferred = acceptLanguageHeader.split(",").map((part) => {
|
|
260
188
|
const [lang, qValue] = part.split(";");
|
|
261
|
-
const q = qValue ? parseFloat(qValue.split("=")[1]) : 1;
|
|
262
|
-
if (isNaN(q)) {
|
|
189
|
+
const q = qValue ? Number.parseFloat(qValue.split("=")[1]) : 1;
|
|
190
|
+
if (Number.isNaN(q)) {
|
|
263
191
|
return { lang: lang.trim(), q: 0 };
|
|
264
192
|
}
|
|
265
193
|
return { lang: lang.trim(), q };
|
|
266
|
-
}).
|
|
194
|
+
}).toSorted((a, b) => b.q - a.q).find(({ lang }) => supportedLocalesSet.has(lang))?.lang;
|
|
267
195
|
return preferred;
|
|
268
196
|
};
|
|
269
197
|
|
|
@@ -272,8 +200,8 @@ var normalizePathname = (rawPathname, options = {}) => {
|
|
|
272
200
|
const length = rawPathname.length;
|
|
273
201
|
let start = 0;
|
|
274
202
|
let end = length - 1;
|
|
275
|
-
while (start <= end && rawPathname.
|
|
276
|
-
while (end >= start && rawPathname.
|
|
203
|
+
while (start <= end && (rawPathname.codePointAt(start) ?? 0) <= 32) start++;
|
|
204
|
+
while (end >= start && (rawPathname.codePointAt(end) ?? 0) <= 32) end--;
|
|
277
205
|
if (start > end) return "/";
|
|
278
206
|
let result = "";
|
|
279
207
|
let hasSlash = false;
|
|
@@ -284,11 +212,7 @@ var normalizePathname = (rawPathname, options = {}) => {
|
|
|
284
212
|
hasSlash = true;
|
|
285
213
|
}
|
|
286
214
|
} else {
|
|
287
|
-
|
|
288
|
-
result += "/" + char;
|
|
289
|
-
} else {
|
|
290
|
-
result += char;
|
|
291
|
-
}
|
|
215
|
+
result += hasSlash || result === "" ? "/" + char : char;
|
|
292
216
|
hasSlash = false;
|
|
293
217
|
}
|
|
294
218
|
}
|
|
@@ -312,8 +236,8 @@ var extractPathname = ({
|
|
|
312
236
|
} else if (basePath && normalizedPathname === basePath) {
|
|
313
237
|
prefixedPathname = "/";
|
|
314
238
|
}
|
|
315
|
-
const
|
|
316
|
-
const maybeLocale =
|
|
239
|
+
const pathPart = prefixedPathname.split("/").find(Boolean);
|
|
240
|
+
const maybeLocale = pathPart || "";
|
|
317
241
|
const isLocalePrefixed = config.supportedLocales?.includes(maybeLocale);
|
|
318
242
|
let unprefixedPathname = prefixedPathname;
|
|
319
243
|
if (prefix === "all") {
|
|
@@ -346,7 +270,7 @@ var standardizePathname = ({
|
|
|
346
270
|
PREFIX_PLACEHOLDER,
|
|
347
271
|
normalizePathname(pathname)
|
|
348
272
|
];
|
|
349
|
-
const standardizedPathname = parts.join("/").
|
|
273
|
+
const standardizedPathname = parts.join("/").replaceAll(/\/{2,}/g, "/");
|
|
350
274
|
return normalizePathname(standardizedPathname);
|
|
351
275
|
};
|
|
352
276
|
|
|
@@ -458,8 +382,8 @@ var loadApiMessages = async ({
|
|
|
458
382
|
loggerOptions.id,
|
|
459
383
|
basePath,
|
|
460
384
|
locale,
|
|
461
|
-
|
|
462
|
-
|
|
385
|
+
(fallbackLocales ?? []).toSorted().join(","),
|
|
386
|
+
(namespaces ?? []).toSorted().join(",")
|
|
463
387
|
]);
|
|
464
388
|
if (cache.enabled && key) {
|
|
465
389
|
const cached = await pool?.get(key);
|
|
@@ -580,6 +504,8 @@ function useMessages() {
|
|
|
580
504
|
throw new Error("useMessages must be used within a MessagesProvider");
|
|
581
505
|
return context;
|
|
582
506
|
}
|
|
507
|
+
|
|
508
|
+
// src/adapters/next/contexts/locale/utils/use-init-lazy-load.ts
|
|
583
509
|
var useInitLazyLoad = ({
|
|
584
510
|
loaderOptions,
|
|
585
511
|
currentLocale
|
|
@@ -594,6 +520,41 @@ var useInitLazyLoad = ({
|
|
|
594
520
|
}
|
|
595
521
|
}, [lazyLoad, currentLocale, refetchMessages, isFirstLoadedRef]);
|
|
596
522
|
};
|
|
523
|
+
|
|
524
|
+
// src/adapters/next/shared/utils/build-cookie-string.ts
|
|
525
|
+
var buildCookieString = (cookie, locale) => {
|
|
526
|
+
const parts = [`${cookie.name}=${encodeURIComponent(locale)}`];
|
|
527
|
+
if (cookie.maxAge) {
|
|
528
|
+
const expires = new Date(Date.now() + cookie.maxAge * 1e3).toUTCString();
|
|
529
|
+
parts.push(`expires=${expires}`, `max-age=${cookie.maxAge}`);
|
|
530
|
+
}
|
|
531
|
+
parts.push(`path=${cookie.path ?? "/"}`);
|
|
532
|
+
if (cookie.domain) {
|
|
533
|
+
parts.push(`domain=${cookie.domain}`);
|
|
534
|
+
}
|
|
535
|
+
if (cookie.sameSite) {
|
|
536
|
+
parts.push(
|
|
537
|
+
`SameSite=${cookie.sameSite[0].toUpperCase()}${cookie.sameSite.slice(1).toLowerCase()}`
|
|
538
|
+
);
|
|
539
|
+
}
|
|
540
|
+
if (cookie.secure !== false) {
|
|
541
|
+
parts.push(`Secure`);
|
|
542
|
+
}
|
|
543
|
+
return parts.join("; ");
|
|
544
|
+
};
|
|
545
|
+
|
|
546
|
+
// src/adapters/next/shared/utils/set-locale-cookie-browser.ts
|
|
547
|
+
var setLocaleCookieBrowser = ({
|
|
548
|
+
cookie,
|
|
549
|
+
locale
|
|
550
|
+
}) => {
|
|
551
|
+
if (globalThis.window === void 0) return;
|
|
552
|
+
if (cookie.disabled || !cookie.autoSetCookie) return;
|
|
553
|
+
const cookieString = buildCookieString(cookie, locale);
|
|
554
|
+
document.cookie = cookieString;
|
|
555
|
+
};
|
|
556
|
+
|
|
557
|
+
// src/adapters/next/contexts/locale/utils/use-init-locale-cookie.ts
|
|
597
558
|
var useInitLocaleCookie = ({
|
|
598
559
|
config,
|
|
599
560
|
locale
|
|
@@ -611,6 +572,31 @@ var useInitLocaleCookie = ({
|
|
|
611
572
|
}, []);
|
|
612
573
|
};
|
|
613
574
|
|
|
575
|
+
// src/adapters/next/contexts/locale/utils/change-locale.ts
|
|
576
|
+
var changeLocale = ({
|
|
577
|
+
currentLocale,
|
|
578
|
+
newLocale,
|
|
579
|
+
loaderOptions,
|
|
580
|
+
cookie,
|
|
581
|
+
setLocale,
|
|
582
|
+
refetchMessages
|
|
583
|
+
}) => {
|
|
584
|
+
if (typeof document === "undefined") return;
|
|
585
|
+
const loaderType = loaderOptions?.type;
|
|
586
|
+
if (newLocale === currentLocale) return;
|
|
587
|
+
if (loaderType === "import") {
|
|
588
|
+
console.warn(
|
|
589
|
+
`[Intor] You are using dynamic import to switch languages. Please make sure to use the wrapped <Link> component to trigger a page reload, ensuring that the translation data is dynamically updated.`
|
|
590
|
+
);
|
|
591
|
+
}
|
|
592
|
+
setLocale(newLocale);
|
|
593
|
+
setLocaleCookieBrowser({ cookie, locale: newLocale });
|
|
594
|
+
document.documentElement.lang = newLocale;
|
|
595
|
+
if (loaderType === "api" && refetchMessages) {
|
|
596
|
+
void refetchMessages(newLocale);
|
|
597
|
+
}
|
|
598
|
+
};
|
|
599
|
+
|
|
614
600
|
// src/adapters/next/contexts/locale/provider.tsx
|
|
615
601
|
function LocaleProvider({
|
|
616
602
|
value: { initialLocale },
|
|
@@ -709,7 +695,7 @@ function useTranslator() {
|
|
|
709
695
|
const context = React7.useContext(TranslatorContext);
|
|
710
696
|
if (!context)
|
|
711
697
|
throw new Error(
|
|
712
|
-
"
|
|
698
|
+
"useTranslator must be used within IntorTranslatorProvider"
|
|
713
699
|
);
|
|
714
700
|
return context;
|
|
715
701
|
}
|
|
@@ -732,13 +718,12 @@ function useTranslator2(preKey) {
|
|
|
732
718
|
isLoading: translator.isLoading,
|
|
733
719
|
setLocale
|
|
734
720
|
};
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
}
|
|
721
|
+
const scoped = translator.scoped(preKey);
|
|
722
|
+
return {
|
|
723
|
+
...props,
|
|
724
|
+
hasKey: preKey ? scoped.hasKey : translator.hasKey,
|
|
725
|
+
t: preKey ? scoped.t : translator.t
|
|
726
|
+
};
|
|
742
727
|
}
|
|
743
728
|
|
|
744
729
|
// src/adapters/next/shared/utils/locale-prefix-pathname.ts
|
|
@@ -758,15 +743,11 @@ var localePrefixPathname = ({
|
|
|
758
743
|
);
|
|
759
744
|
}
|
|
760
745
|
if (prefix === "except-default") {
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
)
|
|
765
|
-
|
|
766
|
-
return normalizePathname(
|
|
767
|
-
standardizedPathname.replaceAll(PREFIX_PLACEHOLDER, locale)
|
|
768
|
-
);
|
|
769
|
-
}
|
|
746
|
+
return locale === config.defaultLocale ? normalizePathname(
|
|
747
|
+
standardizedPathname.replaceAll(`/${PREFIX_PLACEHOLDER}`, "")
|
|
748
|
+
) : normalizePathname(
|
|
749
|
+
standardizedPathname.replaceAll(PREFIX_PLACEHOLDER, locale)
|
|
750
|
+
);
|
|
770
751
|
}
|
|
771
752
|
return normalizePathname(
|
|
772
753
|
standardizedPathname.replaceAll(`/${PREFIX_PLACEHOLDER}`, "")
|
|
@@ -858,7 +839,7 @@ var useLocaleSwitch = () => {
|
|
|
858
839
|
if (isExternal) return;
|
|
859
840
|
if (shouldFullReload({ config, targetPathname, locale, currentLocale })) {
|
|
860
841
|
setLocaleCookieBrowser({ cookie: config.cookie, locale: targetLocale });
|
|
861
|
-
|
|
842
|
+
globalThis.location.href = resolvedHref;
|
|
862
843
|
return;
|
|
863
844
|
} else {
|
|
864
845
|
setLocale(targetLocale);
|
|
@@ -45,15 +45,15 @@ var setPathnameHeader = ({
|
|
|
45
45
|
var PREFIX_PLACEHOLDER = "{locale}";
|
|
46
46
|
|
|
47
47
|
// src/shared/utils/locale/normalize-locale.ts
|
|
48
|
+
var toCanonical = (input) => {
|
|
49
|
+
try {
|
|
50
|
+
return Intl.getCanonicalLocales(input)[0]?.toLowerCase();
|
|
51
|
+
} catch {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
48
55
|
var normalizeLocale = (locale = "", supportedLocales = []) => {
|
|
49
56
|
if (!locale || supportedLocales.length === 0) return;
|
|
50
|
-
const toCanonical = (input) => {
|
|
51
|
-
try {
|
|
52
|
-
return Intl.getCanonicalLocales(input)[0]?.toLowerCase();
|
|
53
|
-
} catch {
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
57
|
const canonicalLocale = toCanonical(locale);
|
|
58
58
|
if (!canonicalLocale) return;
|
|
59
59
|
const supportedCanonicalMap = /* @__PURE__ */ new Map();
|
|
@@ -84,12 +84,12 @@ var resolvePreferredLocale = (acceptLanguageHeader, supportedLocales) => {
|
|
|
84
84
|
const supportedLocalesSet = new Set(supportedLocales);
|
|
85
85
|
const preferred = acceptLanguageHeader.split(",").map((part) => {
|
|
86
86
|
const [lang, qValue] = part.split(";");
|
|
87
|
-
const q = qValue ? parseFloat(qValue.split("=")[1]) : 1;
|
|
88
|
-
if (isNaN(q)) {
|
|
87
|
+
const q = qValue ? Number.parseFloat(qValue.split("=")[1]) : 1;
|
|
88
|
+
if (Number.isNaN(q)) {
|
|
89
89
|
return { lang: lang.trim(), q: 0 };
|
|
90
90
|
}
|
|
91
91
|
return { lang: lang.trim(), q };
|
|
92
|
-
}).
|
|
92
|
+
}).toSorted((a, b) => b.q - a.q).find(({ lang }) => supportedLocalesSet.has(lang))?.lang;
|
|
93
93
|
return preferred;
|
|
94
94
|
};
|
|
95
95
|
|
|
@@ -98,8 +98,8 @@ var normalizePathname = (rawPathname, options = {}) => {
|
|
|
98
98
|
const length = rawPathname.length;
|
|
99
99
|
let start = 0;
|
|
100
100
|
let end = length - 1;
|
|
101
|
-
while (start <= end && rawPathname.
|
|
102
|
-
while (end >= start && rawPathname.
|
|
101
|
+
while (start <= end && (rawPathname.codePointAt(start) ?? 0) <= 32) start++;
|
|
102
|
+
while (end >= start && (rawPathname.codePointAt(end) ?? 0) <= 32) end--;
|
|
103
103
|
if (start > end) return "/";
|
|
104
104
|
let result = "";
|
|
105
105
|
let hasSlash = false;
|
|
@@ -110,11 +110,7 @@ var normalizePathname = (rawPathname, options = {}) => {
|
|
|
110
110
|
hasSlash = true;
|
|
111
111
|
}
|
|
112
112
|
} else {
|
|
113
|
-
|
|
114
|
-
result += "/" + char;
|
|
115
|
-
} else {
|
|
116
|
-
result += char;
|
|
117
|
-
}
|
|
113
|
+
result += hasSlash || result === "" ? "/" + char : char;
|
|
118
114
|
hasSlash = false;
|
|
119
115
|
}
|
|
120
116
|
}
|
|
@@ -138,8 +134,8 @@ var extractPathname = ({
|
|
|
138
134
|
} else if (basePath && normalizedPathname === basePath) {
|
|
139
135
|
prefixedPathname = "/";
|
|
140
136
|
}
|
|
141
|
-
const
|
|
142
|
-
const maybeLocale =
|
|
137
|
+
const pathPart = prefixedPathname.split("/").find(Boolean);
|
|
138
|
+
const maybeLocale = pathPart || "";
|
|
143
139
|
const isLocalePrefixed = config.supportedLocales?.includes(maybeLocale);
|
|
144
140
|
let unprefixedPathname = prefixedPathname;
|
|
145
141
|
if (prefix === "all") {
|
|
@@ -172,7 +168,7 @@ var standardizePathname = ({
|
|
|
172
168
|
PREFIX_PLACEHOLDER,
|
|
173
169
|
normalizePathname(pathname)
|
|
174
170
|
];
|
|
175
|
-
const standardizedPathname = parts.join("/").
|
|
171
|
+
const standardizedPathname = parts.join("/").replaceAll(/\/{2,}/g, "/");
|
|
176
172
|
return normalizePathname(standardizedPathname);
|
|
177
173
|
};
|
|
178
174
|
|
|
@@ -193,15 +189,11 @@ var localePrefixPathname = ({
|
|
|
193
189
|
);
|
|
194
190
|
}
|
|
195
191
|
if (prefix === "except-default") {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
)
|
|
200
|
-
|
|
201
|
-
return normalizePathname(
|
|
202
|
-
standardizedPathname.replaceAll(PREFIX_PLACEHOLDER, locale)
|
|
203
|
-
);
|
|
204
|
-
}
|
|
192
|
+
return locale === config.defaultLocale ? normalizePathname(
|
|
193
|
+
standardizedPathname.replaceAll(`/${PREFIX_PLACEHOLDER}`, "")
|
|
194
|
+
) : normalizePathname(
|
|
195
|
+
standardizedPathname.replaceAll(PREFIX_PLACEHOLDER, locale)
|
|
196
|
+
);
|
|
205
197
|
}
|
|
206
198
|
return normalizePathname(
|
|
207
199
|
standardizedPathname.replaceAll(`/${PREFIX_PLACEHOLDER}`, "")
|
|
@@ -251,12 +243,7 @@ var createResponse = ({
|
|
|
251
243
|
locale
|
|
252
244
|
});
|
|
253
245
|
url.pathname = localePrefixedPathname;
|
|
254
|
-
|
|
255
|
-
if (responseType === "redirect") {
|
|
256
|
-
response = server.NextResponse.redirect(url);
|
|
257
|
-
} else {
|
|
258
|
-
response = server.NextResponse.next();
|
|
259
|
-
}
|
|
246
|
+
const response = responseType === "redirect" ? server.NextResponse.redirect(url) : server.NextResponse.next();
|
|
260
247
|
if (locale) {
|
|
261
248
|
setLocaleCookieEdge({
|
|
262
249
|
request,
|
|
@@ -276,7 +263,8 @@ var determineInitialLocale = async (config) => {
|
|
|
276
263
|
const { defaultLocale, supportedLocales, routing } = config;
|
|
277
264
|
let initialLocale = defaultLocale;
|
|
278
265
|
if (routing.firstVisit.localeSource === "browser") {
|
|
279
|
-
const
|
|
266
|
+
const headersStore = await headers.headers();
|
|
267
|
+
const acceptLanguageHeader = headersStore.get("accept-language") || void 0;
|
|
280
268
|
const preferredLocale = resolvePreferredLocale(
|
|
281
269
|
acceptLanguageHeader,
|
|
282
270
|
supportedLocales
|
|
@@ -287,10 +275,7 @@ var determineInitialLocale = async (config) => {
|
|
|
287
275
|
};
|
|
288
276
|
|
|
289
277
|
// src/adapters/next/middleware/handle-prefix/handle-prefix-all.ts
|
|
290
|
-
var handlePrefixAll = async ({
|
|
291
|
-
request,
|
|
292
|
-
config
|
|
293
|
-
}) => {
|
|
278
|
+
var handlePrefixAll = async (config, request) => {
|
|
294
279
|
const { cookie, routing } = config;
|
|
295
280
|
const { maybeLocale, isLocalePrefixed } = extractPathname({
|
|
296
281
|
config,
|
|
@@ -328,10 +313,7 @@ var handlePrefixAll = async ({
|
|
|
328
313
|
};
|
|
329
314
|
|
|
330
315
|
// src/adapters/next/middleware/handle-prefix/handle-prefix-except-default.ts
|
|
331
|
-
var handlePrefixExceptDefault = async ({
|
|
332
|
-
request,
|
|
333
|
-
config
|
|
334
|
-
}) => {
|
|
316
|
+
var handlePrefixExceptDefault = async (config, request) => {
|
|
335
317
|
const { defaultLocale, cookie, routing } = config;
|
|
336
318
|
const { maybeLocale, isLocalePrefixed } = extractPathname({
|
|
337
319
|
config,
|
|
@@ -381,10 +363,7 @@ var handlePrefixExceptDefault = async ({
|
|
|
381
363
|
};
|
|
382
364
|
|
|
383
365
|
// src/adapters/next/middleware/handle-prefix/handle-prefix-none.ts
|
|
384
|
-
var handlePrefixNone = async ({
|
|
385
|
-
request,
|
|
386
|
-
config
|
|
387
|
-
}) => {
|
|
366
|
+
var handlePrefixNone = async (config, request) => {
|
|
388
367
|
let locale = request.cookies.get(config.cookie.name)?.value;
|
|
389
368
|
if (!locale) {
|
|
390
369
|
locale = await determineInitialLocale(config);
|
|
@@ -393,18 +372,15 @@ var handlePrefixNone = async ({
|
|
|
393
372
|
};
|
|
394
373
|
|
|
395
374
|
// src/adapters/next/middleware/intor-middleware.ts
|
|
396
|
-
async function intorMiddleware({
|
|
397
|
-
request,
|
|
398
|
-
config
|
|
399
|
-
}) {
|
|
375
|
+
async function intorMiddleware(config, request) {
|
|
400
376
|
const { prefix } = config.routing;
|
|
401
377
|
if (prefix === "none") {
|
|
402
|
-
return handlePrefixNone(
|
|
378
|
+
return handlePrefixNone(config, request);
|
|
403
379
|
}
|
|
404
380
|
if (prefix === "except-default") {
|
|
405
|
-
return await handlePrefixExceptDefault(
|
|
381
|
+
return await handlePrefixExceptDefault(config, request);
|
|
406
382
|
}
|
|
407
|
-
return await handlePrefixAll(
|
|
383
|
+
return await handlePrefixAll(config, request);
|
|
408
384
|
}
|
|
409
385
|
|
|
410
386
|
exports.PATHNAME_HEADER_NAME = PATHNAME_HEADER_NAME;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { NextRequest } from 'next/server';
|
|
2
1
|
import { Level, NormalizerConfig, FormatterConfig, LoggerPreset } from 'logry/edge';
|
|
3
|
-
import { Locale,
|
|
2
|
+
import { Locale, LocaleMessages, FallbackLocalesMap } from 'intor-translator';
|
|
3
|
+
import { NextRequest } from 'next/server';
|
|
4
4
|
|
|
5
5
|
type CookieRawOptions = {
|
|
6
6
|
/** Completely disable cookie usage (no read, no write, no lookup by name) - default: false */
|
|
@@ -110,7 +110,7 @@ type WithLoader = {
|
|
|
110
110
|
};
|
|
111
111
|
type IntorResolvedConfig = (WithLoader | WithoutLoader) & {
|
|
112
112
|
readonly id: string;
|
|
113
|
-
readonly messages?:
|
|
113
|
+
readonly messages?: LocaleMessages;
|
|
114
114
|
readonly defaultLocale: Locale;
|
|
115
115
|
readonly fallbackLocales: FallbackLocalesMap;
|
|
116
116
|
readonly translator?: TranslatorOptions;
|
|
@@ -120,14 +120,10 @@ type IntorResolvedConfig = (WithLoader | WithoutLoader) & {
|
|
|
120
120
|
readonly cache: CacheResolvedOptions;
|
|
121
121
|
};
|
|
122
122
|
|
|
123
|
-
interface IntorMiddlewareParams<Req extends NextRequest = NextRequest> {
|
|
124
|
-
request: Req;
|
|
125
|
-
config: IntorResolvedConfig;
|
|
126
|
-
}
|
|
127
123
|
/**
|
|
128
124
|
* Handle locale routing based on prefix config
|
|
129
125
|
*/
|
|
130
|
-
declare function intorMiddleware<Req extends NextRequest = NextRequest>(
|
|
126
|
+
declare function intorMiddleware<Req extends NextRequest = NextRequest>(config: IntorResolvedConfig, request: Req): Promise<Response>;
|
|
131
127
|
|
|
132
128
|
declare const PATHNAME_HEADER_NAME = "x-intor-pathname";
|
|
133
129
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { NextRequest } from 'next/server';
|
|
2
1
|
import { Level, NormalizerConfig, FormatterConfig, LoggerPreset } from 'logry/edge';
|
|
3
|
-
import { Locale,
|
|
2
|
+
import { Locale, LocaleMessages, FallbackLocalesMap } from 'intor-translator';
|
|
3
|
+
import { NextRequest } from 'next/server';
|
|
4
4
|
|
|
5
5
|
type CookieRawOptions = {
|
|
6
6
|
/** Completely disable cookie usage (no read, no write, no lookup by name) - default: false */
|
|
@@ -110,7 +110,7 @@ type WithLoader = {
|
|
|
110
110
|
};
|
|
111
111
|
type IntorResolvedConfig = (WithLoader | WithoutLoader) & {
|
|
112
112
|
readonly id: string;
|
|
113
|
-
readonly messages?:
|
|
113
|
+
readonly messages?: LocaleMessages;
|
|
114
114
|
readonly defaultLocale: Locale;
|
|
115
115
|
readonly fallbackLocales: FallbackLocalesMap;
|
|
116
116
|
readonly translator?: TranslatorOptions;
|
|
@@ -120,14 +120,10 @@ type IntorResolvedConfig = (WithLoader | WithoutLoader) & {
|
|
|
120
120
|
readonly cache: CacheResolvedOptions;
|
|
121
121
|
};
|
|
122
122
|
|
|
123
|
-
interface IntorMiddlewareParams<Req extends NextRequest = NextRequest> {
|
|
124
|
-
request: Req;
|
|
125
|
-
config: IntorResolvedConfig;
|
|
126
|
-
}
|
|
127
123
|
/**
|
|
128
124
|
* Handle locale routing based on prefix config
|
|
129
125
|
*/
|
|
130
|
-
declare function intorMiddleware<Req extends NextRequest = NextRequest>(
|
|
126
|
+
declare function intorMiddleware<Req extends NextRequest = NextRequest>(config: IntorResolvedConfig, request: Req): Promise<Response>;
|
|
131
127
|
|
|
132
128
|
declare const PATHNAME_HEADER_NAME = "x-intor-pathname";
|
|
133
129
|
|