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:
parent
7b6a61a750
commit
3f84a55ba3
3 changed files with 91 additions and 2 deletions
|
@ -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
|
||||
}
|
||||
|
|
56
test/integration/i18n-support/pages/frank.js
Normal file
56
test/integration/i18n-support/pages/frank.js
Normal 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,
|
||||
},
|
||||
}
|
||||
}
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in a new issue