intor 2.3.32 → 2.3.34

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 (124) hide show
  1. package/dist/core/src/core/utils/resolve-loader-options.js +7 -3
  2. package/dist/core/src/server/messages/load-messages.js +5 -5
  3. package/dist/express/export/express/index.js +2 -2
  4. package/dist/express/src/adapters/express/{middleware/create-intor-middleware.js → create-intor-handler.js} +13 -12
  5. package/dist/express/src/adapters/express/{helpers/get-translator.js → get-translator.js} +2 -6
  6. package/dist/express/src/core/utils/resolve-loader-options.js +3 -1
  7. package/dist/express/src/routing/inbound/resolve-inbound.js +3 -4
  8. package/dist/express/src/routing/inbound/resolve-locale/resolve-locale.js +6 -5
  9. package/dist/express/src/routing/locale/get-locale-from-query.js +1 -9
  10. package/dist/express/src/server/messages/load-messages.js +5 -5
  11. package/dist/next/export/next/index.js +4 -3
  12. package/dist/next/src/adapters/next/{proxy/intor-proxy.js → create-intor-handler.js} +13 -12
  13. package/dist/next/src/adapters/next/{navigation/link.js → link.js} +6 -6
  14. package/dist/next/src/adapters/next/{navigation/redirect.js → redirect.js} +4 -4
  15. package/dist/next/src/adapters/next/server/get-translator.js +0 -4
  16. package/dist/next/src/adapters/next/{navigation/use-router.js → use-router.js} +10 -10
  17. package/dist/next/src/client/shared/navigation/execute-navigation.js +6 -6
  18. package/dist/next/src/core/utils/resolve-loader-options.js +7 -3
  19. package/dist/next/src/policies/shoud-full-reload.js +1 -1
  20. package/dist/next/src/routing/inbound/resolve-inbound.js +4 -5
  21. package/dist/next/src/routing/inbound/resolve-locale/resolve-locale.js +6 -5
  22. package/dist/next/src/routing/locale/get-locale-from-query.js +1 -9
  23. package/dist/next/src/routing/{navigation → outbound}/decide-strategy.js +2 -5
  24. package/dist/{svelte-kit/src/routing/navigation/derive-target.js → next/src/routing/outbound/determine-target.js} +3 -6
  25. package/dist/next/src/routing/outbound/resolve-outbound.js +23 -0
  26. package/dist/next/src/server/messages/load-messages.js +5 -5
  27. package/dist/react/src/client/react/helpers/use-intor.js +3 -8
  28. package/dist/react/src/client/react/provider/intor-provider.js +2 -2
  29. package/dist/react/src/client/shared/messages/create-refetch-messages.js +1 -1
  30. package/dist/react/src/core/utils/resolve-loader-options.js +4 -2
  31. package/dist/svelte/src/client/shared/messages/create-refetch-messages.js +1 -1
  32. package/dist/svelte/src/core/utils/resolve-loader-options.js +4 -2
  33. package/dist/svelte-kit/export/svelte-kit/index.js +1 -1
  34. package/dist/svelte-kit/export/svelte-kit/server/index.js +1 -1
  35. package/dist/svelte-kit/src/adapters/svelte-kit/server/{create-intor-handle.js → create-intor-handler.js} +10 -9
  36. package/dist/svelte-kit/src/adapters/svelte-kit/{navigation/use-navigation.js → use-navigation.js} +6 -6
  37. package/dist/svelte-kit/src/client/shared/navigation/execute-navigation.js +6 -6
  38. package/dist/svelte-kit/src/core/utils/resolve-loader-options.js +7 -3
  39. package/dist/svelte-kit/src/policies/shoud-full-reload.js +1 -1
  40. package/dist/svelte-kit/src/routing/inbound/resolve-inbound.js +3 -4
  41. package/dist/svelte-kit/src/routing/inbound/resolve-locale/resolve-locale.js +6 -5
  42. package/dist/svelte-kit/src/routing/locale/get-locale-from-query.js +1 -9
  43. package/dist/svelte-kit/src/routing/{navigation → outbound}/decide-strategy.js +2 -5
  44. package/dist/{next/src/routing/navigation/derive-target.js → svelte-kit/src/routing/outbound/determine-target.js} +3 -6
  45. package/dist/svelte-kit/src/routing/outbound/resolve-outbound.js +23 -0
  46. package/dist/svelte-kit/src/server/messages/load-messages.js +5 -5
  47. package/dist/types/export/express/index.d.ts +1 -1
  48. package/dist/types/export/index.d.ts +1 -1
  49. package/dist/types/export/next/index.d.ts +1 -1
  50. package/dist/types/export/svelte-kit/index.d.ts +1 -1
  51. package/dist/types/export/svelte-kit/server/index.d.ts +1 -1
  52. package/dist/types/src/adapters/express/{middleware/create-intor-middleware.d.ts → create-intor-handler.d.ts} +3 -3
  53. package/dist/types/src/adapters/express/{helpers/get-translator.d.ts → get-translator.d.ts} +3 -3
  54. package/dist/types/src/adapters/express/global.d.ts +5 -4
  55. package/dist/types/src/adapters/express/index.d.ts +2 -2
  56. package/dist/types/src/adapters/next/{proxy/intor-proxy.d.ts → create-intor-handler.d.ts} +2 -2
  57. package/dist/types/src/adapters/next/{navigation/index.d.ts → index.d.ts} +1 -0
  58. package/dist/types/src/adapters/next/{navigation/link.d.ts → link.d.ts} +1 -1
  59. package/dist/types/src/adapters/next/{navigation/redirect.d.ts → redirect.d.ts} +2 -2
  60. package/dist/types/src/adapters/next/{navigation/use-router.d.ts → use-router.d.ts} +1 -1
  61. package/dist/types/src/adapters/svelte-kit/server/{create-intor-handle.d.ts → create-intor-handler.d.ts} +1 -1
  62. package/dist/types/src/adapters/svelte-kit/server/index.d.ts +1 -1
  63. package/dist/types/src/adapters/svelte-kit/server/utils/is-svelte-kit-ssg.d.ts +1 -1
  64. package/dist/types/src/adapters/svelte-kit/{navigation/use-navigation.d.ts → use-navigation.d.ts} +1 -1
  65. package/dist/types/src/client/react/helpers/use-intor.d.ts +2 -2
  66. package/dist/types/src/client/react/provider/intor-provider.d.ts +1 -1
  67. package/dist/types/src/client/shared/messages/create-refetch-messages.d.ts +2 -2
  68. package/dist/types/src/client/shared/navigation/execute-navigation.d.ts +9 -8
  69. package/dist/types/src/client/shared/utils/locale/set-document-locale.d.ts +2 -1
  70. package/dist/types/src/client/shared/utils/locale/set-locale-cookie.d.ts +2 -1
  71. package/dist/types/src/client/vue/helpers/use-intor.d.ts +1 -1
  72. package/dist/types/src/config/types/intor-config.d.ts +2 -2
  73. package/dist/types/src/config/types/loader.d.ts +3 -3
  74. package/dist/types/src/config/validators/validate-default-locale.d.ts +2 -1
  75. package/dist/types/src/core/index.d.ts +1 -1
  76. package/dist/types/src/core/messages/load-remote-messages/collect-remote-resources.d.ts +2 -1
  77. package/dist/types/src/core/messages/load-remote-messages/types.d.ts +3 -2
  78. package/dist/types/src/core/utils/index.d.ts +1 -1
  79. package/dist/types/src/core/utils/normalizers/index.d.ts +1 -1
  80. package/dist/types/src/core/utils/normalizers/normalize-locale.d.ts +2 -1
  81. package/dist/types/src/core/utils/normalizers/normalize-query.d.ts +2 -1
  82. package/dist/types/src/policies/should-sync-locale.d.ts +2 -1
  83. package/dist/types/src/routing/inbound/index.d.ts +1 -1
  84. package/dist/types/src/routing/inbound/resolve-inbound.d.ts +12 -7
  85. package/dist/types/src/routing/inbound/resolve-locale/resolve-locale.d.ts +3 -3
  86. package/dist/types/src/routing/inbound/resolve-locale/types.d.ts +7 -6
  87. package/dist/types/src/routing/inbound/resolve-pathname/types.d.ts +2 -1
  88. package/dist/types/src/routing/inbound/types.d.ts +4 -3
  89. package/dist/types/src/routing/index.d.ts +2 -2
  90. package/dist/types/src/routing/locale/get-locale-from-query.d.ts +2 -5
  91. package/dist/types/src/routing/outbound/decide-strategy.d.ts +7 -0
  92. package/dist/types/src/routing/outbound/determine-target.d.ts +14 -0
  93. package/dist/types/src/routing/outbound/index.d.ts +1 -0
  94. package/dist/types/src/routing/outbound/resolve-outbound.d.ts +14 -0
  95. package/dist/types/src/server/helpers/get-translator.d.ts +2 -2
  96. package/dist/types/src/server/messages/load-local-messages/read-locale-messages/types.d.ts +2 -1
  97. package/dist/types/src/server/messages/load-local-messages/types.d.ts +2 -1
  98. package/dist/types/src/server/translator/create-translator.d.ts +2 -2
  99. package/dist/vue/src/client/shared/messages/create-refetch-messages.js +1 -1
  100. package/dist/vue/src/client/vue/helpers/use-intor.js +2 -10
  101. package/dist/vue/src/client/vue/provider/intor-provider.js +0 -1
  102. package/dist/vue/src/core/utils/resolve-loader-options.js +4 -2
  103. package/package.json +1 -5
  104. package/dist/next/export/next/proxy/index.js +0 -1
  105. package/dist/next/src/routing/navigation/resolve-navigation.js +0 -26
  106. package/dist/svelte-kit/src/routing/navigation/resolve-navigation.js +0 -26
  107. package/dist/types/export/next/proxy/index.d.ts +0 -1
  108. package/dist/types/src/adapters/express/helpers/index.d.ts +0 -1
  109. package/dist/types/src/adapters/express/middleware/index.d.ts +0 -1
  110. package/dist/types/src/adapters/next/proxy/index.d.ts +0 -1
  111. package/dist/types/src/routing/navigation/decide-strategy.d.ts +0 -17
  112. package/dist/types/src/routing/navigation/derive-target.d.ts +0 -17
  113. package/dist/types/src/routing/navigation/index.d.ts +0 -1
  114. package/dist/types/src/routing/navigation/resolve-navigation.d.ts +0 -25
  115. /package/dist/next/src/routing/{navigation → outbound}/utils/derive-host-destination.js +0 -0
  116. /package/dist/next/src/routing/{navigation → outbound}/utils/derive-query-destination.js +0 -0
  117. /package/dist/next/src/routing/{navigation → outbound}/utils/is-external-destination.js +0 -0
  118. /package/dist/svelte-kit/src/routing/{navigation → outbound}/utils/derive-host-destination.js +0 -0
  119. /package/dist/svelte-kit/src/routing/{navigation → outbound}/utils/derive-query-destination.js +0 -0
  120. /package/dist/svelte-kit/src/routing/{navigation → outbound}/utils/is-external-destination.js +0 -0
  121. /package/dist/types/src/adapters/svelte-kit/{navigation/index.d.ts → index.d.ts} +0 -0
  122. /package/dist/types/src/routing/{navigation → outbound}/utils/derive-host-destination.d.ts +0 -0
  123. /package/dist/types/src/routing/{navigation → outbound}/utils/derive-query-destination.d.ts +0 -0
  124. /package/dist/types/src/routing/{navigation → outbound}/utils/is-external-destination.d.ts +0 -0
@@ -18,16 +18,20 @@
18
18
  * for the given runtime.
19
19
  */
20
20
  const resolveLoaderOptions = (config, runtime) => {
21
- // --- runtime: client ---
21
+ // ------------------------------------------------
22
+ // runtime: client
23
+ // ------------------------------------------------
22
24
  if (runtime === "client") {
23
25
  const client = config.client?.loader;
24
26
  if (client) {
25
27
  // Client loader is always remote by design
26
- return { type: "remote", ...client };
28
+ return { mode: "remote", ...client };
27
29
  }
28
30
  return config.server?.loader ?? config.loader;
29
31
  }
30
- // --- runtime: server ---
32
+ // ------------------------------------------------
33
+ // runtime: server
34
+ // ------------------------------------------------
31
35
  return config.server?.loader ?? config.loader;
32
36
  };
33
37
 
@@ -29,12 +29,12 @@ const loadMessages = async ({ config, locale, readers, allowCacheWrite = false,
29
29
  logger.warn("No loader options have been configured in the current config.");
30
30
  return;
31
31
  }
32
- const { type, namespaces, concurrency } = loader;
32
+ const { mode, namespaces, concurrency } = loader;
33
33
  const fallbackLocales = config.fallbackLocales[locale] || [];
34
34
  logger.info(`Loading messages for locale "${locale}".`);
35
35
  logger.trace("Starting to load messages with runtime context.", {
36
- loaderType: type,
37
- ...(type === "local" ? { rootDir: loader.rootDir } : {}),
36
+ loaderMode: mode,
37
+ ...(mode === "local" ? { rootDir: loader.rootDir } : {}),
38
38
  locale,
39
39
  fallbackLocales: fallbackLocales.join(", "),
40
40
  namespaces: namespaces && namespaces.length > 0 ? [...namespaces] : "*",
@@ -43,7 +43,7 @@ const loadMessages = async ({ config, locale, readers, allowCacheWrite = false,
43
43
  // Dispatch to loader implementation
44
44
  // ---------------------------------------------------------------------------
45
45
  let loadedMessages;
46
- if (type === "local") {
46
+ if (mode === "local") {
47
47
  loadedMessages = await loadLocalMessages({
48
48
  id: config.id,
49
49
  locale,
@@ -56,7 +56,7 @@ const loadMessages = async ({ config, locale, readers, allowCacheWrite = false,
56
56
  loggerOptions: config.logger,
57
57
  });
58
58
  }
59
- else if (type === "remote") {
59
+ else if (mode === "remote") {
60
60
  loadedMessages = await loadRemoteMessages({
61
61
  locale,
62
62
  fallbackLocales,
@@ -1,2 +1,2 @@
1
- export { createIntorMiddleware } from '../../src/adapters/express/middleware/create-intor-middleware.js';
2
- export { getTranslator } from '../../src/adapters/express/helpers/get-translator.js';
1
+ export { createIntorHandler } from '../../src/adapters/express/create-intor-handler.js';
2
+ export { getTranslator } from '../../src/adapters/express/get-translator.js';
@@ -1,14 +1,14 @@
1
- import '../../../core/error/intor-error.js';
2
- import { normalizeQuery } from '../../../core/utils/normalizers/normalize-query.js';
1
+ import '../../core/error/intor-error.js';
2
+ import { normalizeQuery } from '../../core/utils/normalizers/normalize-query.js';
3
3
  import 'logry';
4
4
  import 'p-limit';
5
5
  import 'intor-translator';
6
- import { resolveInbound } from '../../../routing/inbound/resolve-inbound.js';
7
- import { getLocaleFromAcceptLanguage } from '../../../routing/locale/get-locale-from-accept-language.js';
6
+ import { resolveInbound } from '../../routing/inbound/resolve-inbound.js';
7
+ import { getLocaleFromAcceptLanguage } from '../../routing/locale/get-locale-from-accept-language.js';
8
8
  import 'node:path';
9
9
  import 'node:fs/promises';
10
- import { getTranslator } from '../../../server/helpers/get-translator.js';
11
- import { parseCookieHeader } from '../../../server/shared/utils/parse-cookie-header.js';
10
+ import { getTranslator } from '../../server/helpers/get-translator.js';
11
+ import { parseCookieHeader } from '../../server/shared/utils/parse-cookie-header.js';
12
12
 
13
13
  /**
14
14
  * Resolves locale-aware routing for the current execution context.
@@ -20,15 +20,15 @@ import { parseCookieHeader } from '../../../server/shared/utils/parse-cookie-hea
20
20
  *
21
21
  * @platform Express
22
22
  */
23
- function createIntorMiddleware(config, options) {
24
- return async function intorMiddleware(req, _res, next) {
23
+ function createIntorHandler(config, options) {
24
+ return async function intorHandler(req, _res, next) {
25
25
  // Locale from Accept-Language header
26
26
  const acceptLanguage = req.headers["accept-language"];
27
27
  const localeFromAcceptLanguage = getLocaleFromAcceptLanguage(acceptLanguage, config.supportedLocales);
28
28
  // ----------------------------------------------------------
29
29
  // Resolve inbound routing decision (pure computation)
30
30
  // ----------------------------------------------------------
31
- const { locale, localeSource, pathname } = await resolveInbound(config, req.path, false, {
31
+ const { locale, localeSource, pathname } = await resolveInbound(config, req.path, {
32
32
  host: req.hostname,
33
33
  query: normalizeQuery(req.query),
34
34
  cookie: parseCookieHeader(req.headers.cookie)[config.cookie.name],
@@ -38,19 +38,20 @@ function createIntorMiddleware(config, options) {
38
38
  // Bind inbound routing context
39
39
  // --------------------------------------------------
40
40
  req.intor = { locale, localeSource, pathname };
41
- const { hasKey, t } = (await getTranslator(config, {
41
+ const { hasKey, t, tRich } = await getTranslator(config, {
42
42
  locale,
43
43
  handlers: options?.handlers,
44
44
  plugins: options?.plugins,
45
45
  readers: options?.readers,
46
46
  allowCacheWrite: true,
47
- }));
47
+ });
48
48
  // DX shortcuts (optional)
49
49
  req.locale = locale;
50
50
  req.hasKey = hasKey;
51
51
  req.t = t;
52
+ req.tRich = tRich;
52
53
  return next();
53
54
  };
54
55
  }
55
56
 
56
- export { createIntorMiddleware };
57
+ export { createIntorHandler };
@@ -1,10 +1,10 @@
1
- import '../../../core/error/intor-error.js';
1
+ import '../../core/error/intor-error.js';
2
2
  import 'logry';
3
3
  import 'p-limit';
4
4
  import 'intor-translator';
5
5
  import 'node:path';
6
6
  import 'node:fs/promises';
7
- import { getTranslator as getTranslator$1 } from '../../../server/helpers/get-translator.js';
7
+ import { getTranslator as getTranslator$1 } from '../../server/helpers/get-translator.js';
8
8
 
9
9
  // Implementation
10
10
  async function getTranslator(config, req, params) {
@@ -16,10 +16,6 @@ async function getTranslator(config, req, params) {
16
16
  plugins,
17
17
  readers,
18
18
  allowCacheWrite,
19
- // NOTE:
20
- // The runtime implementation is intentionally erased.
21
- // Type safety is guaranteed by public type contracts.
22
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
23
19
  });
24
20
  }
25
21
 
@@ -18,7 +18,9 @@
18
18
  * for the given runtime.
19
19
  */
20
20
  const resolveLoaderOptions = (config, runtime) => {
21
- // --- runtime: server ---
21
+ // ------------------------------------------------
22
+ // runtime: server
23
+ // ------------------------------------------------
22
24
  return config.server?.loader ?? config.loader;
23
25
  };
24
26
 
@@ -13,7 +13,8 @@ import { resolvePathname } from './resolve-pathname/resolve-pathname.js';
13
13
  *
14
14
  * No side effects. No navigation.
15
15
  */
16
- async function resolveInbound(config, rawPathname, hasRedirected, localeInputs) {
16
+ async function resolveInbound(config, rawPathname, localeInputs, options) {
17
+ const { queryKey } = config.routing.inbound;
17
18
  const { host, query, cookie, detected } = localeInputs;
18
19
  // ------------------------------------------------------
19
20
  // Resolve locale from inbound inputs
@@ -22,9 +23,7 @@ async function resolveInbound(config, rawPathname, hasRedirected, localeInputs)
22
23
  const { locale, localeSource } = resolveLocale(config, {
23
24
  path: { locale: pathLocale },
24
25
  host: { locale: getLocaleFromHost(host) },
25
- query: {
26
- locale: getLocaleFromQuery(query, config.routing.inbound.queryKey),
27
- },
26
+ query: { locale: getLocaleFromQuery(query, queryKey) },
28
27
  cookie: { locale: cookie },
29
28
  detected: { locale: detected },
30
29
  });
@@ -7,9 +7,9 @@ import 'intor-translator';
7
7
  /**
8
8
  * Resolve the active locale from inbound routing configuration.
9
9
  *
10
- * Iterates through configured locale sources and returns the first
11
- * normalized, supported locale. Falls back to the detected locale
12
- * or the default locale if none match.
10
+ * Iterates through configured locale sources and returns the first normalized, supported locale.
11
+ *
12
+ * Falls back to the detected locale or the default locale if none match.
13
13
  */
14
14
  function resolveLocale(config, context) {
15
15
  const { localeSources } = config.routing.inbound;
@@ -24,9 +24,10 @@ function resolveLocale(config, context) {
24
24
  };
25
25
  }
26
26
  // Fallback: detected is always available
27
+ const fallback = normalizeLocale(context.detected.locale, config.supportedLocales) ||
28
+ config.defaultLocale;
27
29
  return {
28
- locale: normalizeLocale(context.detected.locale, config.supportedLocales) ||
29
- config.defaultLocale,
30
+ locale: fallback,
30
31
  localeSource: "detected",
31
32
  };
32
33
  }
@@ -11,19 +11,11 @@
11
11
  *
12
12
  * getLocaleFromQuery({}, "locale")
13
13
  * // => undefined
14
- *
15
- * getLocaleFromQuery({ locale: ["zh-TW"] }, "locale")
16
- * // => "zh-TW"
17
- * ```
18
14
  */
19
15
  function getLocaleFromQuery(query, queryKey) {
20
16
  if (!query)
21
17
  return;
22
- const raw = query[queryKey];
23
- if (!raw)
24
- return;
25
- const value = Array.isArray(raw) ? raw[0] : raw;
26
- return value;
18
+ return query[queryKey];
27
19
  }
28
20
 
29
21
  export { getLocaleFromQuery };
@@ -29,12 +29,12 @@ const loadMessages = async ({ config, locale, readers, allowCacheWrite = false,
29
29
  logger.warn("No loader options have been configured in the current config.");
30
30
  return;
31
31
  }
32
- const { type, namespaces, concurrency } = loader;
32
+ const { mode, namespaces, concurrency } = loader;
33
33
  const fallbackLocales = config.fallbackLocales[locale] || [];
34
34
  logger.info(`Loading messages for locale "${locale}".`);
35
35
  logger.trace("Starting to load messages with runtime context.", {
36
- loaderType: type,
37
- ...(type === "local" ? { rootDir: loader.rootDir } : {}),
36
+ loaderMode: mode,
37
+ ...(mode === "local" ? { rootDir: loader.rootDir } : {}),
38
38
  locale,
39
39
  fallbackLocales: fallbackLocales.join(", "),
40
40
  namespaces: namespaces && namespaces.length > 0 ? [...namespaces] : "*",
@@ -43,7 +43,7 @@ const loadMessages = async ({ config, locale, readers, allowCacheWrite = false,
43
43
  // Dispatch to loader implementation
44
44
  // ---------------------------------------------------------------------------
45
45
  let loadedMessages;
46
- if (type === "local") {
46
+ if (mode === "local") {
47
47
  loadedMessages = await loadLocalMessages({
48
48
  id: config.id,
49
49
  locale,
@@ -56,7 +56,7 @@ const loadMessages = async ({ config, locale, readers, allowCacheWrite = false,
56
56
  loggerOptions: config.logger,
57
57
  });
58
58
  }
59
- else if (type === "remote") {
59
+ else if (mode === "remote") {
60
60
  loadedMessages = await loadRemoteMessages({
61
61
  locale,
62
62
  fallbackLocales,
@@ -1,3 +1,4 @@
1
- export { Link } from '../../src/adapters/next/navigation/link.js';
2
- export { useRouter } from '../../src/adapters/next/navigation/use-router.js';
3
- export { redirect } from '../../src/adapters/next/navigation/redirect.js';
1
+ export { Link } from '../../src/adapters/next/link.js';
2
+ export { useRouter } from '../../src/adapters/next/use-router.js';
3
+ export { redirect } from '../../src/adapters/next/redirect.js';
4
+ export { createIntorHandler } from '../../src/adapters/next/create-intor-handler.js';
@@ -1,12 +1,12 @@
1
1
  import { NextResponse } from 'next/server';
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';
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
5
  import 'logry';
6
6
  import 'p-limit';
7
7
  import 'intor-translator';
8
- import { resolveInbound } from '../../../routing/inbound/resolve-inbound.js';
9
- import { getLocaleFromAcceptLanguage } from '../../../routing/locale/get-locale-from-accept-language.js';
8
+ import { resolveInbound } from '../../routing/inbound/resolve-inbound.js';
9
+ import { getLocaleFromAcceptLanguage } from '../../routing/locale/get-locale-from-accept-language.js';
10
10
 
11
11
  /**
12
12
  * Resolves locale-aware routing for the current execution context.
@@ -17,21 +17,22 @@ import { getLocaleFromAcceptLanguage } from '../../../routing/locale/get-locale-
17
17
  *
18
18
  * @platform Next.js
19
19
  */
20
- const intorProxy = async (config, request) => {
20
+ const createIntorHandler = async (config, request) => {
21
+ const { host, searchParams, pathname: rawPathname } = request.nextUrl;
21
22
  // Locale from Accept-Language header
22
23
  const acceptLanguageHeader = request.headers.get("accept-language");
23
24
  const localeFromAcceptLanguage = getLocaleFromAcceptLanguage(acceptLanguageHeader, config.supportedLocales);
24
25
  // Check whether this navigation flow has already redirected
25
- const hasRedirectedForLocale = request.headers.get("x-intor-redirected") === "1";
26
+ const hasRedirected = request.headers.get(INTOR_HEADERS.REDIRECTED) === "1";
26
27
  // ----------------------------------------------------------
27
28
  // Resolve inbound routing decision (pure computation)
28
29
  // ----------------------------------------------------------
29
- const { locale, localeSource, pathname, shouldRedirect } = await resolveInbound(config, request.nextUrl.pathname, hasRedirectedForLocale, {
30
- host: request.nextUrl.host,
31
- query: normalizeQuery(Object.fromEntries(request.nextUrl.searchParams.entries())),
30
+ const { locale, localeSource, pathname, shouldRedirect } = await resolveInbound(config, rawPathname, {
31
+ host,
32
+ query: normalizeQuery(Object.fromEntries(searchParams.entries())),
32
33
  cookie: request.cookies.get(config.cookie.name)?.value,
33
34
  detected: localeFromAcceptLanguage || config.defaultLocale,
34
- });
35
+ }, { hasRedirected });
35
36
  // ----------------------------------------------------------
36
37
  // Prepare Next.js response (redirect or pass-through)
37
38
  // ----------------------------------------------------------
@@ -52,4 +53,4 @@ const intorProxy = async (config, request) => {
52
53
  return response;
53
54
  };
54
55
 
55
- export { intorProxy };
56
+ export { createIntorHandler };
@@ -4,13 +4,13 @@ import { formatUrl } from 'next/dist/shared/lib/router/utils/format-url';
4
4
  import NextLink from 'next/link';
5
5
  import { usePathname } from 'next/navigation';
6
6
  import 'react';
7
- import { executeNavigation } from '../../../client/shared/navigation/execute-navigation.js';
7
+ import { executeNavigation } from '../../client/shared/navigation/execute-navigation.js';
8
8
  import { useIntorContext } from 'intor/react';
9
- import '../../../core/error/intor-error.js';
9
+ import '../../core/error/intor-error.js';
10
10
  import 'logry';
11
11
  import 'p-limit';
12
12
  import 'intor-translator';
13
- import { resolveNavigation } from '../../../routing/navigation/resolve-navigation.js';
13
+ import { resolveOutbound } from '../../routing/outbound/resolve-outbound.js';
14
14
 
15
15
  /**
16
16
  * Render a locale-aware link for the current execution context.
@@ -26,7 +26,7 @@ const Link = ({ href, locale, children, onClick, ...props }) => {
26
26
  // Normalize href into a string destination
27
27
  const rawDestination = typeof href === "string" ? href : href ? formatUrl(href) : undefined;
28
28
  // Resolve navigation result for this link
29
- const navigationResult = resolveNavigation(config, currentLocale, currentPathname, { destination: rawDestination, locale });
29
+ const outboundResult = resolveOutbound(config, currentLocale, currentPathname, { destination: rawDestination, locale });
30
30
  // --------------------------------------------------
31
31
  // Execute navigation on user interaction
32
32
  // --------------------------------------------------
@@ -34,9 +34,9 @@ const Link = ({ href, locale, children, onClick, ...props }) => {
34
34
  onClick?.(e);
35
35
  if (e.defaultPrevented)
36
36
  return;
37
- executeNavigation(navigationResult, { config, currentLocale, setLocale }, e);
37
+ executeNavigation(outboundResult, { config, currentLocale, setLocale }, e);
38
38
  };
39
- return (jsx(NextLink, { href: navigationResult.destination, onClick: handleClick, ...props, children: children }));
39
+ return (jsx(NextLink, { href: outboundResult.destination, onClick: handleClick, ...props, children: children }));
40
40
  };
41
41
 
42
42
  export { Link };
@@ -1,10 +1,10 @@
1
1
  import { redirect as redirect$1 } from 'next/navigation';
2
- import '../../../core/error/intor-error.js';
2
+ import '../../core/error/intor-error.js';
3
3
  import 'logry';
4
4
  import 'p-limit';
5
5
  import 'intor-translator';
6
- import { resolveNavigation } from '../../../routing/navigation/resolve-navigation.js';
7
- import { getLocale } from '../server/get-locale.js';
6
+ import { resolveOutbound } from '../../routing/outbound/resolve-outbound.js';
7
+ import { getLocale } from './server/get-locale.js';
8
8
 
9
9
  /**
10
10
  * Redirect to a locale-aware destination for the current execution context.
@@ -16,7 +16,7 @@ import { getLocale } from '../server/get-locale.js';
16
16
  */
17
17
  const redirect = async (config, url, { locale, type }) => {
18
18
  const currentLocale = await getLocale(config);
19
- const { destination, kind } = resolveNavigation(config, currentLocale, url, {
19
+ const { destination, kind } = resolveOutbound(config, currentLocale, url, {
20
20
  locale,
21
21
  });
22
22
  if (kind === "external") {
@@ -17,10 +17,6 @@ async function getTranslator(config, params) {
17
17
  plugins,
18
18
  readers,
19
19
  allowCacheWrite,
20
- // NOTE:
21
- // The runtime implementation is intentionally erased.
22
- // Type safety is guaranteed by public type contracts.
23
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
24
20
  });
25
21
  }
26
22
 
@@ -1,11 +1,11 @@
1
1
  import { usePathname, useRouter as useRouter$1 } from 'next/navigation';
2
- import { executeNavigation } from '../../../client/shared/navigation/execute-navigation.js';
2
+ import { executeNavigation } from '../../client/shared/navigation/execute-navigation.js';
3
3
  import { useIntorContext } from 'intor/react';
4
- import '../../../core/error/intor-error.js';
4
+ import '../../core/error/intor-error.js';
5
5
  import 'logry';
6
6
  import 'p-limit';
7
7
  import 'intor-translator';
8
- import { resolveNavigation } from '../../../routing/navigation/resolve-navigation.js';
8
+ import { resolveOutbound } from '../../routing/outbound/resolve-outbound.js';
9
9
 
10
10
  /**
11
11
  * Locale-aware router hook for the current execution context.
@@ -23,23 +23,23 @@ const useRouter = () => {
23
23
  // push
24
24
  // --------------------------------------------------
25
25
  const push = (href, options) => {
26
- const navigationResult = resolveNavigation(config, currentLocale, currentPathname, { destination: href, locale: options?.locale });
27
- executeNavigation(navigationResult, { config, currentLocale, setLocale });
28
- nextRouterPush(navigationResult.destination, options);
26
+ const outboundResult = resolveOutbound(config, currentLocale, currentPathname, { destination: href, locale: options?.locale });
27
+ executeNavigation(outboundResult, { config, currentLocale, setLocale });
28
+ nextRouterPush(outboundResult.destination, options);
29
29
  };
30
30
  // --------------------------------------------------
31
31
  // replace
32
32
  // --------------------------------------------------
33
33
  const replace = (href, options) => {
34
- const navigationResult = resolveNavigation(config, currentLocale, currentPathname, { destination: href, locale: options?.locale });
35
- executeNavigation(navigationResult, { config, currentLocale, setLocale });
36
- nextRouterReplace(navigationResult.destination, options);
34
+ const outboundResult = resolveOutbound(config, currentLocale, currentPathname, { destination: href, locale: options?.locale });
35
+ executeNavigation(outboundResult, { config, currentLocale, setLocale });
36
+ nextRouterReplace(outboundResult.destination, options);
37
37
  };
38
38
  // --------------------------------------------------
39
39
  // prefetch
40
40
  // --------------------------------------------------
41
41
  const prefetch = (href, options) => {
42
- const { kind, destination } = resolveNavigation(config, currentLocale, currentPathname, { destination: href, locale: options?.locale });
42
+ const { kind, destination } = resolveOutbound(config, currentLocale, currentPathname, { destination: href, locale: options?.locale });
43
43
  if (kind !== "client")
44
44
  return; // Prefetch only makes sense for client-side navigation
45
45
  nextRouterPrefetch(destination, options);
@@ -6,17 +6,17 @@ import { shouldSyncLocale } from '../../../policies/should-sync-locale.js';
6
6
  import { setLocaleCookie } from '../utils/locale/set-locale-cookie.js';
7
7
 
8
8
  /**
9
- * Executes a resolved navigation result.
9
+ * Executes a resolved outbound routing result.
10
10
  *
11
- * Applies all imperative side effects required to complete navigation,
12
- * including locale synchronization, cookie persistence, and full reloads.
11
+ * Applies all imperative side effects required to realize the outbound decision,
12
+ * including locale synchronization, cookie persistence, and full page reloads.
13
13
  *
14
- * This function must be called after `resolveNavigation`.
14
+ * This function must be called after `resolveOutbound`.
15
15
  */
16
- function executeNavigation(navigationResult, context, e) {
16
+ function executeNavigation(outboundResult, context, e) {
17
17
  const { config, currentLocale, setLocale } = context;
18
18
  const { cookie } = config;
19
- const { destination, kind, locale } = navigationResult;
19
+ const { destination, kind, locale } = outboundResult;
20
20
  // ------------------------------------------------------
21
21
  // External navigation: let browser handle it
22
22
  // ------------------------------------------------------
@@ -18,16 +18,20 @@
18
18
  * for the given runtime.
19
19
  */
20
20
  const resolveLoaderOptions = (config, runtime) => {
21
- // --- runtime: client ---
21
+ // ------------------------------------------------
22
+ // runtime: client
23
+ // ------------------------------------------------
22
24
  if (runtime === "client") {
23
25
  const client = config.client?.loader;
24
26
  if (client) {
25
27
  // Client loader is always remote by design
26
- return { type: "remote", ...client };
28
+ return { mode: "remote", ...client };
27
29
  }
28
30
  return config.server?.loader ?? config.loader;
29
31
  }
30
- // --- runtime: server ---
32
+ // ------------------------------------------------
33
+ // runtime: server
34
+ // ------------------------------------------------
31
35
  return config.server?.loader ?? config.loader;
32
36
  };
33
37
 
@@ -9,7 +9,7 @@ import 'intor-translator';
9
9
  */
10
10
  function shouldFullReload(config) {
11
11
  const loader = resolveLoaderOptions(config, "client");
12
- return (loader?.type === "local" || config.routing.outbound.forceFullReload === true);
12
+ return (loader?.mode === "local" || config.routing.outbound.forceFullReload === true);
13
13
  }
14
14
 
15
15
  export { shouldFullReload };
@@ -13,7 +13,8 @@ import { resolvePathname } from './resolve-pathname/resolve-pathname.js';
13
13
  *
14
14
  * No side effects. No navigation.
15
15
  */
16
- async function resolveInbound(config, rawPathname, hasRedirected, localeInputs) {
16
+ async function resolveInbound(config, rawPathname, localeInputs, options) {
17
+ const { queryKey } = config.routing.inbound;
17
18
  const { host, query, cookie, detected } = localeInputs;
18
19
  // ------------------------------------------------------
19
20
  // Resolve locale from inbound inputs
@@ -22,9 +23,7 @@ async function resolveInbound(config, rawPathname, hasRedirected, localeInputs)
22
23
  const { locale, localeSource } = resolveLocale(config, {
23
24
  path: { locale: pathLocale },
24
25
  host: { locale: getLocaleFromHost(host) },
25
- query: {
26
- locale: getLocaleFromQuery(query, config.routing.inbound.queryKey),
27
- },
26
+ query: { locale: getLocaleFromQuery(query, queryKey) },
28
27
  cookie: { locale: cookie },
29
28
  detected: { locale: detected },
30
29
  });
@@ -35,7 +34,7 @@ async function resolveInbound(config, rawPathname, hasRedirected, localeInputs)
35
34
  locale,
36
35
  hasPathLocale: !!pathLocale,
37
36
  hasPersisted: !!cookie,
38
- hasRedirected,
37
+ hasRedirected: !!options?.hasRedirected,
39
38
  });
40
39
  return {
41
40
  locale,
@@ -7,9 +7,9 @@ import 'intor-translator';
7
7
  /**
8
8
  * Resolve the active locale from inbound routing configuration.
9
9
  *
10
- * Iterates through configured locale sources and returns the first
11
- * normalized, supported locale. Falls back to the detected locale
12
- * or the default locale if none match.
10
+ * Iterates through configured locale sources and returns the first normalized, supported locale.
11
+ *
12
+ * Falls back to the detected locale or the default locale if none match.
13
13
  */
14
14
  function resolveLocale(config, context) {
15
15
  const { localeSources } = config.routing.inbound;
@@ -24,9 +24,10 @@ function resolveLocale(config, context) {
24
24
  };
25
25
  }
26
26
  // Fallback: detected is always available
27
+ const fallback = normalizeLocale(context.detected.locale, config.supportedLocales) ||
28
+ config.defaultLocale;
27
29
  return {
28
- locale: normalizeLocale(context.detected.locale, config.supportedLocales) ||
29
- config.defaultLocale,
30
+ locale: fallback,
30
31
  localeSource: "detected",
31
32
  };
32
33
  }
@@ -11,19 +11,11 @@
11
11
  *
12
12
  * getLocaleFromQuery({}, "locale")
13
13
  * // => undefined
14
- *
15
- * getLocaleFromQuery({ locale: ["zh-TW"] }, "locale")
16
- * // => "zh-TW"
17
- * ```
18
14
  */
19
15
  function getLocaleFromQuery(query, queryKey) {
20
16
  if (!query)
21
17
  return;
22
- const raw = query[queryKey];
23
- if (!raw)
24
- return;
25
- const value = Array.isArray(raw) ? raw[0] : raw;
26
- return value;
18
+ return query[queryKey];
27
19
  }
28
20
 
29
21
  export { getLocaleFromQuery };
@@ -2,16 +2,13 @@ import { shouldFullReload } from '../../policies/shoud-full-reload.js';
2
2
 
3
3
  /**
4
4
  * Decide how a resolved navigation target should be executed.
5
- *
6
- * This function determines whether navigation should be handled
7
- * by the browser, performed client-side, or forced to reload.
8
5
  */
9
6
  function decideStrategy(config, target) {
10
7
  // External destinations are always handled by the browser
11
8
  if (target.isExternal) {
12
- return { kind: "external" };
9
+ return "external";
13
10
  }
14
- return shouldFullReload(config) ? { kind: "reload" } : { kind: "client" };
11
+ return shouldFullReload(config) ? "reload" : "client";
15
12
  }
16
13
 
17
14
  export { decideStrategy };
@@ -5,12 +5,9 @@ import { deriveQueryDestination } from './utils/derive-query-destination.js';
5
5
  import { isExternalDestination } from './utils/is-external-destination.js';
6
6
 
7
7
  /**
8
- * Derives a navigation target for a single navigation attempt.
9
- *
10
- * This function computes the final destination URL and execution flags
11
- * based on the current routing configuration and locale context.
8
+ * Determines the outbound routing target.
12
9
  */
13
- function deriveTarget(config, currentLocale, currentPathname, intent) {
10
+ function determineTarget(config, currentLocale, currentPathname, intent) {
14
11
  const { supportedLocales, routing } = config;
15
12
  // ----------------------------------------------------------------
16
13
  // Resolve effective locale
@@ -55,4 +52,4 @@ function deriveTarget(config, currentLocale, currentPathname, intent) {
55
52
  };
56
53
  }
57
54
 
58
- export { deriveTarget };
55
+ export { determineTarget };