intor 2.2.11 → 2.2.13

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.
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var React6 = require('react');
3
+ var React7 = require('react');
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
5
  var logry = require('logry');
6
6
  var Keyv = require('keyv');
@@ -27,25 +27,76 @@ function _interopNamespace(e) {
27
27
  return Object.freeze(n);
28
28
  }
29
29
 
30
- var React6__namespace = /*#__PURE__*/_interopNamespace(React6);
30
+ var React7__namespace = /*#__PURE__*/_interopNamespace(React7);
31
31
  var Keyv__default = /*#__PURE__*/_interopDefault(Keyv);
32
32
  var merge__default = /*#__PURE__*/_interopDefault(merge);
33
33
 
34
34
  // src/client/react/contexts/intor-provider/intor-provider.tsx
35
- var ConfigContext = React6__namespace.createContext(void 0);
35
+ var ConfigContext = React7__namespace.createContext(void 0);
36
36
  function ConfigProvider({
37
37
  value: { config, pathname },
38
38
  children
39
39
  }) {
40
- const value = React6__namespace.useMemo(() => ({ config, pathname }), [config, pathname]);
40
+ const value = React7__namespace.useMemo(() => ({ config, pathname }), [config, pathname]);
41
41
  return /* @__PURE__ */ jsxRuntime.jsx(ConfigContext.Provider, { value, children });
42
42
  }
43
43
  function useConfig() {
44
- const context = React6__namespace.useContext(ConfigContext);
44
+ const context = React7__namespace.useContext(ConfigContext);
45
45
  if (!context) throw new Error("useConfig must be used within ConfigProvider");
46
46
  return context;
47
47
  }
48
48
 
49
+ // src/shared/utils/client/build-cookie-string.ts
50
+ var buildCookieString = (cookie, locale) => {
51
+ const parts = [`${cookie.name}=${encodeURIComponent(locale)}`];
52
+ if (cookie.maxAge) {
53
+ const expires = new Date(Date.now() + cookie.maxAge * 1e3).toUTCString();
54
+ parts.push(`expires=${expires}`, `max-age=${cookie.maxAge}`);
55
+ }
56
+ parts.push(`path=${cookie.path ?? "/"}`);
57
+ if (cookie.domain) {
58
+ parts.push(`domain=${cookie.domain}`);
59
+ }
60
+ if (cookie.sameSite) {
61
+ parts.push(
62
+ `SameSite=${cookie.sameSite[0].toUpperCase()}${cookie.sameSite.slice(1).toLowerCase()}`
63
+ );
64
+ }
65
+ if (cookie.secure !== false) {
66
+ parts.push(`Secure`);
67
+ }
68
+ return parts.join("; ");
69
+ };
70
+
71
+ // src/shared/utils/client/set-locale-cookie-browser.ts
72
+ var setLocaleCookieBrowser = ({
73
+ cookie,
74
+ locale
75
+ }) => {
76
+ if (typeof document === "undefined") return;
77
+ if (!cookie.enabled || !cookie.autoSetCookie) return;
78
+ const cookieString = buildCookieString(cookie, locale);
79
+ document.cookie = cookieString;
80
+ };
81
+
82
+ // src/client/react/contexts/locale/utils/use-init-locale-cookie.ts
83
+ var useInitLocaleCookie = ({
84
+ config,
85
+ locale
86
+ }) => {
87
+ React7__namespace.useEffect(() => {
88
+ if (typeof document === "undefined") return;
89
+ const { cookie, routing } = config;
90
+ const { firstVisit } = routing;
91
+ const cookies = document.cookie.split(";").map((c) => c.trim());
92
+ const isCookieExists = cookies.some((c) => c.startsWith(`${cookie.name}=`));
93
+ if (isCookieExists) return;
94
+ if (!firstVisit.redirect) return;
95
+ if (!cookie.enabled || !cookie.autoSetCookie) return;
96
+ setLocaleCookieBrowser({ cookie, locale });
97
+ }, []);
98
+ };
99
+
49
100
  // src/config/constants/cache.constants.ts
50
101
  var DEFAULT_CACHE_OPTIONS = {
51
102
  enabled: process.env.NODE_ENV === "production",
@@ -358,19 +409,19 @@ var useRefetchMessages = ({
358
409
  setLoadedMessages,
359
410
  setIsLoadingMessages
360
411
  }) => {
361
- const { messages: staticMessages } = config;
362
- const namespaces = React6__namespace.useMemo(() => {
363
- if (!config.loader) return [];
412
+ const { messages: staticMessages, loader } = config;
413
+ const namespaces = React7__namespace.useMemo(() => {
414
+ if (!loader) return [];
364
415
  return resolveNamespaces({ config, pathname });
365
416
  }, [config, pathname]);
366
- const refetchMessages = React6__namespace.useCallback(
417
+ const refetchMessages = React7__namespace.useCallback(
367
418
  async (newLocale) => {
368
- if (config.loader?.type === "remote") {
419
+ if (loader?.type === "remote") {
369
420
  setIsLoadingMessages(true);
370
421
  const loadedMessages = await loadRemoteMessages({
371
- rootDir: config.loader.rootDir,
372
- remoteUrl: config.loader.remoteUrl,
373
- remoteHeaders: config.loader.remoteHeaders,
422
+ rootDir: loader.rootDir,
423
+ remoteUrl: loader.remoteUrl,
424
+ remoteHeaders: loader.remoteHeaders,
374
425
  locale: newLocale,
375
426
  fallbackLocales: config.fallbackLocales[newLocale] || [],
376
427
  namespaces,
@@ -385,8 +436,9 @@ var useRefetchMessages = ({
385
436
  }
386
437
  },
387
438
  [
388
- config.loader,
439
+ loader,
389
440
  config.fallbackLocales,
441
+ config.cache,
390
442
  config.id,
391
443
  setIsLoadingMessages,
392
444
  namespaces,
@@ -396,21 +448,21 @@ var useRefetchMessages = ({
396
448
  );
397
449
  return { refetchMessages };
398
450
  };
399
- var MessagesContext = React6__namespace.createContext(void 0);
451
+ var MessagesContext = React7__namespace.createContext(void 0);
400
452
  function MessagesProvider({
401
453
  value: { messages = {} },
402
454
  children
403
455
  }) {
404
456
  const { config, pathname } = useConfig();
405
- const [loadedMessages, setLoadedMessages] = React6__namespace.useState(null);
406
- const [isLoadingMessages, setIsLoadingMessages] = React6__namespace.useState(false);
457
+ const [loadedMessages, setLoadedMessages] = React7__namespace.useState(null);
458
+ const [isLoadingMessages, setIsLoadingMessages] = React7__namespace.useState(false);
407
459
  const { refetchMessages } = useRefetchMessages({
408
460
  config,
409
461
  pathname,
410
462
  setLoadedMessages,
411
463
  setIsLoadingMessages
412
464
  });
413
- const value = React6__namespace.useMemo(
465
+ const value = React7__namespace.useMemo(
414
466
  () => ({
415
467
  messages: loadedMessages || messages,
416
468
  isLoading: isLoadingMessages,
@@ -423,128 +475,61 @@ function MessagesProvider({
423
475
  return /* @__PURE__ */ jsxRuntime.jsx(MessagesContext.Provider, { value, children });
424
476
  }
425
477
  function useMessages() {
426
- const context = React6__namespace.useContext(MessagesContext);
478
+ const context = React7__namespace.useContext(MessagesContext);
427
479
  if (!context)
428
480
  throw new Error("useMessages must be used within a MessagesProvider");
429
481
  return context;
430
482
  }
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);
483
+ var LocaleContext = React7__namespace.createContext(void 0);
499
484
 
500
485
  // src/client/react/contexts/locale/utils/change-locale.ts
501
486
  var changeLocale = ({
502
487
  currentLocale,
503
488
  newLocale,
504
- loaderOptions,
489
+ loader,
505
490
  cookie,
506
491
  setLocale,
507
492
  refetchMessages
508
493
  }) => {
509
494
  if (typeof document === "undefined") return;
510
- const loaderType = loaderOptions?.type;
495
+ const { type } = loader || {};
511
496
  if (newLocale === currentLocale) return;
512
- if (loaderType === "local") {
497
+ if (type === "local") {
513
498
  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.`
499
+ `[Intor] You are using "loader type: 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
500
  );
516
501
  }
517
502
  setLocale(newLocale);
518
503
  setLocaleCookieBrowser({ cookie, locale: newLocale });
519
504
  document.documentElement.lang = newLocale;
520
- if (loaderType === "remote" && refetchMessages) {
505
+ if (type === "remote" && refetchMessages) {
521
506
  void refetchMessages(newLocale);
522
507
  }
523
508
  };
524
509
  function LocaleProvider({
525
- value: { initialLocale },
510
+ value: { initialLocale, onLocaleChange },
526
511
  children
527
512
  }) {
528
513
  const { config } = useConfig();
529
514
  const { refetchMessages } = useMessages();
530
- const { loader: loaderOptions, cookie } = config;
531
- const [currentLocale, setCurrentLocale] = React6__namespace.useState(initialLocale);
532
- useInitLazyLoad({ loaderOptions, currentLocale });
515
+ const { loader, cookie } = config;
516
+ const [currentLocale, setCurrentLocale] = React7__namespace.useState(initialLocale);
533
517
  useInitLocaleCookie({ config, locale: initialLocale });
534
- const setLocale = React6__namespace.useCallback(
535
- (newLocale) => {
518
+ const setLocale = React7__namespace.useCallback(
519
+ async (newLocale) => {
536
520
  changeLocale({
537
521
  currentLocale,
538
522
  newLocale,
539
- loaderOptions,
523
+ loader,
540
524
  cookie,
541
525
  setLocale: setCurrentLocale,
542
526
  refetchMessages
543
527
  });
528
+ onLocaleChange?.(newLocale);
544
529
  },
545
- [currentLocale, loaderOptions, cookie, refetchMessages]
530
+ [currentLocale, loader, cookie, refetchMessages, onLocaleChange]
546
531
  );
547
- const value = React6__namespace.useMemo(
532
+ const value = React7__namespace.useMemo(
548
533
  () => ({
549
534
  locale: currentLocale,
550
535
  setLocale
@@ -554,66 +539,56 @@ function LocaleProvider({
554
539
  return /* @__PURE__ */ jsxRuntime.jsx(LocaleContext.Provider, { value, children });
555
540
  }
556
541
  function useLocale() {
557
- const context = React6__namespace.useContext(LocaleContext);
542
+ const context = React7__namespace.useContext(LocaleContext);
558
543
  if (!context)
559
544
  throw new Error("useLocale must be used within a LocaleProvider");
560
545
  return context;
561
546
  }
562
- var TranslateHandlersContext = React6__namespace.createContext(void 0);
547
+ var TranslateHandlersContext = React7__namespace.createContext(void 0);
563
548
  var TranslateHandlersProvider = ({
564
- children,
565
- handlers
549
+ handlers,
550
+ children
566
551
  }) => {
567
- const value = handlers;
568
- return /* @__PURE__ */ jsxRuntime.jsx(TranslateHandlersContext.Provider, { value, children });
552
+ return /* @__PURE__ */ jsxRuntime.jsx(TranslateHandlersContext.Provider, { value: { handlers }, children });
569
553
  };
570
554
  function useTranslateHandlers() {
571
- const context = React6__namespace.useContext(TranslateHandlersContext);
555
+ const context = React7__namespace.useContext(TranslateHandlersContext);
572
556
  return context;
573
557
  }
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 }) {
558
+ var TranslatorContext = React7__namespace.createContext(void 0);
559
+ function TranslatorProvider({
560
+ value: { isLoading: externalIsLoading },
561
+ children
562
+ }) {
586
563
  const { config } = useConfig();
587
- const { messages, isLoading } = useMessages();
564
+ const { messages, isLoading: internalIsLoading } = useMessages();
588
565
  const { locale } = useLocale();
589
- const translatorHandlers = useTranslateHandlers();
566
+ const { handlers } = useTranslateHandlers();
590
567
  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,
568
+ const isLoading = Boolean(externalIsLoading ?? internalIsLoading);
569
+ const translator = React7__namespace.useMemo(() => {
570
+ return new intorTranslator.Translator({
571
+ messages,
595
572
  locale,
573
+ isLoading,
596
574
  fallbackLocales,
597
575
  loadingMessage: translatorOptions?.loadingMessage,
598
576
  placeholder: translatorOptions?.placeholder,
599
- handlers: translatorHandlers
577
+ handlers
600
578
  });
601
- translator.setLoading(isBeforeCSRLoading || isLoading);
602
- return { translator };
603
579
  }, [
604
- fallbackLocales,
605
- isBeforeCSRLoading,
606
- isLoading,
607
- locale,
608
580
  messages,
609
- translatorHandlers,
581
+ locale,
582
+ isLoading,
583
+ fallbackLocales,
584
+ handlers,
610
585
  translatorOptions?.loadingMessage,
611
586
  translatorOptions?.placeholder
612
587
  ]);
613
- return /* @__PURE__ */ jsxRuntime.jsx(TranslatorContext.Provider, { value, children });
588
+ return /* @__PURE__ */ jsxRuntime.jsx(TranslatorContext.Provider, { value: { translator }, children });
614
589
  }
615
590
  function useTranslator() {
616
- const context = React6__namespace.useContext(TranslatorContext);
591
+ const context = React7__namespace.useContext(TranslatorContext);
617
592
  if (!context)
618
593
  throw new Error(
619
594
  "useTranslator must be used within IntorTranslatorProvider"
@@ -621,10 +596,17 @@ function useTranslator() {
621
596
  return context;
622
597
  }
623
598
  var IntorProvider = ({
624
- value: { config, pathname = "", initialLocale, messages = config.messages },
599
+ value: {
600
+ config,
601
+ pathname = "",
602
+ initialLocale,
603
+ messages = config.messages,
604
+ onLocaleChange,
605
+ isLoading
606
+ },
625
607
  children
626
608
  }) => {
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 }) }) }) });
609
+ return /* @__PURE__ */ jsxRuntime.jsx(ConfigProvider, { value: { config, pathname }, children: /* @__PURE__ */ jsxRuntime.jsx(MessagesProvider, { value: { messages }, children: /* @__PURE__ */ jsxRuntime.jsx(LocaleProvider, { value: { initialLocale, onLocaleChange }, children: /* @__PURE__ */ jsxRuntime.jsx(TranslatorProvider, { value: { isLoading }, children }) }) }) });
628
610
  };
629
611
 
630
612
  // src/client/react/hooks/use-translator.ts
@@ -4,8 +4,8 @@ import { Locale, LocaleMessages, FallbackLocalesMap, TranslateHandlers, ScopedLe
4
4
  import * as React from 'react';
5
5
 
6
6
  type CookieRawOptions = {
7
- /** Completely disable cookie usage (no read, no write, no lookup by name) - default: false */
8
- disabled?: boolean;
7
+ /** Enable cookie usage (read/write) - default: true */
8
+ enabled?: boolean;
9
9
  /** Allow the system to automatically set cookies - default: true */
10
10
  autoSetCookie?: boolean;
11
11
  /** default: "intor.i18n.locale" */
@@ -53,7 +53,6 @@ type BaseLoaderOptions = {
53
53
  namespaces?: string[];
54
54
  routeNamespaces?: RouteNamespaces;
55
55
  concurrency?: number;
56
- lazyLoad?: boolean;
57
56
  };
58
57
  type LocalLoader = BaseLoaderOptions & {
59
58
  type: "local";
@@ -90,6 +89,7 @@ type RoutingRawOptions = {
90
89
  type RoutingResolvedOptions = Required<RoutingRawOptions>;
91
90
 
92
91
  type CacheRawOptions = {
92
+ /** default: process.env.NODE_ENV === "production" */
93
93
  enabled?: boolean;
94
94
  /** default: 60\*60\*1000 (1 hour) */
95
95
  ttl?: number;
@@ -125,18 +125,20 @@ interface IntorProviderProps {
125
125
  initialLocale: Locale;
126
126
  pathname?: string;
127
127
  messages?: Readonly<LocaleMessages>;
128
+ onLocaleChange?: (newLocale: string) => Promise<void> | void;
129
+ isLoading?: boolean;
128
130
  };
129
131
  children: React.ReactNode;
130
132
  }
131
133
 
132
- declare const IntorProvider: ({ value: { config, pathname, initialLocale, messages }, children, }: IntorProviderProps) => react_jsx_runtime.JSX.Element;
134
+ declare const IntorProvider: ({ value: { config, pathname, initialLocale, messages, onLocaleChange, isLoading, }, children, }: IntorProviderProps) => react_jsx_runtime.JSX.Element;
133
135
 
134
136
  type TranslateHandlersProviderProps = {
135
- children: React.ReactNode;
136
137
  handlers: TranslateHandlers;
138
+ children: React.ReactNode;
137
139
  };
138
140
 
139
- declare const TranslateHandlersProvider: ({ children, handlers, }: TranslateHandlersProviderProps) => react_jsx_runtime.JSX.Element;
141
+ declare const TranslateHandlersProvider: ({ handlers, children, }: TranslateHandlersProviderProps) => react_jsx_runtime.JSX.Element;
140
142
 
141
143
  declare const PREFIX_PLACEHOLDER = "{locale}";
142
144
 
@@ -4,8 +4,8 @@ import { Locale, LocaleMessages, FallbackLocalesMap, TranslateHandlers, ScopedLe
4
4
  import * as React from 'react';
5
5
 
6
6
  type CookieRawOptions = {
7
- /** Completely disable cookie usage (no read, no write, no lookup by name) - default: false */
8
- disabled?: boolean;
7
+ /** Enable cookie usage (read/write) - default: true */
8
+ enabled?: boolean;
9
9
  /** Allow the system to automatically set cookies - default: true */
10
10
  autoSetCookie?: boolean;
11
11
  /** default: "intor.i18n.locale" */
@@ -53,7 +53,6 @@ type BaseLoaderOptions = {
53
53
  namespaces?: string[];
54
54
  routeNamespaces?: RouteNamespaces;
55
55
  concurrency?: number;
56
- lazyLoad?: boolean;
57
56
  };
58
57
  type LocalLoader = BaseLoaderOptions & {
59
58
  type: "local";
@@ -90,6 +89,7 @@ type RoutingRawOptions = {
90
89
  type RoutingResolvedOptions = Required<RoutingRawOptions>;
91
90
 
92
91
  type CacheRawOptions = {
92
+ /** default: process.env.NODE_ENV === "production" */
93
93
  enabled?: boolean;
94
94
  /** default: 60\*60\*1000 (1 hour) */
95
95
  ttl?: number;
@@ -125,18 +125,20 @@ interface IntorProviderProps {
125
125
  initialLocale: Locale;
126
126
  pathname?: string;
127
127
  messages?: Readonly<LocaleMessages>;
128
+ onLocaleChange?: (newLocale: string) => Promise<void> | void;
129
+ isLoading?: boolean;
128
130
  };
129
131
  children: React.ReactNode;
130
132
  }
131
133
 
132
- declare const IntorProvider: ({ value: { config, pathname, initialLocale, messages }, children, }: IntorProviderProps) => react_jsx_runtime.JSX.Element;
134
+ declare const IntorProvider: ({ value: { config, pathname, initialLocale, messages, onLocaleChange, isLoading, }, children, }: IntorProviderProps) => react_jsx_runtime.JSX.Element;
133
135
 
134
136
  type TranslateHandlersProviderProps = {
135
- children: React.ReactNode;
136
137
  handlers: TranslateHandlers;
138
+ children: React.ReactNode;
137
139
  };
138
140
 
139
- declare const TranslateHandlersProvider: ({ children, handlers, }: TranslateHandlersProviderProps) => react_jsx_runtime.JSX.Element;
141
+ declare const TranslateHandlersProvider: ({ handlers, children, }: TranslateHandlersProviderProps) => react_jsx_runtime.JSX.Element;
140
142
 
141
143
  declare const PREFIX_PLACEHOLDER = "{locale}";
142
144