diff --git a/astro.config.mjs b/astro.config.mjs index 796c8e0..222a1b3 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -13,6 +13,7 @@ export default defineConfig({ site: baseUrl, trailingSlash: 'never', compressHTML: false, + output: 'server', adapter: node({ mode: 'standalone', diff --git a/src/i18n/utils.ts b/src/i18n/utils.ts index b094369..dd29f5a 100644 --- a/src/i18n/utils.ts +++ b/src/i18n/utils.ts @@ -1,4 +1,4 @@ -import { DEFAULT_LOCALE, type Locale, LOCALE_CODES, ui } from '.'; +import { DEFAULT_LOCALE, type Locale, ui } from '.'; export function getLocaleFromUrl(url: URL): Locale { const [, lang] = url.pathname.split('/'); @@ -29,9 +29,5 @@ export function removeTrailingSlash(string: string) { return string.replace(/(?:\/+(\?))/, '$1').replace(/\/+$/, ''); } -export function generateLangStaticPaths() { - return LOCALE_CODES.map((l) => ({ params: { lang: l } })); -} - export const getPostSlug = (postId: string) => postId.split('/').slice(0, -1).join('/'); export const getPostLang = (postId: string) => postId.split('/').at(-1)!; diff --git a/src/middleware.ts b/src/middleware.ts new file mode 100644 index 0000000..d0b06c7 --- /dev/null +++ b/src/middleware.ts @@ -0,0 +1,41 @@ +import { DEFAULT_LOCALE, LOCALE_CODES, removeTrailingSlash, useTranslatedPaths } from '@i18n'; +import { defineMiddleware } from 'astro:middleware'; +import { handleRedirect } from './redirects'; + +export const onRequest = defineMiddleware((context, next) => { + const [_, langParam, ...restUrl] = context.url.pathname.split('/'); + + const noLangPathname = LOCALE_CODES.includes(langParam) + ? `/${restUrl.join('/')}` + : context.url.pathname; + + // if it's an astro path / secret path, skip it + if (noLangPathname.startsWith('/_')) { + return next(); + } + + // check for redirections first + const redirectedUrl = handleRedirect(noLangPathname) ?? handleRedirect(context.url.pathname); + if (redirectedUrl) { + return context.redirect(removeTrailingSlash(redirectedUrl)); + } + + // if there's no lang parameter, detect language and redirect + if (!langParam || !LOCALE_CODES.includes(langParam)) { + const headerLang = context.request.headers.get('Accept-Language'); + const pathnameWithParams = context.url.href.replace(context.url.origin, ''); + const path = removeTrailingSlash(pathnameWithParams); + + // if the lang is french, serve the content in french + if (headerLang?.includes('fr')) { + const translatePaths = useTranslatedPaths('fr'); + return context.redirect(translatePaths(path)); + } + + // otherwise serve english + const translatePaths = useTranslatedPaths(DEFAULT_LOCALE); + return context.redirect(translatePaths(path)); + } + + return next(); +}); diff --git a/src/pages/404.astro b/src/pages/404.astro index bfb2d1d..d2a55ee 100644 --- a/src/pages/404.astro +++ b/src/pages/404.astro @@ -1,7 +1,4 @@ --- -// to enable localization -export const prerender = false; - import Button from '@components/Button.astro'; import { getLocaleFromUrl, useTranslations, useTranslatedPaths } from '@i18n'; import Layout from 'src/layouts/Layout.astro'; diff --git a/src/pages/[...route].astro b/src/pages/[...route].astro deleted file mode 100644 index 58b3661..0000000 --- a/src/pages/[...route].astro +++ /dev/null @@ -1,41 +0,0 @@ ---- -// server route -export const prerender = false; - -import { DEFAULT_LOCALE, LOCALE_CODES, removeTrailingSlash, useTranslatedPaths } from '@i18n'; -import { handleRedirect } from '../redirects'; - -const [_, langParam, ...restUrl] = Astro.url.pathname.split('/'); -const noLangPathname = LOCALE_CODES.includes(langParam) - ? `/${restUrl.join('/')}` - : Astro.url.pathname; - -// check for redirections first -const redirectedUrl = handleRedirect(noLangPathname) ?? handleRedirect(Astro.url.pathname); - -if (redirectedUrl) { - return Astro.redirect(removeTrailingSlash(redirectedUrl)); -} - -// if there's no lang parameter, detect language and redirect -if (!langParam || !LOCALE_CODES.includes(langParam)) { - const headerLang = Astro.request.headers.get('Accept-Language'); - const pathnameWithParams = Astro.url.href.replace(Astro.url.origin, ''); - const path = removeTrailingSlash(pathnameWithParams); - - // if the lang is french, serve the content in french - if (headerLang?.includes('fr')) { - const translatePaths = useTranslatedPaths('fr'); - return Astro.redirect(translatePaths(path)); - } - - // otherwise serve english - const translatePaths = useTranslatedPaths(DEFAULT_LOCALE); - return Astro.redirect(translatePaths(path)); -} - -// if the page isnt found, return 404 lol -return new Response(null, { - status: 404, -}); ---- diff --git a/src/pages/[lang]/blog/[...slug].astro b/src/pages/[lang]/blog/[...slug].astro index ef0fe2f..579105d 100644 --- a/src/pages/[lang]/blog/[...slug].astro +++ b/src/pages/[lang]/blog/[...slug].astro @@ -1,19 +1,6 @@ --- -// generate all possible slugs for both langs (if either is unavailable, fallback) -export async function getStaticPaths() { - const posts = await getCollection('blog'); - - const slugs = new Set(posts.map((post) => getPostSlug(post.id))); - - return Array.from(slugs).flatMap((slug) => { - return LOCALE_CODES.map((lang) => ({ - params: { lang, slug }, - })); - }); -} - import Callout from '@components/Callout.astro'; -import { getLocaleFromUrl, getPostLang, getPostSlug, LOCALE_CODES, useTranslations } from '@i18n'; +import { getLocaleFromUrl, getPostLang, getPostSlug, useTranslations } from '@i18n'; import { getCollection, render } from 'astro:content'; import Blog from '../../../layouts/Blog.astro'; diff --git a/src/pages/[lang]/blog/index.astro b/src/pages/[lang]/blog/index.astro index 44a8a68..2c6f1d1 100644 --- a/src/pages/[lang]/blog/index.astro +++ b/src/pages/[lang]/blog/index.astro @@ -1,12 +1,9 @@ --- -export const getStaticPaths = generateLangStaticPaths; - import Globe from '@assets/icons/globe.svg'; import RSS from '@assets/icons/rss.svg'; import MetaImageBlog from '@assets/meta-images/blog.webp'; import Button from '@components/Button.astro'; import { - generateLangStaticPaths, getLocaleFromUrl, getPostLang, getPostSlug, diff --git a/src/pages/[lang]/blog/rss.xml.ts b/src/pages/[lang]/blog/rss.xml.ts index 5e64a20..8963c09 100644 --- a/src/pages/[lang]/blog/rss.xml.ts +++ b/src/pages/[lang]/blog/rss.xml.ts @@ -8,8 +8,6 @@ import { } from '@i18n'; import { getCollection } from 'astro:content'; -export const prerender = false; - export async function GET(context: Astro) { const lang = getLocaleFromUrl(context.url); const t = useTranslations(lang); diff --git a/src/pages/[lang]/contact/index.astro b/src/pages/[lang]/contact/index.astro index 5cd409b..6c2f886 100644 --- a/src/pages/[lang]/contact/index.astro +++ b/src/pages/[lang]/contact/index.astro @@ -1,6 +1,4 @@ --- -export const prerender = false; - import Bluesky from '@assets/icons/bluesky.svg'; import Codeberg from '@assets/icons/codeberg.svg'; import Email from '@assets/icons/email.svg'; diff --git a/src/pages/[lang]/index.astro b/src/pages/[lang]/index.astro index d815bf7..e82005f 100644 --- a/src/pages/[lang]/index.astro +++ b/src/pages/[lang]/index.astro @@ -1,6 +1,4 @@ --- -export const getStaticPaths = generateLangStaticPaths; - import Briefcase from '@assets/icons/briefcase.svg'; import MetaImageEn from '@assets/meta-images/index-en.webp'; import MetaImageFr from '@assets/meta-images/index-fr.webp'; @@ -26,12 +24,7 @@ import sifaProfile, { type Main as SifaProfile } from '@atp/lexicons/id/sifa/pro import AvailabilityCTA from '@components/AvailabilityCTA.astro'; import Button from '@components/Button.astro'; import ProjectCard from '@components/ProjectCard.astro'; -import { - generateLangStaticPaths, - getLocaleFromUrl, - useTranslatedPaths, - useTranslations, -} from '@i18n'; +import { getLocaleFromUrl, useTranslatedPaths, useTranslations } from '@i18n'; import Layout from '../../layouts/Layout.astro'; import Avatar from './_Avatar.astro'; diff --git a/src/pages/[lang]/login/callback.ts b/src/pages/[lang]/login/callback.ts index 76d8277..9207afb 100644 --- a/src/pages/[lang]/login/callback.ts +++ b/src/pages/[lang]/login/callback.ts @@ -1,8 +1,6 @@ import { authedAtp, oauthClient } from '@atp/client'; import type { APIRoute } from 'astro'; -export const prerender = false; - export const GET = (async (context) => { const { session } = await oauthClient.callback(context.url.searchParams); diff --git a/src/pages/[lang]/login/index.astro b/src/pages/[lang]/login/index.astro index b8ac0c4..4c4aac8 100644 --- a/src/pages/[lang]/login/index.astro +++ b/src/pages/[lang]/login/index.astro @@ -1,6 +1,4 @@ --- -export const prerender = false; - import { authedAtp, oauthClient } from '@atp/client'; import bskyProfile from '@atp/lexicons/app/bsky/actor/profile.js'; import { getBlobCidString } from '@atproto/lex'; diff --git a/src/pages/[lang]/resume/index.astro b/src/pages/[lang]/resume/index.astro index 4fe4cf4..1397618 100644 --- a/src/pages/[lang]/resume/index.astro +++ b/src/pages/[lang]/resume/index.astro @@ -1,6 +1,4 @@ --- -export const prerender = false; - import { atpClient } from '@atp/client'; import { type Main as Location } from '@atp/lexicons/community/lexicon/location/address'; import * as sifa from '@atp/lexicons/id/sifa/profile';