From c56a22b5dc408472e07925fda92fbe9080961342 Mon Sep 17 00:00:00 2001 From: Julien Froidefond Date: Thu, 27 Feb 2025 11:41:35 +0100 Subject: [PATCH] fix: hydration on i18n --- src/app/layout.tsx | 9 +++++++-- src/components/providers/I18nProvider.tsx | 22 ++++++++++++++++++++-- src/middleware.ts | 23 +++++++++++++++++++++++ 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/app/layout.tsx b/src/app/layout.tsx index af7ae6c..0131b85 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -6,6 +6,8 @@ import ClientLayout from "@/components/layout/ClientLayout"; import { PreferencesProvider } from "@/contexts/PreferencesContext"; import { I18nProvider } from "@/components/providers/I18nProvider"; import "@/i18n/i18n"; // Import i18next configuration +import { cookies } from "next/headers"; +import { defaultLocale } from "@/i18n/config"; const inter = Inter({ subsets: ["latin"] }); @@ -58,8 +60,11 @@ export const metadata: Metadata = { }; export default function RootLayout({ children }: { children: React.ReactNode }) { + const cookieStore = cookies(); + const locale = cookieStore.get("NEXT_LOCALE")?.value || defaultLocale; + return ( - + - + {children} diff --git a/src/components/providers/I18nProvider.tsx b/src/components/providers/I18nProvider.tsx index 6b474ad..a4a3a10 100644 --- a/src/components/providers/I18nProvider.tsx +++ b/src/components/providers/I18nProvider.tsx @@ -1,8 +1,26 @@ "use client"; -import { PropsWithChildren, useEffect } from "react"; +import { PropsWithChildren } from "react"; +import { useTranslate } from "@/hooks/useTranslate"; import "@/i18n/i18n"; -export function I18nProvider({ children }: PropsWithChildren) { +export function I18nProvider({ children, locale }: PropsWithChildren<{ locale: string }>) { + const { i18n } = useTranslate(); + // Synchroniser la langue avec celle du cookie côté client + if (typeof window !== "undefined") { + const localeCookie = document.cookie.split("; ").find((row) => row.startsWith("NEXT_LOCALE=")); + console.log(localeCookie); + if (localeCookie) { + const locale = localeCookie.split("=")[1]; + if (i18n.language !== locale) { + i18n.changeLanguage(locale); + } + } + } else { + if (i18n.language !== locale) { + i18n.changeLanguage(locale); + } + } + return <>{children}; } diff --git a/src/middleware.ts b/src/middleware.ts index e0a922d..c5904ff 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -10,8 +10,31 @@ const publicRoutes = ["/login", "/register", "/images"]; // Routes d'API qui ne nécessitent pas d'authentification const publicApiRoutes = ["/api/auth/login", "/api/auth/register", "/api/komga/test"]; +// Langues supportées +const locales = ["fr", "en"]; +const defaultLocale = "fr"; + export function middleware(request: NextRequest) { const { pathname } = request.nextUrl; + + // Gestion de la langue + let locale = request.cookies.get("NEXT_LOCALE")?.value; + + // Si pas de cookie de langue ou langue non supportée, on utilise la langue par défaut + if (!locale || !locales.includes(locale)) { + locale = defaultLocale; + + // On crée une nouvelle réponse avec le cookie de langue + const response = NextResponse.next(); + response.cookies.set("NEXT_LOCALE", locale, { + path: "/", + maxAge: 365 * 24 * 60 * 60, // 1 an + }); + + return response; + } + + // Gestion de l'authentification const user = request.cookies.get("stripUser"); // Si l'utilisateur est connecté et essaie d'accéder à la page de login ou register