Untitled
unknown
plain_text
2 days ago
5.6 kB
3
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