diff --git a/.changeset/warm-poems-breathe.md b/.changeset/warm-poems-breathe.md new file mode 100644 index 000000000000..e4e9acf80d52 --- /dev/null +++ b/.changeset/warm-poems-breathe.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Fixes an issue where `Astro.currentLocale` was not correctly returning the locale for 404 and 500 pages. diff --git a/packages/astro/src/core/render-context.ts b/packages/astro/src/core/render-context.ts index 7ccbdd2ef564..5b6243f30a6f 100644 --- a/packages/astro/src/core/render-context.ts +++ b/packages/astro/src/core/render-context.ts @@ -36,6 +36,7 @@ import { callMiddleware } from './middleware/callMiddleware.js'; import { sequence } from './middleware/index.js'; import { renderRedirect } from './redirects/render.js'; import { type Pipeline, Slots, getParams, getProps } from './render/index.js'; +import { isRoute404or500 } from './routing/match.js'; import { copyRequest, setOriginPathname } from './routing/rewrite.js'; export const apiContextRoutesSymbol = Symbol.for('context.routes'); @@ -541,11 +542,9 @@ export class RenderContext { } let computedLocale; - if (routeData.pathname) { - computedLocale = computeCurrentLocale(routeData.pathname, locales, defaultLocale); - } else { - computedLocale = computeCurrentLocale(url.pathname, locales, defaultLocale); - } + const pathname = + routeData.pathname && !isRoute404or500(routeData) ? routeData.pathname : url.pathname; + computedLocale = computeCurrentLocale(pathname, locales, defaultLocale); this.#currentLocale = computedLocale ?? fallbackTo; return this.#currentLocale; diff --git a/packages/astro/src/core/routing/match.ts b/packages/astro/src/core/routing/match.ts index 40a8b95fba29..dbcd173761d7 100644 --- a/packages/astro/src/core/routing/match.ts +++ b/packages/astro/src/core/routing/match.ts @@ -15,3 +15,13 @@ export function matchRoute(pathname: string, manifest: ManifestData): RouteData export function matchAllRoutes(pathname: string, manifest: ManifestData): RouteData[] { return manifest.routes.filter((route) => route.pattern.test(decodeURI(pathname))); } + +/** + * Determines if the given route matches a 404 or 500 error page. + * + * @param {RouteData} route - The route data to check. + * @returns {boolean} `true` if the route matches a 404 or 500 error page, otherwise `false`. + */ +export function isRoute404or500(route: RouteData): boolean { + return route.pattern.test('/404') || route.pattern.test('/500'); +} diff --git a/packages/astro/test/fixtures/i18n-routing/src/pages/404.astro b/packages/astro/test/fixtures/i18n-routing/src/pages/404.astro new file mode 100644 index 000000000000..fce4a30b836c --- /dev/null +++ b/packages/astro/test/fixtures/i18n-routing/src/pages/404.astro @@ -0,0 +1,12 @@ +--- +const currentLocale = Astro.currentLocale; +--- + + + 404 - Not Found + + +

404 - Not Found

+

Current Locale: {currentLocale ? currentLocale : "none"}

+ + diff --git a/packages/astro/test/i18n-routing.test.js b/packages/astro/test/i18n-routing.test.js index 10c35bacd9b3..d91a06ec3f73 100644 --- a/packages/astro/test/i18n-routing.test.js +++ b/packages/astro/test/i18n-routing.test.js @@ -82,6 +82,18 @@ describe('[DEV] i18n routing', () => { assert.equal(response.status, 200); assert.equal((await response.text()).includes('Endurance'), true); }); + + it('should return the correct locale on 404 page for non existing default locale page', async () => { + const response = await fixture.fetch('/es/nonexistent-page'); + assert.equal(response.status, 404); + assert.equal((await response.text()).includes('Current Locale: es'), true); + }); + + it('should return the correct locale on 404 page for non existing english locale page', async () => { + const response = await fixture.fetch('/en/nonexistent-page'); + assert.equal(response.status, 404); + assert.equal((await response.text()).includes('Current Locale: en'), true); + }); }); describe('i18n routing', () => { @@ -1200,6 +1212,20 @@ describe('[SSR] i18n routing', () => { assert.equal(response.status, 200); assert.equal((await response.text()).includes('Endurance'), true); }); + + it('should return the correct locale on 404 page for non existing default locale page', async () => { + let request = new Request('http://example.com/es/nonexistent-page'); + let response = await app.render(request); + assert.equal(response.status, 404); + assert.equal((await response.text()).includes('Current Locale: es'), true); + }); + + it('should return the correct locale on 404 page for non existing english locale page', async () => { + let request = new Request('http://example.com/en/nonexistent-page'); + let response = await app.render(request); + assert.equal(response.status, 404); + assert.equal((await response.text()).includes('Current Locale: en'), true); + }); }); describe('default', () => {