diff --git a/packages/next/next-server/lib/router/router.ts b/packages/next/next-server/lib/router/router.ts index e9502affb3ba2..28e6d864c9ac4 100644 --- a/packages/next/next-server/lib/router/router.ts +++ b/packages/next/next-server/lib/router/router.ts @@ -113,10 +113,13 @@ export function addLocale( defaultLocale?: string ) { if (process.env.__NEXT_I18N_SUPPORT) { + const pathLower = path.toLowerCase() + const localeLower = locale && locale.toLowerCase() + return locale && locale !== defaultLocale && - !path.startsWith('/' + locale + '/') && - path !== '/' + locale + !pathLower.startsWith('/' + localeLower + '/') && + pathLower !== '/' + localeLower ? addPathPrefix(path, '/' + locale) : path } @@ -126,8 +129,12 @@ export function addLocale( export function delLocale(path: string, locale?: string) { if (process.env.__NEXT_I18N_SUPPORT) { const pathname = pathNoQueryHash(path) + const pathLower = pathname.toLowerCase() + const localeLower = locale && locale.toLowerCase() + return locale && - (pathname.startsWith('/' + locale + '/') || pathname === '/' + locale) + (pathLower.startsWith('/' + localeLower + '/') || + pathLower === '/' + localeLower) ? (pathname.length === locale.length + 1 ? '/' : '') + path.substr(locale.length + 1) : path diff --git a/test/integration/i18n-support/test/shared.js b/test/integration/i18n-support/test/shared.js index 615908aa94b46..d8c5326d88cbe 100644 --- a/test/integration/i18n-support/test/shared.js +++ b/test/integration/i18n-support/test/shared.js @@ -37,6 +37,40 @@ async function addDefaultLocaleCookie(browser) { } export function runTests(ctx) { + it('should handle navigating back to different casing of locale', async () => { + const browser = await webdriver( + ctx.appPort, + `${ctx.basePath || ''}/FR/links` + ) + + expect(await browser.eval(() => document.location.pathname)).toBe( + `${ctx.basePath || ''}/FR/links` + ) + expect(await browser.elementByCss('#router-pathname').text()).toBe('/links') + expect(await browser.elementByCss('#router-locale').text()).toBe('fr') + + await browser + .elementByCss('#to-another') + .click() + .waitForElementByCss('#another') + + expect(await browser.eval(() => document.location.pathname)).toBe( + `${ctx.basePath || ''}/fr/another` + ) + expect(await browser.elementByCss('#router-pathname').text()).toBe( + '/another' + ) + expect(await browser.elementByCss('#router-locale').text()).toBe('fr') + + await browser.back().waitForElementByCss('#links') + + expect(await browser.eval(() => document.location.pathname)).toBe( + `${ctx.basePath || ''}/FR/links` + ) + expect(await browser.elementByCss('#router-pathname').text()).toBe('/links') + expect(await browser.elementByCss('#router-locale').text()).toBe('fr') + }) + it('should have correct initial query values for fallback', async () => { const res = await fetchViaHTTP( ctx.appPort,