intor 2.3.29 → 2.3.30

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.
Files changed (171) hide show
  1. package/dist/core/src/core/messages/load-remote-messages/fetch-remote-resource.js +1 -1
  2. package/dist/core/src/core/messages/load-remote-messages/load-remote-messages.js +2 -2
  3. package/dist/core/src/routing/pathname/canonicalize-pathname.js +11 -7
  4. package/dist/core/src/server/helpers/get-translator.js +2 -2
  5. package/dist/core/src/server/intor/intor.js +3 -8
  6. package/dist/core/src/server/messages/load-messages.js +2 -1
  7. package/dist/core/src/server/translator/init-translator.js +9 -3
  8. package/dist/express/src/core/messages/load-remote-messages/fetch-remote-resource.js +1 -1
  9. package/dist/express/src/core/messages/load-remote-messages/load-remote-messages.js +2 -2
  10. package/dist/express/src/routing/pathname/canonicalize-pathname.js +11 -7
  11. package/dist/express/src/server/helpers/get-translator.js +2 -2
  12. package/dist/express/src/server/messages/load-messages.js +2 -1
  13. package/dist/express/src/server/translator/init-translator.js +9 -3
  14. package/dist/next/export/next/index.js +0 -1
  15. package/dist/next/export/next/server/index.js +0 -1
  16. package/dist/next/src/adapters/next/navigation/link.js +11 -10
  17. package/dist/next/src/adapters/next/navigation/use-router.js +14 -20
  18. package/dist/next/src/adapters/next/server/intor.js +1 -1
  19. package/dist/next/src/client/shared/navigation/execute-navigation.js +50 -0
  20. package/dist/next/src/client/shared/utils/build-cookie-string.js +30 -0
  21. package/dist/next/src/client/shared/utils/locale/set-locale-cookie.js +15 -0
  22. package/dist/next/src/core/messages/load-remote-messages/fetch-remote-resource.js +1 -1
  23. package/dist/next/src/core/messages/load-remote-messages/load-remote-messages.js +2 -2
  24. package/dist/next/src/routing/pathname/canonicalize-pathname.js +11 -7
  25. package/dist/next/src/server/helpers/get-translator.js +2 -2
  26. package/dist/next/src/server/intor/intor.js +3 -8
  27. package/dist/next/src/server/messages/load-messages.js +2 -1
  28. package/dist/next/src/server/translator/init-translator.js +9 -3
  29. package/dist/react/export/react/index.js +0 -2
  30. package/dist/react/src/client/shared/messages/create-refetch-messages.js +1 -0
  31. package/dist/react/src/core/messages/load-remote-messages/fetch-remote-resource.js +1 -1
  32. package/dist/react/src/core/messages/load-remote-messages/load-remote-messages.js +2 -2
  33. package/dist/svelte/export/svelte/index.js +4 -2
  34. package/dist/svelte/src/client/shared/messages/create-refetch-messages.js +1 -0
  35. package/dist/svelte/src/client/svelte/{store → provider}/create-intor-store.js +7 -14
  36. package/dist/svelte/src/client/svelte/provider/intor-provider.svelte +7 -0
  37. package/dist/svelte/src/client/svelte/provider/use-intor-context.js +11 -0
  38. package/dist/svelte/src/client/svelte/render/create-svelte-renderer.js +5 -6
  39. package/dist/svelte/src/client/svelte/translator/create-t-rich.js +23 -0
  40. package/dist/svelte/src/client/svelte/translator/use-translator.js +32 -0
  41. package/dist/svelte/src/core/messages/load-remote-messages/fetch-remote-resource.js +1 -1
  42. package/dist/svelte/src/core/messages/load-remote-messages/load-remote-messages.js +2 -2
  43. package/dist/svelte-kit/export/svelte-kit/index.js +1 -0
  44. package/dist/svelte-kit/export/svelte-kit/server/index.js +2 -0
  45. package/dist/svelte-kit/src/adapters/svelte-kit/navigation/use-navigation.js +36 -0
  46. package/dist/svelte-kit/src/adapters/svelte-kit/server/create-intor-handle.js +58 -0
  47. package/dist/svelte-kit/src/adapters/svelte-kit/server/intor.js +24 -0
  48. package/dist/svelte-kit/src/client/shared/navigation/execute-navigation.js +49 -0
  49. package/dist/svelte-kit/src/client/shared/utils/build-cookie-string.js +30 -0
  50. package/dist/svelte-kit/src/client/shared/utils/locale/set-locale-cookie.js +15 -0
  51. package/dist/svelte-kit/src/core/constants/headers.js +6 -0
  52. package/dist/svelte-kit/src/core/error/intor-error.js +9 -0
  53. package/dist/svelte-kit/src/core/logger/get-logger.js +39 -0
  54. package/dist/svelte-kit/src/core/logger/global-logger-pool.js +8 -0
  55. package/dist/svelte-kit/src/core/messages/load-remote-messages/collect-remote-resources.js +25 -0
  56. package/dist/svelte-kit/src/core/messages/load-remote-messages/fetch-remote-resource.js +47 -0
  57. package/dist/svelte-kit/src/core/messages/load-remote-messages/load-remote-messages.js +93 -0
  58. package/dist/svelte-kit/src/core/messages/load-remote-messages/resolve-remote-resources.js +24 -0
  59. package/dist/svelte-kit/src/core/messages/merge-messages.js +33 -0
  60. package/dist/svelte-kit/src/core/messages/utils/is-valid-messages.js +44 -0
  61. package/dist/svelte-kit/src/core/messages/utils/nest-object-from-path.js +21 -0
  62. package/dist/svelte-kit/src/core/utils/deep-merge.js +47 -0
  63. package/dist/svelte-kit/src/core/utils/normalizers/normalize-cache-key.js +45 -0
  64. package/dist/svelte-kit/src/core/utils/normalizers/normalize-locale.js +59 -0
  65. package/dist/svelte-kit/src/core/utils/normalizers/normalize-query.js +25 -0
  66. package/dist/svelte-kit/src/core/utils/resolve-loader-options.js +34 -0
  67. package/dist/{react → svelte-kit}/src/policies/shoud-full-reload.js +1 -1
  68. package/dist/svelte-kit/src/policies/should-sync-locale.js +8 -0
  69. package/dist/svelte-kit/src/routing/inbound/resolve-inbound.js +46 -0
  70. package/dist/svelte-kit/src/routing/inbound/resolve-locale/resolve-locale.js +33 -0
  71. package/dist/svelte-kit/src/routing/inbound/resolve-pathname/resolve-pathname.js +42 -0
  72. package/dist/svelte-kit/src/routing/inbound/resolve-pathname/strategies/all.js +28 -0
  73. package/dist/svelte-kit/src/routing/inbound/resolve-pathname/strategies/except-default.js +29 -0
  74. package/dist/svelte-kit/src/routing/inbound/resolve-pathname/strategies/none.js +8 -0
  75. package/dist/svelte-kit/src/routing/locale/get-locale-from-accept-language.js +38 -0
  76. package/dist/svelte-kit/src/routing/locale/get-locale-from-host.js +32 -0
  77. package/dist/svelte-kit/src/routing/locale/get-locale-from-pathname.js +46 -0
  78. package/dist/svelte-kit/src/routing/locale/get-locale-from-query.js +29 -0
  79. package/dist/{react → svelte-kit}/src/routing/pathname/canonicalize-pathname.js +11 -7
  80. package/dist/svelte-kit/src/server/intor/intor.js +31 -0
  81. package/dist/svelte-kit/src/server/messages/load-local-messages/cache/messages-pool.js +11 -0
  82. package/dist/svelte-kit/src/server/messages/load-local-messages/load-local-messages.js +107 -0
  83. package/dist/svelte-kit/src/server/messages/load-local-messages/read-locale-messages/collect-file-entries/collect-file-entries.js +90 -0
  84. package/dist/svelte-kit/src/server/messages/load-local-messages/read-locale-messages/parse-file-entries/parse-file-entries.js +102 -0
  85. package/dist/svelte-kit/src/server/messages/load-local-messages/read-locale-messages/parse-file-entries/utils/json-reader.js +12 -0
  86. package/dist/svelte-kit/src/server/messages/load-local-messages/read-locale-messages/read-locale-messages.js +42 -0
  87. package/dist/svelte-kit/src/server/messages/load-messages.js +77 -0
  88. package/dist/svelte-kit/src/server/translator/create-translator.js +40 -0
  89. package/dist/svelte-kit/src/server/translator/init-translator.js +42 -0
  90. package/dist/types/export/next/index.d.ts +1 -1
  91. package/dist/types/export/next/server/index.d.ts +1 -1
  92. package/dist/types/export/react/index.d.ts +2 -2
  93. package/dist/types/export/svelte/index.d.ts +3 -1
  94. package/dist/types/export/svelte-kit/index.d.ts +1 -0
  95. package/dist/types/export/svelte-kit/server/index.d.ts +1 -0
  96. package/dist/types/src/adapters/express/global.d.ts +5 -8
  97. package/dist/types/src/adapters/next/navigation/index.d.ts +0 -1
  98. package/dist/types/src/adapters/next/server/index.d.ts +0 -1
  99. package/dist/types/src/adapters/svelte-kit/navigation/index.d.ts +1 -0
  100. package/dist/types/src/adapters/svelte-kit/navigation/use-navigation.d.ts +15 -0
  101. package/dist/types/src/adapters/svelte-kit/server/create-intor-handle.d.ts +12 -0
  102. package/dist/types/src/adapters/svelte-kit/server/index.d.ts +2 -0
  103. package/dist/types/src/adapters/svelte-kit/server/intor.d.ts +16 -0
  104. package/dist/types/src/client/index.d.ts +1 -0
  105. package/dist/types/src/client/react/index.d.ts +0 -1
  106. package/dist/types/src/client/shared/navigation/execute-navigation.d.ts +19 -0
  107. package/dist/types/src/client/shared/navigation/index.d.ts +1 -0
  108. package/dist/types/src/client/svelte/index.d.ts +2 -2
  109. package/dist/types/src/client/svelte/provider/create-intor-store.d.ts +3 -0
  110. package/dist/types/src/client/svelte/provider/index.d.ts +3 -0
  111. package/dist/types/src/client/svelte/provider/types.d.ts +18 -0
  112. package/dist/types/src/client/svelte/provider/use-intor-context.d.ts +2 -0
  113. package/dist/types/src/client/svelte/render/types.d.ts +7 -13
  114. package/dist/types/src/client/svelte/translator/create-t-rich.d.ts +15 -0
  115. package/dist/types/src/client/svelte/translator/index.d.ts +1 -0
  116. package/dist/types/src/client/svelte/translator/translator-instance.d.ts +20 -0
  117. package/dist/types/src/client/svelte/translator/use-translator.d.ts +8 -0
  118. package/dist/types/src/core/index.d.ts +1 -1
  119. package/dist/types/src/core/messages/load-remote-messages/fetch-remote-resource.d.ts +3 -1
  120. package/dist/types/src/core/messages/load-remote-messages/load-remote-messages.d.ts +1 -1
  121. package/dist/types/src/core/messages/load-remote-messages/types.d.ts +2 -0
  122. package/dist/types/src/core/types/index.d.ts +1 -0
  123. package/dist/types/src/core/types/runtime-fetch.d.ts +1 -0
  124. package/dist/types/src/routing/inbound/index.d.ts +1 -0
  125. package/dist/types/src/routing/inbound/resolve-inbound.d.ts +1 -12
  126. package/dist/types/src/routing/inbound/types.d.ts +12 -0
  127. package/dist/types/src/routing/index.d.ts +1 -1
  128. package/dist/types/src/routing/pathname/canonicalize-pathname.d.ts +2 -0
  129. package/dist/types/src/server/helpers/get-translator.d.ts +2 -1
  130. package/dist/types/src/server/intor/intor.d.ts +4 -3
  131. package/dist/types/src/server/intor/types.d.ts +0 -2
  132. package/dist/types/src/server/messages/load-messages.d.ts +1 -1
  133. package/dist/types/src/server/messages/types.d.ts +2 -1
  134. package/dist/types/src/server/translator/init-translator.d.ts +2 -2
  135. package/dist/vue/src/client/shared/messages/create-refetch-messages.js +1 -0
  136. package/dist/vue/src/core/messages/load-remote-messages/fetch-remote-resource.js +1 -1
  137. package/dist/vue/src/core/messages/load-remote-messages/load-remote-messages.js +2 -2
  138. package/package.json +11 -1
  139. package/dist/next/src/adapters/next/navigation/use-pathname.js +0 -26
  140. package/dist/next/src/adapters/next/server/get-pathname.js +0 -28
  141. package/dist/react/src/client/react/navigation/use-execute-navigation.js +0 -41
  142. package/dist/react/src/client/react/navigation/use-resolve-navigation.js +0 -16
  143. package/dist/svelte/src/client/svelte/helpers/create-intor.js +0 -45
  144. package/dist/svelte/src/client/svelte/store/create-translator-bindings.js +0 -25
  145. package/dist/types/src/adapters/next/navigation/use-pathname.d.ts +0 -14
  146. package/dist/types/src/adapters/next/server/get-pathname.d.ts +0 -16
  147. package/dist/types/src/client/react/navigation/index.d.ts +0 -2
  148. package/dist/types/src/client/react/navigation/use-execute-navigation.d.ts +0 -5
  149. package/dist/types/src/client/react/navigation/use-resolve-navigation.d.ts +0 -5
  150. package/dist/types/src/client/svelte/helpers/create-intor.d.ts +0 -4
  151. package/dist/types/src/client/svelte/helpers/index.d.ts +0 -1
  152. package/dist/types/src/client/svelte/store/create-intor-store.d.ts +0 -2
  153. package/dist/types/src/client/svelte/store/create-translator-bindings.d.ts +0 -13
  154. package/dist/types/src/client/svelte/store/index.d.ts +0 -2
  155. package/dist/types/src/client/svelte/store/types.d.ts +0 -31
  156. /package/dist/{react → next}/src/policies/should-sync-locale.js +0 -0
  157. /package/dist/svelte/src/client/svelte/{store → provider}/effects/locale-effects.js +0 -0
  158. /package/dist/svelte/src/client/svelte/{store → provider}/effects/messages-effects.js +0 -0
  159. /package/dist/{react → svelte-kit}/src/core/constants/prefix-placeholder.js +0 -0
  160. /package/dist/{react → svelte-kit}/src/core/utils/normalizers/normalize-pathname.js +0 -0
  161. /package/dist/{react → svelte-kit}/src/routing/navigation/decide-strategy.js +0 -0
  162. /package/dist/{react → svelte-kit}/src/routing/navigation/derive-target.js +0 -0
  163. /package/dist/{react → svelte-kit}/src/routing/navigation/resolve-navigation.js +0 -0
  164. /package/dist/{react → svelte-kit}/src/routing/navigation/utils/derive-host-destination.js +0 -0
  165. /package/dist/{react → svelte-kit}/src/routing/navigation/utils/derive-query-destination.js +0 -0
  166. /package/dist/{react → svelte-kit}/src/routing/navigation/utils/is-external-destination.js +0 -0
  167. /package/dist/{react → svelte-kit}/src/routing/pathname/localize-pathname.js +0 -0
  168. /package/dist/{react → svelte-kit}/src/routing/pathname/materialize-pathname.js +0 -0
  169. /package/dist/{react → svelte-kit}/src/routing/pathname/standardize-pathname.js +0 -0
  170. /package/dist/types/src/client/svelte/{store → provider}/effects/locale-effects.d.ts +0 -0
  171. /package/dist/types/src/client/svelte/{store → provider}/effects/messages-effects.d.ts +0 -0
@@ -17,7 +17,7 @@ import { loadLocalMessages } from './load-local-messages/load-local-messages.js'
17
17
  * Message traversal, parsing, fallback resolution, and caching logic
18
18
  * are delegated to the selected loader.
19
19
  */
20
- const loadMessages = async ({ config, locale, readers, allowCacheWrite = false, }) => {
20
+ const loadMessages = async ({ config, locale, readers, allowCacheWrite = false, fetch, }) => {
21
21
  const baseLogger = getLogger(config.logger);
22
22
  const logger = baseLogger.child({ scope: "load-messages" });
23
23
  // ---------------------------------------------------------------------------
@@ -61,6 +61,7 @@ const loadMessages = async ({ config, locale, readers, allowCacheWrite = false,
61
61
  fallbackLocales,
62
62
  namespaces,
63
63
  concurrency,
64
+ fetch,
64
65
  url: loader.url,
65
66
  headers: loader.headers,
66
67
  loggerOptions: config.logger,
@@ -14,13 +14,19 @@ import { createTranslator } from './create-translator.js';
14
14
  * - Returns an immutable translator snapshot.
15
15
  */
16
16
  async function initTranslator(config, locale, options) {
17
- const { readers, allowCacheWrite = false, preKey, handlers, plugins, } = options || {};
17
+ const { readers, allowCacheWrite = false, fetch, preKey, handlers, plugins, } = options;
18
18
  const loader = resolveLoaderOptions(config, "server");
19
19
  // Load messages
20
20
  let messages = {};
21
21
  if (loader) {
22
- messages =
23
- (await loadMessages({ config, locale, readers, allowCacheWrite })) || {};
22
+ const loaded = await loadMessages({
23
+ config,
24
+ locale,
25
+ readers,
26
+ allowCacheWrite,
27
+ fetch,
28
+ });
29
+ messages = loaded || {};
24
30
  }
25
31
  // Create immutable translator snapshot
26
32
  return createTranslator({
@@ -2,7 +2,5 @@ export { IntorProvider } from '../../src/client/react/provider/intor-provider.js
2
2
  export { useIntorContext } from '../../src/client/react/provider/use-intor-context.js';
3
3
  export { useTranslator } from '../../src/client/react/translator/use-translator.js';
4
4
  export { Trans } from '../../src/client/react/translator/trans.js';
5
- export { useResolveNavigation } from '../../src/client/react/navigation/use-resolve-navigation.js';
6
- export { useExecuteNavigation } from '../../src/client/react/navigation/use-execute-navigation.js';
7
5
  export { useIntor } from '../../src/client/react/helpers/use-intor.js';
8
6
  export { getClientLocale } from '../../src/client/shared/helpers/get-client-locale.js';
@@ -30,6 +30,7 @@ const createRefetchMessages = ({ config, onLoadingStart, onLoadingEnd, onMessage
30
30
  fallbackLocales: config.fallbackLocales[newLocale] || [],
31
31
  namespaces: loader.namespaces,
32
32
  concurrency: loader.concurrency,
33
+ fetch: globalThis.fetch,
33
34
  url: loader.url,
34
35
  headers: loader.headers,
35
36
  signal: currentController.signal,
@@ -12,7 +12,7 @@ import { isValidMessages } from '../utils/is-valid-messages.js';
12
12
  * - Validating the returned message structure
13
13
  * - Handling abort and network errors
14
14
  */
15
- async function fetchRemoteResource({ url, headers, signal, loggerOptions, }) {
15
+ async function fetchRemoteResource({ fetch, url, headers, signal, loggerOptions, }) {
16
16
  const baseLogger = getLogger(loggerOptions);
17
17
  const logger = baseLogger.child({ scope: "fetch-locale-messages" });
18
18
  try {
@@ -18,7 +18,7 @@ import { resolveRemoteResources } from './resolve-remote-resources.js';
18
18
  *
19
19
  * Network requests and response validation are delegated to lower-level utilities.
20
20
  */
21
- const loadRemoteMessages = async ({ locale, fallbackLocales, namespaces, concurrency, url: baseUrl, headers, signal, loggerOptions, }) => {
21
+ const loadRemoteMessages = async ({ locale, fallbackLocales, namespaces, concurrency, fetch, url: baseUrl, headers, signal, loggerOptions, }) => {
22
22
  const baseLogger = getLogger(loggerOptions);
23
23
  const logger = baseLogger.child({ scope: "load-remote-messages" });
24
24
  // Abort early if the request has already been cancelled
@@ -49,7 +49,7 @@ const loadRemoteMessages = async ({ locale, fallbackLocales, namespaces, concurr
49
49
  // -----------------------------------------------------------------
50
50
  // Fetch all message chunks in parallel
51
51
  // -----------------------------------------------------------------
52
- const fetchUrl = (url) => fetchRemoteResource({ url, headers, signal, loggerOptions });
52
+ const fetchUrl = (url) => fetchRemoteResource({ url, headers, signal, loggerOptions, fetch });
53
53
  const results = await Promise.all(resources.map(({ url }) => limit ? limit(() => fetchUrl(url)) : fetchUrl(url)));
54
54
  // Guard: no valid remote resources
55
55
  if (!results.some(Boolean))
@@ -1,3 +1,5 @@
1
- export { createIntorStore } from '../../src/client/svelte/store/create-intor-store.js';
2
- export { createIntor } from '../../src/client/svelte/helpers/create-intor.js';
1
+ export { createIntorStore } from '../../src/client/svelte/provider/create-intor-store.js';
2
+ export { default as IntorProvider } from '../../src/client/svelte/provider/intor-provider.svelte';
3
+ export { useIntorContext } from '../../src/client/svelte/provider/use-intor-context.js';
4
+ export { useTranslator } from '../../src/client/svelte/translator/use-translator.js';
3
5
  export { getClientLocale } from '../../src/client/shared/helpers/get-client-locale.js';
@@ -30,6 +30,7 @@ const createRefetchMessages = ({ config, onLoadingStart, onLoadingEnd, onMessage
30
30
  fallbackLocales: config.fallbackLocales[newLocale] || [],
31
31
  namespaces: loader.namespaces,
32
32
  concurrency: loader.concurrency,
33
+ fetch: globalThis.fetch,
33
34
  url: loader.url,
34
35
  headers: loader.headers,
35
36
  signal: currentController.signal,
@@ -1,9 +1,10 @@
1
1
  import { Translator } from 'intor-translator';
2
+ import { setContext } from 'svelte';
2
3
  import { writable, readable, derived, get } from 'svelte/store';
3
- import { createTranslatorBindings } from './create-translator-bindings.js';
4
4
  import { attachLocaleEffects } from './effects/locale-effects.js';
5
5
  import { attachMessagesEffects } from './effects/messages-effects.js';
6
6
 
7
+ const INTOR_CONTEXT_KEY = Symbol("intor:svelte");
7
8
  function createIntorStore({ config, locale: initialLocale, messages, handlers, plugins, onLocaleChange, isLoading: externalIsLoading, }) {
8
9
  // ---------------------------------------------------------------------------
9
10
  // Internal state
@@ -25,11 +26,12 @@ function createIntorStore({ config, locale: initialLocale, messages, handlers, p
25
26
  // ---------------------------------------------------------------------------
26
27
  // Effective state
27
28
  // ---------------------------------------------------------------------------
28
- const externalIsLoadingStore = externalIsLoading ?? readable(false);
29
+ const externalIsLoadingStore = readable(!!externalIsLoading);
29
30
  // external > internal
30
31
  const effectiveIsLoading = derived([externalIsLoadingStore, internalIsLoading], ([$external, $internal]) => $external || $internal);
31
32
  // runtime (client refetch) > initial > config (static)
32
- const effectiveMessages = derived([runtimeMessages, messages ?? readable(undefined)], ([$runtime, $initial]) => $runtime || $initial || config.messages || {});
33
+ const initialMessagesStore = readable(messages || config.messages || {});
34
+ const effectiveMessages = derived([runtimeMessages, initialMessagesStore], ([$runtime, $initial]) => $runtime || $initial);
33
35
  // ---------------------------------------------------------------------------
34
36
  // Translator
35
37
  // ---------------------------------------------------------------------------
@@ -48,16 +50,7 @@ function createIntorStore({ config, locale: initialLocale, messages, handlers, p
48
50
  // ---------------------------------------------------------------------------
49
51
  attachLocaleEffects(locale, config);
50
52
  attachMessagesEffects({ config, locale, runtimeMessages, internalIsLoading });
51
- const { scoped, t, tRich } = createTranslatorBindings(translator);
52
- return {
53
- messages: effectiveMessages,
54
- locale,
55
- isLoading: effectiveIsLoading,
56
- setLocale,
57
- scoped,
58
- t,
59
- tRich,
60
- };
53
+ setContext(INTOR_CONTEXT_KEY, { config, locale, setLocale, translator });
61
54
  }
62
55
 
63
- export { createIntorStore };
56
+ export { INTOR_CONTEXT_KEY, createIntorStore };
@@ -0,0 +1,7 @@
1
+ <script lang="ts">
2
+ import { createIntorStore } from "./create-intor-store";
3
+ export let value;
4
+ createIntorStore(value);
5
+ </script>
6
+
7
+ <slot />
@@ -0,0 +1,11 @@
1
+ import { getContext } from 'svelte';
2
+ import { INTOR_CONTEXT_KEY } from './create-intor-store.js';
3
+
4
+ function useIntorContext() {
5
+ const context = getContext(INTOR_CONTEXT_KEY);
6
+ if (!context)
7
+ throw new Error("useIntorContext must be used within IntorProvider");
8
+ return context;
9
+ }
10
+
11
+ export { useIntorContext };
@@ -18,12 +18,11 @@ const createSvelteRenderer = (options) => {
18
18
  },
19
19
  /** Render semantic tag nodes */
20
20
  tag(name, attributes, children) {
21
- const renderer = tagRenderers?.[name];
22
- // Custom tag renderer
23
- if (renderer) {
24
- return typeof renderer === "function"
25
- ? renderer(children, attributes)
26
- : renderer;
21
+ const tagRenderer = tagRenderers?.[name];
22
+ if (tagRenderer) {
23
+ return typeof tagRenderer === "function"
24
+ ? tagRenderer(children)
25
+ : tagRenderer;
27
26
  }
28
27
  // Default behavior: render as native HTML tag
29
28
  return `<${name}${renderAttributes(attributes)}>${children.join("")}</${name}>`;
@@ -0,0 +1,23 @@
1
+ import { renderRichMessageSvelte } from '../render/render-rich-message-svelte.js';
2
+
3
+ /**
4
+ * Create a Svelte-specific rich translation function.
5
+ *
6
+ * This adapter bridges the core Translator with the Svelte rich
7
+ * message rendering flow.
8
+ *
9
+ * - Resolves translated messages via `translator.t`
10
+ * - Renders semantic tags using Svelte renderers
11
+ * - Supports optional scoped keys via `preKey`
12
+ *
13
+ * Intended for Svelte client usage only.
14
+ */
15
+ const createTRich = (translator, preKey) => {
16
+ const t = preKey ? translator.scoped(preKey).t : translator.t;
17
+ return (key, tagRenderers, replacements) => {
18
+ const message = t(key, replacements);
19
+ return renderRichMessageSvelte(message, tagRenderers);
20
+ };
21
+ };
22
+
23
+ export { createTRich };
@@ -0,0 +1,32 @@
1
+ import { derived } from 'svelte/store';
2
+ import 'intor-translator';
3
+ import 'svelte';
4
+ import '../../../core/error/intor-error.js';
5
+ import 'logry';
6
+ import 'p-limit';
7
+ import '../provider/intor-provider.svelte';
8
+ import { useIntorContext } from '../provider/use-intor-context.js';
9
+ import { createTRich } from './create-t-rich.js';
10
+
11
+ // Implementation
12
+ function useTranslator(preKey) {
13
+ const { translator, locale, setLocale } = useIntorContext();
14
+ const scoped = preKey
15
+ ? derived(translator, ($t) => $t.scoped(preKey))
16
+ : translator;
17
+ return {
18
+ messages: derived(translator, ($t) => $t.messages),
19
+ locale,
20
+ isLoading: derived(translator, ($t) => $t.isLoading),
21
+ setLocale,
22
+ hasKey: derived(scoped, ($t) => $t.hasKey),
23
+ t: derived(scoped, ($t) => $t.t),
24
+ tRich: derived(translator, ($t) => createTRich($t, preKey)),
25
+ // NOTE:
26
+ // The runtime implementation is intentionally erased.
27
+ // Type safety is guaranteed by public type contracts.
28
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
29
+ };
30
+ }
31
+
32
+ export { useTranslator };
@@ -12,7 +12,7 @@ import { isValidMessages } from '../utils/is-valid-messages.js';
12
12
  * - Validating the returned message structure
13
13
  * - Handling abort and network errors
14
14
  */
15
- async function fetchRemoteResource({ url, headers, signal, loggerOptions, }) {
15
+ async function fetchRemoteResource({ fetch, url, headers, signal, loggerOptions, }) {
16
16
  const baseLogger = getLogger(loggerOptions);
17
17
  const logger = baseLogger.child({ scope: "fetch-locale-messages" });
18
18
  try {
@@ -18,7 +18,7 @@ import { resolveRemoteResources } from './resolve-remote-resources.js';
18
18
  *
19
19
  * Network requests and response validation are delegated to lower-level utilities.
20
20
  */
21
- const loadRemoteMessages = async ({ locale, fallbackLocales, namespaces, concurrency, url: baseUrl, headers, signal, loggerOptions, }) => {
21
+ const loadRemoteMessages = async ({ locale, fallbackLocales, namespaces, concurrency, fetch, url: baseUrl, headers, signal, loggerOptions, }) => {
22
22
  const baseLogger = getLogger(loggerOptions);
23
23
  const logger = baseLogger.child({ scope: "load-remote-messages" });
24
24
  // Abort early if the request has already been cancelled
@@ -49,7 +49,7 @@ const loadRemoteMessages = async ({ locale, fallbackLocales, namespaces, concurr
49
49
  // -----------------------------------------------------------------
50
50
  // Fetch all message chunks in parallel
51
51
  // -----------------------------------------------------------------
52
- const fetchUrl = (url) => fetchRemoteResource({ url, headers, signal, loggerOptions });
52
+ const fetchUrl = (url) => fetchRemoteResource({ url, headers, signal, loggerOptions, fetch });
53
53
  const results = await Promise.all(resources.map(({ url }) => limit ? limit(() => fetchUrl(url)) : fetchUrl(url)));
54
54
  // Guard: no valid remote resources
55
55
  if (!results.some(Boolean))
@@ -0,0 +1 @@
1
+ export { useNavigation } from '../../src/adapters/svelte-kit/navigation/use-navigation.js';
@@ -0,0 +1,2 @@
1
+ export { createIntorHandle } from '../../../src/adapters/svelte-kit/server/create-intor-handle.js';
2
+ export { intor } from '../../../src/adapters/svelte-kit/server/intor.js';
@@ -0,0 +1,36 @@
1
+ import { get } from 'svelte/store';
2
+ import { executeNavigation } from '../../../client/shared/navigation/execute-navigation.js';
3
+ import { useIntorContext } from 'intor/svelte';
4
+ import '../../../core/error/intor-error.js';
5
+ import 'logry';
6
+ import 'p-limit';
7
+ import { resolveNavigation } from '../../../routing/navigation/resolve-navigation.js';
8
+ import { goto } from '$app/navigation';
9
+ import { page } from '$app/state';
10
+
11
+ /**
12
+ * Locale-aware navigation utilities for SvelteKit.
13
+ *
14
+ * Provides imperative navigation helpers that integrate
15
+ * Intor's locale-aware routing and side effects.
16
+ *
17
+ * @platform SvelteKit
18
+ */
19
+ function useNavigation() {
20
+ const { config, locale: currentLocale, setLocale } = useIntorContext();
21
+ async function goto$1(url, opts) {
22
+ const { locale, ...rest } = opts || {};
23
+ const navigationResult = resolveNavigation(config, get(currentLocale), page.url.pathname, { destination: url, locale });
24
+ executeNavigation(navigationResult, {
25
+ config,
26
+ currentLocale: get(currentLocale),
27
+ setLocale,
28
+ });
29
+ return goto(navigationResult.destination, rest);
30
+ }
31
+ return {
32
+ goto: goto$1,
33
+ };
34
+ }
35
+
36
+ export { useNavigation };
@@ -0,0 +1,58 @@
1
+ import { redirect } from '@sveltejs/kit';
2
+ import { INTOR_HEADERS } from '../../../core/constants/headers.js';
3
+ import '../../../core/error/intor-error.js';
4
+ import { normalizeQuery } from '../../../core/utils/normalizers/normalize-query.js';
5
+ import 'logry';
6
+ import 'p-limit';
7
+ import { resolveInbound } from '../../../routing/inbound/resolve-inbound.js';
8
+ import { getLocaleFromAcceptLanguage } from '../../../routing/locale/get-locale-from-accept-language.js';
9
+
10
+ /**
11
+ * Resolves locale-aware routing for the current execution context.
12
+ *
13
+ * The resolved routing state is exposed via response headers.
14
+ *
15
+ * - Acts as the canonical routing authority within the SvelteKit request lifecycle.
16
+ *
17
+ * @platform SvelteKit
18
+ */
19
+ function createIntorHandle(config) {
20
+ return async ({ event, resolve }) => {
21
+ // ----------------------------------------------------------
22
+ // Locale from Accept-Language header
23
+ // ----------------------------------------------------------
24
+ const acceptLanguage = event.request.headers.get("accept-language");
25
+ const localeFromAcceptLanguage = getLocaleFromAcceptLanguage(acceptLanguage, config.supportedLocales);
26
+ // ----------------------------------------------------------
27
+ // Resolve inbound routing decision (pure computation)
28
+ // ----------------------------------------------------------
29
+ const { locale, localeSource, pathname, shouldRedirect } = await resolveInbound(config, event.url.pathname, false, {
30
+ host: event.url.host,
31
+ query: normalizeQuery(Object.fromEntries(event.url.searchParams.entries())),
32
+ cookie: event.cookies.get(config.cookie.name),
33
+ detected: localeFromAcceptLanguage || config.defaultLocale,
34
+ });
35
+ // ----------------------------------------------------------
36
+ // Redirect if needed
37
+ // ----------------------------------------------------------
38
+ if (shouldRedirect) {
39
+ throw redirect(307, pathname);
40
+ }
41
+ // ----------------------------------------------------------
42
+ // Attach routing metadata
43
+ // ----------------------------------------------------------
44
+ // @ts-expect-error - App.Locals must be extended by user
45
+ event.locals.intor = {
46
+ locale,
47
+ localeSource,
48
+ pathname,
49
+ };
50
+ const response = await resolve(event);
51
+ response.headers.set(INTOR_HEADERS.LOCALE, locale);
52
+ response.headers.set(INTOR_HEADERS.LOCALE_SOURCE, localeSource);
53
+ response.headers.set(INTOR_HEADERS.PATHNAME, pathname);
54
+ return response;
55
+ };
56
+ }
57
+
58
+ export { createIntorHandle };
@@ -0,0 +1,24 @@
1
+ import '../../../core/error/intor-error.js';
2
+ import 'logry';
3
+ import 'p-limit';
4
+ import { intor as intor$1 } from '../../../server/intor/intor.js';
5
+ import 'node:path';
6
+ import 'node:fs/promises';
7
+ import 'intor-translator';
8
+
9
+ /**
10
+ * Initializes Intor for the current execution context.
11
+ *
12
+ * - Uses the locale resolved by the SvelteKit request lifecycle.
13
+ * - Permits cache writes during server execution.
14
+ * @platform SvelteKit
15
+ */
16
+ async function intor(config, locale, fetch, options) {
17
+ return await intor$1(config, locale, {
18
+ readers: options?.readers,
19
+ allowCacheWrite: options?.allowCacheWrite ?? true,
20
+ fetch,
21
+ });
22
+ }
23
+
24
+ export { intor };
@@ -0,0 +1,49 @@
1
+ import '../../../core/error/intor-error.js';
2
+ import 'logry';
3
+ import 'p-limit';
4
+ import { shouldSyncLocale } from '../../../policies/should-sync-locale.js';
5
+ import { setLocaleCookie } from '../utils/locale/set-locale-cookie.js';
6
+
7
+ /**
8
+ * Executes a resolved navigation result.
9
+ *
10
+ * Applies all imperative side effects required to complete navigation,
11
+ * including locale synchronization, cookie persistence, and full reloads.
12
+ *
13
+ * This function must be called after `resolveNavigation`.
14
+ */
15
+ function executeNavigation(navigationResult, context, e) {
16
+ const { config, currentLocale, setLocale } = context;
17
+ const { cookie } = config;
18
+ const { destination, kind, locale } = navigationResult;
19
+ // ------------------------------------------------------
20
+ // External navigation: let browser handle it
21
+ // ------------------------------------------------------
22
+ if (kind === "external") {
23
+ return;
24
+ }
25
+ // ------------------------------------------------------
26
+ // Full reload: commit locale side effects, then perform document reload
27
+ // ------------------------------------------------------
28
+ if (kind === "reload") {
29
+ if (shouldSyncLocale(locale, currentLocale)) {
30
+ if (cookie.persist) {
31
+ setLocaleCookie(cookie, locale);
32
+ }
33
+ }
34
+ globalThis.location.href = destination;
35
+ return;
36
+ }
37
+ // ------------------------------------------------------
38
+ // Client-side navigation only
39
+ // ------------------------------------------------------
40
+ if (shouldSyncLocale(locale, currentLocale)) {
41
+ // Eagerly persist locale to avoid stale cookie during client-side navigation.
42
+ if (cookie.persist) {
43
+ setLocaleCookie(cookie, locale);
44
+ }
45
+ setLocale(locale);
46
+ }
47
+ }
48
+
49
+ export { executeNavigation };
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Build a serialized cookie string.
3
+ */
4
+ const buildCookieString = (cookieOptions, value) => {
5
+ const { name, maxAge, path, domain, sameSite, secure } = cookieOptions;
6
+ // Cookie name and encoded value
7
+ const parts = [`${name}=${encodeURIComponent(value)}`];
8
+ // Add expiration and max-age if provided
9
+ if (maxAge) {
10
+ const expires = new Date(Date.now() + maxAge * 1000).toUTCString();
11
+ parts.push(`expires=${expires}`, `max-age=${maxAge}`);
12
+ }
13
+ // Set path (default to "/")
14
+ parts.push(`path=${path ?? "/"}`);
15
+ // Add domain if specified
16
+ if (domain) {
17
+ parts.push(`domain=${domain}`);
18
+ }
19
+ // Add SameSite policy (e.g., Lax, Strict)
20
+ if (sameSite) {
21
+ parts.push(`SameSite=${sameSite[0].toUpperCase()}${sameSite.slice(1).toLowerCase()}`);
22
+ }
23
+ // Add Secure flag if not explicitly disabled
24
+ if (secure !== false) {
25
+ parts.push(`Secure`);
26
+ }
27
+ return parts.join("; ");
28
+ };
29
+
30
+ export { buildCookieString };
@@ -0,0 +1,15 @@
1
+ import { buildCookieString } from '../build-cookie-string.js';
2
+
3
+ /**
4
+ * Persist locale to a cookie.
5
+ *
6
+ * This function relies on `document.cookie`.
7
+ */
8
+ const setLocaleCookie = (cookieOptions, locale) => {
9
+ if (typeof document === "undefined")
10
+ return;
11
+ // Build and apply the cookie string
12
+ document.cookie = buildCookieString(cookieOptions, locale);
13
+ };
14
+
15
+ export { setLocaleCookie };
@@ -0,0 +1,6 @@
1
+ const INTOR_HEADERS = {
2
+ LOCALE: "x-intor-locale",
3
+ LOCALE_SOURCE: "x-intor-locale-source",
4
+ PATHNAME: "x-intor-pathname"};
5
+
6
+ export { INTOR_HEADERS };
@@ -0,0 +1,9 @@
1
+ var IntorErrorCode;
2
+ (function (IntorErrorCode) {
3
+ // config
4
+ IntorErrorCode["INVALID_CONFIG_ID"] = "INTOR_INVALID_CONFIG_ID";
5
+ IntorErrorCode["MISSING_SUPPORTED_LOCALES"] = "INTOR_MISSING_SUPPORTED_LOCALES";
6
+ IntorErrorCode["UNSUPPORTED_DEFAULT_LOCALE"] = "INTOR_UNSUPPORTED_DEFAULT_LOCALE";
7
+ })(IntorErrorCode || (IntorErrorCode = {}));
8
+
9
+ export { IntorErrorCode };
@@ -0,0 +1,39 @@
1
+ import { logry } from 'logry';
2
+ import { getGlobalLoggerPool } from './global-logger-pool.js';
3
+
4
+ const DEFAULT_FORMAT_CONFIG = {
5
+ timestamp: { withDate: false },
6
+ };
7
+ const DEFAULT_RENDER_CONFIG = {
8
+ timestamp: {},
9
+ id: { visible: true, prefix: "<", suffix: ">" },
10
+ meta: { lineBreaksAfter: 1 },
11
+ };
12
+ /**
13
+ * Get a shared logger instance by id.
14
+ * - Safe across hot reloads
15
+ * - Prevents unbounded memory usage via soft LRU
16
+ */
17
+ function getLogger({ id = "default", formatConfig, renderConfig, preset, ...options }) {
18
+ const pool = getGlobalLoggerPool();
19
+ let logger = pool.get(id);
20
+ if (!logger) {
21
+ logger = logry({
22
+ id,
23
+ formatConfig: !formatConfig && !preset ? DEFAULT_FORMAT_CONFIG : formatConfig,
24
+ renderConfig: !renderConfig && !preset ? DEFAULT_RENDER_CONFIG : renderConfig,
25
+ preset,
26
+ ...options,
27
+ });
28
+ pool.set(id, logger);
29
+ // Soft LRU: keep pool size under control
30
+ if (pool.size > 1000) {
31
+ const keys = [...pool.keys()];
32
+ for (const key of keys.slice(0, 200))
33
+ pool.delete(key);
34
+ }
35
+ }
36
+ return logger;
37
+ }
38
+
39
+ export { getLogger };
@@ -0,0 +1,8 @@
1
+ function getGlobalLoggerPool() {
2
+ if (!globalThis.__INTOR_LOGGER_POOL__) {
3
+ globalThis.__INTOR_LOGGER_POOL__ = new Map();
4
+ }
5
+ return globalThis.__INTOR_LOGGER_POOL__;
6
+ }
7
+
8
+ export { getGlobalLoggerPool };
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Collect remote message resources for a given locale.
3
+ *
4
+ * - Always includes the root `index.json`
5
+ * - Optionally includes namespace-specific resources
6
+ * - Produces semantic paths for later message nesting
7
+ *
8
+ * This function performs no I/O and does not validate resource existence.
9
+ */
10
+ function collectRemoteResources({ locale, baseUrl, namespaces, }) {
11
+ const basePath = `${baseUrl}/${locale}`;
12
+ // Root translation resource (always loaded)
13
+ const indexResource = { url: `${basePath}/index.json`, path: [] };
14
+ // When no namespaces are provided, the locale domain consists of index only
15
+ if (!namespaces || namespaces.length === 0)
16
+ return [indexResource];
17
+ // Namespace-specific resources are nested under their namespace key
18
+ const nsResources = namespaces.map((ns) => ({
19
+ url: `${basePath}/${ns}.json`,
20
+ path: [ns],
21
+ }));
22
+ return [indexResource, ...nsResources];
23
+ }
24
+
25
+ export { collectRemoteResources };
@@ -0,0 +1,47 @@
1
+ import { getLogger } from '../../logger/get-logger.js';
2
+ import { isValidMessages } from '../utils/is-valid-messages.js';
3
+
4
+ /**
5
+ * Fetch a single remote messages resource.
6
+ *
7
+ * This function performs a single HTTP request to retrieve
8
+ * a remote translation messages payload.
9
+ *
10
+ * It is responsible for:
11
+ * - Issuing the network request
12
+ * - Validating the returned message structure
13
+ * - Handling abort and network errors
14
+ */
15
+ async function fetchRemoteResource({ fetch, url, headers, signal, loggerOptions, }) {
16
+ const baseLogger = getLogger(loggerOptions);
17
+ const logger = baseLogger.child({ scope: "fetch-locale-messages" });
18
+ try {
19
+ // Fetch
20
+ const response = await fetch(url, {
21
+ method: "GET",
22
+ headers: { "Content-Type": "application/json", ...headers },
23
+ cache: "no-store",
24
+ signal,
25
+ });
26
+ if (!response.ok) {
27
+ throw new Error(`HTTP ${response.status} ${response.statusText}`);
28
+ }
29
+ // Parse JSON body
30
+ const data = await response.json();
31
+ // Validate messages structure
32
+ if (!isValidMessages(data)) {
33
+ throw new Error("Invalid messages structure");
34
+ }
35
+ return data;
36
+ }
37
+ catch (error) {
38
+ if (error instanceof Error && error.name === "AbortError") {
39
+ logger.debug("Remote fetch aborted.", { url });
40
+ return;
41
+ }
42
+ logger.warn("Failed to fetch remote messages.", { url, error });
43
+ return;
44
+ }
45
+ }
46
+
47
+ export { fetchRemoteResource };