next-intl 3.14.0 → 3.15.0-custom-prefixes.0

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 (129) hide show
  1. package/dist/development/config.js +1 -1
  2. package/dist/development/middleware/config.js +17 -0
  3. package/dist/development/middleware/getAlternateLinksHeaderValue.js +8 -7
  4. package/dist/development/middleware/middleware.js +56 -61
  5. package/dist/development/middleware/resolveLocale.js +5 -6
  6. package/dist/development/middleware/utils.js +58 -30
  7. package/dist/development/navigation/react-client/ClientLink.js +7 -2
  8. package/dist/development/navigation/react-client/createLocalizedPathnamesNavigation.js +18 -16
  9. package/dist/development/navigation/react-client/createSharedPathnamesNavigation.js +17 -12
  10. package/dist/development/navigation/react-client/redirects.js +32 -0
  11. package/dist/development/navigation/react-client/useBasePathname.js +12 -4
  12. package/dist/development/navigation/react-client/useBaseRouter.js +8 -3
  13. package/dist/development/navigation/react-server/ServerLink.js +7 -1
  14. package/dist/development/navigation/react-server/createLocalizedPathnamesNavigation.js +15 -19
  15. package/dist/development/navigation/react-server/createSharedPathnamesNavigation.js +11 -10
  16. package/dist/development/navigation/react-server/redirects.js +24 -0
  17. package/dist/development/navigation/shared/BaseLink.js +6 -5
  18. package/dist/development/navigation/shared/config.js +30 -0
  19. package/dist/development/navigation/shared/redirects.js +22 -0
  20. package/dist/development/navigation/shared/utils.js +2 -4
  21. package/dist/development/routing/config.js +18 -0
  22. package/dist/development/routing.js +2 -0
  23. package/dist/development/server/react-server/RequestLocale.js +1 -1
  24. package/dist/development/shared/utils.js +26 -14
  25. package/dist/esm/config.js +1 -1
  26. package/dist/esm/middleware/config.js +1 -0
  27. package/dist/esm/middleware/getAlternateLinksHeaderValue.js +1 -1
  28. package/dist/esm/middleware/middleware.js +1 -1
  29. package/dist/esm/middleware/resolveLocale.js +1 -1
  30. package/dist/esm/middleware/utils.js +1 -1
  31. package/dist/esm/navigation/react-client/ClientLink.js +1 -1
  32. package/dist/esm/navigation/react-client/createLocalizedPathnamesNavigation.js +1 -1
  33. package/dist/esm/navigation/react-client/createSharedPathnamesNavigation.js +1 -1
  34. package/dist/esm/navigation/react-client/redirects.js +1 -0
  35. package/dist/esm/navigation/react-client/useBasePathname.js +1 -1
  36. package/dist/esm/navigation/react-client/useBaseRouter.js +1 -1
  37. package/dist/esm/navigation/react-server/ServerLink.js +1 -1
  38. package/dist/esm/navigation/react-server/createLocalizedPathnamesNavigation.js +1 -1
  39. package/dist/esm/navigation/react-server/createSharedPathnamesNavigation.js +1 -1
  40. package/dist/esm/navigation/react-server/redirects.js +1 -0
  41. package/dist/esm/navigation/shared/BaseLink.js +1 -1
  42. package/dist/esm/navigation/shared/config.js +1 -0
  43. package/dist/esm/navigation/shared/redirects.js +1 -0
  44. package/dist/esm/navigation/shared/utils.js +1 -1
  45. package/dist/esm/routing/config.js +1 -0
  46. package/dist/esm/routing.js +1 -0
  47. package/dist/esm/server/react-server/RequestLocale.js +1 -1
  48. package/dist/esm/shared/utils.js +1 -1
  49. package/dist/production/config.js +1 -1
  50. package/dist/production/middleware/config.js +1 -0
  51. package/dist/production/middleware/getAlternateLinksHeaderValue.js +1 -1
  52. package/dist/production/middleware/middleware.js +1 -1
  53. package/dist/production/middleware/resolveLocale.js +1 -1
  54. package/dist/production/middleware/utils.js +1 -1
  55. package/dist/production/navigation/react-client/ClientLink.js +1 -1
  56. package/dist/production/navigation/react-client/createLocalizedPathnamesNavigation.js +1 -1
  57. package/dist/production/navigation/react-client/createSharedPathnamesNavigation.js +1 -1
  58. package/dist/production/navigation/react-client/redirects.js +1 -0
  59. package/dist/production/navigation/react-client/useBasePathname.js +1 -1
  60. package/dist/production/navigation/react-client/useBaseRouter.js +1 -1
  61. package/dist/production/navigation/react-server/ServerLink.js +1 -1
  62. package/dist/production/navigation/react-server/createLocalizedPathnamesNavigation.js +1 -1
  63. package/dist/production/navigation/react-server/createSharedPathnamesNavigation.js +1 -1
  64. package/dist/production/navigation/react-server/redirects.js +1 -0
  65. package/dist/production/navigation/shared/BaseLink.js +1 -1
  66. package/dist/production/navigation/shared/config.js +1 -0
  67. package/dist/production/navigation/shared/redirects.js +1 -0
  68. package/dist/production/navigation/shared/utils.js +1 -1
  69. package/dist/production/routing/config.js +1 -0
  70. package/dist/production/routing.js +1 -0
  71. package/dist/production/server/react-server/RequestLocale.js +1 -1
  72. package/dist/production/shared/utils.js +1 -1
  73. package/dist/routing.js +7 -0
  74. package/dist/types/src/middleware/config.d.ts +18 -0
  75. package/dist/types/src/middleware/getAlternateLinksHeaderValue.d.ts +6 -6
  76. package/dist/types/src/middleware/middleware.d.ts +3 -3
  77. package/dist/types/src/middleware/resolveLocale.d.ts +6 -6
  78. package/dist/types/src/middleware/utils.d.ts +19 -12
  79. package/dist/types/src/navigation/react-client/ClientLink.d.ts +10 -7
  80. package/dist/types/src/navigation/react-client/createLocalizedPathnamesNavigation.d.ts +21 -22
  81. package/dist/types/src/navigation/react-client/createSharedPathnamesNavigation.d.ts +22 -10
  82. package/dist/types/src/navigation/react-client/index.d.ts +3 -1
  83. package/dist/types/src/navigation/react-client/redirects.d.ts +10 -0
  84. package/dist/types/src/navigation/react-client/useBasePathname.d.ts +2 -1
  85. package/dist/types/src/navigation/react-client/useBaseRouter.d.ts +7 -7
  86. package/dist/types/src/navigation/react-server/ServerLink.d.ts +5 -4
  87. package/dist/types/src/navigation/react-server/createLocalizedPathnamesNavigation.d.ts +14 -15
  88. package/dist/types/src/navigation/react-server/createSharedPathnamesNavigation.d.ts +4 -6
  89. package/dist/types/src/navigation/react-server/index.d.ts +1 -1
  90. package/dist/types/src/navigation/react-server/redirects.d.ts +10 -0
  91. package/dist/types/src/navigation/shared/BaseLink.d.ts +3 -2
  92. package/dist/types/src/navigation/shared/config.d.ts +24 -0
  93. package/dist/types/src/navigation/shared/redirects.d.ts +11 -0
  94. package/dist/types/src/navigation/shared/utils.d.ts +10 -10
  95. package/dist/types/src/routing/config.d.ts +14 -0
  96. package/dist/types/src/routing/index.d.ts +2 -0
  97. package/dist/types/src/routing/types.d.ts +23 -0
  98. package/dist/types/src/routing.d.ts +1 -0
  99. package/dist/types/src/shared/types.d.ts +0 -5
  100. package/dist/types/src/shared/utils.d.ts +10 -7
  101. package/dist/types/test/navigation/shared/redirects.test.d.ts +1 -0
  102. package/dist/types/test/routing/types.test.d.ts +1 -0
  103. package/package.json +24 -17
  104. package/routing.d.ts +1 -0
  105. package/dist/development/navigation/react-client/clientPermanentRedirect.js +0 -25
  106. package/dist/development/navigation/react-client/clientRedirect.js +0 -25
  107. package/dist/development/navigation/react-server/serverPermanentRedirect.js +0 -19
  108. package/dist/development/navigation/react-server/serverRedirect.js +0 -19
  109. package/dist/development/navigation/shared/basePermanentRedirect.js +0 -16
  110. package/dist/development/navigation/shared/baseRedirect.js +0 -16
  111. package/dist/esm/navigation/react-client/clientPermanentRedirect.js +0 -1
  112. package/dist/esm/navigation/react-client/clientRedirect.js +0 -1
  113. package/dist/esm/navigation/react-server/serverPermanentRedirect.js +0 -1
  114. package/dist/esm/navigation/react-server/serverRedirect.js +0 -1
  115. package/dist/esm/navigation/shared/basePermanentRedirect.js +0 -1
  116. package/dist/esm/navigation/shared/baseRedirect.js +0 -1
  117. package/dist/production/navigation/react-client/clientPermanentRedirect.js +0 -1
  118. package/dist/production/navigation/react-client/clientRedirect.js +0 -1
  119. package/dist/production/navigation/react-server/serverPermanentRedirect.js +0 -1
  120. package/dist/production/navigation/react-server/serverRedirect.js +0 -1
  121. package/dist/production/navigation/shared/basePermanentRedirect.js +0 -1
  122. package/dist/production/navigation/shared/baseRedirect.js +0 -1
  123. package/dist/types/src/middleware/NextIntlMiddlewareConfig.d.ts +0 -31
  124. package/dist/types/src/navigation/react-client/clientPermanentRedirect.d.ts +0 -6
  125. package/dist/types/src/navigation/react-client/clientRedirect.d.ts +0 -6
  126. package/dist/types/src/navigation/react-server/serverPermanentRedirect.d.ts +0 -6
  127. package/dist/types/src/navigation/react-server/serverRedirect.d.ts +0 -6
  128. package/dist/types/src/navigation/shared/basePermanentRedirect.d.ts +0 -7
  129. package/dist/types/src/navigation/shared/baseRedirect.d.ts +0 -7
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  function getConfig() {
6
- throw new Error("Couldn't find next-intl config file. Please follow the instructions at https://next-intl-docs.vercel.app/docs/getting-started/app-router-server-components");
6
+ throw new Error("Couldn't find next-intl config file. Please follow the instructions at https://next-intl-docs.vercel.app/docs/getting-started/app-router");
7
7
  }
8
8
 
9
9
  exports.default = getConfig;
@@ -0,0 +1,17 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var config = require('../routing/config.js');
6
+
7
+ function receiveConfig(input) {
8
+ var _input$alternateLinks, _input$localeDetectio;
9
+ return {
10
+ ...input,
11
+ alternateLinks: (_input$alternateLinks = input === null || input === void 0 ? void 0 : input.alternateLinks) !== null && _input$alternateLinks !== void 0 ? _input$alternateLinks : true,
12
+ localeDetection: (_input$localeDetectio = input === null || input === void 0 ? void 0 : input.localeDetection) !== null && _input$localeDetectio !== void 0 ? _input$localeDetectio : true,
13
+ localePrefix: config.receiveLocalePrefixConfig(input === null || input === void 0 ? void 0 : input.localePrefix)
14
+ };
15
+ }
16
+
17
+ exports.receiveConfig = receiveConfig;
@@ -22,7 +22,7 @@ function getAlternateLinksHeaderValue(_ref) {
22
22
  normalizedUrl.host = host;
23
23
  }
24
24
  normalizedUrl.protocol = (_request$headers$get = request.headers.get('x-forwarded-proto')) !== null && _request$headers$get !== void 0 ? _request$headers$get : normalizedUrl.protocol;
25
- normalizedUrl.pathname = utils.getNormalizedPathname(normalizedUrl.pathname, config.locales);
25
+ normalizedUrl.pathname = utils.getNormalizedPathname(normalizedUrl.pathname, config.locales, config.localePrefix);
26
26
  function getAlternateEntry(url, locale) {
27
27
  if (request.nextUrl.basePath) {
28
28
  url = new URL(url);
@@ -37,12 +37,13 @@ function getAlternateLinksHeaderValue(_ref) {
37
37
  return pathname;
38
38
  }
39
39
  }
40
- const links = config.locales.flatMap(locale => {
40
+ const links = utils.getLocalePrefixes(config.locales, config.localePrefix).flatMap(_ref2 => {
41
+ let [locale, prefix] = _ref2;
41
42
  function prefixPathname(pathname) {
42
43
  if (pathname === '/') {
43
- return "/".concat(locale);
44
+ return prefix;
44
45
  } else {
45
- return "/".concat(locale).concat(pathname);
46
+ return prefix + pathname;
46
47
  }
47
48
  }
48
49
  let url;
@@ -56,7 +57,7 @@ function getAlternateLinksHeaderValue(_ref) {
56
57
  // Important: Use `normalizedUrl` here, as `url` potentially uses
57
58
  // a `basePath` that automatically gets applied to the pathname
58
59
  url.pathname = getLocalizedPathname(normalizedUrl.pathname, locale);
59
- if (locale !== domainConfig.defaultLocale || config.localePrefix === 'always') {
60
+ if (locale !== domainConfig.defaultLocale || config.localePrefix.mode === 'always') {
60
61
  url.pathname = prefixPathname(url.pathname);
61
62
  }
62
63
  return getAlternateEntry(url, locale);
@@ -68,7 +69,7 @@ function getAlternateLinksHeaderValue(_ref) {
68
69
  } else {
69
70
  pathname = normalizedUrl.pathname;
70
71
  }
71
- if (locale !== config.defaultLocale || config.localePrefix === 'always') {
72
+ if (locale !== config.defaultLocale || config.localePrefix.mode === 'always') {
72
73
  pathname = prefixPathname(pathname);
73
74
  }
74
75
  url = new URL(pathname, normalizedUrl);
@@ -79,7 +80,7 @@ function getAlternateLinksHeaderValue(_ref) {
79
80
  // Add x-default entry
80
81
  const shouldAddXDefault =
81
82
  // For domain-based routing there is no reasonable x-default
82
- !config.domains && (config.localePrefix !== 'always' || normalizedUrl.pathname === '/');
83
+ !config.domains && (config.localePrefix.mode !== 'always' || normalizedUrl.pathname === '/');
83
84
  if (shouldAddXDefault) {
84
85
  const url = new URL(getLocalizedPathname(normalizedUrl.pathname, config.defaultLocale), normalizedUrl);
85
86
  links.push(getAlternateEntry(url, 'x-default'));
@@ -5,35 +5,25 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var server = require('next/server');
6
6
  var constants = require('../shared/constants.js');
7
7
  var utils$1 = require('../shared/utils.js');
8
+ var config = require('./config.js');
8
9
  var getAlternateLinksHeaderValue = require('./getAlternateLinksHeaderValue.js');
9
10
  var resolveLocale = require('./resolveLocale.js');
10
11
  var utils = require('./utils.js');
11
12
 
12
- const ROOT_URL = '/';
13
- function receiveConfig(config) {
14
- var _config$alternateLink, _config$localePrefix, _config$localeDetecti;
15
- const result = {
16
- ...config,
17
- alternateLinks: (_config$alternateLink = config.alternateLinks) !== null && _config$alternateLink !== void 0 ? _config$alternateLink : true,
18
- localePrefix: (_config$localePrefix = config.localePrefix) !== null && _config$localePrefix !== void 0 ? _config$localePrefix : 'always',
19
- localeDetection: (_config$localeDetecti = config.localeDetection) !== null && _config$localeDetecti !== void 0 ? _config$localeDetecti : true
20
- };
21
- return result;
22
- }
23
- function createMiddleware(config) {
24
- const configWithDefaults = receiveConfig(config);
13
+ function createMiddleware(input) {
14
+ const config$1 = config.receiveConfig(input);
25
15
  return function middleware(request) {
26
- var _request$cookies$get, _configWithDefaults$d;
16
+ var _request$cookies$get, _config$domains;
27
17
  // Resolve potential foreign symbols (e.g. /ja/%E7%B4%84 → /ja/約))
28
- const nextPathname = decodeURI(request.nextUrl.pathname);
18
+ const externalPathname = decodeURI(request.nextUrl.pathname);
29
19
  const {
30
20
  domain,
31
21
  locale
32
- } = resolveLocale.default(configWithDefaults, request.headers, request.cookies, nextPathname);
33
- const hasOutdatedCookie = configWithDefaults.localeDetection && ((_request$cookies$get = request.cookies.get(constants.COOKIE_LOCALE_NAME)) === null || _request$cookies$get === void 0 ? void 0 : _request$cookies$get.value) !== locale;
34
- const hasMatchedDefaultLocale = domain ? domain.defaultLocale === locale : locale === configWithDefaults.defaultLocale;
35
- const domainConfigs = ((_configWithDefaults$d = configWithDefaults.domains) === null || _configWithDefaults$d === void 0 ? void 0 : _configWithDefaults$d.filter(curDomain => utils.isLocaleSupportedOnDomain(locale, curDomain))) || [];
36
- const hasUnknownHost = configWithDefaults.domains != null && !domain;
22
+ } = resolveLocale.default(config$1, request.headers, request.cookies, externalPathname);
23
+ const hasOutdatedCookie = config$1.localeDetection && ((_request$cookies$get = request.cookies.get(constants.COOKIE_LOCALE_NAME)) === null || _request$cookies$get === void 0 ? void 0 : _request$cookies$get.value) !== locale;
24
+ const hasMatchedDefaultLocale = domain ? domain.defaultLocale === locale : locale === config$1.defaultLocale;
25
+ const domainConfigs = ((_config$domains = config$1.domains) === null || _config$domains === void 0 ? void 0 : _config$domains.filter(curDomain => utils.isLocaleSupportedOnDomain(locale, curDomain))) || [];
26
+ const hasUnknownHost = config$1.domains != null && !domain;
37
27
  function getResponseInit() {
38
28
  const headers = new Headers(request.headers);
39
29
  headers.set(constants.HEADER_LOCALE_NAME, locale);
@@ -51,14 +41,14 @@ function createMiddleware(config) {
51
41
  return server.NextResponse.rewrite(urlObj, getResponseInit());
52
42
  }
53
43
  function redirect(url, redirectDomain) {
54
- const urlObj = new URL(url, request.url);
44
+ const urlObj = new URL(utils.normalizeTrailingSlash(url), request.url);
55
45
  if (domainConfigs.length > 0) {
56
46
  if (!redirectDomain) {
57
47
  const bestMatchingDomain = utils.getBestMatchingDomain(domain, locale, domainConfigs);
58
48
  if (bestMatchingDomain) {
59
49
  redirectDomain = bestMatchingDomain.domain;
60
- if (bestMatchingDomain.defaultLocale === locale && configWithDefaults.localePrefix === 'as-needed' && urlObj.pathname.startsWith("/".concat(locale))) {
61
- urlObj.pathname = utils.getNormalizedPathname(urlObj.pathname, configWithDefaults.locales);
50
+ if (bestMatchingDomain.defaultLocale === locale && config$1.localePrefix.mode === 'as-needed' && urlObj.pathname.startsWith(utils$1.getLocalePrefix(locale, config$1.localePrefix))) {
51
+ urlObj.pathname = utils.getNormalizedPathname(urlObj.pathname, config$1.locales, config$1.localePrefix);
62
52
  }
63
53
  }
64
54
  }
@@ -76,72 +66,77 @@ function createMiddleware(config) {
76
66
  }
77
67
  return server.NextResponse.redirect(urlObj.toString());
78
68
  }
79
- const normalizedPathname = utils.getNormalizedPathname(nextPathname, configWithDefaults.locales);
80
- const pathLocale = utils.getPathnameLocale(nextPathname, configWithDefaults.locales);
81
- const hasLocalePrefix = pathLocale != null;
69
+ const unprefixedExternalPathname = utils.getNormalizedPathname(externalPathname, config$1.locales, config$1.localePrefix);
70
+ const pathnameMatch = utils.getPathnameMatch(externalPathname, config$1.locales, config$1.localePrefix);
71
+ const hasLocalePrefix = pathnameMatch != null;
72
+ const isUnprefixedRouting = config$1.localePrefix.mode === 'never' || hasMatchedDefaultLocale && config$1.localePrefix.mode === 'as-needed';
82
73
  let response;
83
74
  let internalTemplateName;
84
- let pathname = nextPathname;
85
- if (configWithDefaults.pathnames) {
75
+ let unprefixedInternalPathname = unprefixedExternalPathname;
76
+ if (config$1.pathnames) {
86
77
  let resolvedTemplateLocale;
87
- [resolvedTemplateLocale, internalTemplateName] = utils.getInternalTemplate(configWithDefaults.pathnames, normalizedPathname, locale);
78
+ [resolvedTemplateLocale, internalTemplateName] = utils.getInternalTemplate(config$1.pathnames, unprefixedExternalPathname, locale);
88
79
  if (internalTemplateName) {
89
- const pathnameConfig = configWithDefaults.pathnames[internalTemplateName];
90
- const localeTemplate = typeof pathnameConfig === 'string' ? pathnameConfig : pathnameConfig[locale];
91
- if (utils$1.matchesPathname(localeTemplate, normalizedPathname)) {
92
- pathname = utils.formatTemplatePathname(normalizedPathname, localeTemplate, internalTemplateName, pathLocale);
80
+ const pathnameConfig = config$1.pathnames[internalTemplateName];
81
+ const localeTemplate = typeof pathnameConfig === 'string' ? pathnameConfig :
82
+ // @ts-expect-error This is ok
83
+ pathnameConfig[locale];
84
+ if (utils$1.matchesPathname(localeTemplate, unprefixedExternalPathname)) {
85
+ unprefixedInternalPathname = utils.formatTemplatePathname(unprefixedExternalPathname, localeTemplate, internalTemplateName);
93
86
  } else {
94
87
  let sourceTemplate;
95
88
  if (resolvedTemplateLocale) {
96
89
  // A localized pathname from another locale has matched
97
- sourceTemplate = typeof pathnameConfig === 'string' ? pathnameConfig : pathnameConfig[resolvedTemplateLocale];
90
+ sourceTemplate = typeof pathnameConfig === 'string' ? pathnameConfig :
91
+ // @ts-expect-error This is ok
92
+ pathnameConfig[resolvedTemplateLocale];
98
93
  } else {
99
94
  // An internal pathname has matched that
100
95
  // doesn't have a localized pathname
101
96
  sourceTemplate = internalTemplateName;
102
97
  }
103
- const localePrefix = (hasLocalePrefix || !hasMatchedDefaultLocale) && configWithDefaults.localePrefix !== 'never' ? locale : undefined;
104
- response = redirect(utils.getPathWithSearch(utils.formatTemplatePathname(normalizedPathname, sourceTemplate, localeTemplate, localePrefix), request.nextUrl.search));
98
+ const localePrefix = isUnprefixedRouting ? undefined : utils$1.getLocalePrefix(locale, config$1.localePrefix);
99
+ const template = utils.formatTemplatePathname(unprefixedExternalPathname, sourceTemplate, localeTemplate);
100
+ response = redirect(utils.formatPathname(template, localePrefix, request.nextUrl.search));
105
101
  }
106
102
  }
107
103
  }
108
104
  if (!response) {
109
- if (pathname === ROOT_URL) {
110
- const pathWithSearch = utils.getPathWithSearch("/".concat(locale), request.nextUrl.search);
111
- if (configWithDefaults.localePrefix === 'never' || hasMatchedDefaultLocale && configWithDefaults.localePrefix === 'as-needed') {
112
- response = rewrite(pathWithSearch);
105
+ if (unprefixedInternalPathname === '/' && !hasLocalePrefix) {
106
+ if (isUnprefixedRouting) {
107
+ response = rewrite(utils.formatPathname(unprefixedInternalPathname, utils.getLocaleAsPrefix(locale), request.nextUrl.search));
113
108
  } else {
114
- response = redirect(pathWithSearch);
109
+ response = redirect(utils.formatPathname(unprefixedExternalPathname, utils$1.getLocalePrefix(locale, config$1.localePrefix), request.nextUrl.search));
115
110
  }
116
111
  } else {
117
- const internalPathWithSearch = utils.getPathWithSearch(pathname, request.nextUrl.search);
112
+ const internalHref = utils.formatPathname(unprefixedInternalPathname, utils.getLocaleAsPrefix(locale), request.nextUrl.search);
118
113
  if (hasLocalePrefix) {
119
- const normalizedPathnameWithSearch = utils.getPathWithSearch(normalizedPathname, request.nextUrl.search);
120
- if (configWithDefaults.localePrefix === 'never') {
121
- response = redirect(normalizedPathnameWithSearch);
122
- } else if (pathLocale === locale) {
123
- if (hasMatchedDefaultLocale && configWithDefaults.localePrefix === 'as-needed') {
124
- response = redirect(normalizedPathnameWithSearch);
114
+ const externalHref = utils.formatPathname(unprefixedExternalPathname, pathnameMatch.prefix, request.nextUrl.search);
115
+ if (config$1.localePrefix.mode === 'never') {
116
+ response = redirect(utils.formatPathname(unprefixedExternalPathname, undefined, request.nextUrl.search));
117
+ } else if (pathnameMatch.exact) {
118
+ if (hasMatchedDefaultLocale && isUnprefixedRouting) {
119
+ response = redirect(utils.formatPathname(unprefixedExternalPathname, undefined, request.nextUrl.search));
125
120
  } else {
126
- if (configWithDefaults.domains) {
127
- const pathDomain = utils.getBestMatchingDomain(domain, pathLocale, domainConfigs);
121
+ if (config$1.domains) {
122
+ const pathDomain = utils.getBestMatchingDomain(domain, pathnameMatch.locale, domainConfigs);
128
123
  if ((domain === null || domain === void 0 ? void 0 : domain.domain) !== (pathDomain === null || pathDomain === void 0 ? void 0 : pathDomain.domain) && !hasUnknownHost) {
129
- response = redirect(normalizedPathnameWithSearch, pathDomain === null || pathDomain === void 0 ? void 0 : pathDomain.domain);
124
+ response = redirect(externalHref, pathDomain === null || pathDomain === void 0 ? void 0 : pathDomain.domain);
130
125
  } else {
131
- response = rewrite(internalPathWithSearch);
126
+ response = rewrite(internalHref);
132
127
  }
133
128
  } else {
134
- response = rewrite(internalPathWithSearch);
129
+ response = rewrite(internalHref);
135
130
  }
136
131
  }
137
132
  } else {
138
- response = redirect("/".concat(locale).concat(normalizedPathnameWithSearch));
133
+ response = redirect(externalHref);
139
134
  }
140
135
  } else {
141
- if (configWithDefaults.localePrefix === 'never' || hasMatchedDefaultLocale && (configWithDefaults.localePrefix === 'as-needed' || configWithDefaults.domains)) {
142
- response = rewrite("/".concat(locale).concat(internalPathWithSearch));
136
+ if (isUnprefixedRouting) {
137
+ response = rewrite(internalHref);
143
138
  } else {
144
- response = redirect("/".concat(locale).concat(internalPathWithSearch));
139
+ response = redirect(utils.formatPathname(unprefixedExternalPathname, utils$1.getLocalePrefix(locale, config$1.localePrefix), request.nextUrl.search));
145
140
  }
146
141
  }
147
142
  }
@@ -153,11 +148,11 @@ function createMiddleware(config) {
153
148
  maxAge: constants.COOKIE_MAX_AGE
154
149
  });
155
150
  }
156
- if (configWithDefaults.localePrefix !== 'never' && configWithDefaults.alternateLinks && configWithDefaults.locales.length > 1) {
157
- var _configWithDefaults$p;
151
+ if (config$1.localePrefix.mode !== 'never' && config$1.alternateLinks && config$1.locales.length > 1) {
152
+ var _config$pathnames;
158
153
  response.headers.set('Link', getAlternateLinksHeaderValue.default({
159
- config: configWithDefaults,
160
- localizedPathnames: internalTemplateName != null ? (_configWithDefaults$p = configWithDefaults.pathnames) === null || _configWithDefaults$p === void 0 ? void 0 : _configWithDefaults$p[internalTemplateName] : undefined,
154
+ config: config$1,
155
+ localizedPathnames: internalTemplateName != null ? (_config$pathnames = config$1.pathnames) === null || _config$pathnames === void 0 ? void 0 : _config$pathnames[internalTemplateName] : undefined,
161
156
  request,
162
157
  resolvedLocale: locale
163
158
  }));
@@ -36,10 +36,6 @@ function getAcceptLanguageLocale(requestHeaders, locales, defaultLocale) {
36
36
  }
37
37
  return locale;
38
38
  }
39
- function getLocaleFromPrefix(pathname, locales) {
40
- const pathLocaleCandidate = utils.getFirstPathnameSegment(pathname);
41
- return utils.findCaseInsensitiveLocale(pathLocaleCandidate, locales);
42
- }
43
39
  function getLocaleFromCookie(requestCookies, locales) {
44
40
  if (requestCookies.has(constants.COOKIE_LOCALE_NAME)) {
45
41
  var _requestCookies$get;
@@ -53,13 +49,15 @@ function resolveLocaleFromPrefix(_ref, requestHeaders, requestCookies, pathname)
53
49
  let {
54
50
  defaultLocale,
55
51
  localeDetection,
52
+ localePrefix,
56
53
  locales
57
54
  } = _ref;
58
55
  let locale;
59
56
 
60
57
  // Prio 1: Use route prefix
61
58
  if (pathname) {
62
- locale = getLocaleFromPrefix(pathname, locales);
59
+ var _getPathnameMatch;
60
+ locale = (_getPathnameMatch = utils.getPathnameMatch(pathname, locales, localePrefix)) === null || _getPathnameMatch === void 0 ? void 0 : _getPathnameMatch.locale;
63
61
  }
64
62
 
65
63
  // Prio 2: Use existing cookie
@@ -90,7 +88,8 @@ function resolveLocaleFromDomain(config, requestHeaders, requestCookies, pathnam
90
88
 
91
89
  // Prio 1: Use route prefix
92
90
  if (pathname) {
93
- const prefixLocale = getLocaleFromPrefix(pathname, config.locales);
91
+ var _getPathnameMatch2;
92
+ const prefixLocale = (_getPathnameMatch2 = utils.getPathnameMatch(pathname, config.locales, config.localePrefix)) === null || _getPathnameMatch2 === void 0 ? void 0 : _getPathnameMatch2.locale;
94
93
  if (prefixLocale) {
95
94
  if (utils.isLocaleSupportedOnDomain(prefixLocale, domain)) {
96
95
  locale = prefixLocale;
@@ -4,9 +4,6 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var utils = require('../shared/utils.js');
6
6
 
7
- function getFirstPathnameSegment(pathname) {
8
- return pathname.split('/')[1];
9
- }
10
7
  function isOptionalCatchAllSegment(pathname) {
11
8
  return pathname.includes('[[...');
12
9
  }
@@ -94,40 +91,64 @@ function getInternalTemplate(pathnames, pathname, locale) {
94
91
  // No match
95
92
  return [undefined, undefined];
96
93
  }
97
- function formatTemplatePathname(sourcePathname, sourceTemplate, targetTemplate, localePrefix) {
94
+ function formatTemplatePathname(sourcePathname, sourceTemplate, targetTemplate, prefix) {
98
95
  const params = getRouteParams(sourceTemplate, sourcePathname);
99
96
  let targetPathname = '';
100
- if (localePrefix) {
101
- targetPathname = "/".concat(localePrefix);
97
+ if (prefix) {
98
+ targetPathname = "/".concat(prefix);
102
99
  }
103
- targetPathname += formatPathname(targetTemplate, params);
100
+ targetPathname += formatPathnameTemplate(targetTemplate, params);
104
101
  targetPathname = normalizeTrailingSlash(targetPathname);
105
102
  return targetPathname;
106
103
  }
107
104
 
108
105
  /**
109
- * Removes potential locales from the pathname.
106
+ * Removes potential prefixes from the pathname.
110
107
  */
111
- function getNormalizedPathname(pathname, locales) {
108
+ function getNormalizedPathname(pathname, locales, localePrefix) {
112
109
  // Add trailing slash for consistent handling
113
110
  // both for the root as well as nested paths
114
111
  if (!pathname.endsWith('/')) {
115
112
  pathname += '/';
116
113
  }
117
- const match = pathname.match(new RegExp("^/(".concat(locales.join('|'), ")/(.*)"), 'i'));
114
+ const localePrefixes = getLocalePrefixes(locales, localePrefix);
115
+ const regex = new RegExp("^(".concat(localePrefixes.map(_ref2 => {
116
+ let [, prefix] = _ref2;
117
+ return prefix.replaceAll('/', '\\/');
118
+ }).join('|'), ")/(.*)"), 'i');
119
+ const match = pathname.match(regex);
118
120
  let result = match ? '/' + match[2] : pathname;
119
121
  if (result !== '/') {
120
122
  result = normalizeTrailingSlash(result);
121
123
  }
122
124
  return result;
123
125
  }
124
- function findCaseInsensitiveLocale(candidate, locales) {
125
- return locales.find(locale => locale.toLowerCase() === candidate.toLowerCase());
126
+ function getLocalePrefixes(locales, localePrefix) {
127
+ return locales.map(locale => [locale, utils.getLocalePrefix(locale, localePrefix)]);
126
128
  }
127
- function getPathnameLocale(pathname, locales) {
128
- const pathLocaleCandidate = getFirstPathnameSegment(pathname);
129
- const pathLocale = findCaseInsensitiveLocale(pathLocaleCandidate, locales) ? pathLocaleCandidate : undefined;
130
- return pathLocale;
129
+ function getPathnameMatch(pathname, locales, localePrefix) {
130
+ const localePrefixes = getLocalePrefixes(locales, localePrefix);
131
+ for (const [locale, prefix] of localePrefixes) {
132
+ let exact, matches;
133
+ if (pathname === prefix || pathname.startsWith(prefix + '/')) {
134
+ exact = matches = true;
135
+ } else {
136
+ const normalizedPathname = pathname.toLowerCase();
137
+ const normalizedPrefix = prefix.toLowerCase();
138
+ if (normalizedPathname === normalizedPrefix || normalizedPathname.startsWith(normalizedPrefix + '/')) {
139
+ exact = false;
140
+ matches = true;
141
+ }
142
+ }
143
+ if (matches) {
144
+ return {
145
+ locale,
146
+ prefix,
147
+ matchedPrefix: pathname.slice(0, prefix.length),
148
+ exact
149
+ };
150
+ }
151
+ }
131
152
  }
132
153
  function getRouteParams(template, pathname) {
133
154
  const regex = utils.templateToRegex(template);
@@ -141,29 +162,32 @@ function getRouteParams(template, pathname) {
141
162
  }
142
163
  return params;
143
164
  }
144
- function formatPathname(template, params) {
165
+ function formatPathnameTemplate(template, params) {
145
166
  if (!params) return template;
146
167
 
147
168
  // Simplify syntax for optional catchall ('[[...slug]]') so
148
169
  // we can replace the value with simple interpolation
149
170
  template = template.replace(/\[\[/g, '[').replace(/\]\]/g, ']');
150
171
  let result = template;
151
- Object.entries(params).forEach(_ref2 => {
152
- let [key, value] = _ref2;
172
+ Object.entries(params).forEach(_ref3 => {
173
+ let [key, value] = _ref3;
153
174
  result = result.replace("[".concat(key, "]"), value);
154
175
  });
155
176
  return result;
156
177
  }
157
- function getPathWithSearch(pathname, search) {
158
- let pathWithSearch = pathname;
178
+ function formatPathname(pathname, prefix, search) {
179
+ let result = pathname;
180
+ if (prefix) {
181
+ result = utils.prefixPathname(prefix, result);
182
+ }
159
183
  if (search) {
160
- pathWithSearch += search;
184
+ result += search;
161
185
  }
162
- return pathWithSearch;
186
+ return result;
163
187
  }
164
188
  function getHost(requestHeaders) {
165
- var _ref3, _requestHeaders$get;
166
- return (_ref3 = (_requestHeaders$get = requestHeaders.get('x-forwarded-host')) !== null && _requestHeaders$get !== void 0 ? _requestHeaders$get : requestHeaders.get('host')) !== null && _ref3 !== void 0 ? _ref3 : undefined;
189
+ var _ref4, _requestHeaders$get;
190
+ return (_ref4 = (_requestHeaders$get = requestHeaders.get('x-forwarded-host')) !== null && _requestHeaders$get !== void 0 ? _requestHeaders$get : requestHeaders.get('host')) !== null && _ref4 !== void 0 ? _ref4 : undefined;
167
191
  }
168
192
  function isLocaleSupportedOnDomain(locale, domain) {
169
193
  return domain.defaultLocale === locale || !domain.locales || domain.locales.includes(locale);
@@ -201,24 +225,28 @@ function applyBasePath(pathname, basePath) {
201
225
  return normalizeTrailingSlash(basePath + pathname);
202
226
  }
203
227
  function normalizeTrailingSlash(pathname) {
204
- if (pathname.endsWith('/')) {
228
+ if (pathname !== '/' && pathname.endsWith('/')) {
205
229
  pathname = pathname.slice(0, -1);
206
230
  }
207
231
  return pathname;
208
232
  }
233
+ function getLocaleAsPrefix(locale) {
234
+ return "/".concat(locale);
235
+ }
209
236
 
210
237
  exports.applyBasePath = applyBasePath;
211
238
  exports.comparePathnamePairs = comparePathnamePairs;
212
- exports.findCaseInsensitiveLocale = findCaseInsensitiveLocale;
213
239
  exports.formatPathname = formatPathname;
240
+ exports.formatPathnameTemplate = formatPathnameTemplate;
214
241
  exports.formatTemplatePathname = formatTemplatePathname;
215
242
  exports.getBestMatchingDomain = getBestMatchingDomain;
216
- exports.getFirstPathnameSegment = getFirstPathnameSegment;
217
243
  exports.getHost = getHost;
218
244
  exports.getInternalTemplate = getInternalTemplate;
245
+ exports.getLocaleAsPrefix = getLocaleAsPrefix;
246
+ exports.getLocalePrefixes = getLocalePrefixes;
219
247
  exports.getNormalizedPathname = getNormalizedPathname;
220
- exports.getPathWithSearch = getPathWithSearch;
221
- exports.getPathnameLocale = getPathnameLocale;
248
+ exports.getPathnameMatch = getPathnameMatch;
222
249
  exports.getRouteParams = getRouteParams;
223
250
  exports.getSortedPathnames = getSortedPathnames;
224
251
  exports.isLocaleSupportedOnDomain = isLocaleSupportedOnDomain;
252
+ exports.normalizeTrailingSlash = normalizeTrailingSlash;
@@ -5,6 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var _rollupPluginBabelHelpers = require('../../_virtual/_rollupPluginBabelHelpers.js');
6
6
  var React = require('react');
7
7
  var useLocale = require('../../react-client/useLocale.js');
8
+ var utils = require('../../shared/utils.js');
8
9
  var BaseLink = require('../shared/BaseLink.js');
9
10
 
10
11
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
@@ -14,13 +15,17 @@ var React__default = /*#__PURE__*/_interopDefault(React);
14
15
  function ClientLink(_ref, ref) {
15
16
  let {
16
17
  locale,
18
+ localePrefix,
17
19
  ...rest
18
20
  } = _ref;
19
21
  const defaultLocale = useLocale.default();
20
- const linkLocale = locale || defaultLocale;
22
+ const finalLocale = locale || defaultLocale;
23
+ const prefix = utils.getLocalePrefix(finalLocale, localePrefix);
21
24
  return /*#__PURE__*/React__default.default.createElement(BaseLink.default, _rollupPluginBabelHelpers.extends({
22
25
  ref: ref,
23
- locale: linkLocale
26
+ locale: finalLocale,
27
+ localePrefixMode: localePrefix.mode,
28
+ prefix: prefix
24
29
  }, rest));
25
30
  }
26
31
 
@@ -5,10 +5,10 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var _rollupPluginBabelHelpers = require('../../_virtual/_rollupPluginBabelHelpers.js');
6
6
  var React = require('react');
7
7
  var useLocale = require('../../react-client/useLocale.js');
8
+ var config = require('../shared/config.js');
8
9
  var utils = require('../shared/utils.js');
9
10
  var ClientLink = require('./ClientLink.js');
10
- var clientPermanentRedirect = require('./clientPermanentRedirect.js');
11
- var clientRedirect = require('./clientRedirect.js');
11
+ var redirects = require('./redirects.js');
12
12
  var useBasePathname = require('./useBasePathname.js');
13
13
  var useBaseRouter = require('./useBaseRouter.js');
14
14
 
@@ -16,10 +16,11 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
16
16
 
17
17
  var React__default = /*#__PURE__*/_interopDefault(React);
18
18
 
19
- function createLocalizedPathnamesNavigation(opts) {
19
+ function createLocalizedPathnamesNavigation(input) {
20
+ const config$1 = config.receiveLocalizedNavigationRoutingConfig(input);
20
21
  function useTypedLocale() {
21
22
  const locale = useLocale.default();
22
- const isValid = opts.locales.includes(locale);
23
+ const isValid = config$1.locales.includes(locale);
23
24
  if (!isValid) {
24
25
  throw new Error("Unknown locale encountered: \"".concat(locale, "\". Make sure to validate the locale in `i18n.ts`.") );
25
26
  }
@@ -41,10 +42,10 @@ function createLocalizedPathnamesNavigation(opts) {
41
42
  pathname: href,
42
43
  // @ts-expect-error -- This is ok
43
44
  params: typeof href === 'object' ? href.params : undefined,
44
- pathnames: opts.pathnames
45
+ pathnames: config$1.pathnames
45
46
  }),
46
47
  locale: locale,
47
- localePrefix: opts.localePrefix
48
+ localePrefix: config$1.localePrefix
48
49
  }, rest));
49
50
  }
50
51
  const LinkWithRef = /*#__PURE__*/React.forwardRef(Link);
@@ -59,9 +60,9 @@ function createLocalizedPathnamesNavigation(opts) {
59
60
  for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
60
61
  args[_key - 1] = arguments[_key];
61
62
  }
62
- return clientRedirect.default({
63
- ...opts,
64
- pathname: resolvedHref
63
+ return redirects.clientRedirect({
64
+ pathname: resolvedHref,
65
+ localePrefix: config$1.localePrefix
65
66
  }, ...args);
66
67
  }
67
68
  function permanentRedirect(href) {
@@ -74,13 +75,13 @@ function createLocalizedPathnamesNavigation(opts) {
74
75
  for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
75
76
  args[_key2 - 1] = arguments[_key2];
76
77
  }
77
- return clientPermanentRedirect.default({
78
- ...opts,
79
- pathname: resolvedHref
78
+ return redirects.clientPermanentRedirect({
79
+ pathname: resolvedHref,
80
+ localePrefix: config$1.localePrefix
80
81
  }, ...args);
81
82
  }
82
83
  function useRouter() {
83
- const baseRouter = useBaseRouter.default();
84
+ const baseRouter = useBaseRouter.default(config$1.localePrefix);
84
85
  const defaultLocale = useTypedLocale();
85
86
  return {
86
87
  ...baseRouter,
@@ -120,13 +121,14 @@ function createLocalizedPathnamesNavigation(opts) {
120
121
  };
121
122
  }
122
123
  function usePathname() {
123
- const pathname = useBasePathname.default();
124
+ const pathname = useBasePathname.default(config$1.localePrefix);
124
125
  const locale = useTypedLocale();
126
+
125
127
  // @ts-expect-error -- Mirror the behavior from Next.js, where `null` is returned when `usePathname` is used outside of Next, but the types indicate that a string is always returned.
126
128
  return pathname ? utils.getRoute({
127
129
  pathname,
128
130
  locale,
129
- pathnames: opts.pathnames
131
+ pathnames: config$1.pathnames
130
132
  }) : pathname;
131
133
  }
132
134
  function getPathname(_ref2) {
@@ -137,7 +139,7 @@ function createLocalizedPathnamesNavigation(opts) {
137
139
  return utils.compileLocalizedPathname({
138
140
  ...utils.normalizeNameOrNameWithParams(href),
139
141
  locale,
140
- pathnames: opts.pathnames
142
+ pathnames: config$1.pathnames
141
143
  });
142
144
  }
143
145
  return {