fix 404 page i18n handling

This commit is contained in:
leander committed 2026-10-30 21:11:53 +01:00
1 parent 52b8f2b7b7
commit d44fbfa9d7
8 files changed
+80 -60

No files matched your search

+6
View File
@@ -0,0 +1,6 @@
import { notFound } from "next/navigation"
// Catch unknown paths below a locale so they render [locale]/not-found.tsx
export default function CatchAll() {
notFound()
}
+10 -3
View File
@@ -1,17 +1,24 @@
// app/[locale]/layout.tsx
import { NextIntlClientProvider } from "next-intl"
import { getLocale } from "next-intl/server"
import { hasLocale, NextIntlClientProvider } from "next-intl"
import { notFound } from "next/navigation"
import LanguageSelector from "@components/ui/languageSelector"
import UmamiAnalytics from "@/components/umamiAnalytics"
import { locales } from "@/i18n"
import { getAnalyticsConfig } from "@/lib/analyticsConfig"
export default async function LocaleLayout({
children,
params,
}: {
children: React.ReactNode
params: Promise<{ locale: string }>
}) {
const locale = (await getLocale()) as "no" | "en"
const { locale } = await params
// [locale] matches any first path segment, e.g. /favicon.txt or /de
if (!hasLocale(locales, locale)) notFound()
const messages = (await import(`../../../messages/${locale}.json`)).default
const analyticsConfig = getAnalyticsConfig()
+9
View File
@@ -0,0 +1,9 @@
import NotFound from "@/components/page-sections/notFound"
import { getLocale } from "next-intl/server"
export default async function LocaleNotFound() {
const locale = await getLocale()
return <NotFound locale={locale} />
}
-46
View File
@@ -1,46 +0,0 @@
import Layout from "@/app/layout"
import { generateSeoMetadata, generateSeoViewport } from "@/components/seo"
import { Metadata, Viewport } from "next"
import { getTranslations } from "next-intl/server"
import { useTranslations } from "next-intl"
import Link from "next/link"
import * as styles from "./global-not-found.module.css"
export async function generateMetadata(): Promise<Metadata> {
const t = await getTranslations("404")
return generateSeoMetadata({
title: t("title"),
description: "Uh oh :(",
})
}
export function generateViewport(): Viewport {
return generateSeoViewport()
}
const NotFoundPage = () => {
const t = useTranslations("404")
return (
<Layout>
<div className={styles.container}>
<h1 className={styles.centeredText}>{t("title")}</h1>
<p className={styles.centeredText}>
{t("text")}{" "}
<span role="img" aria-label="eyes">
👀
</span>
</p>
<Link href="/" className={`${styles.centeredText} ${styles.homeLink}`}>
{t("back")}
</Link>
</div>
</Layout>
)
}
export default NotFoundPage
+16 -3
View File
@@ -1,5 +1,18 @@
import { redirect } from "next/navigation"
import NotFound from "@/components/page-sections/notFound"
export default function RootPage() {
redirect("/en/404")
import { defaultLocale } from "@/i18n"
import { Metadata } from "next"
import { getTranslations } from "next-intl/server"
export async function generateMetadata(): Promise<Metadata> {
const t = await getTranslations({ locale: defaultLocale, namespace: "404" })
return { title: `${t("title")} | UiO Gaming` }
}
// Rendered when [locale]/layout.tsx rejects an unknown locale (e.g. /de),
// so there is no valid locale to use
export default function RootNotFound() {
return <NotFound locale={defaultLocale} />
}
+28
View File
@@ -0,0 +1,28 @@
import { getTranslations } from "next-intl/server"
import Link from "next/link"
import * as styles from "./notFound.module.css"
const NotFound = async ({ locale }: { locale: string }) => {
const t = await getTranslations({ locale, namespace: "404" })
return (
<div className={styles.container}>
<h1 className={styles.centeredText}>{t("title")}</h1>
<p className={styles.centeredText}>
{t("text")}{" "}
<span role="img" aria-label="eyes">
👀
</span>
</p>
<Link
href={`/${locale}`}
className={`${styles.centeredText} ${styles.homeLink}`}
>
{t("back")}
</Link>
</div>
)
}
export default NotFound
+11 -8
View File
@@ -1,15 +1,18 @@
import { notFound } from "next/navigation"
import { hasLocale } from "next-intl"
import { getRequestConfig } from "next-intl/server"
const locales = ["no", "en"]
export const locales = ["no", "en"] as const
export const defaultLocale = "no"
export default getRequestConfig(async ({ requestLocale }) => {
const locale = await requestLocale
if (!locale || !locales.includes(locale as "no" | "en")) notFound()
export default getRequestConfig(async ({ locale, requestLocale }) => {
// An explicit locale (e.g. getTranslations({ locale })) takes precedence.
// Fall back to the default instead of throwing, so pages rendered outside
// a valid locale (like the root not-found page) can still be translated
const requested = locale ?? (await requestLocale)
const resolved = hasLocale(locales, requested) ? requested : defaultLocale
return {
locale,
messages: (await import(`../messages/${locale}.json`)).default,
locale: resolved,
messages: (await import(`../messages/${resolved}.json`)).default,
}
})