Skip to content

Commit cf0d8b0

Browse files
ematipicodelucisbluwy
authoredNov 26, 2024··
fix(i18n): render 404.astro when i18n is enabled (#12525)
Co-authored-by: Chris Swithinbank <[email protected]> Co-authored-by: delucis <[email protected]> Co-authored-by: bluwy <[email protected]>
1 parent 8b0e36c commit cf0d8b0

File tree

6 files changed

+28
-25
lines changed

6 files changed

+28
-25
lines changed
 

‎.changeset/hot-dingos-dress.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'astro': patch
3+
---
4+
5+
Fixes an issue where with `i18n` enabled, Astro couldn't render the `404.astro` component for non-existent routes.

‎packages/astro/src/i18n/middleware.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { APIContext, MiddlewareHandler, SSRManifest } from '../@types/astro.js';
22
import type { SSRManifestI18n } from '../core/app/types.js';
3-
import { ROUTE_TYPE_HEADER } from '../core/constants.js';
3+
import { REROUTE_DIRECTIVE_HEADER, ROUTE_TYPE_HEADER } from '../core/constants.js';
44
import {
55
type MiddlewarePayload,
66
normalizeTheLocale,
@@ -65,6 +65,12 @@ export function createI18nMiddleware(
6565
return async (context, next) => {
6666
const response = await next();
6767
const type = response.headers.get(ROUTE_TYPE_HEADER);
68+
69+
// This is case where we are internally rendering a 404/500, so we need to bypass checks that were done already
70+
const isReroute = response.headers.get(REROUTE_DIRECTIVE_HEADER);
71+
if (isReroute === 'no' && typeof i18n.fallback === 'undefined') {
72+
return response;
73+
}
6874
// If the route we're processing is not a page, then we ignore it
6975
if (type !== 'page' && type !== 'fallback') {
7076
return response;

‎packages/astro/src/vite-plugin-astro-server/request.ts

-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ export async function handleRequest({
6363
url,
6464
pathname: resolvedPathname,
6565
body,
66-
origin,
6766
pipeline,
6867
manifestData,
6968
incomingRequest: incomingRequest,

‎packages/astro/src/vite-plugin-astro-server/route.ts

+9-23
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@ type HandleRoute = {
127127
url: URL;
128128
pathname: string;
129129
body: ArrayBuffer | undefined;
130-
origin: string;
131130
manifestData: ManifestData;
132131
incomingRequest: http.IncomingMessage;
133132
incomingResponse: http.ServerResponse;
@@ -139,7 +138,6 @@ export async function handleRoute({
139138
url,
140139
pathname,
141140
body,
142-
origin,
143141
pipeline,
144142
manifestData,
145143
incomingRequest,
@@ -156,12 +154,10 @@ export async function handleRoute({
156154
let request: Request;
157155
let renderContext: RenderContext;
158156
let mod: ComponentInstance | undefined = undefined;
159-
let options: SSROptions | undefined = undefined;
160157
let route: RouteData;
161158
const middleware = (await loadMiddleware(loader)).onRequest;
162159
const locals = Reflect.get(incomingRequest, clientLocalsSymbol);
163160

164-
const filePath: URL | undefined = matchedRoute.filePath;
165161
const { preloadedComponent } = matchedRoute;
166162
route = matchedRoute.route;
167163
// Allows adapters to pass in locals in dev mode.
@@ -181,15 +177,6 @@ export async function handleRoute({
181177
if (value) incomingResponse.setHeader(name, value);
182178
}
183179

184-
options = {
185-
pipeline,
186-
filePath,
187-
preload: preloadedComponent,
188-
pathname,
189-
request,
190-
route,
191-
};
192-
193180
mod = preloadedComponent;
194181

195182
renderContext = await RenderContext.create({
@@ -248,18 +235,17 @@ export async function handleRoute({
248235

249236
if (statusCode === 404 && response.headers.get(REROUTE_DIRECTIVE_HEADER) !== 'no') {
250237
const fourOhFourRoute = await matchRoute('/404', manifestData, pipeline);
251-
if (options && options.route !== fourOhFourRoute?.route)
252-
return handleRoute({
253-
...options,
254-
matchedRoute: fourOhFourRoute,
255-
url: new URL(pathname, url),
256-
body,
257-
origin,
238+
if (fourOhFourRoute) {
239+
renderContext = await RenderContext.create({
240+
locals,
258241
pipeline,
259-
manifestData,
260-
incomingRequest,
261-
incomingResponse,
242+
pathname,
243+
middleware: isDefaultPrerendered404(fourOhFourRoute.route) ? undefined : middleware,
244+
request,
245+
routeData: fourOhFourRoute.route,
262246
});
247+
response = await renderContext.render(fourOhFourRoute.preloadedComponent);
248+
}
263249
}
264250

265251
// We remove the internally-used header before we send the response to the user agent.

‎packages/astro/test/fixtures/i18n-routing/src/pages/404.astro

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const currentLocale = Astro.currentLocale;
77
</head>
88
<body>
99
<h1>404 - Not Found</h1>
10+
<h2>Custom 404</h2>
1011
<p>Current Locale: {currentLocale ? currentLocale : "none"}</p>
1112
</body>
1213
</html>

‎packages/astro/test/i18n-routing.test.js

+6
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@ describe('[DEV] i18n routing', () => {
8383
assert.equal((await response.text()).includes('Endurance'), true);
8484
});
8585

86+
it('should render the 404.astro file', async () => {
87+
const response = await fixture.fetch('/do-not-exist');
88+
assert.equal(response.status, 404);
89+
assert.match(await response.text(), /Custom 404/);
90+
});
91+
8692
it('should return the correct locale on 404 page for non existing default locale page', async () => {
8793
const response = await fixture.fetch('/es/nonexistent-page');
8894
assert.equal(response.status, 404);

0 commit comments

Comments
 (0)
Please sign in to comment.