Skip to content

Commit

Permalink
Ensure correct default locale is detected for domain locale (#18046)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
ijjk committed Oct 20, 2020
1 parent 85842ce commit 8be3562
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 15 deletions.
5 changes: 4 additions & 1 deletion packages/next/build/webpack-config.ts
Expand Up @@ -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
),
Expand Down
Expand Up @@ -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
Expand Down Expand Up @@ -291,6 +295,7 @@ const nextServerlessLoader: loader.Loader = function () {
if (
!fromExport &&
!nextStartMode &&
!req.headers["${vercelHeader}"] &&
i18n.localeDetection !== false &&
(
localeDomainRedirect ||
Expand Down
18 changes: 17 additions & 1 deletion packages/next/client/index.tsx
Expand Up @@ -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)

Expand All @@ -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
}
}
}

Expand Down
8 changes: 1 addition & 7 deletions packages/next/next-server/lib/i18n/detect-domain-locale.ts
@@ -1,5 +1,3 @@
import { IncomingMessage } from 'http'

export function detectDomainLocale(
domainItems:
| Array<{
Expand All @@ -8,7 +6,7 @@ export function detectDomainLocale(
defaultLocale: string
}>
| undefined,
req?: IncomingMessage,
hostname?: string,
detectedLocale?: string
) {
let domainItem:
Expand All @@ -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()
Expand Down
6 changes: 3 additions & 3 deletions packages/next/next-server/lib/router/router.ts
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
11 changes: 9 additions & 2 deletions packages/next/next-server/server/next-server.ts
Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit 8be3562

Please sign in to comment.