From 6189fe969314e3f97f5eac8d0718c07c79af478f Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Mon, 28 Dec 2020 11:58:07 -0600 Subject: [PATCH] Ensure query is present with i18n and history navigation (#20441) This makes sure the query isn't dropped when doing a history navigation with i18n. Additional tests have been added to ensure this is working correctly as well. Fixes: https://github.com/vercel/next.js/issues/20212 --- .../next/next-server/lib/router/router.ts | 10 +++- .../pages/gssp/index.js | 8 +++- .../i18n-support/pages/gssp/index.js | 8 +++- test/integration/i18n-support/test/shared.js | 46 ++++++++++++++++++- 4 files changed, 68 insertions(+), 4 deletions(-) diff --git a/packages/next/next-server/lib/router/router.ts b/packages/next/next-server/lib/router/router.ts index 692df9dbc4..74622ecb6c 100644 --- a/packages/next/next-server/lib/router/router.ts +++ b/packages/next/next-server/lib/router/router.ts @@ -635,9 +635,17 @@ export default class Router implements BaseRouter { parsedAs.pathname, this.locales ) + if (localePathResult.detectedLocale) { this.locale = localePathResult.detectedLocale - url = addBasePath(localePathResult.pathname) + parsedAs.pathname = addBasePath(parsedAs.pathname) + as = formatWithValidation(parsedAs) + url = addBasePath( + normalizeLocalePath( + hasBasePath(url) ? delBasePath(url) : url, + this.locales + ).pathname + ) } // if the locale isn't configured hard navigate to show 404 page diff --git a/test/integration/i18n-support-base-path/pages/gssp/index.js b/test/integration/i18n-support-base-path/pages/gssp/index.js index dfae0973c5..4d566474e1 100644 --- a/test/integration/i18n-support-base-path/pages/gssp/index.js +++ b/test/integration/i18n-support-base-path/pages/gssp/index.js @@ -22,9 +22,15 @@ export default function Page(props) { ) } -export const getServerSideProps = ({ locale, locales, defaultLocale }) => { +export const getServerSideProps = ({ + locale, + locales, + defaultLocale, + query, +}) => { return { props: { + query, locale, locales, defaultLocale, diff --git a/test/integration/i18n-support/pages/gssp/index.js b/test/integration/i18n-support/pages/gssp/index.js index dfae0973c5..4d566474e1 100644 --- a/test/integration/i18n-support/pages/gssp/index.js +++ b/test/integration/i18n-support/pages/gssp/index.js @@ -22,9 +22,15 @@ export default function Page(props) { ) } -export const getServerSideProps = ({ locale, locales, defaultLocale }) => { +export const getServerSideProps = ({ + locale, + locales, + defaultLocale, + query, +}) => { return { props: { + query, locale, locales, defaultLocale, diff --git a/test/integration/i18n-support/test/shared.js b/test/integration/i18n-support/test/shared.js index eebc8471ea..2e4bd25a4a 100644 --- a/test/integration/i18n-support/test/shared.js +++ b/test/integration/i18n-support/test/shared.js @@ -27,6 +27,46 @@ async function addDefaultLocaleCookie(browser) { } export function runTests(ctx) { + it('should navigate through history with query correctly', async () => { + const browser = await webdriver(ctx.appPort, `${ctx.basePath || '/'}`) + + await browser.eval(`(function() { + window.beforeNav = 1 + window.next.router.push( + window.next.router.pathname, + window.next.router.asPath, + { locale: 'nl' } + ) + window.next.router.push( + '/gssp?page=1' + ) + })()`) + + await browser.waitForElementByCss('#gssp') + + const props = JSON.parse(await browser.elementByCss('#props').text()) + expect(props).toEqual({ + locale: 'nl', + locales, + defaultLocale: 'en-US', + query: { page: '1' }, + }) + + await browser + .back() + .waitForElementByCss('#index') + .forward() + .waitForElementByCss('#gssp') + + const props2 = JSON.parse(await browser.elementByCss('#props').text()) + expect(props2).toEqual({ + locale: 'nl', + locales, + defaultLocale: 'en-US', + query: { page: '1' }, + }) + }) + if (!ctx.isDev) { it('should not contain backslashes in pages-manifest', async () => { const pagesManifestContent = await fs.readFile( @@ -1310,7 +1350,7 @@ export function runTests(ctx) { } }) - it('should provide correctly defaultLocale for locale domain', async () => { + it('should provide defaultLocale correctly for locale domain', async () => { for (const { host, locale } of [ { host: 'example.fr', locale: 'fr' }, { host: 'example.be', locale: 'nl-BE' }, @@ -1336,6 +1376,7 @@ export function runTests(ctx) { defaultLocale: locale, locale, locales, + query: {}, }) expect(JSON.parse($('#router-locales').text())).toEqual(locales) } @@ -1954,6 +1995,7 @@ export function runTests(ctx) { expect(JSON.parse($('#props').text())).toEqual({ locale: 'en-US', locales, + query: {}, defaultLocale: 'en-US', }) expect($('#router-locale').text()).toBe('en-US') @@ -2165,6 +2207,7 @@ export function runTests(ctx) { expect(JSON.parse($('#props').text())).toEqual({ locale: 'en-US', locales, + query: {}, defaultLocale: 'en-US', }) expect($('#router-locale').text()).toBe('en-US') @@ -2178,6 +2221,7 @@ export function runTests(ctx) { expect(JSON.parse($2('#props').text())).toEqual({ locale: 'nl-NL', locales, + query: {}, defaultLocale: 'en-US', }) expect($2('#router-locale').text()).toBe('nl-NL') -- GitLab