Skip to content

Commit

Permalink
Ensure correct defaultLocale is provided for locale domain (#19040)
Browse files Browse the repository at this point in the history
This ensures we use the `defaultLocale` for a locale domain when rendering non-static pages. Static pages will initially contain the global `defaultLocale` and then be updated on the client since we don't currently prerender a version of the pages for each locale domain. 

Closes: #18970
  • Loading branch information
ijjk authored Nov 11, 2020
1 parent 6de34e7 commit a429a47
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,7 @@ const nextServerlessLoader: loader.Loader = function () {
err: undefined,
locale: detectedLocale,
locales,
defaultLocale: i18n.defaultLocale,
defaultLocale,
}))
sendPayload(req, res, result, 'html', ${
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export default function prepareDestination(
// clone query so we don't modify the original
query = Object.assign({}, query)
delete query.__nextLocale
delete query.__nextDefaultLocale

if (destination.startsWith('/')) {
parsedDestination = parseRelativeUrl(destination)
Expand Down
7 changes: 6 additions & 1 deletion packages/next/next-server/server/incremental-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import LRUCache from 'next/dist/compiled/lru-cache'
import path from 'path'
import { PrerenderManifest } from '../../build'
import { PRERENDER_MANIFEST } from '../lib/constants'
import { normalizeLocalePath } from '../lib/i18n/normalize-locale-path'
import { normalizePagePath } from './normalize-page-path'

function toRoute(pathname: string): string {
Expand Down Expand Up @@ -30,19 +31,22 @@ export class IncrementalCache {

prerenderManifest: PrerenderManifest
cache: LRUCache<string, IncrementalCacheValue>
locales?: string[]

constructor({
max,
dev,
distDir,
pagesDir,
flushToDisk,
locales,
}: {
dev: boolean
max?: number
distDir: string
pagesDir: string
flushToDisk?: boolean
locales?: string[]
}) {
this.incrementalOptions = {
dev,
Expand All @@ -51,6 +55,7 @@ export class IncrementalCache {
flushToDisk:
!dev && (typeof flushToDisk !== 'undefined' ? flushToDisk : true),
}
this.locales = locales

if (dev) {
this.prerenderManifest = {
Expand Down Expand Up @@ -82,7 +87,7 @@ export class IncrementalCache {
}

private calculateRevalidate(pathname: string): number | false {
pathname = toRoute(pathname)
pathname = toRoute(normalizeLocalePath(pathname, this.locales).pathname)

// in development we don't have a prerender-manifest
// and default to always revalidating to allow easier debugging
Expand Down
24 changes: 18 additions & 6 deletions packages/next/next-server/server/next-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,6 @@ export default class Server {
? requireFontManifest(this.distDir, this._isLikeServerless)
: null,
optimizeImages: this.nextConfig.experimental.optimizeImages,
defaultLocale: this.nextConfig.i18n?.defaultLocale,
}

// Only the `publicRuntimeConfig` key is exposed to the client side
Expand Down Expand Up @@ -259,6 +258,7 @@ export default class Server {
'pages'
),
flushToDisk: this.nextConfig.experimental.sprFlushToDisk,
locales: this.nextConfig.i18n?.locales,
})

/**
Expand Down Expand Up @@ -438,6 +438,9 @@ export default class Server {
return
}

parsedUrl.query.__nextDefaultLocale =
detectedDomain?.defaultLocale || i18n.defaultLocale

parsedUrl.query.__nextLocale =
localePathResult.detectedLocale ||
detectedDomain?.defaultLocale ||
Expand Down Expand Up @@ -603,7 +606,10 @@ export default class Server {
pathname = localePathResult.pathname
detectedLocale = localePathResult.detectedLocale
}

_parsedUrl.query.__nextLocale = detectedLocale!
_parsedUrl.query.__nextDefaultLocale =
defaultLocale || i18n.defaultLocale
}
pathname = getRouteFromAssetPath(pathname, '.json')

Expand Down Expand Up @@ -1145,6 +1151,7 @@ export default class Server {
amp: query.amp,
_nextDataReq: query._nextDataReq,
__nextLocale: query.__nextLocale,
__nextDefaultLocale: query.__nextDefaultLocale,
}
: query),
...(params || {}),
Expand Down Expand Up @@ -1217,7 +1224,12 @@ export default class Server {
}

const locale = query.__nextLocale as string
const defaultLocale = isSSG
? this.nextConfig.i18n?.defaultLocale
: (query.__nextDefaultLocale as string)

delete query.__nextLocale
delete query.__nextDefaultLocale

const { i18n } = this.nextConfig
const locales = i18n.locales as string[]
Expand Down Expand Up @@ -1281,9 +1293,9 @@ export default class Server {
let ssgCacheKey =
isPreviewMode || !isSSG
? undefined // Preview mode bypasses the cache
: `${locale ? `/${locale}` : ''}${resolvedUrlPathname}${
query.amp ? '.amp' : ''
}`
: `${locale ? `/${locale}` : ''}${
pathname === '/' && locale ? '' : resolvedUrlPathname
}${query.amp ? '.amp' : ''}`

if (is404Page && isSSG) {
ssgCacheKey = `${locale ? `/${locale}` : ''}${pathname}${
Expand Down Expand Up @@ -1371,7 +1383,7 @@ export default class Server {
fontManifest: this.renderOpts.fontManifest,
locale,
locales,
// defaultLocale,
defaultLocale,
}
)

Expand All @@ -1395,7 +1407,7 @@ export default class Server {
resolvedUrl,
locale,
locales,
// defaultLocale,
defaultLocale,
// For getServerSideProps we need to ensure we use the original URL
// and not the resolved URL to prevent a hydration mismatch on
// asPath
Expand Down
1 change: 1 addition & 0 deletions packages/next/next-server/server/render.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,7 @@ export async function renderToHTML(
const isFallback = !!query.__nextFallback
delete query.__nextFallback
delete query.__nextLocale
delete query.__nextDefaultLocale

const isSSG = !!getStaticProps
const isBuildTimeSSG = isSSG && renderOpts.nextExport
Expand Down
1 change: 1 addition & 0 deletions test/integration/i18n-support/pages/frank.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export default function Page(props) {
<p id="frank">frank page</p>
<p id="props">{JSON.stringify(props)}</p>
<p id="router-locale">{router.locale}</p>
<p id="router-default-locale">{router.defaultLocale}</p>
<p id="router-locales">{JSON.stringify(router.locales)}</p>
<p id="router-query">{JSON.stringify(router.query)}</p>
<p id="router-pathname">{router.pathname}</p>
Expand Down
1 change: 1 addition & 0 deletions test/integration/i18n-support/pages/gssp/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export default function Page(props) {
<p id="gssp">gssp page</p>
<p id="props">{JSON.stringify(props)}</p>
<p id="router-locale">{router.locale}</p>
<p id="router-default-locale">{router.defaultLocale}</p>
<p id="router-locales">{JSON.stringify(router.locales)}</p>
<p id="router-query">{JSON.stringify(router.query)}</p>
<p id="router-pathname">{router.pathname}</p>
Expand Down
32 changes: 32 additions & 0 deletions test/integration/i18n-support/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -996,6 +996,9 @@ function runTests(isDev) {
expect($('html').attr('lang')).toBe(locale)
expect($('#router-locale').text()).toBe(locale)
expect(JSON.parse($('#router-locales').text())).toEqual(locales)
// this will not be the domain's defaultLocale since we don't
// generate a prerendered version for each locale domain currently
expect($('#router-default-locale').text()).toBe('en-US')
}
}

Expand All @@ -1006,6 +1009,32 @@ function runTests(isDev) {
}
})

it('should provide correctly defaultLocale for locale domain', async () => {
for (const { host, locale } of [
{ host: 'example.fr', locale: 'fr' },
{ host: 'example.be', locale: 'nl-BE' },
]) {
const res = await fetchViaHTTP(appPort, '/gssp', undefined, {
redirect: 'manual',
headers: {
host,
},
})

expect(res.status).toBe(200)
const html = await res.text()
const $ = cheerio.load(html)
expect($('#router-locale').text()).toBe(locale)
expect($('#router-default-locale').text()).toBe(locale)
expect(JSON.parse($('#props').text())).toEqual({
defaultLocale: locale,
locale,
locales,
})
expect(JSON.parse($('#router-locales').text())).toEqual(locales)
}
})

it('should generate AMP pages with all locales', async () => {
for (const locale of locales) {
const localePath = locale !== 'en-US' ? `/${locale}` : ''
Expand Down Expand Up @@ -1160,6 +1189,9 @@ function runTests(isDev) {
await browser.waitForElementByCss('#frank')

expect(await browser.elementByCss('#router-locale').text()).toBe('fr')
expect(await browser.elementByCss('#router-default-locale').text()).toBe(
'en-US'
)
expect(
JSON.parse(await browser.elementByCss('#router-locales').text())
).toEqual(locales)
Expand Down

0 comments on commit a429a47

Please sign in to comment.