From 206c3f38153e0c8560b630e20d5438ecc173ebcc Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Thu, 11 Apr 2024 13:36:00 +0100 Subject: [PATCH] fix(i18n): fallback SSR --- .changeset/old-pugs-jog.md | 5 ++++ packages/astro/src/i18n/index.ts | 7 ++++- packages/astro/src/i18n/middleware.ts | 1 - packages/astro/test/i18n-routing.test.js | 33 ++++++++++++++++++++++++ 4 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 .changeset/old-pugs-jog.md diff --git a/.changeset/old-pugs-jog.md b/.changeset/old-pugs-jog.md new file mode 100644 index 000000000000..8b5aa217edd1 --- /dev/null +++ b/.changeset/old-pugs-jog.md @@ -0,0 +1,5 @@ +--- +"astro": patch +--- + +Fixes a case where the i18n fallback faild to correctly redirect to the index when the fallback is enabled in SSR diff --git a/packages/astro/src/i18n/index.ts b/packages/astro/src/i18n/index.ts index 32cd24f9cff0..b8114019bdcf 100644 --- a/packages/astro/src/i18n/index.ts +++ b/packages/astro/src/i18n/index.ts @@ -343,6 +343,7 @@ export function redirectToFallback({ locales, defaultLocale, strategy, + base, }: MiddlewarePayload) { return function (context: APIContext, response: Response): Response { if (response.status >= 300 && fallback) { @@ -370,7 +371,11 @@ export function redirectToFallback({ // If a locale falls back to the default locale, we want to **remove** the locale because // the default locale doesn't have a prefix if (pathFallbackLocale === defaultLocale && strategy === 'pathname-prefix-other-locales') { - newPathname = context.url.pathname.replace(`/${urlLocale}`, ``); + if (context.url.pathname.includes(`${base}`)) { + newPathname = context.url.pathname.replace(`/${urlLocale}`, ``); + } else { + newPathname = context.url.pathname.replace(`/${urlLocale}`, `/`); + } } else { newPathname = context.url.pathname.replace(`/${urlLocale}`, `/${pathFallbackLocale}`); } diff --git a/packages/astro/src/i18n/middleware.ts b/packages/astro/src/i18n/middleware.ts index 42c0f0e763df..df5d63761c74 100644 --- a/packages/astro/src/i18n/middleware.ts +++ b/packages/astro/src/i18n/middleware.ts @@ -3,7 +3,6 @@ import type { SSRManifestI18n } from '../core/app/types.js'; import { ROUTE_TYPE_HEADER } from '../core/constants.js'; import { type MiddlewarePayload, - getPathByLocale, normalizeTheLocale, notFound, redirectToDefaultLocale, diff --git a/packages/astro/test/i18n-routing.test.js b/packages/astro/test/i18n-routing.test.js index 6e1503819b40..609af16f8421 100644 --- a/packages/astro/test/i18n-routing.test.js +++ b/packages/astro/test/i18n-routing.test.js @@ -1871,3 +1871,36 @@ describe('i18n routing does not break assets and endpoints', () => { }); }); }); + +describe('SSR fallback from missing locale index to default locale index', () => { + /** @type {import('./test-utils').Fixture} */ + let fixture; + let app; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/i18n-routing-prefix-other-locales/', + output: 'server', + adapter: testAdapter(), + i18n: { + defaultLocale: 'en', + locales: ['en', 'fr'], + routing: { + prefixDefaultLocale: false, + }, + fallback: { + fr: 'en', + }, + }, + }); + await fixture.build(); + app = await fixture.loadTestAdapterApp(); + }); + + it('should correctly redirect', async () => { + let request = new Request('http://example.com/fr'); + let response = await app.render(request); + assert.equal(response.status, 302); + assert.equal(response.headers.get('location'), '/'); + }); +});