Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/canary' into basepath/multi-le…
Browse files Browse the repository at this point in the history
…vel-public
  • Loading branch information
ijjk committed Nov 3, 2020
2 parents f2b0f24 + 3f84a55 commit 146ddb2
Show file tree
Hide file tree
Showing 12 changed files with 188 additions and 7 deletions.
Expand Up @@ -370,7 +370,10 @@ const nextServerlessLoader: loader.Loader = function () {
return
}
detectedLocale = detectedLocale || defaultLocale
detectedLocale =
localePathResult.detectedLocale ||
(detectedDomain && detectedDomain.defaultLocale) ||
defaultLocale
`
: `
const i18n = {}
Expand Down
14 changes: 12 additions & 2 deletions packages/next/client/index.tsx
Expand Up @@ -92,11 +92,21 @@ if (process.env.__NEXT_I18N_SUPPORT) {
detectDomainLocale,
} = require('../next-server/lib/i18n/detect-domain-locale') as typeof import('../next-server/lib/i18n/detect-domain-locale')

const {
parseRelativeUrl,
} = require('../next-server/lib/router/utils/parse-relative-url') as typeof import('../next-server/lib/router/utils/parse-relative-url')

const {
formatUrl,
} = require('../next-server/lib/router/utils/format-url') as typeof import('../next-server/lib/router/utils/format-url')

if (locales) {
const localePathResult = normalizeLocalePath(asPath, locales)
const parsedAs = parseRelativeUrl(asPath)
const localePathResult = normalizeLocalePath(parsedAs.pathname, locales)

if (localePathResult.detectedLocale) {
asPath = asPath.substr(localePathResult.detectedLocale.length + 1) || '/'
parsedAs.pathname = localePathResult.pathname
asPath = formatUrl(parsedAs)
} else {
// derive the default locale if it wasn't detected in the asPath
// since we don't prerender static pages with all possible default
Expand Down
8 changes: 6 additions & 2 deletions packages/next/next-server/lib/router/router.ts
Expand Up @@ -62,7 +62,10 @@ export function addLocale(
defaultLocale?: string
) {
if (process.env.__NEXT_I18N_SUPPORT) {
return locale && locale !== defaultLocale && !path.startsWith('/' + locale)
return locale &&
locale !== defaultLocale &&
!path.startsWith('/' + locale + '/') &&
path !== '/' + locale
? addPathPrefix(path, '/' + locale)
: path
}
Expand All @@ -71,7 +74,8 @@ export function addLocale(

export function delLocale(path: string, locale?: string) {
if (process.env.__NEXT_I18N_SUPPORT) {
return locale && path.startsWith('/' + locale)
return locale &&
(path.startsWith('/' + locale + '/') || path === '/' + locale)
? path.substr(locale.length + 1) || '/'
: path
}
Expand Down
6 changes: 5 additions & 1 deletion packages/next/next-server/server/next-server.ts
Expand Up @@ -429,7 +429,11 @@ export default class Server {
res.end()
return
}
parsedUrl.query.__nextLocale = detectedLocale || defaultLocale

parsedUrl.query.__nextLocale =
localePathResult.detectedLocale ||
detectedDomain?.defaultLocale ||
defaultLocale
}

res.statusCode = 200
Expand Down
19 changes: 19 additions & 0 deletions test/integration/i18n-support/pages/_app.js
@@ -0,0 +1,19 @@
if (typeof window !== 'undefined') {
window.caughtWarns = []

const origWarn = window.console.warn
const origError = window.console.error

window.console.warn = function (...args) {
window.caughtWarns.push(args.join(' '))
origWarn(...args)
}
window.console.error = function (...args) {
window.caughtWarns.push(args.join(' '))
origError(...args)
}
}

export default function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
1 change: 1 addition & 0 deletions test/integration/i18n-support/pages/another.js
Expand Up @@ -9,6 +9,7 @@ export default function Page(props) {
<p id="another">another 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
56 changes: 56 additions & 0 deletions test/integration/i18n-support/pages/frank.js
@@ -0,0 +1,56 @@
import Link from 'next/link'
import { useRouter } from 'next/router'

export default function Page(props) {
const router = useRouter()

return (
<>
<p id="frank">frank 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="/another">
<a id="to-another">to /another</a>
</Link>
<br />
<Link href="/gsp">
<a id="to-gsp">to /gsp</a>
</Link>
<br />
<Link href="/gsp/fallback/first">
<a id="to-fallback-first">to /gsp/fallback/first</a>
</Link>
<br />
<Link href="/gsp/fallback/hello">
<a id="to-fallback-hello">to /gsp/fallback/hello</a>
</Link>
<br />
<Link href="/gsp/no-fallback/first">
<a id="to-no-fallback-first">to /gsp/no-fallback/first</a>
</Link>
<br />
<Link href="/gssp">
<a id="to-gssp">to /gssp</a>
</Link>
<br />
<Link href="/gssp/first">
<a id="to-gssp-slug">to /gssp/first</a>
</Link>
<br />
</>
)
}

export const getStaticProps = ({ locale, locales, defaultLocale }) => {
return {
props: {
locale,
locales,
defaultLocale,
},
}
}
1 change: 1 addition & 0 deletions test/integration/i18n-support/pages/gsp/fallback/[slug].js
Expand Up @@ -11,6 +11,7 @@ export default function Page(props) {
<p id="gsp">gsp 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
Expand Up @@ -11,6 +11,7 @@ export default function Page(props) {
<p id="gsp">gsp 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/index.js
Expand Up @@ -9,6 +9,7 @@ export default function Page(props) {
<p id="index">index 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/links.js
Expand Up @@ -10,6 +10,7 @@ export default function Page(props) {
<p id="links">links 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
82 changes: 81 additions & 1 deletion test/integration/i18n-support/test/index.test.js
Expand Up @@ -41,6 +41,49 @@ async function addDefaultLocaleCookie(browser) {
}

function runTests(isDev) {
it('should have correct values for non-prefixed path', async () => {
for (const paths of [
['/links', '/links'],
['/another', '/another'],
['/gsp/fallback/first', '/gsp/fallback/[slug]'],
['/gsp/no-fallback/first', '/gsp/no-fallback/[slug]'],
]) {
const [asPath, pathname] = paths

const res = await fetchViaHTTP(appPort, asPath, undefined, {
redirect: 'manual',
headers: {
'accept-language': 'fr',
},
})

expect(res.status).toBe(200)
const $ = cheerio.load(await res.text())
expect($('html').attr('lang')).toBe('en-US')
expect($('#router-locale').text()).toBe('en-US')
expect($('#router-default-locale').text()).toBe('en-US')
expect(JSON.parse($('#router-locales').text())).toEqual(locales)
expect($('#router-pathname').text()).toBe(pathname)
expect($('#router-as-path').text()).toBe(asPath)
}
})

it('should not have hydration mis-match from hash', async () => {
const browser = await webdriver(appPort, '/en#')

expect(await browser.elementByCss('html').getAttribute('lang')).toBe('en')
expect(await browser.elementByCss('#router-locale').text()).toBe('en')
expect(await browser.elementByCss('#router-default-locale').text()).toBe(
'en-US'
)
expect(
JSON.parse(await browser.elementByCss('#router-locales').text())
).toEqual(locales)
expect(await browser.elementByCss('#router-pathname').text()).toBe('/')
expect(await browser.elementByCss('#router-as-path').text()).toBe('/')
expect(await browser.eval('window.caughtWarns')).toEqual([])
})

if (!isDev) {
it('should add i18n config to routes-manifest', async () => {
const routesManifest = await fs.readJSON(
Expand Down Expand Up @@ -129,6 +172,11 @@ function runTests(isDev) {
initialRevalidateSeconds: false,
srcRoute: '/not-found/fallback/[slug]',
},
'/frank': {
dataRoute: `/_next/data/${buildId}/frank.json`,
initialRevalidateSeconds: false,
srcRoute: null,
},
'/gsp': {
dataRoute: `/_next/data/${buildId}/gsp.json`,
srcRoute: null,
Expand Down Expand Up @@ -365,11 +413,13 @@ function runTests(isDev) {
expect(parsedUrl.pathname).toBe('/fr/another')
expect(parsedUrl.query).toEqual({})
expect(await browser.eval('window.beforeNav')).toBe(1)
expect(await browser.eval('window.caughtWarns')).toEqual([])
})

it('should navigate with locale prop correctly GSP', async () => {
const browser = await webdriver(appPort, '/links?nextLocale=nl')
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 @@ -451,6 +501,8 @@ function runTests(isDev) {
parsedUrl = url.parse(await browser.eval('window.location.href'), true)
expect(parsedUrl.pathname).toBe('/nl/gsp/fallback/first')
expect(parsedUrl.query).toEqual({})
expect(await browser.eval('window.beforeNav')).toBe(1)
expect(await browser.eval('window.caughtWarns')).toEqual([])
})

it('should navigate with locale false correctly', async () => {
Expand Down Expand Up @@ -571,11 +623,13 @@ function runTests(isDev) {
expect(parsedUrl.pathname).toBe('/fr/another')
expect(parsedUrl.query).toEqual({})
expect(await browser.eval('window.beforeNav')).toBe(1)
expect(await browser.eval('window.caughtWarns')).toEqual([])
})

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

expect(await browser.elementByCss('#router-pathname').text()).toBe(
'/locale-false'
Expand Down Expand Up @@ -661,6 +715,8 @@ function runTests(isDev) {
parsedUrl = url.parse(await browser.eval('window.location.href'), true)
expect(parsedUrl.pathname).toBe('/nl/gsp/fallback/first')
expect(parsedUrl.query).toEqual({})
expect(await browser.eval('window.beforeNav')).toBe(1)
expect(await browser.eval('window.caughtWarns')).toEqual([])
})

it('should update asPath on the client correctly', async () => {
Expand Down Expand Up @@ -1041,6 +1097,30 @@ function runTests(isDev) {
}
})

it('should transition on client properly for page that starts with locale', async () => {
const browser = await webdriver(appPort, '/fr')
await browser.eval(`(function() {
window.beforeNav = 1
window.next.router.push('/frank')
})()`)

await browser.waitForElementByCss('#frank')

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({})
expect(await browser.elementByCss('#router-pathname').text()).toBe('/frank')
expect(await browser.elementByCss('#router-as-path').text()).toBe('/frank')
expect(
url.parse(await browser.eval(() => window.location.href)).pathname
).toBe('/fr/frank')
expect(await browser.eval('window.beforeNav')).toBe(1)
})

it('should 404 for GSP that returned notFound on client-transition', async () => {
const browser = await webdriver(appPort, '/en')
await browser.eval(`(function() {
Expand Down Expand Up @@ -1581,7 +1661,7 @@ function runTests(isDev) {
it('should load getStaticProps non-fallback correctly another locale via cookie', async () => {
const html = await renderViaHTTP(
appPort,
'/gsp/no-fallback/second',
'/nl-NL/gsp/no-fallback/second',
{},
{
headers: {
Expand Down

0 comments on commit 146ddb2

Please sign in to comment.