intor 2.2.5 → 2.2.7

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.
@@ -0,0 +1,650 @@
1
+ 'use strict';
2
+
3
+ var React6 = require('react');
4
+ var jsxRuntime = require('react/jsx-runtime');
5
+ var logry = require('logry');
6
+ var Keyv = require('keyv');
7
+ var merge = require('lodash.merge');
8
+ var intorTranslator = require('intor-translator');
9
+
10
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
11
+
12
+ function _interopNamespace(e) {
13
+ if (e && e.__esModule) return e;
14
+ var n = Object.create(null);
15
+ if (e) {
16
+ Object.keys(e).forEach(function (k) {
17
+ if (k !== 'default') {
18
+ var d = Object.getOwnPropertyDescriptor(e, k);
19
+ Object.defineProperty(n, k, d.get ? d : {
20
+ enumerable: true,
21
+ get: function () { return e[k]; }
22
+ });
23
+ }
24
+ });
25
+ }
26
+ n.default = e;
27
+ return Object.freeze(n);
28
+ }
29
+
30
+ var React6__namespace = /*#__PURE__*/_interopNamespace(React6);
31
+ var Keyv__default = /*#__PURE__*/_interopDefault(Keyv);
32
+ var merge__default = /*#__PURE__*/_interopDefault(merge);
33
+
34
+ // src/client/react/contexts/intor-provider/intor-provider.tsx
35
+ var ConfigContext = React6__namespace.createContext(void 0);
36
+ function ConfigProvider({
37
+ value: { config, pathname },
38
+ children
39
+ }) {
40
+ const value = React6__namespace.useMemo(() => ({ config, pathname }), [config, pathname]);
41
+ return /* @__PURE__ */ jsxRuntime.jsx(ConfigContext.Provider, { value, children });
42
+ }
43
+ function useConfig() {
44
+ const context = React6__namespace.useContext(ConfigContext);
45
+ if (!context) throw new Error("useConfig must be used within ConfigProvider");
46
+ return context;
47
+ }
48
+
49
+ // src/config/constants/cache.constants.ts
50
+ var DEFAULT_CACHE_OPTIONS = {
51
+ enabled: process.env.NODE_ENV === "production",
52
+ ttl: 60 * 60 * 1e3
53
+ // 1 hour
54
+ };
55
+
56
+ // src/server/shared/logger/global-logger-pool.ts
57
+ function getGlobalLoggerPool() {
58
+ if (!globalThis.__INTOR_LOGGER_POOL__) {
59
+ globalThis.__INTOR_LOGGER_POOL__ = /* @__PURE__ */ new Map();
60
+ }
61
+ return globalThis.__INTOR_LOGGER_POOL__;
62
+ }
63
+
64
+ // src/server/shared/logger/get-logger.ts
65
+ var DEFAULT_FORMATTER_CONFIG = {
66
+ node: { meta: { compact: true }, lineBreaksAfter: 1 }
67
+ };
68
+ function getLogger({
69
+ id = "default",
70
+ formatterConfig,
71
+ preset,
72
+ ...options
73
+ }) {
74
+ const pool = getGlobalLoggerPool();
75
+ let logger = pool.get(id);
76
+ const useDefault = !formatterConfig && !preset;
77
+ if (!logger) {
78
+ logger = logry.logry({
79
+ id,
80
+ formatterConfig: useDefault ? DEFAULT_FORMATTER_CONFIG : formatterConfig,
81
+ preset,
82
+ ...options
83
+ });
84
+ pool.set(id, logger);
85
+ if (pool.size > 1e3) {
86
+ const keys = [...pool.keys()];
87
+ for (const key of keys.slice(0, 200)) pool.delete(key);
88
+ }
89
+ }
90
+ return logger;
91
+ }
92
+
93
+ // src/server/messages/shared/utils/is-valid-messages.ts
94
+ function isPlainObject(value) {
95
+ return typeof value === "object" && value !== null && !Array.isArray(value);
96
+ }
97
+ function isValidMessages(value) {
98
+ if (!isPlainObject(value)) return false;
99
+ const stack = [value];
100
+ while (stack.length > 0) {
101
+ const current = stack.pop();
102
+ for (const v of Object.values(current)) {
103
+ if (typeof v === "string") continue;
104
+ if (isPlainObject(v)) {
105
+ stack.push(v);
106
+ } else {
107
+ return false;
108
+ }
109
+ }
110
+ }
111
+ return true;
112
+ }
113
+ function getGlobalMessagesPool() {
114
+ if (!globalThis.__INTOR_MESSAGES_POOL__) {
115
+ globalThis.__INTOR_MESSAGES_POOL__ = new Keyv__default.default();
116
+ }
117
+ return globalThis.__INTOR_MESSAGES_POOL__;
118
+ }
119
+ var mergeMessages = (staticMessages = {}, loadedMessages = {}) => {
120
+ if (!loadedMessages) return { ...staticMessages };
121
+ return merge__default.default({}, staticMessages, loadedMessages);
122
+ };
123
+
124
+ // src/shared/utils/normalize-cache-key.ts
125
+ var CACHE_KEY_DELIMITER = "|";
126
+ var sanitize = (k) => k.replaceAll(/[\u200B-\u200D\uFEFF]/g, "").replaceAll(/[\r\n]/g, "").trim();
127
+ var normalizeCacheKey = (key, delimiter = CACHE_KEY_DELIMITER) => {
128
+ if (key === null || key === void 0) return null;
129
+ if (Array.isArray(key)) {
130
+ if (key.length === 0) return null;
131
+ const normalized = key.map((k) => {
132
+ if (k === null) return "__null";
133
+ if (k === void 0) return "__undefined";
134
+ if (typeof k === "boolean") return k ? "__true" : "__false";
135
+ return sanitize(String(k));
136
+ });
137
+ return normalized.join(delimiter);
138
+ }
139
+ if (typeof key === "boolean") return key ? "__true" : "__false";
140
+ return String(key);
141
+ };
142
+
143
+ // src/shared/constants/prefix-placeholder.ts
144
+ var PREFIX_PLACEHOLDER = "{locale}";
145
+
146
+ // src/shared/utils/resolve-namespaces.ts
147
+ var resolveNamespaces = ({
148
+ config,
149
+ pathname
150
+ }) => {
151
+ const { loader } = config;
152
+ const { routeNamespaces = {}, namespaces } = loader || {};
153
+ if (Object.keys(routeNamespaces).length === 0 && !namespaces)
154
+ return void 0;
155
+ const standardizedPathname = standardizePathname({ config, pathname });
156
+ const placeholderRemovedPathname = standardizedPathname.replace(
157
+ `/${PREFIX_PLACEHOLDER}`,
158
+ ""
159
+ );
160
+ const collected = [
161
+ ...routeNamespaces.default || [],
162
+ // default
163
+ ...namespaces || [],
164
+ // default
165
+ ...routeNamespaces[standardizedPathname] || [],
166
+ // exact match
167
+ ...routeNamespaces[placeholderRemovedPathname] || []
168
+ // exact match
169
+ ];
170
+ const prefixPatterns = Object.keys(routeNamespaces).filter(
171
+ (pattern) => pattern.endsWith("/*")
172
+ );
173
+ for (const pattern of prefixPatterns) {
174
+ const basePath = pattern.replace(/\/\*$/, "");
175
+ if (standardizedPathname.startsWith(basePath) || placeholderRemovedPathname.startsWith(basePath)) {
176
+ collected.push(...routeNamespaces[pattern] || []);
177
+ }
178
+ }
179
+ return [...new Set(collected)];
180
+ };
181
+
182
+ // src/shared/utils/pathname/normalize-pathname.ts
183
+ var normalizePathname = (rawPathname, options = {}) => {
184
+ const length = rawPathname.length;
185
+ let start = 0;
186
+ let end = length - 1;
187
+ while (start <= end && (rawPathname.codePointAt(start) ?? 0) <= 32) start++;
188
+ while (end >= start && (rawPathname.codePointAt(end) ?? 0) <= 32) end--;
189
+ if (start > end) return "/";
190
+ let result = "";
191
+ let hasSlash = false;
192
+ for (let i = start; i <= end; i++) {
193
+ const char = rawPathname[i];
194
+ if (char === "/") {
195
+ if (!hasSlash) {
196
+ hasSlash = true;
197
+ }
198
+ } else {
199
+ result += hasSlash || result === "" ? "/" + char : char;
200
+ hasSlash = false;
201
+ }
202
+ }
203
+ if (options.removeLeadingSlash && result.startsWith("/")) {
204
+ result = result.slice(1);
205
+ }
206
+ return result || "/";
207
+ };
208
+
209
+ // src/shared/utils/pathname/standardize-pathname.ts
210
+ var standardizePathname = ({
211
+ config,
212
+ pathname
213
+ }) => {
214
+ const { routing } = config;
215
+ const { basePath } = routing;
216
+ const parts = [
217
+ normalizePathname(basePath),
218
+ PREFIX_PLACEHOLDER,
219
+ normalizePathname(pathname)
220
+ ];
221
+ const standardizedPathname = parts.join("/").replaceAll(/\/{2,}/g, "/");
222
+ return normalizePathname(standardizedPathname);
223
+ };
224
+
225
+ // src/server/messages/load-remote-messages/fetch-locale-messages/fetch-locale-messages.ts
226
+ var fetchLocaleMessages = async ({
227
+ remoteUrl,
228
+ remoteHeaders,
229
+ searchParams,
230
+ locale,
231
+ extraOptions: { loggerOptions } = {}
232
+ }) => {
233
+ const baseLogger = getLogger({ ...loggerOptions });
234
+ const logger = baseLogger.child({ scope: "fetch-locale-messages" });
235
+ try {
236
+ const params = new URLSearchParams(searchParams);
237
+ params.append("locale", locale);
238
+ const url = `${remoteUrl}?${params.toString()}`;
239
+ const headers = {
240
+ "Content-Type": "application/json",
241
+ ...remoteHeaders
242
+ };
243
+ const response = await fetch(url, {
244
+ method: "GET",
245
+ headers,
246
+ cache: "no-store"
247
+ });
248
+ if (!response.ok) {
249
+ throw new Error(`HTTP error ${response.status} ${response.statusText}`);
250
+ }
251
+ const data = await response.json();
252
+ if (!isValidMessages(data[locale])) {
253
+ throw new Error("JSON file does not match NamespaceMessages structure");
254
+ }
255
+ return data;
256
+ } catch (error) {
257
+ logger.warn("Fetching locale messages failed.", {
258
+ locale,
259
+ remoteUrl,
260
+ searchParams: decodeURIComponent(searchParams.toString()),
261
+ error
262
+ });
263
+ return;
264
+ }
265
+ };
266
+
267
+ // src/server/messages/load-remote-messages/fetch-locale-messages/utils/build-search-params.ts
268
+ var buildSearchParams = (params) => {
269
+ const searchParams = new URLSearchParams();
270
+ const appendParam = (key, value) => {
271
+ if (value === void 0 || value === null) return;
272
+ if (Array.isArray(value) && value.length === 0) return;
273
+ if (Array.isArray(value)) {
274
+ value.forEach((v) => v && searchParams.append(key, v));
275
+ } else {
276
+ searchParams.append(key, value);
277
+ }
278
+ };
279
+ Object.entries(params).forEach(([key, value]) => {
280
+ appendParam(key, value);
281
+ });
282
+ return searchParams;
283
+ };
284
+
285
+ // src/server/messages/load-remote-messages/load-remote-messages.ts
286
+ var loadRemoteMessages = async ({
287
+ pool = getGlobalMessagesPool(),
288
+ rootDir,
289
+ remoteUrl,
290
+ remoteHeaders,
291
+ locale,
292
+ fallbackLocales = [],
293
+ namespaces = [],
294
+ extraOptions: {
295
+ cacheOptions = DEFAULT_CACHE_OPTIONS,
296
+ loggerOptions = { id: "default" }
297
+ } = {},
298
+ allowCacheWrite
299
+ }) => {
300
+ const baseLogger = getLogger({ ...loggerOptions });
301
+ const logger = baseLogger.child({ scope: "load-remote-messages" });
302
+ const start = performance.now();
303
+ logger.debug("Loading remote messages from api.", { remoteUrl });
304
+ const key = normalizeCacheKey([
305
+ loggerOptions.id,
306
+ "loaderType:remote",
307
+ rootDir,
308
+ locale,
309
+ (fallbackLocales ?? []).toSorted().join(","),
310
+ (namespaces ?? []).toSorted().join(",")
311
+ ]);
312
+ if (cacheOptions.enabled && key) {
313
+ const cached = await pool?.get(key);
314
+ if (cached) {
315
+ logger.debug("Messages cache hit.", { key });
316
+ return cached;
317
+ }
318
+ }
319
+ const searchParams = buildSearchParams({ rootDir, namespaces });
320
+ const candidateLocales = [locale, ...fallbackLocales || []];
321
+ let messages;
322
+ for (const candidateLocale of candidateLocales) {
323
+ try {
324
+ const result = await fetchLocaleMessages({
325
+ remoteUrl,
326
+ remoteHeaders,
327
+ searchParams,
328
+ locale: candidateLocale,
329
+ extraOptions: { loggerOptions }
330
+ });
331
+ if (result && Object.values(result[candidateLocale] || {}).length > 0) {
332
+ messages = result;
333
+ break;
334
+ }
335
+ } catch (error) {
336
+ logger.error("Failed to fetch locale messages.", {
337
+ locale: candidateLocale,
338
+ error
339
+ });
340
+ }
341
+ }
342
+ if (allowCacheWrite && cacheOptions.enabled && key && messages) {
343
+ await pool?.set(key, messages, cacheOptions.ttl);
344
+ }
345
+ const end = performance.now();
346
+ const duration = Math.round(end - start);
347
+ logger.trace("Finished loading remote messages.", {
348
+ loadedLocale: messages ? Object.keys(messages)[0] : void 0,
349
+ duration: `${duration} ms`
350
+ });
351
+ return messages;
352
+ };
353
+
354
+ // src/client/react/contexts/messages/utils/use-refetch-messages.ts
355
+ var useRefetchMessages = ({
356
+ config,
357
+ pathname,
358
+ setLoadedMessages,
359
+ setIsLoadingMessages
360
+ }) => {
361
+ const { messages: staticMessages } = config;
362
+ const namespaces = React6__namespace.useMemo(() => {
363
+ if (!config.loader) return [];
364
+ return resolveNamespaces({ config, pathname });
365
+ }, [config, pathname]);
366
+ const refetchMessages = React6__namespace.useCallback(
367
+ async (newLocale) => {
368
+ if (config.loader?.type === "remote") {
369
+ setIsLoadingMessages(true);
370
+ const loadedMessages = await loadRemoteMessages({
371
+ rootDir: config.loader.rootDir,
372
+ remoteUrl: config.loader.remoteUrl,
373
+ remoteHeaders: config.loader.remoteHeaders,
374
+ locale: newLocale,
375
+ fallbackLocales: config.fallbackLocales[newLocale] || [],
376
+ namespaces,
377
+ extraOptions: {
378
+ cacheOptions: config.cache,
379
+ loggerOptions: { id: config.id }
380
+ }
381
+ });
382
+ const messages = mergeMessages(staticMessages, loadedMessages);
383
+ setLoadedMessages(messages);
384
+ setIsLoadingMessages(false);
385
+ }
386
+ },
387
+ [
388
+ config.loader,
389
+ config.fallbackLocales,
390
+ config.id,
391
+ setIsLoadingMessages,
392
+ namespaces,
393
+ staticMessages,
394
+ setLoadedMessages
395
+ ]
396
+ );
397
+ return { refetchMessages };
398
+ };
399
+ var MessagesContext = React6__namespace.createContext(void 0);
400
+ function MessagesProvider({
401
+ value: { messages = {} },
402
+ children
403
+ }) {
404
+ const { config, pathname } = useConfig();
405
+ const [loadedMessages, setLoadedMessages] = React6__namespace.useState(null);
406
+ const [isLoadingMessages, setIsLoadingMessages] = React6__namespace.useState(false);
407
+ const { refetchMessages } = useRefetchMessages({
408
+ config,
409
+ pathname,
410
+ setLoadedMessages,
411
+ setIsLoadingMessages
412
+ });
413
+ const value = React6__namespace.useMemo(
414
+ () => ({
415
+ messages: loadedMessages || messages,
416
+ isLoading: isLoadingMessages,
417
+ setLoadedMessages,
418
+ setIsLoadingMessages,
419
+ refetchMessages
420
+ }),
421
+ [loadedMessages, messages, isLoadingMessages, refetchMessages]
422
+ );
423
+ return /* @__PURE__ */ jsxRuntime.jsx(MessagesContext.Provider, { value, children });
424
+ }
425
+ function useMessages() {
426
+ const context = React6__namespace.useContext(MessagesContext);
427
+ if (!context)
428
+ throw new Error("useMessages must be used within a MessagesProvider");
429
+ return context;
430
+ }
431
+
432
+ // src/client/react/contexts/locale/utils/use-init-lazy-load.ts
433
+ var useInitLazyLoad = ({
434
+ loaderOptions,
435
+ currentLocale
436
+ }) => {
437
+ const { refetchMessages } = useMessages();
438
+ const lazyLoad = !!loaderOptions?.lazyLoad;
439
+ const isFirstLoadedRef = React6__namespace.useRef(false);
440
+ React6__namespace.useEffect(() => {
441
+ if (lazyLoad && !isFirstLoadedRef.current) {
442
+ void refetchMessages(currentLocale);
443
+ isFirstLoadedRef.current = true;
444
+ }
445
+ }, [lazyLoad, currentLocale, refetchMessages, isFirstLoadedRef]);
446
+ };
447
+
448
+ // src/shared/utils/client/build-cookie-string.ts
449
+ var buildCookieString = (cookie, locale) => {
450
+ const parts = [`${cookie.name}=${encodeURIComponent(locale)}`];
451
+ if (cookie.maxAge) {
452
+ const expires = new Date(Date.now() + cookie.maxAge * 1e3).toUTCString();
453
+ parts.push(`expires=${expires}`, `max-age=${cookie.maxAge}`);
454
+ }
455
+ parts.push(`path=${cookie.path ?? "/"}`);
456
+ if (cookie.domain) {
457
+ parts.push(`domain=${cookie.domain}`);
458
+ }
459
+ if (cookie.sameSite) {
460
+ parts.push(
461
+ `SameSite=${cookie.sameSite[0].toUpperCase()}${cookie.sameSite.slice(1).toLowerCase()}`
462
+ );
463
+ }
464
+ if (cookie.secure !== false) {
465
+ parts.push(`Secure`);
466
+ }
467
+ return parts.join("; ");
468
+ };
469
+
470
+ // src/shared/utils/client/set-locale-cookie-browser.ts
471
+ var setLocaleCookieBrowser = ({
472
+ cookie,
473
+ locale
474
+ }) => {
475
+ if (globalThis.window === void 0) return;
476
+ if (cookie.disabled || !cookie.autoSetCookie) return;
477
+ const cookieString = buildCookieString(cookie, locale);
478
+ document.cookie = cookieString;
479
+ };
480
+
481
+ // src/client/react/contexts/locale/utils/use-init-locale-cookie.ts
482
+ var useInitLocaleCookie = ({
483
+ config,
484
+ locale
485
+ }) => {
486
+ React6__namespace.useEffect(() => {
487
+ if (typeof document === "undefined") return;
488
+ const { cookie, routing } = config;
489
+ const { firstVisit } = routing;
490
+ const cookies = document.cookie.split(";").map((c) => c.trim());
491
+ const isCookieExists = cookies.some((c) => c.startsWith(`${cookie.name}=`));
492
+ if (isCookieExists) return;
493
+ if (!firstVisit.redirect) return;
494
+ if (cookie.disabled || !cookie.autoSetCookie) return;
495
+ setLocaleCookieBrowser({ cookie, locale });
496
+ }, []);
497
+ };
498
+ var LocaleContext = React6__namespace.createContext(void 0);
499
+
500
+ // src/client/react/contexts/locale/utils/change-locale.ts
501
+ var changeLocale = ({
502
+ currentLocale,
503
+ newLocale,
504
+ loaderOptions,
505
+ cookie,
506
+ setLocale,
507
+ refetchMessages
508
+ }) => {
509
+ if (typeof document === "undefined") return;
510
+ const loaderType = loaderOptions?.type;
511
+ if (newLocale === currentLocale) return;
512
+ if (loaderType === "local") {
513
+ console.warn(
514
+ `[Intor] You are using dynamic local 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.`
515
+ );
516
+ }
517
+ setLocale(newLocale);
518
+ setLocaleCookieBrowser({ cookie, locale: newLocale });
519
+ document.documentElement.lang = newLocale;
520
+ if (loaderType === "remote" && refetchMessages) {
521
+ void refetchMessages(newLocale);
522
+ }
523
+ };
524
+ function LocaleProvider({
525
+ value: { initialLocale },
526
+ children
527
+ }) {
528
+ const { config } = useConfig();
529
+ const { refetchMessages } = useMessages();
530
+ const { loader: loaderOptions, cookie } = config;
531
+ const [currentLocale, setCurrentLocale] = React6__namespace.useState(initialLocale);
532
+ useInitLazyLoad({ loaderOptions, currentLocale });
533
+ useInitLocaleCookie({ config, locale: initialLocale });
534
+ const setLocale = React6__namespace.useCallback(
535
+ (newLocale) => {
536
+ changeLocale({
537
+ currentLocale,
538
+ newLocale,
539
+ loaderOptions,
540
+ cookie,
541
+ setLocale: setCurrentLocale,
542
+ refetchMessages
543
+ });
544
+ },
545
+ [currentLocale, loaderOptions, cookie, refetchMessages]
546
+ );
547
+ const value = React6__namespace.useMemo(
548
+ () => ({
549
+ locale: currentLocale,
550
+ setLocale
551
+ }),
552
+ [currentLocale, setLocale]
553
+ );
554
+ return /* @__PURE__ */ jsxRuntime.jsx(LocaleContext.Provider, { value, children });
555
+ }
556
+ function useLocale() {
557
+ const context = React6__namespace.useContext(LocaleContext);
558
+ if (!context)
559
+ throw new Error("useLocale must be used within a LocaleProvider");
560
+ return context;
561
+ }
562
+ var TranslateHandlersContext = React6__namespace.createContext(void 0);
563
+ var TranslateHandlersProvider = ({
564
+ children,
565
+ handlers
566
+ }) => {
567
+ const value = handlers;
568
+ return /* @__PURE__ */ jsxRuntime.jsx(TranslateHandlersContext.Provider, { value, children });
569
+ };
570
+ function useTranslateHandlers() {
571
+ const context = React6__namespace.useContext(TranslateHandlersContext);
572
+ return context;
573
+ }
574
+ var useInitLoadingState = (config) => {
575
+ const lazyLoad = !!config.loader?.lazyLoad;
576
+ const [isCsr, setIsCsr] = React6__namespace.useState(false);
577
+ React6__namespace.useEffect(() => {
578
+ setIsCsr(true);
579
+ }, []);
580
+ const isBeforeCSRLoading = lazyLoad && !isCsr;
581
+ return isBeforeCSRLoading;
582
+ };
583
+ var TranslatorContext = React6__namespace.createContext(void 0);
584
+ var EMPTY_OBJECT = Object.freeze({});
585
+ function TranslatorProvider({ children }) {
586
+ const { config } = useConfig();
587
+ const { messages, isLoading } = useMessages();
588
+ const { locale } = useLocale();
589
+ const translatorHandlers = useTranslateHandlers();
590
+ const { fallbackLocales, translator: translatorOptions } = config;
591
+ const isBeforeCSRLoading = useInitLoadingState(config);
592
+ const value = React6__namespace.useMemo(() => {
593
+ const translator = new intorTranslator.Translator({
594
+ messages: messages || EMPTY_OBJECT,
595
+ locale,
596
+ fallbackLocales,
597
+ loadingMessage: translatorOptions?.loadingMessage,
598
+ placeholder: translatorOptions?.placeholder,
599
+ handlers: translatorHandlers
600
+ });
601
+ translator.setLoading(isBeforeCSRLoading || isLoading);
602
+ return { translator };
603
+ }, [
604
+ fallbackLocales,
605
+ isBeforeCSRLoading,
606
+ isLoading,
607
+ locale,
608
+ messages,
609
+ translatorHandlers,
610
+ translatorOptions?.loadingMessage,
611
+ translatorOptions?.placeholder
612
+ ]);
613
+ return /* @__PURE__ */ jsxRuntime.jsx(TranslatorContext.Provider, { value, children });
614
+ }
615
+ function useTranslator() {
616
+ const context = React6__namespace.useContext(TranslatorContext);
617
+ if (!context)
618
+ throw new Error(
619
+ "useTranslator must be used within IntorTranslatorProvider"
620
+ );
621
+ return context;
622
+ }
623
+ var IntorProvider = ({
624
+ value: { config, pathname = "", initialLocale, messages = config.messages },
625
+ children
626
+ }) => {
627
+ return /* @__PURE__ */ jsxRuntime.jsx(ConfigProvider, { value: { config, pathname }, children: /* @__PURE__ */ jsxRuntime.jsx(MessagesProvider, { value: { messages }, children: /* @__PURE__ */ jsxRuntime.jsx(LocaleProvider, { value: { initialLocale }, children: /* @__PURE__ */ jsxRuntime.jsx(TranslatorProvider, { children }) }) }) });
628
+ };
629
+
630
+ // src/client/react/hooks/use-translator.ts
631
+ function useTranslator2(preKey) {
632
+ const { translator } = useTranslator();
633
+ const { setLocale } = useLocale();
634
+ const props = {
635
+ messages: translator.messages,
636
+ locale: translator.locale,
637
+ isLoading: translator.isLoading,
638
+ setLocale
639
+ };
640
+ const scoped = translator.scoped(preKey);
641
+ return {
642
+ ...props,
643
+ hasKey: preKey ? scoped.hasKey : translator.hasKey,
644
+ t: preKey ? scoped.t : translator.t
645
+ };
646
+ }
647
+
648
+ exports.IntorProvider = IntorProvider;
649
+ exports.TranslateHandlersProvider = TranslateHandlersProvider;
650
+ exports.useTranslator = useTranslator2;