summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Emanuele Stoppa <my.burning@gmail.com> 2023-11-09 14:32:57 +0000
committerGravatar GitHub <noreply@github.com> 2023-11-09 14:32:57 +0000
commit4e9f171ef2a900b87dceb5d314733aae46cf63c9 (patch)
tree490902078fa462bc8e27be3426159073266066c0
parent4e63467d74e5b0b0eba1c80772e4daf64ff2b2d1 (diff)
downloadastro-4e9f171ef2a900b87dceb5d314733aae46cf63c9.tar.gz
astro-4e9f171ef2a900b87dceb5d314733aae46cf63c9.tar.zst
astro-4e9f171ef2a900b87dceb5d314733aae46cf63c9.zip
fix(i18n): fallback index when routing is prefix-always (#9032)
* fix(i18n): fallback index when routing is prefix-always * chore: add comment as per feedback
-rw-r--r--packages/astro/src/core/build/buildPipeline.ts6
-rw-r--r--packages/astro/src/core/routing/manifest/create.ts158
-rw-r--r--packages/astro/src/vite-plugin-astro-server/route.ts3
-rw-r--r--packages/astro/test/fixtures/i18n-routing-prefix-always/src/pages/index.astro8
4 files changed, 106 insertions, 69 deletions
diff --git a/packages/astro/src/core/build/buildPipeline.ts b/packages/astro/src/core/build/buildPipeline.ts
index b668c0756..83e45f808 100644
--- a/packages/astro/src/core/build/buildPipeline.ts
+++ b/packages/astro/src/core/build/buildPipeline.ts
@@ -161,7 +161,11 @@ export class BuildPipeline extends Pipeline {
for (const pageData of pageDataList) {
if (routeIsRedirect(pageData.route)) {
pages.set(pageData, path);
- } else if (routeIsFallback(pageData.route) && i18nHasFallback(this.getConfig())) {
+ } else if (
+ routeIsFallback(pageData.route) &&
+ (i18nHasFallback(this.getConfig()) ||
+ (routeIsFallback(pageData.route) && pageData.route.route === '/'))
+ ) {
pages.set(pageData, path);
}
}
diff --git a/packages/astro/src/core/routing/manifest/create.ts b/packages/astro/src/core/routing/manifest/create.ts
index 6f2409091..f5b6e0ccd 100644
--- a/packages/astro/src/core/routing/manifest/create.ts
+++ b/packages/astro/src/core/routing/manifest/create.ts
@@ -485,13 +485,13 @@ export function createRouteManifest(
routes.push(routeData);
});
const i18n = settings.config.experimental.i18n;
-
- if (i18n && i18n.fallback) {
- let fallback = Object.entries(i18n.fallback);
+ if (i18n) {
+ // In this block of code we group routes based on their locale
// A map like: locale => RouteData[]
const routesByLocale = new Map<string, RouteData[]>();
- // We create a set, so we can remove the routes that have been added to the previous map
+ // This type is here only as a helper. We copy the routes and make them unique, so we don't "process" the same route twice.
+ // The assumption is that a route in the file system belongs to only one locale.
const setRoutes = new Set(routes);
// First loop
@@ -524,70 +524,110 @@ export function createRouteManifest(
setRoutes.delete(route);
}
- if (fallback.length > 0) {
- for (const [fallbackFromLocale, fallbackToLocale] of fallback) {
- let fallbackToRoutes;
- if (fallbackToLocale === i18n.defaultLocale) {
- fallbackToRoutes = routesByLocale.get(i18n.defaultLocale);
- } else {
- fallbackToRoutes = routesByLocale.get(fallbackToLocale);
- }
- const fallbackFromRoutes = routesByLocale.get(fallbackFromLocale);
+ // Work done, now we start creating "fallback" routes based on the configuration
- // Technically, we should always have a fallback to. Added this to make TS happy.
- if (!fallbackToRoutes) {
- continue;
+ if (i18n.routingStrategy === 'prefix-always') {
+ // we attempt to retrieve the index page of the default locale
+ const defaultLocaleRoutes = routesByLocale.get(i18n.defaultLocale);
+ if (defaultLocaleRoutes) {
+ const indexDefaultRoute = defaultLocaleRoutes.find((routeData) => {
+ // it should be safe to assume that an index page has "index" in their name
+ return routeData.component.includes('index');
+ });
+ if (indexDefaultRoute) {
+ // we found the index of the default locale, now we create a root index that will redirect to the index of the default locale
+ const pathname = '/';
+ const route = '/';
+
+ const segments = removeLeadingForwardSlash(route)
+ .split(path.posix.sep)
+ .filter(Boolean)
+ .map((s: string) => {
+ validateSegment(s);
+ return getParts(s, route);
+ });
+ routes.push({
+ ...indexDefaultRoute,
+ pathname,
+ route,
+ segments,
+ pattern: getPattern(segments, config),
+ type: 'fallback',
+ });
}
+ }
+ }
+
+ if (i18n.fallback) {
+ let fallback = Object.entries(i18n.fallback);
+
+ if (fallback.length > 0) {
+ for (const [fallbackFromLocale, fallbackToLocale] of fallback) {
+ let fallbackToRoutes;
+ if (fallbackToLocale === i18n.defaultLocale) {
+ fallbackToRoutes = routesByLocale.get(i18n.defaultLocale);
+ } else {
+ fallbackToRoutes = routesByLocale.get(fallbackToLocale);
+ }
+ const fallbackFromRoutes = routesByLocale.get(fallbackFromLocale);
- for (const fallbackToRoute of fallbackToRoutes) {
- const hasRoute =
- fallbackFromRoutes &&
- // we check if the fallback from locale (the origin) has already this route
- fallbackFromRoutes.some((route) => {
+ // Technically, we should always have a fallback to. Added this to make TS happy.
+ if (!fallbackToRoutes) {
+ continue;
+ }
+
+ for (const fallbackToRoute of fallbackToRoutes) {
+ const hasRoute =
+ fallbackFromRoutes &&
+ // we check if the fallback from locale (the origin) has already this route
+ fallbackFromRoutes.some((route) => {
+ if (fallbackToLocale === i18n.defaultLocale) {
+ return (
+ route.route.replace(`/${fallbackFromLocale}`, '') === fallbackToRoute.route
+ );
+ } else {
+ return (
+ route.route.replace(`/${fallbackToLocale}`, `/${fallbackFromLocale}`) ===
+ fallbackToRoute.route
+ );
+ }
+ });
+
+ if (!hasRoute) {
+ let pathname: string | undefined;
+ let route: string;
if (fallbackToLocale === i18n.defaultLocale) {
- return route.route.replace(`/${fallbackFromLocale}`, '') === fallbackToRoute.route;
+ if (fallbackToRoute.pathname) {
+ pathname = `/${fallbackFromLocale}${fallbackToRoute.pathname}`;
+ }
+ route = `/${fallbackFromLocale}${fallbackToRoute.route}`;
} else {
- return (
- route.route.replace(`/${fallbackToLocale}`, `/${fallbackFromLocale}`) ===
- fallbackToRoute.route
+ pathname = fallbackToRoute.pathname?.replace(
+ `/${fallbackToLocale}`,
+ `/${fallbackFromLocale}`
+ );
+ route = fallbackToRoute.route.replace(
+ `/${fallbackToLocale}`,
+ `/${fallbackFromLocale}`
);
}
- });
-
- if (!hasRoute) {
- let pathname: string | undefined;
- let route: string;
- if (fallbackToLocale === i18n.defaultLocale) {
- if (fallbackToRoute.pathname) {
- pathname = `/${fallbackFromLocale}${fallbackToRoute.pathname}`;
- }
- route = `/${fallbackFromLocale}${fallbackToRoute.route}`;
- } else {
- pathname = fallbackToRoute.pathname?.replace(
- `/${fallbackToLocale}`,
- `/${fallbackFromLocale}`
- );
- route = fallbackToRoute.route.replace(
- `/${fallbackToLocale}`,
- `/${fallbackFromLocale}`
- );
- }
- const segments = removeLeadingForwardSlash(route)
- .split(path.posix.sep)
- .filter(Boolean)
- .map((s: string) => {
- validateSegment(s);
- return getParts(s, route);
+ const segments = removeLeadingForwardSlash(route)
+ .split(path.posix.sep)
+ .filter(Boolean)
+ .map((s: string) => {
+ validateSegment(s);
+ return getParts(s, route);
+ });
+ routes.push({
+ ...fallbackToRoute,
+ pathname,
+ route,
+ segments,
+ pattern: getPattern(segments, config),
+ type: 'fallback',
});
- routes.push({
- ...fallbackToRoute,
- pathname,
- route,
- segments,
- pattern: getPattern(segments, config),
- type: 'fallback',
- });
+ }
}
}
}
diff --git a/packages/astro/src/vite-plugin-astro-server/route.ts b/packages/astro/src/vite-plugin-astro-server/route.ts
index 2b0bcbea7..89173a1ec 100644
--- a/packages/astro/src/vite-plugin-astro-server/route.ts
+++ b/packages/astro/src/vite-plugin-astro-server/route.ts
@@ -187,7 +187,8 @@ export async function handleRoute({
.some((segment) => {
return locales.includes(segment);
});
- if (!pathNameHasLocale) {
+ // Even when we have `config.base`, the pathname is still `/` because it gets stripped before
+ if (!pathNameHasLocale && pathname !== '/') {
return handle404Response(origin, incomingRequest, incomingResponse);
}
request = createRequest({
diff --git a/packages/astro/test/fixtures/i18n-routing-prefix-always/src/pages/index.astro b/packages/astro/test/fixtures/i18n-routing-prefix-always/src/pages/index.astro
deleted file mode 100644
index 05faf7b0b..000000000
--- a/packages/astro/test/fixtures/i18n-routing-prefix-always/src/pages/index.astro
+++ /dev/null
@@ -1,8 +0,0 @@
-<html>
-<head>
- <title>Astro</title>
-</head>
-<body>
- Hello
-</body>
-</html>