From a94e76a6a16f4b514800643283e4848405dd36c2 Mon Sep 17 00:00:00 2001 From: abdout Date: Sat, 25 Apr 2026 19:26:28 +0300 Subject: [PATCH] fix(ts): align [lang]/layout params with Next 16 LayoutProps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Next 16's auto-generated LayoutConfig<"/[lang]"> expects params: Promise<{ lang: string }> but the layout was declaring params: Promise<{ lang: Locale }> (narrowed). The narrower type was an over-promise. Loosens params to string and validates inside via a small resolveLocale() helper that falls back to i18n.defaultLocale for unknown segments. Applied to both generateMetadata and LocaleLayout. Stacked on fix/auth-restore-session-provider (PR #10) — auto-merges when that lands. Closes #45 Co-Authored-By: Claude Opus 4.7 (1M context) --- src/app/[lang]/layout.tsx | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/app/[lang]/layout.tsx b/src/app/[lang]/layout.tsx index c1f3021..6ad56fc 100644 --- a/src/app/[lang]/layout.tsx +++ b/src/app/[lang]/layout.tsx @@ -8,10 +8,16 @@ import { ThemeProvider } from "@/components/atom/theme-provider"; import { ImageKitProvider } from "@/components/ui/imagekit-provider"; import { Toaster } from "sonner"; import { getDictionary } from "@/components/internationalization/dictionaries"; -import { type Locale, localeConfig } from "@/components/internationalization/config"; +import { i18n, type Locale, localeConfig } from "@/components/internationalization/config"; import { SessionProvider } from "next-auth/react"; import { auth } from "@/auth"; +function resolveLocale(rawLang: string): Locale { + return (i18n.locales as readonly string[]).includes(rawLang) + ? (rawLang as Locale) + : i18n.defaultLocale; +} + // Configure Rubik font for Arabic const rubik = Rubik({ subsets: ['arabic', 'latin'], @@ -29,9 +35,10 @@ export const viewport: Viewport = { export async function generateMetadata({ params, }: { - params: Promise<{ lang: Locale }>; + params: Promise<{ lang: string }>; }): Promise { - const { lang } = await params; + const { lang: rawLang } = await params; + const lang = resolveLocale(rawLang); const dict = await getDictionary(lang); const baseUrl = process.env.NEXT_PUBLIC_BASE_URL || 'https://databayt.org'; @@ -78,9 +85,10 @@ export default async function LocaleLayout({ params, }: Readonly<{ children: React.ReactNode; - params: Promise<{ lang: Locale }>; + params: Promise<{ lang: string }>; }>) { - const [{ lang }, session] = await Promise.all([params, auth()]); + const [{ lang: rawLang }, session] = await Promise.all([params, auth()]); + const lang = resolveLocale(rawLang); const config = localeConfig[lang]; const isRTL = config.dir === 'rtl';