Commit 2589c41

HPCesia <me@hpcesia.com>
2026-09-21 09:45:57
i18n: drop the default locale path prefix
Assisted-by: crush:deepseek-v4-flash
1 parent 871a458
src/components/Footer.astro
@@ -2,14 +2,14 @@
 import { getIntlayer, type Locale } from "intlayer";
 
 import { SITE_CONFIG } from "@/config";
-import { getRelativeLocaleUrl } from "@/utils/url.ts";
+import { getLocaleFeedUrl } from "@/utils/url.ts";
 
 const locale = Astro.currentLocale! as Locale;
 const globalI18n = getIntlayer("global", locale);
 ---
 <footer class="footer">
   <div class="footer-alternatives">
-    <a href={getRelativeLocaleUrl("/feed.atom", locale).slice(0, -1)}>
+    <a href={getLocaleFeedUrl(locale)}>
       {globalI18n.feed}
     </a>
     <a href="https://git.trin.one/HPCesia/kerplunk">{globalI18n.source}</a>
src/layouts/BaseLayout.astro
@@ -4,9 +4,9 @@ import { getIntlayer, type Locale } from "intlayer";
 
 import { DEFAULT_LOCALE, SITE_CONFIG } from "@/config";
 import {
+  getLocaleFeedUrl,
   getPathWithoutLocale,
   getRelativeLocaleUrl,
-  joinUrl,
   url,
 } from "@/utils/url.ts";
 
@@ -65,13 +65,13 @@ const getAbsoluteLocaleUrl = (
       type="application/atom+xml"
       hreflang={locale ?? DEFAULT_LOCALE}
       title="Atom Feed"
-      href={url(joinUrl(locale ?? DEFAULT_LOCALE, "feed.atom"))}
+      href={getLocaleFeedUrl(locale ?? DEFAULT_LOCALE)}
     />
     <link
       rel="alternate"
       type="application/atom+xml"
       title="Atom Feed"
-      href={`${import.meta.env.BASE_URL}feed.atom`}
+      href={url("/feed.atom")}
     />
 
     <title>{title}</title>
src/pages/[locale]/posts/[slug].astro → src/pages/[...locale]/posts/[slug].astro
@@ -4,7 +4,11 @@ import { getCollection, render } from "astro:content";
 
 import { SITE_CONFIG } from "@/config.ts";
 import { getPostsLocaleMap } from "@/utils/content.ts";
-import { getPathWithoutLocale, getRelativeLocaleUrl } from "@/utils/url.ts";
+import {
+  getLocaleRouteParam,
+  getPathWithoutLocale,
+  getRelativeLocaleUrl,
+} from "@/utils/url.ts";
 
 import BaseLayout from "@/layouts/BaseLayout.astro";
 import "@/styles/article/index.scss";
@@ -26,7 +30,7 @@ export const getStaticPaths = (async () => {
         return undefined;
       } else {
         return {
-          params: { locale, slug },
+          params: { locale: getLocaleRouteParam(locale), slug },
           props: { entry, availableLocales },
         };
       }
src/pages/[locale]/posts/index.astro → src/pages/[...locale]/posts/index.astro
@@ -5,6 +5,7 @@ import { getIntlayer } from "intlayer";
 
 import { SITE_CONFIG } from "@/config.ts";
 import { getLocalePosts } from "@/utils/content.ts";
+import { getLocaleRouteParam } from "@/utils/url.ts";
 
 import BaseLayout from "@/layouts/BaseLayout.astro";
 import PostsList from "@/components/widgets/PostsList.astro";
@@ -12,7 +13,9 @@ import PostsList from "@/components/widgets/PostsList.astro";
 type Props = InferGetStaticPropsType<typeof getStaticPaths>;
 
 export const getStaticPaths = (() => {
-  return SITE_CONFIG.locales.map((locale) => ({ params: { locale } }));
+  return SITE_CONFIG.locales.map((locale) => ({
+    params: { locale: getLocaleRouteParam(locale) },
+  }));
 }) satisfies GetStaticPaths;
 
 const locale = Astro.currentLocale;
src/pages/[locale]/about.astro → src/pages/[...locale]/about.astro
@@ -4,12 +4,13 @@ import { getIntlayer } from "intlayer";
 
 import { SITE_CONFIG } from "@/config.ts";
 import { loadLocaleContent } from "@/utils/content.ts";
+import { getLocaleRouteParam } from "@/utils/url.ts";
 
 import BaseLayout from "@/layouts/BaseLayout.astro";
 import "@/styles/article/index.scss";
 
 export const getStaticPaths: GetStaticPaths = () => (SITE_CONFIG.locales.map(
-  (locale) => ({ params: { locale } }),
+  (locale) => ({ params: { locale: getLocaleRouteParam(locale) } }),
 ));
 
 const locale = Astro.currentLocale;
src/pages/[locale]/index.astro → src/pages/[...locale]/index.astro
@@ -6,6 +6,7 @@ import { getIntlayer } from "intlayer";
 import { SITE_CONFIG } from "@/config.ts";
 import { loadLocaleContent } from "@/utils/content.ts";
 import { getLocalePosts } from "@/utils/content.ts";
+import { getLocaleRouteParam } from "@/utils/url.ts";
 
 import BaseLayout from "@/layouts/BaseLayout.astro";
 import PostsList from "@/components/widgets/PostsList.astro";
@@ -14,7 +15,9 @@ import "@/styles/article/index.scss";
 type Props = InferGetStaticPropsType<typeof getStaticPaths>;
 
 export const getStaticPaths = (() => {
-  return SITE_CONFIG.locales.map((locale) => ({ params: { locale } }));
+  return SITE_CONFIG.locales.map((locale) => ({
+    params: { locale: getLocaleRouteParam(locale) },
+  }));
 }) satisfies GetStaticPaths;
 
 const locale = Astro.currentLocale;
src/pages/404.astro
@@ -3,20 +3,4 @@ import BaseLayout from "@/layouts/BaseLayout.astro";
 ---
 <BaseLayout>
   <div>404 Not Found</div>
-  <script>
-  import { DEFAULT_LOCALE } from "@/config.ts";
-  import {
-    getPathWithoutLocale,
-    getRelativeLocaleUrl,
-    getRelativeUrl,
-  } from "@/utils/url.ts";
-
-  const { pathname, search, hash } = window.location;
-  const pathLocale = getRelativeUrl(pathname).split("/")[1] ?? "";
-
-  if (pathLocale !== DEFAULT_LOCALE) {
-    const target = getRelativeLocaleUrl(getPathWithoutLocale(pathname));
-    window.location.replace(target + search + hash);
-  }
-  </script>
 </BaseLayout>
src/pages/[locale]/feed.atom.ts → src/pages/feed.[locale].atom.ts
@@ -4,7 +4,7 @@ import type { Locale } from "intlayer";
 
 import { SITE_CONFIG } from "@/config.ts";
 import { createFeed, localePostUrl } from "@/utils/feed.ts";
-import { getRelativeLocaleUrl, joinUrl, url } from "@/utils/url.ts";
+import { getLocaleFeedUrl, getRelativeLocaleUrl, url } from "@/utils/url.ts";
 
 export const getStaticPaths = (() => {
   return SITE_CONFIG.locales.map((locale) => ({ params: { locale } }));
@@ -21,7 +21,7 @@ export const GET: APIRoute = async ({ site, params }) => {
   );
   const feed = await createFeed({
     id: new URL(getRelativeLocaleUrl("/", locale), origin).toString(),
-    feedUrl: new URL(url(joinUrl(locale, "feed.atom")), origin).toString(),
+    feedUrl: new URL(getLocaleFeedUrl(locale), origin).toString(),
     favicon: new URL(url("/favicon.ico"), origin).toString(),
     title: SITE_CONFIG.title,
     description: SITE_CONFIG.description[locale],
src/utils/url.ts
@@ -19,8 +19,16 @@ export function getRelativeUrl(path: string) {
   return joinUrl("/", path.replace(import.meta.env.BASE_URL, ""));
 }
 
+export function getLocaleRouteParam(locale: string): string | undefined {
+  return locale === DEFAULT_LOCALE ? undefined : locale;
+}
+
 export function getRelativeLocaleUrl(path: string, locale = DEFAULT_LOCALE) {
-  return url(joinUrl(locale, path, "/"));
+  return url(joinUrl(getLocaleRouteParam(locale) ?? "", path, "/"));
+}
+
+export function getLocaleFeedUrl(locale = DEFAULT_LOCALE) {
+  return url(`/feed.${locale}.atom`);
 }
 
 export function getPathWithoutLocale(path: string): string {
astro.config.ts
@@ -17,7 +17,7 @@ export default defineConfig({
     locales: SITE_CONFIG.locales,
     defaultLocale: DEFAULT_LOCALE,
     routing: {
-      prefixDefaultLocale: true,
+      prefixDefaultLocale: false,
     },
   },
   image: {