intor 2.3.5 → 2.3.6

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,4 +1,5 @@
1
1
  export { PREFIX_PLACEHOLDER } from '../src/shared/constants/prefix-placeholder.js';
2
+ export { deepMerge } from '../src/shared/utils/deep-merge.js';
2
3
  export { localizePathname } from '../src/shared/utils/pathname/localize-pathname.js';
3
4
  export { IntorError, IntorErrorCode } from '../src/shared/error/intor-error.js';
4
5
  import 'intor-translator';
@@ -73,13 +73,10 @@ async function parseFileEntries({ fileEntries, limit, extraOptions: { messagesRe
73
73
  for (const { namespace, messages } of parsedFileEntries) {
74
74
  // Handle root-level namespace (i.e., [rootDir]/index.json)
75
75
  if (namespace === "index") {
76
- const merged = deepMerge(result, messages);
77
- if (merged)
78
- Object.assign(result, merged);
76
+ Object.assign(result, deepMerge(result, messages));
79
77
  }
80
78
  else {
81
- result[namespace] =
82
- deepMerge(result[namespace] ?? {}, messages) || {};
79
+ result[namespace] = deepMerge(result[namespace], messages);
83
80
  }
84
81
  }
85
82
  return result;
@@ -1,15 +1,12 @@
1
1
  /**
2
2
  * Deeply merges two objects.
3
+ *
3
4
  * - Nested objects → merged recursively
4
5
  * - Array / primitive → b overwrites a
6
+ *
7
+ * This function always returns a plain object.
5
8
  */
6
- const deepMerge = (a, b) => {
7
- if (!a && !b)
8
- return undefined;
9
- if (!a)
10
- return b;
11
- if (!b)
12
- return a;
9
+ const deepMerge = (a = {}, b = {}) => {
13
10
  const result = { ...a };
14
11
  for (const key in b) {
15
12
  if (Object.prototype.hasOwnProperty.call(b, key)) {
@@ -21,11 +18,9 @@ const deepMerge = (a, b) => {
21
18
  typeof bv === "object" &&
22
19
  !Array.isArray(av) &&
23
20
  !Array.isArray(bv)) {
24
- // recursive merge
25
21
  result[key] = deepMerge(av, bv);
26
22
  }
27
23
  else {
28
- // overwrite with primitive or array
29
24
  result[key] = bv;
30
25
  }
31
26
  }
@@ -73,13 +73,10 @@ async function parseFileEntries({ fileEntries, limit, extraOptions: { messagesRe
73
73
  for (const { namespace, messages } of parsedFileEntries) {
74
74
  // Handle root-level namespace (i.e., [rootDir]/index.json)
75
75
  if (namespace === "index") {
76
- const merged = deepMerge(result, messages);
77
- if (merged)
78
- Object.assign(result, merged);
76
+ Object.assign(result, deepMerge(result, messages));
79
77
  }
80
78
  else {
81
- result[namespace] =
82
- deepMerge(result[namespace] ?? {}, messages) || {};
79
+ result[namespace] = deepMerge(result[namespace], messages);
83
80
  }
84
81
  }
85
82
  return result;
@@ -1,15 +1,12 @@
1
1
  /**
2
2
  * Deeply merges two objects.
3
+ *
3
4
  * - Nested objects → merged recursively
4
5
  * - Array / primitive → b overwrites a
6
+ *
7
+ * This function always returns a plain object.
5
8
  */
6
- const deepMerge = (a, b) => {
7
- if (!a && !b)
8
- return undefined;
9
- if (!a)
10
- return b;
11
- if (!b)
12
- return a;
9
+ const deepMerge = (a = {}, b = {}) => {
13
10
  const result = { ...a };
14
11
  for (const key in b) {
15
12
  if (Object.prototype.hasOwnProperty.call(b, key)) {
@@ -21,11 +18,9 @@ const deepMerge = (a, b) => {
21
18
  typeof bv === "object" &&
22
19
  !Array.isArray(av) &&
23
20
  !Array.isArray(bv)) {
24
- // recursive merge
25
21
  result[key] = deepMerge(av, bv);
26
22
  }
27
23
  else {
28
- // overwrite with primitive or array
29
24
  result[key] = bv;
30
25
  }
31
26
  }
@@ -39,7 +39,7 @@ const useRefetchMessages = ({ config, setRuntimeMessages, setIsLoadingMessages,
39
39
  });
40
40
  // Update state only if this request was not aborted
41
41
  if (!controller.signal.aborted) {
42
- setRuntimeMessages(deepMerge(config.messages, loadedMessages) || {});
42
+ setRuntimeMessages(deepMerge(config.messages, loadedMessages));
43
43
  }
44
44
  }
45
45
  finally {
@@ -20,7 +20,15 @@ function TranslatorProvider({ value: { isLoading: externalIsLoading } = {}, chil
20
20
  const { messages, isLoading: internalIsLoading } = useMessages();
21
21
  const { locale } = useLocale();
22
22
  const runtime = useTranslatorRuntime();
23
- const isLoading = Boolean(externalIsLoading ?? internalIsLoading);
23
+ // Treat locale changes as a loading boundary to avoid transient missing states.
24
+ // isLoading defaults to false, but is eagerly set to true on locale switches.
25
+ const prevLocaleRef = React.useRef(locale);
26
+ // eslint-disable-next-line react-hooks/refs -- intentional render-time read to detect locale switches
27
+ const localeChanged = prevLocaleRef.current !== locale;
28
+ React.useEffect(() => {
29
+ prevLocaleRef.current = locale;
30
+ }, [locale]);
31
+ const isLoading = !!externalIsLoading || internalIsLoading || localeChanged;
24
32
  // context value
25
33
  const value = React.useMemo(() => {
26
34
  const translator = new Translator({
@@ -1,15 +1,12 @@
1
1
  /**
2
2
  * Deeply merges two objects.
3
+ *
3
4
  * - Nested objects → merged recursively
4
5
  * - Array / primitive → b overwrites a
6
+ *
7
+ * This function always returns a plain object.
5
8
  */
6
- const deepMerge = (a, b) => {
7
- if (!a && !b)
8
- return undefined;
9
- if (!a)
10
- return b;
11
- if (!b)
12
- return a;
9
+ const deepMerge = (a = {}, b = {}) => {
13
10
  const result = { ...a };
14
11
  for (const key in b) {
15
12
  if (Object.prototype.hasOwnProperty.call(b, key)) {
@@ -21,11 +18,9 @@ const deepMerge = (a, b) => {
21
18
  typeof bv === "object" &&
22
19
  !Array.isArray(av) &&
23
20
  !Array.isArray(bv)) {
24
- // recursive merge
25
21
  result[key] = deepMerge(av, bv);
26
22
  }
27
23
  else {
28
- // overwrite with primitive or array
29
24
  result[key] = bv;
30
25
  }
31
26
  }
@@ -1,4 +1,4 @@
1
1
  export { PREFIX_PLACEHOLDER } from "../src/shared/constants";
2
- export { localizePathname, } from "../src/shared/utils";
2
+ export { deepMerge, localizePathname, } from "../src/shared/utils";
3
3
  export { IntorError, IntorErrorCode } from "../src/shared/error";
4
4
  export { type TranslatorPlugin, type TranslateHandlers, type FormatHandler, type LoadingHandler, type MissingHandler, type HandlerContext, type TranslateContext, type TranslateHook, type LocaleMessages, } from "intor-translator";
@@ -1,8 +1,11 @@
1
1
  type PlainObject = Record<string, unknown>;
2
2
  /**
3
3
  * Deeply merges two objects.
4
+ *
4
5
  * - Nested objects → merged recursively
5
6
  * - Array / primitive → b overwrites a
7
+ *
8
+ * This function always returns a plain object.
6
9
  */
7
- export declare const deepMerge: <T extends PlainObject, U extends PlainObject>(a?: T, b?: U) => (T & U) | T | U | undefined;
10
+ export declare const deepMerge: <T extends PlainObject, U extends PlainObject>(a?: T, b?: U) => T & U;
8
11
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "intor",
3
- "version": "2.3.5",
3
+ "version": "2.3.6",
4
4
  "description": "A modular and extensible i18n core designed for TypeScript and JavaScript projects. Intor enables custom translation logic with support for both frontend and backend environments, featuring runtime configuration, caching, adapters, and message loaders.",
5
5
  "author": "Yiming Liao",
6
6
  "homepage": "https://github.com/yiming-liao/intor#readme",