From e1737809db9a16e622e9ca7772d0a0f3d9db71d2 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Fri, 20 Nov 2020 15:50:26 -0600 Subject: [PATCH] Update fallback locale for locale: false (#19322) This updates the fallback locale for `locale: false` to be the `defaultLocale` instead of the currently active `locale` as it allows passing through URLs more seamlessly as a URL without the locale prefixed can be treated as the `defaultLocale` instead of having to worry if the locale matches the currently active locale. This also ensures `locale={false}` is tested in the i18n-support-catchall suite Closes: https://github.com/vercel/next.js/issues/19048 --- .../next/next-server/lib/router/router.ts | 9 ++- .../pages/locale-false.js | 8 ++ .../pages/[[...slug]].js | 4 +- .../i18n-support/pages/locale-false.js | 8 ++ test/integration/i18n-support/test/shared.js | 73 ++++++++----------- 5 files changed, 53 insertions(+), 49 deletions(-) diff --git a/packages/next/next-server/lib/router/router.ts b/packages/next/next-server/lib/router/router.ts index ec81aacb34..e37a9b3e99 100644 --- a/packages/next/next-server/lib/router/router.ts +++ b/packages/next/next-server/lib/router/router.ts @@ -616,7 +616,10 @@ export default class Router implements BaseRouter { let localeChange = options.locale !== this.locale if (process.env.__NEXT_I18N_SUPPORT) { - this.locale = options.locale || this.locale + this.locale = + options.locale === false + ? this.defaultLocale + : options.locale || this.locale if (typeof options.locale === 'undefined') { options.locale = this.locale @@ -627,12 +630,10 @@ export default class Router implements BaseRouter { } = require('../i18n/normalize-locale-path') as typeof import('../i18n/normalize-locale-path') const parsedAs = parseRelativeUrl(hasBasePath(as) ? delBasePath(as) : as) - const localePathResult = normalizeLocalePath( parsedAs.pathname, this.locales ) - if (localePathResult.detectedLocale) { this.locale = localePathResult.detectedLocale url = addBasePath(localePathResult.pathname) @@ -1235,7 +1236,7 @@ export default class Router implements BaseRouter { this.locales ) parsedAs.pathname = localePathResult.pathname - options.locale = localePathResult.detectedLocale || options.locale + options.locale = localePathResult.detectedLocale || this.defaultLocale asPath = formatWithValidation(parsedAs) } } diff --git a/test/integration/i18n-support-base-path/pages/locale-false.js b/test/integration/i18n-support-base-path/pages/locale-false.js index 8c1f618686..e0de4c056a 100644 --- a/test/integration/i18n-support-base-path/pages/locale-false.js +++ b/test/integration/i18n-support-base-path/pages/locale-false.js @@ -42,6 +42,14 @@ export default function Page(props) { to /gssp/first
+ + to /gssp/first (default locale) + +
+ + to /gsp (default locale) + +
) } diff --git a/test/integration/i18n-support-catchall/pages/[[...slug]].js b/test/integration/i18n-support-catchall/pages/[[...slug]].js index be4f2f3fb3..33504f801f 100644 --- a/test/integration/i18n-support-catchall/pages/[[...slug]].js +++ b/test/integration/i18n-support-catchall/pages/[[...slug]].js @@ -35,12 +35,12 @@ export default function Page(props) {
- + to /fr
- + to /fr/another
diff --git a/test/integration/i18n-support/pages/locale-false.js b/test/integration/i18n-support/pages/locale-false.js index 8c1f618686..e0de4c056a 100644 --- a/test/integration/i18n-support/pages/locale-false.js +++ b/test/integration/i18n-support/pages/locale-false.js @@ -42,6 +42,14 @@ export default function Page(props) { to /gssp/first
+ + to /gssp/first (default locale) + +
+ + to /gsp (default locale) + +
) } diff --git a/test/integration/i18n-support/test/shared.js b/test/integration/i18n-support/test/shared.js index 03c4abc6fd..d0656a6a05 100644 --- a/test/integration/i18n-support/test/shared.js +++ b/test/integration/i18n-support/test/shared.js @@ -27,56 +27,42 @@ async function addDefaultLocaleCookie(browser) { } export function runTests(ctx) { - it('should trigger full navigation for unsupported locale', async () => { - const browser = await webdriver(ctx.appPort, '/') + it('should use default locale when no locale is in href with locale false', async () => { + const browser = await webdriver( + ctx.appPort, + `${ctx.basePath}/nl/locale-false?nextLocale=fr` + ) await browser.eval('window.beforeNav = 1') - await browser.eval(`(function() { - window.next.router.push('/auto-export', '/auto-export', { locale: 'no' }) - })()`) - - await browser.waitForElementByCss('#not-found') - expect(await browser.eval('window.beforeNav')).toBe(null) - - const props = JSON.parse(await browser.elementByCss('#props').text()) - expect(props.is404).toBe(true) - expect(props.locale).toBe('en-US') - expect(props.locales).toEqual(locales) - expect(props.defaultLocale).toBe('en-US') - }) - it('should 404 for non configured locales direct visit', async () => { - for (const [pathname, gssp] of [ - ['/gsp', true], - ['/gssp', true], - ['/auto-export'], - ['/'], - ['/gsp/fallback/first'], - ]) { - const res = await fetchViaHTTP( - ctx.appPort, - `/no${pathname === '/' ? '' : pathname}`, - undefined, - { - redirect: 'manual', - } - ) + if (!ctx.isDev) { + await browser.eval(`(function() { + document.querySelector('#to-gssp-slug-default').scrollIntoView() + document.querySelector('#to-gsp-default').scrollIntoView() + })()`) - expect(res.status).toBe(404) + await check(async () => { + const hrefs = await browser.eval(`Object.keys(window.next.router.sdc)`) + hrefs.sort() - if (gssp) { - const res = await fetchViaHTTP( - ctx.appPort, - `/_next/data/${ctx.buildId}/no${pathname}.json`, - undefined, - { - redirect: 'manual', - } + assert.deepEqual( + hrefs.map((href) => + new URL(href).pathname + .replace(ctx.basePath, '') + .replace(/^\/_next\/data\/[^/]+/, '') + ), + [ + '/en-US/gsp.json', + '/fr/gsp.json', + '/fr/gsp/fallback/first.json', + '/fr/gsp/fallback/hello.json', + ] ) - - expect(res.status).toBe(404) - } + return 'yes' + }, 'yes') } + + expect(await browser.eval('window.beforeNav')).toBe(1) }) if (ctx.isDev) { @@ -802,6 +788,7 @@ export function runTests(ctx) { .replace(/^\/_next\/data\/[^/]+/, '') ), [ + '/en-US/gsp.json', '/fr/gsp.json', '/fr/gsp/fallback/first.json', '/fr/gsp/fallback/hello.json', -- GitLab