Skip to content

Commit

Permalink
Add locale false handling (#18115)
Browse files Browse the repository at this point in the history
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
ijjk and kodiakhq[bot] committed Oct 22, 2020
1 parent 9fb1e60 commit 9bbfa0e
Show file tree
Hide file tree
Showing 5 changed files with 255 additions and 14 deletions.
6 changes: 3 additions & 3 deletions packages/next/client/index.tsx
Expand Up @@ -86,11 +86,11 @@ if (hasBasePath(asPath)) {
if (process.env.__NEXT_I18N_SUPPORT) {
const {
normalizeLocalePath,
} = require('../next-server/lib/i18n/normalize-locale-path')
} = require('../next-server/lib/i18n/normalize-locale-path') as typeof import('../next-server/lib/i18n/normalize-locale-path')

const {
detectDomainLocale,
} = require('../next-server/lib/i18n/detect-domain-locale')
} = require('../next-server/lib/i18n/detect-domain-locale') as typeof import('../next-server/lib/i18n/detect-domain-locale')

if (locales) {
const localePathResult = normalizeLocalePath(asPath, locales)
Expand All @@ -106,7 +106,7 @@ if (process.env.__NEXT_I18N_SUPPORT) {

// attempt detecting default locale based on hostname
const detectedDomain = detectDomainLocale(
process.env.__NEXT_I18N_DOMAINS,
process.env.__NEXT_I18N_DOMAINS as any,
window.location.hostname
)

Expand Down
6 changes: 3 additions & 3 deletions packages/next/client/link.tsx
Expand Up @@ -26,7 +26,7 @@ export type LinkProps = {
shallow?: boolean
passHref?: boolean
prefetch?: boolean
locale?: string
locale?: string | false
}
type LinkPropsRequired = RequiredKeys<LinkProps>
type LinkPropsOptional = OptionalKeys<LinkProps>
Expand Down Expand Up @@ -127,7 +127,7 @@ function linkClicked(
replace?: boolean,
shallow?: boolean,
scroll?: boolean,
locale?: string
locale?: string | false
): void {
const { nodeName } = e.currentTarget

Expand Down Expand Up @@ -344,7 +344,7 @@ function Link(props: React.PropsWithChildren<LinkProps>) {
childProps.href = addBasePath(
addLocale(
as,
locale || (router && router.locale),
typeof locale !== 'undefined' ? locale : router && router.locale,
router && router.defaultLocale
)
)
Expand Down
29 changes: 24 additions & 5 deletions packages/next/next-server/lib/router/router.ts
Expand Up @@ -29,7 +29,7 @@ import escapePathDelimiters from './utils/escape-path-delimiters'

interface TransitionOptions {
shallow?: boolean
locale?: string
locale?: string | false
}

interface NextHistoryState {
Expand Down Expand Up @@ -58,7 +58,7 @@ function addPathPrefix(path: string, prefix?: string) {

export function addLocale(
path: string,
locale?: string,
locale?: string | false,
defaultLocale?: string
) {
if (process.env.__NEXT_I18N_SUPPORT) {
Expand Down Expand Up @@ -553,6 +553,7 @@ export default class Router implements BaseRouter {
as,
Object.assign({}, options, {
shallow: options.shallow && this._shallow,
locale: options.locale || this.defaultLocale,
})
)
}
Expand Down Expand Up @@ -600,7 +601,25 @@ export default class Router implements BaseRouter {
window.location.href = url
return false
}
this.locale = options.locale || this.locale

if (process.env.__NEXT_I18N_SUPPORT) {
this.locale = options.locale || this.locale

if (typeof options.locale === 'undefined') {
options.locale = this.locale
}

const {
normalizeLocalePath,
} = require('../i18n/normalize-locale-path') as typeof import('../i18n/normalize-locale-path')

const localePathResult = normalizeLocalePath(as, this.locales)

if (localePathResult.detectedLocale) {
this.locale = localePathResult.detectedLocale
url = localePathResult.pathname
}
}

if (!(options as any)._h) {
this.isSsr = false
Expand All @@ -614,7 +633,7 @@ export default class Router implements BaseRouter {
this.abortComponentLoad(this._inFlightRoute)
}

as = addLocale(as, this.locale, this.defaultLocale)
as = addLocale(as, options.locale, this.defaultLocale)
const cleanedAs = delLocale(
hasBasePath(as) ? delBasePath(as) : as,
this.locale
Expand Down Expand Up @@ -811,7 +830,7 @@ export default class Router implements BaseRouter {
this.changeState(
method,
url,
addLocale(as, this.locale, this.defaultLocale),
addLocale(as, options.locale, this.defaultLocale),
options
)

Expand Down
54 changes: 54 additions & 0 deletions test/integration/i18n-support/pages/locale-false.js
@@ -0,0 +1,54 @@
import Link from 'next/link'
import { useRouter } from 'next/router'

export default function Page(props) {
const router = useRouter()
const { nextLocale } = router.query

return (
<>
<p id="links">links page</p>
<p id="props">{JSON.stringify(props)}</p>
<p id="router-locale">{router.locale}</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>
<p id="router-as-path">{router.asPath}</p>
<Link href={`/${nextLocale}/another`} locale={false}>
<a id="to-another">to /another</a>
</Link>
<br />
<Link href={`/${nextLocale}/gsp`} locale={false}>
<a id="to-gsp">to /gsp</a>
</Link>
<br />
<Link href={`/${nextLocale}/gsp/fallback/first`} locale={false}>
<a id="to-fallback-first">to /gsp/fallback/first</a>
</Link>
<br />
<Link href={`/${nextLocale}/gsp/fallback/hello`} locale={false}>
<a id="to-fallback-hello">to /gsp/fallback/hello</a>
</Link>
<br />
<Link href={`/${nextLocale}/gsp/no-fallback/first`} locale={false}>
<a id="to-no-fallback-first">to /gsp/no-fallback/first</a>
</Link>
<br />
<Link href={`/${nextLocale}/gssp`} locale={false}>
<a id="to-gssp">to /gssp</a>
</Link>
<br />
<Link href={`/${nextLocale}/gssp/first`} locale={false}>
<a id="to-gssp-slug">to /gssp/first</a>
</Link>
<br />
</>
)
}

// make SSR page so we have query values immediately
export const getServerSideProps = () => {
return {
props: {},
}
}
174 changes: 171 additions & 3 deletions test/integration/i18n-support/test/index.test.js
Expand Up @@ -167,6 +167,7 @@ function runTests(isDev) {
it('should navigate with locale prop correctly', async () => {
const browser = await webdriver(appPort, '/links?nextLocale=fr')
await addDefaultLocaleCookie(browser)
await browser.eval('window.beforeNav = 1')

expect(await browser.elementByCss('#router-pathname').text()).toBe('/links')
expect(await browser.elementByCss('#router-as-path').text()).toBe(
Expand Down Expand Up @@ -208,7 +209,7 @@ function runTests(isDev) {
expect(await browser.elementByCss('#router-as-path').text()).toBe(
'/links?nextLocale=fr'
)
expect(await browser.elementByCss('#router-locale').text()).toBe('fr')
expect(await browser.elementByCss('#router-locale').text()).toBe('en-US')
expect(
JSON.parse(await browser.elementByCss('#router-locales').text())
).toEqual(locales)
Expand All @@ -217,7 +218,7 @@ function runTests(isDev) {
).toEqual({ nextLocale: 'fr' })

parsedUrl = url.parse(await browser.eval('window.location.href'), true)
expect(parsedUrl.pathname).toBe('/fr/links')
expect(parsedUrl.pathname).toBe('/links')
expect(parsedUrl.query).toEqual({ nextLocale: 'fr' })

await browser.eval('window.history.forward()')
Expand All @@ -240,6 +241,7 @@ function runTests(isDev) {
parsedUrl = url.parse(await browser.eval('window.location.href'), true)
expect(parsedUrl.pathname).toBe('/fr/another')
expect(parsedUrl.query).toEqual({})
expect(await browser.eval('window.beforeNav')).toBe(1)
})

it('should navigate with locale prop correctly GSP', async () => {
Expand Down Expand Up @@ -286,16 +288,182 @@ function runTests(isDev) {
expect(await browser.elementByCss('#router-as-path').text()).toBe(
'/links?nextLocale=nl'
)
expect(await browser.elementByCss('#router-locale').text()).toBe('en-US')
expect(
JSON.parse(await browser.elementByCss('#router-locales').text())
).toEqual(locales)
expect(
JSON.parse(await browser.elementByCss('#router-query').text())
).toEqual({ nextLocale: 'nl' })

parsedUrl = url.parse(await browser.eval('window.location.href'), true)
expect(parsedUrl.pathname).toBe('/links')
expect(parsedUrl.query).toEqual({ nextLocale: 'nl' })

await browser.eval('window.history.forward()')
await browser.waitForElementByCss('#gsp')

expect(await browser.elementByCss('#router-pathname').text()).toBe(
'/gsp/fallback/[slug]'
)
expect(await browser.elementByCss('#router-as-path').text()).toBe(
'/gsp/fallback/first'
)
expect(await browser.elementByCss('#router-locale').text()).toBe('nl')
expect(
JSON.parse(await browser.elementByCss('#router-locales').text())
).toEqual(locales)
expect(
JSON.parse(await browser.elementByCss('#router-query').text())
).toEqual({ slug: 'first' })

parsedUrl = url.parse(await browser.eval('window.location.href'), true)
expect(parsedUrl.pathname).toBe('/nl/gsp/fallback/first')
expect(parsedUrl.query).toEqual({})
})

it('should navigate with locale false correctly', async () => {
const browser = await webdriver(appPort, '/locale-false?nextLocale=fr')
await addDefaultLocaleCookie(browser)
await browser.eval('window.beforeNav = 1')

expect(await browser.elementByCss('#router-pathname').text()).toBe(
'/locale-false'
)
expect(await browser.elementByCss('#router-as-path').text()).toBe(
'/locale-false?nextLocale=fr'
)
expect(await browser.elementByCss('#router-locale').text()).toBe('en-US')
expect(
JSON.parse(await browser.elementByCss('#router-locales').text())
).toEqual(locales)
expect(
JSON.parse(await browser.elementByCss('#router-query').text())
).toEqual({ nextLocale: 'fr' })

await browser.elementByCss('#to-another').click()
await browser.waitForElementByCss('#another')

expect(await browser.elementByCss('#router-pathname').text()).toBe(
'/another'
)
expect(await browser.elementByCss('#router-as-path').text()).toBe(
'/another'
)
expect(await browser.elementByCss('#router-locale').text()).toBe('fr')
expect(
JSON.parse(await browser.elementByCss('#router-locales').text())
).toEqual(locales)
expect(
JSON.parse(await browser.elementByCss('#router-query').text())
).toEqual({})

let parsedUrl = url.parse(await browser.eval('window.location.href'), true)
expect(parsedUrl.pathname).toBe('/fr/another')
expect(parsedUrl.query).toEqual({})

await browser.eval('window.history.back()')
await browser.waitForElementByCss('#links')

expect(await browser.elementByCss('#router-pathname').text()).toBe(
'/locale-false'
)
expect(await browser.elementByCss('#router-as-path').text()).toBe(
'/locale-false?nextLocale=fr'
)
expect(await browser.elementByCss('#router-locale').text()).toBe('en-US')
expect(
JSON.parse(await browser.elementByCss('#router-locales').text())
).toEqual(locales)
expect(
JSON.parse(await browser.elementByCss('#router-query').text())
).toEqual({ nextLocale: 'fr' })

parsedUrl = url.parse(await browser.eval('window.location.href'), true)
expect(parsedUrl.pathname).toBe('/locale-false')
expect(parsedUrl.query).toEqual({ nextLocale: 'fr' })

await browser.eval('window.history.forward()')
await browser.waitForElementByCss('#another')

expect(await browser.elementByCss('#router-pathname').text()).toBe(
'/another'
)
expect(await browser.elementByCss('#router-as-path').text()).toBe(
'/another'
)
expect(await browser.elementByCss('#router-locale').text()).toBe('fr')
expect(
JSON.parse(await browser.elementByCss('#router-locales').text())
).toEqual(locales)
expect(
JSON.parse(await browser.elementByCss('#router-query').text())
).toEqual({})

parsedUrl = url.parse(await browser.eval('window.location.href'), true)
expect(parsedUrl.pathname).toBe('/fr/another')
expect(parsedUrl.query).toEqual({})
expect(await browser.eval('window.beforeNav')).toBe(1)
})

it('should navigate with locale false correctly GSP', async () => {
const browser = await webdriver(appPort, '/locale-false?nextLocale=nl')
await addDefaultLocaleCookie(browser)

expect(await browser.elementByCss('#router-pathname').text()).toBe(
'/locale-false'
)
expect(await browser.elementByCss('#router-as-path').text()).toBe(
'/locale-false?nextLocale=nl'
)
expect(await browser.elementByCss('#router-locale').text()).toBe('en-US')
expect(
JSON.parse(await browser.elementByCss('#router-locales').text())
).toEqual(locales)
expect(
JSON.parse(await browser.elementByCss('#router-query').text())
).toEqual({ nextLocale: 'nl' })

await browser.elementByCss('#to-fallback-first').click()
await browser.waitForElementByCss('#gsp')

expect(await browser.elementByCss('#router-pathname').text()).toBe(
'/gsp/fallback/[slug]'
)
expect(await browser.elementByCss('#router-as-path').text()).toBe(
'/gsp/fallback/first'
)
expect(await browser.elementByCss('#router-locale').text()).toBe('nl')
expect(
JSON.parse(await browser.elementByCss('#router-locales').text())
).toEqual(locales)
expect(
JSON.parse(await browser.elementByCss('#router-query').text())
).toEqual({ slug: 'first' })

let parsedUrl = url.parse(await browser.eval('window.location.href'), true)
expect(parsedUrl.pathname).toBe('/nl/gsp/fallback/first')
expect(parsedUrl.query).toEqual({})

await browser.eval('window.history.back()')
await browser.waitForElementByCss('#links')

expect(await browser.elementByCss('#router-pathname').text()).toBe(
'/locale-false'
)
expect(await browser.elementByCss('#router-as-path').text()).toBe(
'/locale-false?nextLocale=nl'
)
expect(await browser.elementByCss('#router-locale').text()).toBe('en-US')
expect(
JSON.parse(await browser.elementByCss('#router-locales').text())
).toEqual(locales)
expect(
JSON.parse(await browser.elementByCss('#router-query').text())
).toEqual({ nextLocale: 'nl' })

parsedUrl = url.parse(await browser.eval('window.location.href'), true)
expect(parsedUrl.pathname).toBe('/nl/links')
expect(parsedUrl.pathname).toBe('/locale-false')
expect(parsedUrl.query).toEqual({ nextLocale: 'nl' })

await browser.eval('window.history.forward()')
Expand Down

0 comments on commit 9bbfa0e

Please sign in to comment.