From 85ea4e6200bbf0540877dfa3182e86e3160dfb81 Mon Sep 17 00:00:00 2001 From: nxtkofi Date: Tue, 21 Apr 2026 20:53:13 +0200 Subject: [PATCH] feat(i18n): add locale layout and dynamic lang attribute Add [locale] layout with locale validation and static rendering support. Update root layout to read x-next-intl-locale header for dynamic lang attribute. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- src/app/[locale]/layout.tsx | 26 ++++++++++++++++++++++++++ src/app/layout.tsx | 8 ++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 src/app/[locale]/layout.tsx diff --git a/src/app/[locale]/layout.tsx b/src/app/[locale]/layout.tsx new file mode 100644 index 0000000..1430e59 --- /dev/null +++ b/src/app/[locale]/layout.tsx @@ -0,0 +1,26 @@ +import { setRequestLocale } from 'next-intl/server'; +import { hasLocale } from 'next-intl'; +import { notFound } from 'next/navigation'; +import { routing } from '@/i18n/routing'; + +export function generateStaticParams() { + return routing.locales.map((locale) => ({ locale })); +} + +export default async function LocaleLayout({ + children, + params, +}: { + children: React.ReactNode; + params: Promise<{ locale: string }>; +}) { + const { locale } = await params; + + if (!hasLocale(routing.locales, locale)) { + notFound(); + } + + setRequestLocale(locale); + + return <>{children}; +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 8e51c13..e32c57e 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,4 +1,5 @@ import type { Metadata } from 'next'; +import { headers } from 'next/headers'; import './globals.css'; import { NextIntlClientProvider } from 'next-intl'; import { ThemeProvider } from '@wrksz/themes/next'; @@ -14,14 +15,17 @@ export const metadata: Metadata = { description: 'Create SaaS in a day!', }; -export default function RootLayout({ +export default async function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { + const headersList = await headers(); + const locale = headersList.get('x-next-intl-locale') || 'en'; + return (