Skip to content

Commit 8be3562

Browse files
authored
Ensure correct default locale is detected for domain locale (#18046)
This makes sure that we detect the correct default locale for domain specific locales since a domain can have a different default locale residing at the root and we need to check this on the client for prerendered/auto-static pages. This also makes sure we disable the built-in redirect handling when on Vercel since it's handled already. Tests for this are tricky since we need to load the browser with a custom domain which requires editing the host file. Existing tests should ensure this doesn't break non-domain specific locale behavior though. This was also tested manually while testing vercel/vercel#5298 x-ref: #17370
1 parent 85842ce commit 8be3562

File tree

6 files changed

+40
-15
lines changed

6 files changed

+40
-15
lines changed

packages/next/build/webpack-config.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1012,9 +1012,12 @@ export default async function getBaseWebpackConfig(
10121012
'process.env.__NEXT_IMAGE_OPTS': JSON.stringify(config.images),
10131013
'process.env.__NEXT_ROUTER_BASEPATH': JSON.stringify(config.basePath),
10141014
'process.env.__NEXT_HAS_REWRITES': JSON.stringify(hasRewrites),
1015-
'process.env.__NEXT_i18n_SUPPORT': JSON.stringify(
1015+
'process.env.__NEXT_I18N_SUPPORT': JSON.stringify(
10161016
!!config.experimental.i18n
10171017
),
1018+
'process.env.__NEXT_I18N_DOMAINS': JSON.stringify(
1019+
config.experimental.i18n.domains
1020+
),
10181021
'process.env.__NEXT_ANALYTICS_ID': JSON.stringify(
10191022
config.experimental.analyticsId
10201023
),

packages/next/build/webpack/loaders/next-serverless-loader.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,9 +233,13 @@ const nextServerlessLoader: loader.Loader = function () {
233233
i18n.locales
234234
)
235235
236+
const { host } = req.headers || {}
237+
// remove port from host and remove port if present
238+
const hostname = host && host.split(':')[0].toLowerCase()
239+
236240
const detectedDomain = detectDomainLocale(
237241
i18n.domains,
238-
req,
242+
hostname,
239243
)
240244
if (detectedDomain) {
241245
defaultLocale = detectedDomain.defaultLocale
@@ -291,6 +295,7 @@ const nextServerlessLoader: loader.Loader = function () {
291295
if (
292296
!fromExport &&
293297
!nextStartMode &&
298+
!req.headers["${vercelHeader}"] &&
294299
i18n.localeDetection !== false &&
295300
(
296301
localeDomainRedirect ||

packages/next/client/index.tsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,15 @@ if (hasBasePath(asPath)) {
8383
asPath = delBasePath(asPath)
8484
}
8585

86-
if (process.env.__NEXT_i18n_SUPPORT) {
86+
if (process.env.__NEXT_I18N_SUPPORT) {
8787
const {
8888
normalizeLocalePath,
8989
} = require('../next-server/lib/i18n/normalize-locale-path')
9090

91+
const {
92+
detectDomainLocale,
93+
} = require('../next-server/lib/i18n/detect-domain-locale')
94+
9195
if (locales) {
9296
const localePathResult = normalizeLocalePath(asPath, locales)
9397

@@ -99,6 +103,18 @@ if (process.env.__NEXT_i18n_SUPPORT) {
99103
// locales
100104
defaultLocale = locale
101105
}
106+
107+
// attempt detecting default locale based on hostname
108+
const detectedDomain = detectDomainLocale(
109+
process.env.__NEXT_I18N_DOMAINS,
110+
window.location.hostname
111+
)
112+
113+
// TODO: investigate if defaultLocale needs to be populated after
114+
// hydration to prevent mismatched renders
115+
if (detectedDomain) {
116+
defaultLocale = detectedDomain.defaultLocale
117+
}
102118
}
103119
}
104120

packages/next/next-server/lib/i18n/detect-domain-locale.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import { IncomingMessage } from 'http'
2-
31
export function detectDomainLocale(
42
domainItems:
53
| Array<{
@@ -8,7 +6,7 @@ export function detectDomainLocale(
86
defaultLocale: string
97
}>
108
| undefined,
11-
req?: IncomingMessage,
9+
hostname?: string,
1210
detectedLocale?: string
1311
) {
1412
let domainItem:
@@ -20,10 +18,6 @@ export function detectDomainLocale(
2018
| undefined
2119

2220
if (domainItems) {
23-
const { host } = req?.headers || {}
24-
// remove port from host and remove port if present
25-
const hostname = host?.split(':')[0].toLowerCase()
26-
2721
for (const item of domainItems) {
2822
// remove port if present
2923
const domainHostname = item.domain?.split(':')[0].toLowerCase()

packages/next/next-server/lib/router/router.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export function addLocale(
6161
locale?: string,
6262
defaultLocale?: string
6363
) {
64-
if (process.env.__NEXT_i18n_SUPPORT) {
64+
if (process.env.__NEXT_I18N_SUPPORT) {
6565
return locale && locale !== defaultLocale && !path.startsWith('/' + locale)
6666
? addPathPrefix(path, '/' + locale)
6767
: path
@@ -70,7 +70,7 @@ export function addLocale(
7070
}
7171

7272
export function delLocale(path: string, locale?: string) {
73-
if (process.env.__NEXT_i18n_SUPPORT) {
73+
if (process.env.__NEXT_I18N_SUPPORT) {
7474
return locale && path.startsWith('/' + locale)
7575
? path.substr(locale.length + 1) || '/'
7676
: path
@@ -453,7 +453,7 @@ export default class Router implements BaseRouter {
453453

454454
this.isFallback = isFallback
455455

456-
if (process.env.__NEXT_i18n_SUPPORT) {
456+
if (process.env.__NEXT_I18N_SUPPORT) {
457457
this.locale = locale
458458
this.locales = locales
459459
this.defaultLocale = defaultLocale

packages/next/next-server/server/next-server.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,11 @@ export default class Server {
318318
i18n.locales
319319
)
320320

321-
const detectedDomain = detectDomainLocale(i18n.domains, req)
321+
const { host } = req?.headers || {}
322+
// remove port from host and remove port if present
323+
const hostname = host?.split(':')[0].toLowerCase()
324+
325+
const detectedDomain = detectDomainLocale(i18n.domains, hostname)
322326
if (detectedDomain) {
323327
defaultLocale = detectedDomain.defaultLocale
324328
detectedLocale = defaultLocale
@@ -564,9 +568,12 @@ export default class Server {
564568
const { i18n } = this.nextConfig.experimental
565569

566570
if (i18n) {
571+
const { host } = req?.headers || {}
572+
// remove port from host and remove port if present
573+
const hostname = host?.split(':')[0].toLowerCase()
567574
const localePathResult = normalizeLocalePath(pathname, i18n.locales)
568575
const { defaultLocale } =
569-
detectDomainLocale(i18n.domains, req) || {}
576+
detectDomainLocale(i18n.domains, hostname) || {}
570577
let detectedLocale = defaultLocale
571578

572579
if (localePathResult.detectedLocale) {

0 commit comments

Comments
 (0)