diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts index 0df798ee8034364..f9df1470e32b01c 100644 --- a/packages/next/build/webpack-config.ts +++ b/packages/next/build/webpack-config.ts @@ -1012,9 +1012,12 @@ export default async function getBaseWebpackConfig( 'process.env.__NEXT_IMAGE_OPTS': JSON.stringify(config.images), 'process.env.__NEXT_ROUTER_BASEPATH': JSON.stringify(config.basePath), 'process.env.__NEXT_HAS_REWRITES': JSON.stringify(hasRewrites), - 'process.env.__NEXT_i18n_SUPPORT': JSON.stringify( + 'process.env.__NEXT_I18N_SUPPORT': JSON.stringify( !!config.experimental.i18n ), + 'process.env.__NEXT_I18N_DOMAINS': JSON.stringify( + config.experimental.i18n.domains + ), 'process.env.__NEXT_ANALYTICS_ID': JSON.stringify( config.experimental.analyticsId ), diff --git a/packages/next/build/webpack/loaders/next-serverless-loader.ts b/packages/next/build/webpack/loaders/next-serverless-loader.ts index 53a18a0409ab4af..3f2c092357418b7 100644 --- a/packages/next/build/webpack/loaders/next-serverless-loader.ts +++ b/packages/next/build/webpack/loaders/next-serverless-loader.ts @@ -233,9 +233,13 @@ const nextServerlessLoader: loader.Loader = function () { i18n.locales ) + const { host } = req.headers || {} + // remove port from host and remove port if present + const hostname = host && host.split(':')[0].toLowerCase() + const detectedDomain = detectDomainLocale( i18n.domains, - req, + hostname, ) if (detectedDomain) { defaultLocale = detectedDomain.defaultLocale @@ -291,6 +295,7 @@ const nextServerlessLoader: loader.Loader = function () { if ( !fromExport && !nextStartMode && + !req.headers["${vercelHeader}"] && i18n.localeDetection !== false && ( localeDomainRedirect || diff --git a/packages/next/client/index.tsx b/packages/next/client/index.tsx index 43fae5b351d4bfc..5cc0056da5c2442 100644 --- a/packages/next/client/index.tsx +++ b/packages/next/client/index.tsx @@ -83,11 +83,15 @@ if (hasBasePath(asPath)) { asPath = delBasePath(asPath) } -if (process.env.__NEXT_i18n_SUPPORT) { +if (process.env.__NEXT_I18N_SUPPORT) { const { normalizeLocalePath, } = require('../next-server/lib/i18n/normalize-locale-path') + const { + detectDomainLocale, + } = require('../next-server/lib/i18n/detect-domain-locale') + if (locales) { const localePathResult = normalizeLocalePath(asPath, locales) @@ -99,6 +103,18 @@ if (process.env.__NEXT_i18n_SUPPORT) { // locales defaultLocale = locale } + + // attempt detecting default locale based on hostname + const detectedDomain = detectDomainLocale( + process.env.__NEXT_I18N_DOMAINS, + window.location.hostname + ) + + // TODO: investigate if defaultLocale needs to be populated after + // hydration to prevent mismatched renders + if (detectedDomain) { + defaultLocale = detectedDomain.defaultLocale + } } } diff --git a/packages/next/next-server/lib/i18n/detect-domain-locale.ts b/packages/next/next-server/lib/i18n/detect-domain-locale.ts index e97389c9ea5598d..b77e9adca32f985 100644 --- a/packages/next/next-server/lib/i18n/detect-domain-locale.ts +++ b/packages/next/next-server/lib/i18n/detect-domain-locale.ts @@ -1,5 +1,3 @@ -import { IncomingMessage } from 'http' - export function detectDomainLocale( domainItems: | Array<{ @@ -8,7 +6,7 @@ export function detectDomainLocale( defaultLocale: string }> | undefined, - req?: IncomingMessage, + hostname?: string, detectedLocale?: string ) { let domainItem: @@ -20,10 +18,6 @@ export function detectDomainLocale( | undefined if (domainItems) { - const { host } = req?.headers || {} - // remove port from host and remove port if present - const hostname = host?.split(':')[0].toLowerCase() - for (const item of domainItems) { // remove port if present const domainHostname = item.domain?.split(':')[0].toLowerCase() diff --git a/packages/next/next-server/lib/router/router.ts b/packages/next/next-server/lib/router/router.ts index 85921f4d6ca8b1c..e027649823d031e 100644 --- a/packages/next/next-server/lib/router/router.ts +++ b/packages/next/next-server/lib/router/router.ts @@ -61,7 +61,7 @@ export function addLocale( locale?: string, defaultLocale?: string ) { - if (process.env.__NEXT_i18n_SUPPORT) { + if (process.env.__NEXT_I18N_SUPPORT) { return locale && locale !== defaultLocale && !path.startsWith('/' + locale) ? addPathPrefix(path, '/' + locale) : path @@ -70,7 +70,7 @@ export function addLocale( } export function delLocale(path: string, locale?: string) { - if (process.env.__NEXT_i18n_SUPPORT) { + if (process.env.__NEXT_I18N_SUPPORT) { return locale && path.startsWith('/' + locale) ? path.substr(locale.length + 1) || '/' : path @@ -453,7 +453,7 @@ export default class Router implements BaseRouter { this.isFallback = isFallback - if (process.env.__NEXT_i18n_SUPPORT) { + if (process.env.__NEXT_I18N_SUPPORT) { this.locale = locale this.locales = locales this.defaultLocale = defaultLocale diff --git a/packages/next/next-server/server/next-server.ts b/packages/next/next-server/server/next-server.ts index fe1e5cfcb58f26a..aec5000a4573db7 100644 --- a/packages/next/next-server/server/next-server.ts +++ b/packages/next/next-server/server/next-server.ts @@ -318,7 +318,11 @@ export default class Server { i18n.locales ) - const detectedDomain = detectDomainLocale(i18n.domains, req) + const { host } = req?.headers || {} + // remove port from host and remove port if present + const hostname = host?.split(':')[0].toLowerCase() + + const detectedDomain = detectDomainLocale(i18n.domains, hostname) if (detectedDomain) { defaultLocale = detectedDomain.defaultLocale detectedLocale = defaultLocale @@ -564,9 +568,12 @@ export default class Server { const { i18n } = this.nextConfig.experimental if (i18n) { + const { host } = req?.headers || {} + // remove port from host and remove port if present + const hostname = host?.split(':')[0].toLowerCase() const localePathResult = normalizeLocalePath(pathname, i18n.locales) const { defaultLocale } = - detectDomainLocale(i18n.domains, req) || {} + detectDomainLocale(i18n.domains, hostname) || {} let detectedLocale = defaultLocale if (localePathResult.detectedLocale) {