intor 2.3.29 → 2.3.31

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 (175) 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/adapters/express/middleware/create-intor-middleware.js +4 -11
  9. package/dist/express/src/core/messages/load-remote-messages/fetch-remote-resource.js +1 -1
  10. package/dist/express/src/core/messages/load-remote-messages/load-remote-messages.js +2 -2
  11. package/dist/express/src/routing/pathname/canonicalize-pathname.js +11 -7
  12. package/dist/express/src/server/helpers/get-translator.js +2 -2
  13. package/dist/express/src/server/messages/load-messages.js +2 -1
  14. package/dist/express/src/server/translator/init-translator.js +9 -3
  15. package/dist/next/export/next/index.js +0 -1
  16. package/dist/next/export/next/server/index.js +0 -1
  17. package/dist/next/src/adapters/next/navigation/link.js +11 -10
  18. package/dist/next/src/adapters/next/navigation/use-router.js +14 -20
  19. package/dist/next/src/adapters/next/proxy/intor-proxy.js +1 -1
  20. package/dist/next/src/adapters/next/server/intor.js +1 -1
  21. package/dist/next/src/client/shared/navigation/execute-navigation.js +50 -0
  22. package/dist/next/src/client/shared/utils/build-cookie-string.js +30 -0
  23. package/dist/next/src/client/shared/utils/locale/set-locale-cookie.js +15 -0
  24. package/dist/next/src/core/messages/load-remote-messages/fetch-remote-resource.js +1 -1
  25. package/dist/next/src/core/messages/load-remote-messages/load-remote-messages.js +2 -2
  26. package/dist/next/src/routing/pathname/canonicalize-pathname.js +11 -7
  27. package/dist/next/src/server/helpers/get-translator.js +2 -2
  28. package/dist/next/src/server/intor/intor.js +3 -8
  29. package/dist/next/src/server/messages/load-messages.js +2 -1
  30. package/dist/next/src/server/translator/init-translator.js +9 -3
  31. package/dist/react/export/react/index.js +0 -2
  32. package/dist/react/src/client/shared/messages/create-refetch-messages.js +1 -0
  33. package/dist/react/src/core/messages/load-remote-messages/fetch-remote-resource.js +1 -1
  34. package/dist/react/src/core/messages/load-remote-messages/load-remote-messages.js +2 -2
  35. package/dist/svelte/export/svelte/index.js +4 -2
  36. package/dist/svelte/src/client/shared/messages/create-refetch-messages.js +1 -0
  37. package/dist/svelte/src/client/svelte/{store → provider}/create-intor-store.js +7 -14
  38. package/dist/svelte/src/client/svelte/provider/intor-provider.svelte +7 -0
  39. package/dist/svelte/src/client/svelte/provider/use-intor-context.js +11 -0
  40. package/dist/svelte/src/client/svelte/render/create-svelte-renderer.js +5 -6
  41. package/dist/svelte/src/client/svelte/translator/create-t-rich.js +23 -0
  42. package/dist/svelte/src/client/svelte/translator/use-translator.js +32 -0
  43. package/dist/svelte/src/core/messages/load-remote-messages/fetch-remote-resource.js +1 -1
  44. package/dist/svelte/src/core/messages/load-remote-messages/load-remote-messages.js +2 -2
  45. package/dist/svelte-kit/export/svelte-kit/index.js +1 -0
  46. package/dist/svelte-kit/export/svelte-kit/server/index.js +2 -0
  47. package/dist/svelte-kit/src/adapters/svelte-kit/navigation/use-navigation.js +36 -0
  48. package/dist/svelte-kit/src/adapters/svelte-kit/server/create-intor-handle.js +66 -0
  49. package/dist/svelte-kit/src/adapters/svelte-kit/server/intor.js +24 -0
  50. package/dist/svelte-kit/src/adapters/svelte-kit/server/utils/is-svelte-kit-ssg.js +15 -0
  51. package/dist/svelte-kit/src/client/shared/navigation/execute-navigation.js +49 -0
  52. package/dist/svelte-kit/src/client/shared/utils/build-cookie-string.js +30 -0
  53. package/dist/svelte-kit/src/client/shared/utils/locale/set-locale-cookie.js +15 -0
  54. package/dist/svelte-kit/src/core/error/intor-error.js +9 -0
  55. package/dist/svelte-kit/src/core/logger/get-logger.js +39 -0
  56. package/dist/svelte-kit/src/core/logger/global-logger-pool.js +8 -0
  57. package/dist/svelte-kit/src/core/messages/load-remote-messages/collect-remote-resources.js +25 -0
  58. package/dist/svelte-kit/src/core/messages/load-remote-messages/fetch-remote-resource.js +47 -0
  59. package/dist/svelte-kit/src/core/messages/load-remote-messages/load-remote-messages.js +93 -0
  60. package/dist/svelte-kit/src/core/messages/load-remote-messages/resolve-remote-resources.js +24 -0
  61. package/dist/svelte-kit/src/core/messages/merge-messages.js +33 -0
  62. package/dist/svelte-kit/src/core/messages/utils/is-valid-messages.js +44 -0
  63. package/dist/svelte-kit/src/core/messages/utils/nest-object-from-path.js +21 -0
  64. package/dist/svelte-kit/src/core/utils/deep-merge.js +47 -0
  65. package/dist/svelte-kit/src/core/utils/normalizers/normalize-cache-key.js +45 -0
  66. package/dist/svelte-kit/src/core/utils/normalizers/normalize-locale.js +59 -0
  67. package/dist/svelte-kit/src/core/utils/normalizers/normalize-query.js +25 -0
  68. package/dist/svelte-kit/src/core/utils/resolve-loader-options.js +34 -0
  69. package/dist/{react → svelte-kit}/src/policies/shoud-full-reload.js +1 -1
  70. package/dist/svelte-kit/src/policies/should-sync-locale.js +8 -0
  71. package/dist/svelte-kit/src/routing/inbound/resolve-inbound.js +46 -0
  72. package/dist/svelte-kit/src/routing/inbound/resolve-locale/resolve-locale.js +33 -0
  73. package/dist/svelte-kit/src/routing/inbound/resolve-pathname/resolve-pathname.js +42 -0
  74. package/dist/svelte-kit/src/routing/inbound/resolve-pathname/strategies/all.js +28 -0
  75. package/dist/svelte-kit/src/routing/inbound/resolve-pathname/strategies/except-default.js +29 -0
  76. package/dist/svelte-kit/src/routing/inbound/resolve-pathname/strategies/none.js +8 -0
  77. package/dist/svelte-kit/src/routing/locale/get-locale-from-accept-language.js +38 -0
  78. package/dist/svelte-kit/src/routing/locale/get-locale-from-host.js +32 -0
  79. package/dist/svelte-kit/src/routing/locale/get-locale-from-pathname.js +46 -0
  80. package/dist/svelte-kit/src/routing/locale/get-locale-from-query.js +29 -0
  81. package/dist/{react → svelte-kit}/src/routing/pathname/canonicalize-pathname.js +11 -7
  82. package/dist/svelte-kit/src/server/intor/intor.js +31 -0
  83. package/dist/svelte-kit/src/server/messages/load-local-messages/cache/messages-pool.js +11 -0
  84. package/dist/svelte-kit/src/server/messages/load-local-messages/load-local-messages.js +107 -0
  85. package/dist/svelte-kit/src/server/messages/load-local-messages/read-locale-messages/collect-file-entries/collect-file-entries.js +90 -0
  86. package/dist/svelte-kit/src/server/messages/load-local-messages/read-locale-messages/parse-file-entries/parse-file-entries.js +102 -0
  87. package/dist/svelte-kit/src/server/messages/load-local-messages/read-locale-messages/parse-file-entries/utils/json-reader.js +12 -0
  88. package/dist/svelte-kit/src/server/messages/load-local-messages/read-locale-messages/read-locale-messages.js +42 -0
  89. package/dist/svelte-kit/src/server/messages/load-messages.js +77 -0
  90. package/dist/svelte-kit/src/server/translator/create-translator.js +40 -0
  91. package/dist/svelte-kit/src/server/translator/init-translator.js +42 -0
  92. package/dist/types/export/next/index.d.ts +1 -1
  93. package/dist/types/export/next/server/index.d.ts +1 -1
  94. package/dist/types/export/react/index.d.ts +2 -2
  95. package/dist/types/export/svelte/index.d.ts +3 -1
  96. package/dist/types/export/svelte-kit/index.d.ts +1 -0
  97. package/dist/types/export/svelte-kit/server/index.d.ts +1 -0
  98. package/dist/types/src/adapters/express/global.d.ts +5 -8
  99. package/dist/types/src/adapters/next/navigation/index.d.ts +0 -1
  100. package/dist/types/src/adapters/next/server/index.d.ts +0 -1
  101. package/dist/types/src/adapters/svelte-kit/navigation/index.d.ts +1 -0
  102. package/dist/types/src/adapters/svelte-kit/navigation/use-navigation.d.ts +15 -0
  103. package/dist/types/src/adapters/svelte-kit/server/create-intor-handle.d.ts +12 -0
  104. package/dist/types/src/adapters/svelte-kit/server/index.d.ts +2 -0
  105. package/dist/types/src/adapters/svelte-kit/server/intor.d.ts +16 -0
  106. package/dist/types/src/adapters/svelte-kit/server/utils/is-svelte-kit-ssg.d.ts +8 -0
  107. package/dist/types/src/client/index.d.ts +1 -0
  108. package/dist/types/src/client/react/index.d.ts +0 -1
  109. package/dist/types/src/client/shared/navigation/execute-navigation.d.ts +19 -0
  110. package/dist/types/src/client/shared/navigation/index.d.ts +1 -0
  111. package/dist/types/src/client/svelte/index.d.ts +2 -2
  112. package/dist/types/src/client/svelte/provider/create-intor-store.d.ts +3 -0
  113. package/dist/types/src/client/svelte/provider/index.d.ts +3 -0
  114. package/dist/types/src/client/svelte/provider/types.d.ts +18 -0
  115. package/dist/types/src/client/svelte/provider/use-intor-context.d.ts +2 -0
  116. package/dist/types/src/client/svelte/render/types.d.ts +7 -13
  117. package/dist/types/src/client/svelte/translator/create-t-rich.d.ts +15 -0
  118. package/dist/types/src/client/svelte/translator/index.d.ts +1 -0
  119. package/dist/types/src/client/svelte/translator/translator-instance.d.ts +20 -0
  120. package/dist/types/src/client/svelte/translator/use-translator.d.ts +8 -0
  121. package/dist/types/src/core/index.d.ts +1 -1
  122. package/dist/types/src/core/messages/load-remote-messages/fetch-remote-resource.d.ts +3 -1
  123. package/dist/types/src/core/messages/load-remote-messages/load-remote-messages.d.ts +1 -1
  124. package/dist/types/src/core/messages/load-remote-messages/types.d.ts +2 -0
  125. package/dist/types/src/core/types/index.d.ts +1 -0
  126. package/dist/types/src/core/types/runtime-fetch.d.ts +1 -0
  127. package/dist/types/src/routing/inbound/index.d.ts +1 -0
  128. package/dist/types/src/routing/inbound/resolve-inbound.d.ts +1 -12
  129. package/dist/types/src/routing/inbound/types.d.ts +12 -0
  130. package/dist/types/src/routing/index.d.ts +1 -1
  131. package/dist/types/src/routing/pathname/canonicalize-pathname.d.ts +2 -0
  132. package/dist/types/src/server/helpers/get-translator.d.ts +2 -1
  133. package/dist/types/src/server/intor/intor.d.ts +4 -3
  134. package/dist/types/src/server/intor/types.d.ts +0 -2
  135. package/dist/types/src/server/messages/load-messages.d.ts +1 -1
  136. package/dist/types/src/server/messages/types.d.ts +2 -1
  137. package/dist/types/src/server/translator/init-translator.d.ts +2 -2
  138. package/dist/vue/src/client/shared/messages/create-refetch-messages.js +1 -0
  139. package/dist/vue/src/core/messages/load-remote-messages/fetch-remote-resource.js +1 -1
  140. package/dist/vue/src/core/messages/load-remote-messages/load-remote-messages.js +2 -2
  141. package/package.json +11 -1
  142. package/dist/express/src/core/constants/headers.js +0 -6
  143. package/dist/next/src/adapters/next/navigation/use-pathname.js +0 -26
  144. package/dist/next/src/adapters/next/server/get-pathname.js +0 -28
  145. package/dist/react/src/client/react/navigation/use-execute-navigation.js +0 -41
  146. package/dist/react/src/client/react/navigation/use-resolve-navigation.js +0 -16
  147. package/dist/svelte/src/client/svelte/helpers/create-intor.js +0 -45
  148. package/dist/svelte/src/client/svelte/store/create-translator-bindings.js +0 -25
  149. package/dist/types/src/adapters/next/navigation/use-pathname.d.ts +0 -14
  150. package/dist/types/src/adapters/next/server/get-pathname.d.ts +0 -16
  151. package/dist/types/src/client/react/navigation/index.d.ts +0 -2
  152. package/dist/types/src/client/react/navigation/use-execute-navigation.d.ts +0 -5
  153. package/dist/types/src/client/react/navigation/use-resolve-navigation.d.ts +0 -5
  154. package/dist/types/src/client/svelte/helpers/create-intor.d.ts +0 -4
  155. package/dist/types/src/client/svelte/helpers/index.d.ts +0 -1
  156. package/dist/types/src/client/svelte/store/create-intor-store.d.ts +0 -2
  157. package/dist/types/src/client/svelte/store/create-translator-bindings.d.ts +0 -13
  158. package/dist/types/src/client/svelte/store/index.d.ts +0 -2
  159. package/dist/types/src/client/svelte/store/types.d.ts +0 -31
  160. /package/dist/{react → next}/src/policies/should-sync-locale.js +0 -0
  161. /package/dist/svelte/src/client/svelte/{store → provider}/effects/locale-effects.js +0 -0
  162. /package/dist/svelte/src/client/svelte/{store → provider}/effects/messages-effects.js +0 -0
  163. /package/dist/{react → svelte-kit}/src/core/constants/prefix-placeholder.js +0 -0
  164. /package/dist/{react → svelte-kit}/src/core/utils/normalizers/normalize-pathname.js +0 -0
  165. /package/dist/{react → svelte-kit}/src/routing/navigation/decide-strategy.js +0 -0
  166. /package/dist/{react → svelte-kit}/src/routing/navigation/derive-target.js +0 -0
  167. /package/dist/{react → svelte-kit}/src/routing/navigation/resolve-navigation.js +0 -0
  168. /package/dist/{react → svelte-kit}/src/routing/navigation/utils/derive-host-destination.js +0 -0
  169. /package/dist/{react → svelte-kit}/src/routing/navigation/utils/derive-query-destination.js +0 -0
  170. /package/dist/{react → svelte-kit}/src/routing/navigation/utils/is-external-destination.js +0 -0
  171. /package/dist/{react → svelte-kit}/src/routing/pathname/localize-pathname.js +0 -0
  172. /package/dist/{react → svelte-kit}/src/routing/pathname/materialize-pathname.js +0 -0
  173. /package/dist/{react → svelte-kit}/src/routing/pathname/standardize-pathname.js +0 -0
  174. /package/dist/types/src/client/svelte/{store → provider}/effects/locale-effects.d.ts +0 -0
  175. /package/dist/types/src/client/svelte/{store → provider}/effects/messages-effects.d.ts +0 -0
@@ -2,12 +2,12 @@ import { initTranslator } from '../translator/init-translator.js';
2
2
 
3
3
  // Implementation
4
4
  async function getTranslator(config, params) {
5
- const { readers, allowCacheWrite, preKey, handlers, plugins } = params;
6
- const locale = params.locale;
5
+ const { locale, readers, allowCacheWrite, fetch, preKey, handlers, plugins } = params;
7
6
  // Initialize a locale-bound translator snapshot with messages loaded
8
7
  const translator = await initTranslator(config, locale, {
9
8
  readers,
10
9
  allowCacheWrite,
10
+ fetch: fetch || globalThis.fetch,
11
11
  preKey,
12
12
  plugins,
13
13
  handlers,
@@ -9,21 +9,16 @@ import { initTranslator } from '../translator/init-translator.js';
9
9
  * Produces a server-side snapshot for SSR and
10
10
  * full-stack rendering environments.
11
11
  */
12
- async function intor(config, localeOrResolver, options) {
12
+ async function intor(config, locale, options) {
13
13
  const baseLogger = getLogger(config.logger);
14
14
  const logger = baseLogger.child({ scope: "intor" });
15
15
  logger.info("Start Intor initialization.");
16
- // Resolve locale
17
- const isLocaleFunction = typeof localeOrResolver === "function";
18
- const locale = isLocaleFunction
19
- ? await localeOrResolver(config)
20
- : localeOrResolver || config.defaultLocale;
21
- const source = typeof localeOrResolver === "function" ? "resolver" : "static";
22
- logger.debug(`Initial locale resolved as "${locale}" via "${source}".`);
16
+ logger.debug(`Initializing Intor with locale "${locale}".`);
23
17
  // Initialize a locale-bound translator snapshot with messages loaded
24
18
  const translator = await initTranslator(config, locale, {
25
19
  readers: options?.readers,
26
20
  allowCacheWrite: options?.allowCacheWrite,
21
+ fetch: options?.fetch || globalThis.fetch,
27
22
  });
28
23
  logger.info("Intor initialized.");
29
24
  return {
@@ -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,66 @@
1
+ import { redirect } from '@sveltejs/kit';
2
+ import { isSvelteKitSSG } from './utils/is-svelte-kit-ssg.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
+ // Locale from Accept-Language header
22
+ const acceptLanguage = event.request.headers.get("accept-language");
23
+ const localeFromAcceptLanguage = getLocaleFromAcceptLanguage(acceptLanguage, config.supportedLocales);
24
+ // ----------------------------------------------------------
25
+ // Resolve inbound routing decision (pure computation)
26
+ // ----------------------------------------------------------
27
+ let inbound;
28
+ if (isSvelteKitSSG(event)) {
29
+ inbound = {
30
+ locale: event.params?.locale,
31
+ localeSource: "path",
32
+ pathname: event.url.pathname,
33
+ shouldRedirect: false,
34
+ };
35
+ }
36
+ else {
37
+ inbound = await resolveInbound(config, event.url.pathname, false, {
38
+ host: event.url.host,
39
+ query: normalizeQuery(Object.fromEntries(event.url.searchParams.entries())),
40
+ cookie: event.cookies.get(config.cookie.name),
41
+ detected: localeFromAcceptLanguage || config.defaultLocale,
42
+ });
43
+ }
44
+ const { locale, localeSource, pathname, shouldRedirect } = inbound;
45
+ // ----------------------------------------------------------
46
+ // Redirect if needed
47
+ // ----------------------------------------------------------
48
+ if (shouldRedirect)
49
+ redirect(307, pathname);
50
+ // ----------------------------------------------------------
51
+ // Bind inbound routing context
52
+ // ----------------------------------------------------------
53
+ // @ts-expect-error - App.Locals must be extended by user
54
+ event.locals.intor = {
55
+ locale,
56
+ localeSource,
57
+ pathname,
58
+ };
59
+ const response = await resolve(event, {
60
+ transformPageChunk: ({ html }) => html.replace("%lang%", locale),
61
+ });
62
+ return response;
63
+ };
64
+ }
65
+
66
+ 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,15 @@
1
+ /**
2
+ * Heuristic to detect static (prerender) execution in SvelteKit.
3
+ *
4
+ * This is NOT a guaranteed signal.
5
+ * It intentionally prefers false positives over false negatives.
6
+ */
7
+ function isSvelteKitSSG(event) {
8
+ // No user-agent is a strong signal of static rendering
9
+ if (event.request.headers.get("user-agent") === null) {
10
+ return true;
11
+ }
12
+ return false;
13
+ }
14
+
15
+ export { isSvelteKitSSG };
@@ -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,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 };