Untitled
unknown
plain_text
3 months ago
5.6 kB
15
No Index
import { defineConfig } from "astro/config";
import node from "@astrojs/node";
import auth from "auth-astro";
import type { AstroIntegration, RouteData } from "astro";
import sitemap, { type SitemapOptions } from "@astrojs/sitemap";
interface Route {
path: string;
locales: Record<string, string>;
}
function languageIntegration({
routes,
sitemapOptions,
}: {
routes: Route[];
sitemapOptions: SitemapOptions | false;
}): Array<AstroIntegration | undefined> {
const paths = new Map<
string,
{ route: Route; patterns: { pattern: RegExp; lang: string }[] }
>();
const sitemapPaths = new Map<
Route,
{ linkedPaths: { page: string; lang: string; resourceId?: string }[] }
>();
const siteResources = new Map<string, string>();
const sitemapPathsByUrl = new Map<string, Route>();
return [
{
name: "language-route-handler",
hooks: {
"astro:config:setup": async ({ injectRoute }) => {
for (const route of routes) {
for (const [lang, path] of Object.entries(route.locales)) {
const pattern = `/${lang}/${path}`;
paths.set(pattern, { route, patterns: [] });
injectRoute({
entrypoint: `src/localized/${route.path}.astro`,
pattern,
prerender: true,
});
}
}
},
"astro:route:setup": ({ route: routeOptions }) => {
const route = routeOptions as RouteData;
const oldGenerate = route.generate;
if (!paths.has(route.route)) {
console.log(route);
return;
}
const [_, lang] = route.route.split("/");
paths
.get(route.route)
?.patterns.push({ pattern: route.pattern, lang });
if (route.segments.length <= 1 || !lang) {
return;
}
route.segments[0][0].dynamic = true;
route.segments[0][0].content = "lang";
route.origin = "project";
route.pattern = new RegExp(
route.pattern.source.replace(`^\\/${lang}\\/`, "^\\/([^/]+?)\\/")
);
route.params.unshift("lang");
route.pathname = undefined;
route.generate = (data) => {
const res = oldGenerate({
...data,
lang,
});
if (data.lang !== lang) {
return "../";
}
if (data._resourceId) {
siteResources.set(res, data._resourceId);
}
return res;
};
},
},
},
sitemapOptions
? sitemap({
...sitemapOptions,
filter: (page) => {
const isFiltered = sitemapOptions?.filter?.(page) ?? true;
if (!isFiltered) {
return false;
}
const url = new URL(page);
// Find matched pattern, this is pretty expensive, proof of concept though.
for (const routeData of paths) {
const { route, patterns } = routeData[1];
for (const pattern of patterns) {
if (pattern.pattern.test(url.pathname)) {
sitemapPaths.set(route, {
linkedPaths: [
...(sitemapPaths.get(route)?.linkedPaths ?? []),
{
page,
lang: pattern.lang,
resourceId: siteResources.get(url.pathname.substring(0, url.pathname.length - 1)),
},
],
});
sitemapPathsByUrl.set(page, route);
}
}
}
return isFiltered;
},
serialize(item) {
const route = sitemapPathsByUrl.get(item.url);
if (route) {
const info = sitemapPaths.get(route);
const url = new URL(item.url);
const resourceId = siteResources.get(url.pathname.substring(0, url.pathname.length - 1));
item.links = [
...(item.links ?? []),
...(info?.linkedPaths
.map((path) => ({
lang:
sitemapOptions.i18n?.locales[route.locales[path.lang]] ??
path.lang,
url: path.page,
resourceId: path.resourceId,
}))
.filter(
(path) => !path.resourceId || path.resourceId === resourceId
) ?? []),
];
}
return item;
},
})
: undefined,
];
}
// https://astro.build/config
export default defineConfig({
site: "https://test.com",
adapter: node({
mode: "standalone",
}),
output: "server",
i18n: {
locales: ["es", "en", "pl"],
defaultLocale: "en",
},
integrations: [
auth(),
...languageIntegration({
routes: [
{
path: "about-us",
locales: {
es: "sobre-nosotros",
en: "about-us",
pl: "dobre-nas",
},
},
{
path: "games/[game]",
locales: {
es: "juegos/[game]",
en: "games/[game]",
pl: "gry/[game]",
},
},
],
sitemapOptions: {
i18n: {
defaultLocale: "en",
locales: {
en: "en-US",
es: "es-ES",
pl: "pl-PL",
},
},
},
}),
],
});
Editor is loading...
Leave a Comment