Ensure locale is added/stripped correctly (#18712)

This makes sure we don't incorrectly strip locale characters from the path if it is not a locale prefix e.g. `/fr` should not be removed from `/frank`. Additional tests have been added to ensure this isn't stripped for this case.

Fixes: https://github.com/vercel/next.js/issues/18332
This commit is contained in:
JJ Kasper 2020-11-02 17:32:56 -06:00 committed by GitHub
parent 7b6a61a750
commit 3f84a55ba3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 91 additions and 2 deletions

View file

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

View file

@ -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,
},
}
}

View file

@ -172,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,
@ -1092,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() {