diff --git a/app/[locale]/about/[slug]/page.tsx b/app/[locale]/about/[slug]/page.tsx index 171cd3a1..7fec051e 100644 --- a/app/[locale]/about/[slug]/page.tsx +++ b/app/[locale]/about/[slug]/page.tsx @@ -1,7 +1,9 @@ import { checkIfSlugIsValid, getContentData } from "@/lib/aboutPages"; import { notFound } from "next/navigation"; +import { setRequestLocale } from "next-intl/server"; export type Params = { + locale: string; slug: string; }; @@ -32,7 +34,8 @@ export async function generateMetadata({ params }: Props) { } export default async function Page({ params }: Props) { - const { slug } = await params; + const { locale, slug } = await params; + setRequestLocale(locale); if (!(await checkIfSlugIsValid(slug))) { notFound(); diff --git a/app/[locale]/about/page.tsx b/app/[locale]/about/page.tsx index 1e113547..11af884b 100644 --- a/app/[locale]/about/page.tsx +++ b/app/[locale]/about/page.tsx @@ -1,5 +1,5 @@ import LogoCloud from "@/components/logoCloud/LogoCloud"; -import { useTranslations } from "next-intl"; +import { getTranslations, setRequestLocale } from "next-intl/server"; import Image from "next/image"; import Link from "next/link"; import type { Metadata } from "next"; @@ -9,8 +9,15 @@ export const metadata: Metadata = { description: "It all started with a blog comment.", }; -const AboutPage = () => { - const t = useTranslations("about"); +type Props = { + params: Promise<{ locale: string }>; +}; + +const AboutPage = async ({ params }: Props) => { + const { locale } = await params; + setRequestLocale(locale); + + const t = await getTranslations("about"); return ( <> diff --git a/app/[locale]/about/partners/page.tsx b/app/[locale]/about/partners/page.tsx index 8f8a70a6..5b80b7a5 100644 --- a/app/[locale]/about/partners/page.tsx +++ b/app/[locale]/about/partners/page.tsx @@ -1,6 +1,6 @@ import React from "react"; import partnerSponsorData from "@/data/partnersSponsors"; -import { useTranslations } from "next-intl"; +import { getTranslations, setRequestLocale } from "next-intl/server"; import type { Metadata } from "next"; import Image from "next/image"; import { Badge } from "@/components/ui/badge"; @@ -11,7 +11,14 @@ export const metadata: Metadata = { "Our partners provide us with the resources we need. We wouldn't be here without their help!", }; -const PartnersPage = () => { +type Props = { + params: Promise<{ locale: string }>; +}; + +const PartnersPage = async ({ params }: Props) => { + const { locale } = await params; + setRequestLocale(locale); + const { partners } = partnerSponsorData[0]; const sortedTierOnePartners = partners.flatMap((partner) => partner.tierOne); @@ -19,7 +26,7 @@ const PartnersPage = () => { (partner) => partner.tierFour ); - const t = useTranslations("partners"); + const t = await getTranslations("partners"); return ( <> diff --git a/app/[locale]/about/sponsors/page.tsx b/app/[locale]/about/sponsors/page.tsx index 48606833..b0ff7fc8 100644 --- a/app/[locale]/about/sponsors/page.tsx +++ b/app/[locale]/about/sponsors/page.tsx @@ -1,6 +1,6 @@ import React from "react"; import partnerSponsorData from "@/data/partnersSponsors"; -import { useTranslations } from "next-intl"; +import { getTranslations, setRequestLocale } from "next-intl/server"; import type { Metadata } from "next"; import Image from "next/image"; import { Badge } from "@/components/ui/badge"; @@ -12,7 +12,14 @@ export const metadata: Metadata = { "Our sponsors provide us with financial backing. We wouldn't be here without their help!", }; -const SponsorsPage = () => { +type Props = { + params: Promise<{ locale: string }>; +}; + +const SponsorsPage = async ({ params }: Props) => { + const { locale } = await params; + setRequestLocale(locale); + const { sponsors } = partnerSponsorData[0]; const sortedTierOneSponsors = sponsors.flatMap((sponsor) => sponsor.tierOne); @@ -20,7 +27,7 @@ const SponsorsPage = () => { (sponsor) => sponsor.tierFour ); - const t = useTranslations("sponsors"); + const t = await getTranslations("sponsors"); return ( <> diff --git a/app/[locale]/community/page.tsx b/app/[locale]/community/page.tsx index 9b36253f..4303b104 100644 --- a/app/[locale]/community/page.tsx +++ b/app/[locale]/community/page.tsx @@ -1,4 +1,4 @@ -import { useTranslations } from "next-intl"; +import { getTranslations, setRequestLocale } from "next-intl/server"; import Link from "next/link"; import type { Metadata } from "next"; import Quiz from "./components/Quiz"; @@ -10,8 +10,15 @@ export const metadata: Metadata = { "Welcome! Find out how to get started in the Rocky Linux community.", }; -const AboutPage = () => { - const t = useTranslations("community"); +type Props = { + params: Promise<{ locale: string }>; +}; + +const CommunityPage = async ({ params }: Props) => { + const { locale } = await params; + setRequestLocale(locale); + + const t = await getTranslations("community"); const quizTranslations: QuizInterests = { chatting: t("interests.chatting.title"), @@ -222,4 +229,4 @@ const AboutPage = () => { ); }; -export default AboutPage; +export default CommunityPage; diff --git a/app/[locale]/contribute/shop/page.tsx b/app/[locale]/contribute/shop/page.tsx index ef88cab8..eebc1964 100644 --- a/app/[locale]/contribute/shop/page.tsx +++ b/app/[locale]/contribute/shop/page.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { useTranslations } from "next-intl"; +import { getTranslations, setRequestLocale } from "next-intl/server"; import type { Metadata } from "next"; import Image from "next/image"; @@ -30,8 +30,15 @@ const vendors = [ }, ]; -const ShopPage = () => { - const t = useTranslations("shop"); +type Props = { + params: Promise<{ locale: string }>; +}; + +const ShopPage = async ({ params }: Props) => { + const { locale } = await params; + setRequestLocale(locale); + + const t = await getTranslations("shop"); return ( <> diff --git a/app/[locale]/download/components/Tabs.tsx b/app/[locale]/download/components/Tabs.tsx index a5951151..3b3657aa 100644 --- a/app/[locale]/download/components/Tabs.tsx +++ b/app/[locale]/download/components/Tabs.tsx @@ -1,3 +1,4 @@ +import { Suspense } from "react"; import { useTranslations } from "next-intl"; import TabsClient from "./TabsClient"; @@ -90,10 +91,14 @@ const DownloadTabs = ({ downloadData }: DownloadTabsProps) => { ); return ( - + } + > + + ); }; diff --git a/app/[locale]/download/page.tsx b/app/[locale]/download/page.tsx index eaea6e28..2af60951 100644 --- a/app/[locale]/download/page.tsx +++ b/app/[locale]/download/page.tsx @@ -1,4 +1,4 @@ -import { useTranslations } from "next-intl"; +import { getTranslations, setRequestLocale } from "next-intl/server"; import downloadData from "@/data/downloads.json"; import DownloadTabs from "./components/Tabs"; @@ -13,8 +13,15 @@ export const metadata: Metadata = { description: "Get started and download Rocky Linux today!", }; -const DownloadPage = () => { - const t = useTranslations("download"); +type Props = { + params: Promise<{ locale: string }>; +}; + +const DownloadPage = async ({ params }: Props) => { + const { locale } = await params; + setRequestLocale(locale); + + const t = await getTranslations("download"); const typedDownloadData = downloadData as DownloadData; return ( <> diff --git a/app/[locale]/layout.tsx b/app/[locale]/layout.tsx index 0b2c7604..f0cf0b85 100644 --- a/app/[locale]/layout.tsx +++ b/app/[locale]/layout.tsx @@ -13,7 +13,7 @@ import { ThemeProvider } from "@/components/ThemeProvider"; import Header from "./Header"; import Footer from "./Footer"; import { NextIntlClientProvider } from "next-intl"; -import { getMessages } from "next-intl/server"; +import { getMessages, setRequestLocale } from "next-intl/server"; import type { Metadata } from "next"; @@ -37,12 +37,19 @@ const fontDisplay = FontDisplay({ variable: "--font-display", }); +export function generateStaticParams() { + return availableLanguages.map((locale) => ({ locale })); +} + export default async function RootLayout({ children, params, }: LayoutProps<"/[locale]">) { const { locale } = await params; + // Enable static rendering for this locale + setRequestLocale(locale); + if (!availableLanguages.includes(locale as Locale)) notFound(); const messages = await getMessages(); diff --git a/app/[locale]/legal/[slug]/page.tsx b/app/[locale]/legal/[slug]/page.tsx index 3cc6f054..0b09107a 100644 --- a/app/[locale]/legal/[slug]/page.tsx +++ b/app/[locale]/legal/[slug]/page.tsx @@ -1,7 +1,9 @@ import { checkIfSlugIsValid, getContentData } from "@/lib/legalPages"; import { notFound } from "next/navigation"; +import { setRequestLocale } from "next-intl/server"; export type Params = { + locale: string; slug: string; }; @@ -32,7 +34,8 @@ export async function generateMetadata({ params }: Props) { } export default async function Page({ params }: Props) { - const { slug } = await params; + const { locale, slug } = await params; + setRequestLocale(locale); if (!(await checkIfSlugIsValid(slug))) { notFound(); diff --git a/app/[locale]/news/[slug]/page.tsx b/app/[locale]/news/[slug]/page.tsx index 0e841909..e78f1146 100644 --- a/app/[locale]/news/[slug]/page.tsx +++ b/app/[locale]/news/[slug]/page.tsx @@ -6,8 +6,10 @@ import ShareButtons from "@/components/shareButtons/ShareButtons"; import { checkIfSlugIsValid, getPostData } from "@/lib/news"; import { safeJsonLdStringify } from "@/utils/jsonLd"; import { notFound } from "next/navigation"; +import { setRequestLocale } from "next-intl/server"; export type Params = { + locale: string; slug: string; }; @@ -53,7 +55,8 @@ export async function generateMetadata({ params }: Props): Promise { } export default async function Post({ params }: Props) { - const { slug } = await params; + const { locale, slug } = await params; + setRequestLocale(locale); if (!(await checkIfSlugIsValid(slug))) { notFound(); diff --git a/app/[locale]/news/page.tsx b/app/[locale]/news/page.tsx index 2996cbd1..3c2a6e8a 100644 --- a/app/[locale]/news/page.tsx +++ b/app/[locale]/news/page.tsx @@ -1,6 +1,6 @@ -import type { Metadata, NextPage, Route } from "next"; +import type { Metadata, Route } from "next"; -import { getTranslations } from "next-intl/server"; +import { getTranslations, setRequestLocale } from "next-intl/server"; import Link from "next/link"; import { format } from "date-fns"; @@ -33,7 +33,14 @@ export async function generateMetadata(): Promise { }; } -const NewsPage: NextPage = async () => { +type Props = { + params: Promise<{ locale: string }>; +}; + +const NewsPage = async ({ params }: Props) => { + const { locale } = await params; + setRequestLocale(locale); + const posts = await getSortedPostsData(); const t = await getTranslations("news"); diff --git a/app/[locale]/page.tsx b/app/[locale]/page.tsx index 275e7c0b..5692d15f 100644 --- a/app/[locale]/page.tsx +++ b/app/[locale]/page.tsx @@ -2,8 +2,16 @@ import Hero from "./Hero"; import FeatureOne from "./FeatureOne"; import NewsSnippet from "./NewsSnippet"; import LogoCloud from "@/components/logoCloud/LogoCloud"; +import { setRequestLocale } from "next-intl/server"; + +type Props = { + params: Promise<{ locale: string }>; +}; + +export default async function Home({ params }: Props) { + const { locale } = await params; + setRequestLocale(locale); -export default function Home() { return ( <> diff --git a/app/[locale]/resources/[slug]/page.tsx b/app/[locale]/resources/[slug]/page.tsx index 1f1d35a8..00a150f9 100644 --- a/app/[locale]/resources/[slug]/page.tsx +++ b/app/[locale]/resources/[slug]/page.tsx @@ -1,7 +1,9 @@ import { checkIfSlugIsValid, getContentData } from "@/lib/resourcesPages"; import { notFound } from "next/navigation"; +import { setRequestLocale } from "next-intl/server"; export type Params = { + locale: string; slug: string; }; @@ -32,7 +34,8 @@ export async function generateMetadata({ params }: Props) { } export default async function Page({ params }: Props) { - const { slug } = await params; + const { locale, slug } = await params; + setRequestLocale(locale); if (!(await checkIfSlugIsValid(slug))) { notFound(); diff --git a/app/[locale]/support/support-providers/page.tsx b/app/[locale]/support/support-providers/page.tsx index 3529a81e..c15acea3 100644 --- a/app/[locale]/support/support-providers/page.tsx +++ b/app/[locale]/support/support-providers/page.tsx @@ -1,6 +1,6 @@ import React from "react"; import partnerSponsorData from "@/data/partnersSponsors"; -import { useTranslations } from "next-intl"; +import { getTranslations, setRequestLocale } from "next-intl/server"; import type { Metadata } from "next"; import Image from "next/image"; import { Badge } from "@/components/ui/badge"; @@ -11,7 +11,14 @@ export const metadata: Metadata = { "The following sponsors provide commercial support for Rocky Linux.", }; -const SupportProvidersPage = () => { +type Props = { + params: Promise<{ locale: string }>; +}; + +const SupportProvidersPage = async ({ params }: Props) => { + const { locale } = await params; + setRequestLocale(locale); + const { sponsors } = partnerSponsorData[0]; const sortedTierOneSponsors = sponsors @@ -21,7 +28,7 @@ const SupportProvidersPage = () => { .flatMap((sponsor) => sponsor.tierFour) .filter((sponsor) => sponsor.supportProvider === true); - const t = useTranslations("supportProviders"); + const t = await getTranslations("supportProviders"); return ( <> diff --git a/middleware.ts b/middleware.ts index 324a7d96..5db2f3d8 100644 --- a/middleware.ts +++ b/middleware.ts @@ -6,7 +6,9 @@ export default createMiddleware({ locales: [...availableLanguages], localePrefix: "as-needed", defaultLocale: "en", - localeDetection: true, + // Disable Accept-Language header detection to enable static rendering + // See: docs/i18n/caching-and-locale-detection.md + localeDetection: false, }); export const config = {