intor 2.1.0 → 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 +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 +24 -36
- package/dist/next/middleware/index.d.cts +3 -3
- package/dist/next/middleware/index.d.ts +3 -3
- package/dist/next/middleware/index.js +24 -36
- 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.cjs
CHANGED
|
@@ -4,8 +4,8 @@ var React7 = require('react');
|
|
|
4
4
|
var logry = require('logry');
|
|
5
5
|
var Keyv = require('keyv');
|
|
6
6
|
var intorTranslator = require('intor-translator');
|
|
7
|
-
var NextLink = require('next/link');
|
|
8
7
|
var formatUrl = require('next/dist/shared/lib/router/utils/format-url');
|
|
8
|
+
var NextLink = require('next/link');
|
|
9
9
|
var navigation = require('next/navigation');
|
|
10
10
|
var headers = require('next/headers');
|
|
11
11
|
|
|
@@ -48,66 +48,6 @@ function useConfig() {
|
|
|
48
48
|
return context;
|
|
49
49
|
}
|
|
50
50
|
var LocaleContext = React7__namespace.createContext(void 0);
|
|
51
|
-
|
|
52
|
-
// src/adapters/next/shared/utils/build-cookie-string.ts
|
|
53
|
-
var buildCookieString = (cookie, locale) => {
|
|
54
|
-
const parts = [];
|
|
55
|
-
parts.push(`${cookie.name}=${encodeURIComponent(locale)}`);
|
|
56
|
-
if (cookie.maxAge) {
|
|
57
|
-
const expires = new Date(Date.now() + cookie.maxAge * 1e3).toUTCString();
|
|
58
|
-
parts.push(`expires=${expires}`);
|
|
59
|
-
parts.push(`max-age=${cookie.maxAge}`);
|
|
60
|
-
}
|
|
61
|
-
parts.push(`path=${cookie.path ?? "/"}`);
|
|
62
|
-
if (cookie.domain) {
|
|
63
|
-
parts.push(`domain=${cookie.domain}`);
|
|
64
|
-
}
|
|
65
|
-
if (cookie.sameSite) {
|
|
66
|
-
parts.push(
|
|
67
|
-
`SameSite=${cookie.sameSite[0].toUpperCase()}${cookie.sameSite.slice(1).toLowerCase()}`
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
if (cookie.secure !== false) {
|
|
71
|
-
parts.push(`Secure`);
|
|
72
|
-
}
|
|
73
|
-
return parts.join("; ");
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
// src/adapters/next/shared/utils/set-locale-cookie-browser.ts
|
|
77
|
-
var setLocaleCookieBrowser = ({
|
|
78
|
-
cookie,
|
|
79
|
-
locale
|
|
80
|
-
}) => {
|
|
81
|
-
if (typeof window === "undefined") return;
|
|
82
|
-
if (cookie.disabled || !cookie.autoSetCookie) return;
|
|
83
|
-
const cookieString = buildCookieString(cookie, locale);
|
|
84
|
-
document.cookie = cookieString;
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
// src/adapters/next/contexts/locale/utils/change-locale.ts
|
|
88
|
-
var changeLocale = ({
|
|
89
|
-
currentLocale,
|
|
90
|
-
newLocale,
|
|
91
|
-
loaderOptions,
|
|
92
|
-
cookie,
|
|
93
|
-
setLocale,
|
|
94
|
-
refetchMessages
|
|
95
|
-
}) => {
|
|
96
|
-
if (typeof document === "undefined") return;
|
|
97
|
-
const loaderType = loaderOptions?.type;
|
|
98
|
-
if (newLocale === currentLocale) return;
|
|
99
|
-
if (loaderType === "import") {
|
|
100
|
-
console.warn(
|
|
101
|
-
`[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.`
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
setLocale(newLocale);
|
|
105
|
-
setLocaleCookieBrowser({ cookie, locale: newLocale });
|
|
106
|
-
document.documentElement.lang = newLocale;
|
|
107
|
-
if (loaderType === "api" && refetchMessages) {
|
|
108
|
-
void refetchMessages(newLocale);
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
51
|
var MessagesContext = React7__namespace.createContext(void 0);
|
|
112
52
|
|
|
113
53
|
// src/modules/config/constants/cache.constants.ts
|
|
@@ -146,7 +86,7 @@ function getLogger({
|
|
|
146
86
|
});
|
|
147
87
|
pool.set(id, logger);
|
|
148
88
|
if (pool.size > 1e3) {
|
|
149
|
-
const keys =
|
|
89
|
+
const keys = [...pool.keys()];
|
|
150
90
|
for (const key of keys.slice(0, 200)) pool.delete(key);
|
|
151
91
|
}
|
|
152
92
|
}
|
|
@@ -161,7 +101,7 @@ function getGlobalMessagesPool() {
|
|
|
161
101
|
|
|
162
102
|
// src/shared/utils/merge-messages.ts
|
|
163
103
|
var mergeMessages = (staticMessages = {}, loadedMessages = {}) => {
|
|
164
|
-
const result = Object.keys(staticMessages).length ? { ...staticMessages } : {};
|
|
104
|
+
const result = Object.keys(staticMessages).length > 0 ? { ...staticMessages } : {};
|
|
165
105
|
for (const locale in loadedMessages) {
|
|
166
106
|
const loaded = loadedMessages[locale];
|
|
167
107
|
if (!result[locale]) {
|
|
@@ -180,7 +120,7 @@ var mergeMessages = (staticMessages = {}, loadedMessages = {}) => {
|
|
|
180
120
|
var CACHE_KEY_DELIMITER = "|";
|
|
181
121
|
var sanitize = (k) => k.replaceAll(/[\u200B-\u200D\uFEFF]/g, "").replaceAll(/[\r\n]/g, "").trim();
|
|
182
122
|
var normalizeCacheKey = (key, delimiter = CACHE_KEY_DELIMITER) => {
|
|
183
|
-
if (
|
|
123
|
+
if (key === null || key === void 0) return null;
|
|
184
124
|
if (Array.isArray(key)) {
|
|
185
125
|
if (key.length === 0) return null;
|
|
186
126
|
const normalized = key.map((k) => {
|
|
@@ -204,56 +144,44 @@ var resolveNamespaces = ({
|
|
|
204
144
|
pathname
|
|
205
145
|
}) => {
|
|
206
146
|
const { loader } = config;
|
|
207
|
-
const {
|
|
208
|
-
|
|
209
|
-
namespaces: fallbackNamespaces
|
|
210
|
-
} = loader;
|
|
211
|
-
const { unprefixedPathname } = extractPathname({ config, pathname });
|
|
212
|
-
const standardizedPathname = standardizePathname({
|
|
213
|
-
config,
|
|
214
|
-
pathname: unprefixedPathname
|
|
215
|
-
});
|
|
147
|
+
const { routeNamespaces = {}, namespaces } = loader || {};
|
|
148
|
+
const standardizedPathname = standardizePathname({ config, pathname });
|
|
216
149
|
const placeholderRemovedPathname = standardizedPathname.replace(
|
|
217
150
|
`/${PREFIX_PLACEHOLDER}`,
|
|
218
151
|
""
|
|
219
152
|
);
|
|
220
|
-
const
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
153
|
+
const collected = [
|
|
154
|
+
...routeNamespaces.default || [],
|
|
155
|
+
// default
|
|
156
|
+
...namespaces || [],
|
|
157
|
+
// default
|
|
158
|
+
...routeNamespaces[standardizedPathname] || [],
|
|
159
|
+
// exact match
|
|
160
|
+
...routeNamespaces[placeholderRemovedPathname] || []
|
|
161
|
+
// exact match
|
|
162
|
+
];
|
|
227
163
|
const prefixPatterns = Object.keys(routeNamespaces).filter(
|
|
228
164
|
(pattern) => pattern.endsWith("/*")
|
|
229
165
|
);
|
|
230
166
|
for (const pattern of prefixPatterns) {
|
|
231
167
|
const basePath = pattern.replace(/\/\*$/, "");
|
|
232
|
-
if (standardizedPathname.startsWith(basePath)) {
|
|
233
|
-
|
|
234
|
-
bestMatch = basePath;
|
|
235
|
-
bestNamespaces = routeNamespaces[pattern];
|
|
236
|
-
}
|
|
168
|
+
if (standardizedPathname.startsWith(basePath) || placeholderRemovedPathname.startsWith(basePath)) {
|
|
169
|
+
collected.push(...routeNamespaces[pattern] || []);
|
|
237
170
|
}
|
|
238
171
|
}
|
|
239
|
-
|
|
240
|
-
if (matchedNamespaces.length > 0) {
|
|
241
|
-
return [...defaultNamespaces, ...matchedNamespaces];
|
|
242
|
-
} else {
|
|
243
|
-
return [...defaultNamespaces];
|
|
244
|
-
}
|
|
172
|
+
return [...new Set(collected)];
|
|
245
173
|
};
|
|
246
174
|
|
|
247
175
|
// src/shared/utils/locale/normalize-locale.ts
|
|
176
|
+
var toCanonical = (input) => {
|
|
177
|
+
try {
|
|
178
|
+
return Intl.getCanonicalLocales(input)[0]?.toLowerCase();
|
|
179
|
+
} catch {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
};
|
|
248
183
|
var normalizeLocale = (locale = "", supportedLocales = []) => {
|
|
249
184
|
if (!locale || supportedLocales.length === 0) return;
|
|
250
|
-
const toCanonical = (input) => {
|
|
251
|
-
try {
|
|
252
|
-
return Intl.getCanonicalLocales(input)[0]?.toLowerCase();
|
|
253
|
-
} catch {
|
|
254
|
-
return;
|
|
255
|
-
}
|
|
256
|
-
};
|
|
257
185
|
const canonicalLocale = toCanonical(locale);
|
|
258
186
|
if (!canonicalLocale) return;
|
|
259
187
|
const supportedCanonicalMap = /* @__PURE__ */ new Map();
|
|
@@ -284,12 +212,12 @@ var resolvePreferredLocale = (acceptLanguageHeader, supportedLocales) => {
|
|
|
284
212
|
const supportedLocalesSet = new Set(supportedLocales);
|
|
285
213
|
const preferred = acceptLanguageHeader.split(",").map((part) => {
|
|
286
214
|
const [lang, qValue] = part.split(";");
|
|
287
|
-
const q = qValue ? parseFloat(qValue.split("=")[1]) : 1;
|
|
288
|
-
if (isNaN(q)) {
|
|
215
|
+
const q = qValue ? Number.parseFloat(qValue.split("=")[1]) : 1;
|
|
216
|
+
if (Number.isNaN(q)) {
|
|
289
217
|
return { lang: lang.trim(), q: 0 };
|
|
290
218
|
}
|
|
291
219
|
return { lang: lang.trim(), q };
|
|
292
|
-
}).
|
|
220
|
+
}).toSorted((a, b) => b.q - a.q).find(({ lang }) => supportedLocalesSet.has(lang))?.lang;
|
|
293
221
|
return preferred;
|
|
294
222
|
};
|
|
295
223
|
|
|
@@ -298,8 +226,8 @@ var normalizePathname = (rawPathname, options = {}) => {
|
|
|
298
226
|
const length = rawPathname.length;
|
|
299
227
|
let start = 0;
|
|
300
228
|
let end = length - 1;
|
|
301
|
-
while (start <= end && rawPathname.
|
|
302
|
-
while (end >= start && rawPathname.
|
|
229
|
+
while (start <= end && (rawPathname.codePointAt(start) ?? 0) <= 32) start++;
|
|
230
|
+
while (end >= start && (rawPathname.codePointAt(end) ?? 0) <= 32) end--;
|
|
303
231
|
if (start > end) return "/";
|
|
304
232
|
let result = "";
|
|
305
233
|
let hasSlash = false;
|
|
@@ -310,11 +238,7 @@ var normalizePathname = (rawPathname, options = {}) => {
|
|
|
310
238
|
hasSlash = true;
|
|
311
239
|
}
|
|
312
240
|
} else {
|
|
313
|
-
|
|
314
|
-
result += "/" + char;
|
|
315
|
-
} else {
|
|
316
|
-
result += char;
|
|
317
|
-
}
|
|
241
|
+
result += hasSlash || result === "" ? "/" + char : char;
|
|
318
242
|
hasSlash = false;
|
|
319
243
|
}
|
|
320
244
|
}
|
|
@@ -338,8 +262,8 @@ var extractPathname = ({
|
|
|
338
262
|
} else if (basePath && normalizedPathname === basePath) {
|
|
339
263
|
prefixedPathname = "/";
|
|
340
264
|
}
|
|
341
|
-
const
|
|
342
|
-
const maybeLocale =
|
|
265
|
+
const pathPart = prefixedPathname.split("/").find(Boolean);
|
|
266
|
+
const maybeLocale = pathPart || "";
|
|
343
267
|
const isLocalePrefixed = config.supportedLocales?.includes(maybeLocale);
|
|
344
268
|
let unprefixedPathname = prefixedPathname;
|
|
345
269
|
if (prefix === "all") {
|
|
@@ -372,7 +296,7 @@ var standardizePathname = ({
|
|
|
372
296
|
PREFIX_PLACEHOLDER,
|
|
373
297
|
normalizePathname(pathname)
|
|
374
298
|
];
|
|
375
|
-
const standardizedPathname = parts.join("/").
|
|
299
|
+
const standardizedPathname = parts.join("/").replaceAll(/\/{2,}/g, "/");
|
|
376
300
|
return normalizePathname(standardizedPathname);
|
|
377
301
|
};
|
|
378
302
|
|
|
@@ -484,8 +408,8 @@ var loadApiMessages = async ({
|
|
|
484
408
|
loggerOptions.id,
|
|
485
409
|
basePath,
|
|
486
410
|
locale,
|
|
487
|
-
|
|
488
|
-
|
|
411
|
+
(fallbackLocales ?? []).toSorted().join(","),
|
|
412
|
+
(namespaces ?? []).toSorted().join(",")
|
|
489
413
|
]);
|
|
490
414
|
if (cache.enabled && key) {
|
|
491
415
|
const cached = await pool?.get(key);
|
|
@@ -606,6 +530,8 @@ function useMessages() {
|
|
|
606
530
|
throw new Error("useMessages must be used within a MessagesProvider");
|
|
607
531
|
return context;
|
|
608
532
|
}
|
|
533
|
+
|
|
534
|
+
// src/adapters/next/contexts/locale/utils/use-init-lazy-load.ts
|
|
609
535
|
var useInitLazyLoad = ({
|
|
610
536
|
loaderOptions,
|
|
611
537
|
currentLocale
|
|
@@ -620,6 +546,41 @@ var useInitLazyLoad = ({
|
|
|
620
546
|
}
|
|
621
547
|
}, [lazyLoad, currentLocale, refetchMessages, isFirstLoadedRef]);
|
|
622
548
|
};
|
|
549
|
+
|
|
550
|
+
// src/adapters/next/shared/utils/build-cookie-string.ts
|
|
551
|
+
var buildCookieString = (cookie, locale) => {
|
|
552
|
+
const parts = [`${cookie.name}=${encodeURIComponent(locale)}`];
|
|
553
|
+
if (cookie.maxAge) {
|
|
554
|
+
const expires = new Date(Date.now() + cookie.maxAge * 1e3).toUTCString();
|
|
555
|
+
parts.push(`expires=${expires}`, `max-age=${cookie.maxAge}`);
|
|
556
|
+
}
|
|
557
|
+
parts.push(`path=${cookie.path ?? "/"}`);
|
|
558
|
+
if (cookie.domain) {
|
|
559
|
+
parts.push(`domain=${cookie.domain}`);
|
|
560
|
+
}
|
|
561
|
+
if (cookie.sameSite) {
|
|
562
|
+
parts.push(
|
|
563
|
+
`SameSite=${cookie.sameSite[0].toUpperCase()}${cookie.sameSite.slice(1).toLowerCase()}`
|
|
564
|
+
);
|
|
565
|
+
}
|
|
566
|
+
if (cookie.secure !== false) {
|
|
567
|
+
parts.push(`Secure`);
|
|
568
|
+
}
|
|
569
|
+
return parts.join("; ");
|
|
570
|
+
};
|
|
571
|
+
|
|
572
|
+
// src/adapters/next/shared/utils/set-locale-cookie-browser.ts
|
|
573
|
+
var setLocaleCookieBrowser = ({
|
|
574
|
+
cookie,
|
|
575
|
+
locale
|
|
576
|
+
}) => {
|
|
577
|
+
if (globalThis.window === void 0) return;
|
|
578
|
+
if (cookie.disabled || !cookie.autoSetCookie) return;
|
|
579
|
+
const cookieString = buildCookieString(cookie, locale);
|
|
580
|
+
document.cookie = cookieString;
|
|
581
|
+
};
|
|
582
|
+
|
|
583
|
+
// src/adapters/next/contexts/locale/utils/use-init-locale-cookie.ts
|
|
623
584
|
var useInitLocaleCookie = ({
|
|
624
585
|
config,
|
|
625
586
|
locale
|
|
@@ -637,6 +598,31 @@ var useInitLocaleCookie = ({
|
|
|
637
598
|
}, []);
|
|
638
599
|
};
|
|
639
600
|
|
|
601
|
+
// src/adapters/next/contexts/locale/utils/change-locale.ts
|
|
602
|
+
var changeLocale = ({
|
|
603
|
+
currentLocale,
|
|
604
|
+
newLocale,
|
|
605
|
+
loaderOptions,
|
|
606
|
+
cookie,
|
|
607
|
+
setLocale,
|
|
608
|
+
refetchMessages
|
|
609
|
+
}) => {
|
|
610
|
+
if (typeof document === "undefined") return;
|
|
611
|
+
const loaderType = loaderOptions?.type;
|
|
612
|
+
if (newLocale === currentLocale) return;
|
|
613
|
+
if (loaderType === "import") {
|
|
614
|
+
console.warn(
|
|
615
|
+
`[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.`
|
|
616
|
+
);
|
|
617
|
+
}
|
|
618
|
+
setLocale(newLocale);
|
|
619
|
+
setLocaleCookieBrowser({ cookie, locale: newLocale });
|
|
620
|
+
document.documentElement.lang = newLocale;
|
|
621
|
+
if (loaderType === "api" && refetchMessages) {
|
|
622
|
+
void refetchMessages(newLocale);
|
|
623
|
+
}
|
|
624
|
+
};
|
|
625
|
+
|
|
640
626
|
// src/adapters/next/contexts/locale/provider.tsx
|
|
641
627
|
function LocaleProvider({
|
|
642
628
|
value: { initialLocale },
|
|
@@ -735,7 +721,7 @@ function useTranslator() {
|
|
|
735
721
|
const context = React7__namespace.useContext(TranslatorContext);
|
|
736
722
|
if (!context)
|
|
737
723
|
throw new Error(
|
|
738
|
-
"
|
|
724
|
+
"useTranslator must be used within IntorTranslatorProvider"
|
|
739
725
|
);
|
|
740
726
|
return context;
|
|
741
727
|
}
|
|
@@ -758,13 +744,12 @@ function useTranslator2(preKey) {
|
|
|
758
744
|
isLoading: translator.isLoading,
|
|
759
745
|
setLocale
|
|
760
746
|
};
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
}
|
|
747
|
+
const scoped = translator.scoped(preKey);
|
|
748
|
+
return {
|
|
749
|
+
...props,
|
|
750
|
+
hasKey: preKey ? scoped.hasKey : translator.hasKey,
|
|
751
|
+
t: preKey ? scoped.t : translator.t
|
|
752
|
+
};
|
|
768
753
|
}
|
|
769
754
|
|
|
770
755
|
// src/adapters/next/shared/utils/locale-prefix-pathname.ts
|
|
@@ -784,15 +769,11 @@ var localePrefixPathname = ({
|
|
|
784
769
|
);
|
|
785
770
|
}
|
|
786
771
|
if (prefix === "except-default") {
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
)
|
|
791
|
-
|
|
792
|
-
return normalizePathname(
|
|
793
|
-
standardizedPathname.replaceAll(PREFIX_PLACEHOLDER, locale)
|
|
794
|
-
);
|
|
795
|
-
}
|
|
772
|
+
return locale === config.defaultLocale ? normalizePathname(
|
|
773
|
+
standardizedPathname.replaceAll(`/${PREFIX_PLACEHOLDER}`, "")
|
|
774
|
+
) : normalizePathname(
|
|
775
|
+
standardizedPathname.replaceAll(PREFIX_PLACEHOLDER, locale)
|
|
776
|
+
);
|
|
796
777
|
}
|
|
797
778
|
return normalizePathname(
|
|
798
779
|
standardizedPathname.replaceAll(`/${PREFIX_PLACEHOLDER}`, "")
|
|
@@ -884,7 +865,7 @@ var useLocaleSwitch = () => {
|
|
|
884
865
|
if (isExternal) return;
|
|
885
866
|
if (shouldFullReload({ config, targetPathname, locale, currentLocale })) {
|
|
886
867
|
setLocaleCookieBrowser({ cookie: config.cookie, locale: targetLocale });
|
|
887
|
-
|
|
868
|
+
globalThis.location.href = resolvedHref;
|
|
888
869
|
return;
|
|
889
870
|
} else {
|
|
890
871
|
setLocale(targetLocale);
|
package/dist/next/index.d.cts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
1
|
import { Level, NormalizerConfig, FormatterConfig, LoggerPreset } from 'logry/edge';
|
|
3
|
-
import { Locale,
|
|
4
|
-
import
|
|
2
|
+
import { Locale, LocaleMessages, FallbackLocalesMap, TranslateHandlers, ScopedLeafKeys, LocalizedLeafKeys, Replacement, LocalizedNodeKeys } from 'intor-translator';
|
|
3
|
+
import * as React from 'react';
|
|
5
4
|
import { Url } from 'next/dist/shared/lib/router/router';
|
|
5
|
+
import { LinkProps as LinkProps$1 } from 'next/link';
|
|
6
6
|
import * as next_dist_shared_lib_app_router_context_shared_runtime from 'next/dist/shared/lib/app-router-context.shared-runtime';
|
|
7
7
|
import { NavigateOptions } from 'next/dist/shared/lib/app-router-context.shared-runtime';
|
|
8
8
|
import { RedirectType } from 'next/navigation';
|
|
@@ -115,7 +115,7 @@ type WithLoader = {
|
|
|
115
115
|
};
|
|
116
116
|
type IntorResolvedConfig = (WithLoader | WithoutLoader) & {
|
|
117
117
|
readonly id: string;
|
|
118
|
-
readonly messages?:
|
|
118
|
+
readonly messages?: LocaleMessages;
|
|
119
119
|
readonly defaultLocale: Locale;
|
|
120
120
|
readonly fallbackLocales: FallbackLocalesMap;
|
|
121
121
|
readonly translator?: TranslatorOptions;
|
|
@@ -130,7 +130,7 @@ interface IntorProviderProps {
|
|
|
130
130
|
config: IntorResolvedConfig;
|
|
131
131
|
initialLocale: Locale;
|
|
132
132
|
pathname: string;
|
|
133
|
-
messages: Readonly<
|
|
133
|
+
messages: Readonly<LocaleMessages>;
|
|
134
134
|
};
|
|
135
135
|
children: React.ReactNode;
|
|
136
136
|
}
|
|
@@ -146,37 +146,64 @@ declare const TranslateHandlersProvider: ({ children, handlers, }: TranslateHand
|
|
|
146
146
|
|
|
147
147
|
declare const PREFIX_PLACEHOLDER = "{locale}";
|
|
148
148
|
|
|
149
|
+
/**
|
|
150
|
+
* Conditional type for generated types.
|
|
151
|
+
* - Returns `Then` if `IntorGeneratedTypes` exists, otherwise `Else`.
|
|
152
|
+
*/
|
|
149
153
|
type IfGen<Then, Else = never> = IntorGeneratedTypes extends void ? Else : Then;
|
|
154
|
+
/**
|
|
155
|
+
* Union of all configuration keys.
|
|
156
|
+
* - Defaults to `string` if `IntorGeneratedTypes` does not exist.
|
|
157
|
+
*/
|
|
150
158
|
type GenConfigKeys = IfGen<keyof IntorGeneratedTypes, string>;
|
|
151
|
-
|
|
159
|
+
/**
|
|
160
|
+
* Configuration shape for a given config key.
|
|
161
|
+
* - If `IntorGeneratedTypes` is not defined, falls back to default shape.
|
|
162
|
+
* Otherwise, picks `Locales` and `Messages` according to the key.
|
|
163
|
+
*/
|
|
164
|
+
type GenConfig<CK extends GenConfigKeys = "__default__"> = IntorGeneratedTypes extends void ? {
|
|
152
165
|
Locales: string;
|
|
153
|
-
Messages:
|
|
154
|
-
} :
|
|
155
|
-
Locales: IntorGeneratedTypes[
|
|
166
|
+
Messages: LocaleMessages;
|
|
167
|
+
} : CK extends keyof IntorGeneratedTypes ? {
|
|
168
|
+
Locales: IntorGeneratedTypes[CK]["Locales"];
|
|
156
169
|
Messages: {
|
|
157
|
-
[K in IntorGeneratedTypes[
|
|
170
|
+
[K in IntorGeneratedTypes[CK]["Locales"]]: IntorGeneratedTypes[CK]["Messages"][typeof PREFIX_PLACEHOLDER];
|
|
158
171
|
};
|
|
159
172
|
} : never;
|
|
160
|
-
|
|
161
|
-
type
|
|
162
|
-
|
|
173
|
+
/** Extracts messages for a given config key */
|
|
174
|
+
type GenMessages<CK extends GenConfigKeys = "__default__"> = GenConfig<CK>["Messages"];
|
|
175
|
+
/** Extracts locales for a given config key */
|
|
176
|
+
type GenLocale<CK extends GenConfigKeys = "__default__"> = GenConfig<CK>["Locales"];
|
|
163
177
|
|
|
164
|
-
|
|
165
|
-
interface TranslatorBaseProps<M> {
|
|
178
|
+
/** Base properties shared by all translator instances. */
|
|
179
|
+
interface TranslatorBaseProps<M = unknown> {
|
|
180
|
+
/** `messages`: The message object containing all translations. */
|
|
166
181
|
messages: M;
|
|
167
|
-
locale
|
|
182
|
+
/** Current locale in use. */
|
|
183
|
+
locale: Locale<M>;
|
|
168
184
|
}
|
|
169
|
-
|
|
185
|
+
/** Properties specific to client-side translator behavior. */
|
|
186
|
+
interface TranslatorClientProps<M = unknown> {
|
|
187
|
+
/** `isLoading`: Indicates whether translations are currently loading. */
|
|
170
188
|
isLoading: boolean;
|
|
171
|
-
setLocale
|
|
189
|
+
/** `setLocale`: Function to update the current locale. */
|
|
190
|
+
setLocale: (locale: Locale<M>) => void;
|
|
172
191
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
192
|
+
/**
|
|
193
|
+
* Conditional key type for TranslatorInstance.
|
|
194
|
+
* - Resolves to `ScopedLeafKeys` if a pre-key `PK` is provided,
|
|
195
|
+
* otherwise resolves to `LocalizedLeafKeys`.
|
|
196
|
+
*/
|
|
197
|
+
type Key<M, PK> = IfGen<PK extends string ? ScopedLeafKeys<M, PK> : LocalizedLeafKeys<M>, string>;
|
|
198
|
+
/**
|
|
199
|
+
* Translator instance type.
|
|
200
|
+
* Combines base props, client props, and core translation methods.
|
|
201
|
+
*/
|
|
202
|
+
type TranslatorInstance<M, PK extends string | undefined = undefined> = {
|
|
203
|
+
/** Check if a given key exists in the messages. */
|
|
204
|
+
hasKey: (key?: Key<M, PK>, targetLocale?: Locale<M>) => boolean;
|
|
205
|
+
/** Translate a given key into its string representation. */
|
|
206
|
+
t: <Result = string>(key?: Key<M, PK>, replacements?: Replacement) => Result;
|
|
180
207
|
} & TranslatorBaseProps<M> & TranslatorClientProps<M>;
|
|
181
208
|
|
|
182
209
|
/**
|
|
@@ -186,8 +213,8 @@ type ScopedTranslatorInstance<M, K extends string> = {
|
|
|
186
213
|
* - Supports optional `preKey` to create a scoped translator for nested keys.
|
|
187
214
|
* - Can accept a generic type parameter `M` to strongly type your messages.
|
|
188
215
|
*/
|
|
189
|
-
declare function useTranslator<
|
|
190
|
-
declare function useTranslator<
|
|
216
|
+
declare function useTranslator<CK extends GenConfigKeys = "__default__">(): TranslatorInstance<GenMessages<CK>>;
|
|
217
|
+
declare function useTranslator<CK extends GenConfigKeys = "__default__", PK extends string = LocalizedNodeKeys<GenMessages<CK>>>(preKey: IfGen<PK, string>): TranslatorInstance<GenMessages<CK>, PK>;
|
|
191
218
|
|
|
192
219
|
interface LinkProps extends Omit<LinkProps$1, "href">, Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, "href"> {
|
|
193
220
|
href?: Url;
|
package/dist/next/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
1
|
import { Level, NormalizerConfig, FormatterConfig, LoggerPreset } from 'logry/edge';
|
|
3
|
-
import { Locale,
|
|
4
|
-
import
|
|
2
|
+
import { Locale, LocaleMessages, FallbackLocalesMap, TranslateHandlers, ScopedLeafKeys, LocalizedLeafKeys, Replacement, LocalizedNodeKeys } from 'intor-translator';
|
|
3
|
+
import * as React from 'react';
|
|
5
4
|
import { Url } from 'next/dist/shared/lib/router/router';
|
|
5
|
+
import { LinkProps as LinkProps$1 } from 'next/link';
|
|
6
6
|
import * as next_dist_shared_lib_app_router_context_shared_runtime from 'next/dist/shared/lib/app-router-context.shared-runtime';
|
|
7
7
|
import { NavigateOptions } from 'next/dist/shared/lib/app-router-context.shared-runtime';
|
|
8
8
|
import { RedirectType } from 'next/navigation';
|
|
@@ -115,7 +115,7 @@ type WithLoader = {
|
|
|
115
115
|
};
|
|
116
116
|
type IntorResolvedConfig = (WithLoader | WithoutLoader) & {
|
|
117
117
|
readonly id: string;
|
|
118
|
-
readonly messages?:
|
|
118
|
+
readonly messages?: LocaleMessages;
|
|
119
119
|
readonly defaultLocale: Locale;
|
|
120
120
|
readonly fallbackLocales: FallbackLocalesMap;
|
|
121
121
|
readonly translator?: TranslatorOptions;
|
|
@@ -130,7 +130,7 @@ interface IntorProviderProps {
|
|
|
130
130
|
config: IntorResolvedConfig;
|
|
131
131
|
initialLocale: Locale;
|
|
132
132
|
pathname: string;
|
|
133
|
-
messages: Readonly<
|
|
133
|
+
messages: Readonly<LocaleMessages>;
|
|
134
134
|
};
|
|
135
135
|
children: React.ReactNode;
|
|
136
136
|
}
|
|
@@ -146,37 +146,64 @@ declare const TranslateHandlersProvider: ({ children, handlers, }: TranslateHand
|
|
|
146
146
|
|
|
147
147
|
declare const PREFIX_PLACEHOLDER = "{locale}";
|
|
148
148
|
|
|
149
|
+
/**
|
|
150
|
+
* Conditional type for generated types.
|
|
151
|
+
* - Returns `Then` if `IntorGeneratedTypes` exists, otherwise `Else`.
|
|
152
|
+
*/
|
|
149
153
|
type IfGen<Then, Else = never> = IntorGeneratedTypes extends void ? Else : Then;
|
|
154
|
+
/**
|
|
155
|
+
* Union of all configuration keys.
|
|
156
|
+
* - Defaults to `string` if `IntorGeneratedTypes` does not exist.
|
|
157
|
+
*/
|
|
150
158
|
type GenConfigKeys = IfGen<keyof IntorGeneratedTypes, string>;
|
|
151
|
-
|
|
159
|
+
/**
|
|
160
|
+
* Configuration shape for a given config key.
|
|
161
|
+
* - If `IntorGeneratedTypes` is not defined, falls back to default shape.
|
|
162
|
+
* Otherwise, picks `Locales` and `Messages` according to the key.
|
|
163
|
+
*/
|
|
164
|
+
type GenConfig<CK extends GenConfigKeys = "__default__"> = IntorGeneratedTypes extends void ? {
|
|
152
165
|
Locales: string;
|
|
153
|
-
Messages:
|
|
154
|
-
} :
|
|
155
|
-
Locales: IntorGeneratedTypes[
|
|
166
|
+
Messages: LocaleMessages;
|
|
167
|
+
} : CK extends keyof IntorGeneratedTypes ? {
|
|
168
|
+
Locales: IntorGeneratedTypes[CK]["Locales"];
|
|
156
169
|
Messages: {
|
|
157
|
-
[K in IntorGeneratedTypes[
|
|
170
|
+
[K in IntorGeneratedTypes[CK]["Locales"]]: IntorGeneratedTypes[CK]["Messages"][typeof PREFIX_PLACEHOLDER];
|
|
158
171
|
};
|
|
159
172
|
} : never;
|
|
160
|
-
|
|
161
|
-
type
|
|
162
|
-
|
|
173
|
+
/** Extracts messages for a given config key */
|
|
174
|
+
type GenMessages<CK extends GenConfigKeys = "__default__"> = GenConfig<CK>["Messages"];
|
|
175
|
+
/** Extracts locales for a given config key */
|
|
176
|
+
type GenLocale<CK extends GenConfigKeys = "__default__"> = GenConfig<CK>["Locales"];
|
|
163
177
|
|
|
164
|
-
|
|
165
|
-
interface TranslatorBaseProps<M> {
|
|
178
|
+
/** Base properties shared by all translator instances. */
|
|
179
|
+
interface TranslatorBaseProps<M = unknown> {
|
|
180
|
+
/** `messages`: The message object containing all translations. */
|
|
166
181
|
messages: M;
|
|
167
|
-
locale
|
|
182
|
+
/** Current locale in use. */
|
|
183
|
+
locale: Locale<M>;
|
|
168
184
|
}
|
|
169
|
-
|
|
185
|
+
/** Properties specific to client-side translator behavior. */
|
|
186
|
+
interface TranslatorClientProps<M = unknown> {
|
|
187
|
+
/** `isLoading`: Indicates whether translations are currently loading. */
|
|
170
188
|
isLoading: boolean;
|
|
171
|
-
setLocale
|
|
189
|
+
/** `setLocale`: Function to update the current locale. */
|
|
190
|
+
setLocale: (locale: Locale<M>) => void;
|
|
172
191
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
192
|
+
/**
|
|
193
|
+
* Conditional key type for TranslatorInstance.
|
|
194
|
+
* - Resolves to `ScopedLeafKeys` if a pre-key `PK` is provided,
|
|
195
|
+
* otherwise resolves to `LocalizedLeafKeys`.
|
|
196
|
+
*/
|
|
197
|
+
type Key<M, PK> = IfGen<PK extends string ? ScopedLeafKeys<M, PK> : LocalizedLeafKeys<M>, string>;
|
|
198
|
+
/**
|
|
199
|
+
* Translator instance type.
|
|
200
|
+
* Combines base props, client props, and core translation methods.
|
|
201
|
+
*/
|
|
202
|
+
type TranslatorInstance<M, PK extends string | undefined = undefined> = {
|
|
203
|
+
/** Check if a given key exists in the messages. */
|
|
204
|
+
hasKey: (key?: Key<M, PK>, targetLocale?: Locale<M>) => boolean;
|
|
205
|
+
/** Translate a given key into its string representation. */
|
|
206
|
+
t: <Result = string>(key?: Key<M, PK>, replacements?: Replacement) => Result;
|
|
180
207
|
} & TranslatorBaseProps<M> & TranslatorClientProps<M>;
|
|
181
208
|
|
|
182
209
|
/**
|
|
@@ -186,8 +213,8 @@ type ScopedTranslatorInstance<M, K extends string> = {
|
|
|
186
213
|
* - Supports optional `preKey` to create a scoped translator for nested keys.
|
|
187
214
|
* - Can accept a generic type parameter `M` to strongly type your messages.
|
|
188
215
|
*/
|
|
189
|
-
declare function useTranslator<
|
|
190
|
-
declare function useTranslator<
|
|
216
|
+
declare function useTranslator<CK extends GenConfigKeys = "__default__">(): TranslatorInstance<GenMessages<CK>>;
|
|
217
|
+
declare function useTranslator<CK extends GenConfigKeys = "__default__", PK extends string = LocalizedNodeKeys<GenMessages<CK>>>(preKey: IfGen<PK, string>): TranslatorInstance<GenMessages<CK>, PK>;
|
|
191
218
|
|
|
192
219
|
interface LinkProps extends Omit<LinkProps$1, "href">, Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, "href"> {
|
|
193
220
|
href?: Url;
|