fix: hydration on i18n

This commit is contained in:
Julien Froidefond
2025-02-27 11:41:35 +01:00
parent f39e4779cf
commit c56a22b5dc
3 changed files with 50 additions and 4 deletions

View File

@@ -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 (
<html lang="fr" suppressHydrationWarning>
<html lang={locale} suppressHydrationWarning>
<head>
<meta
name="viewport"
@@ -116,7 +121,7 @@ export default function RootLayout({ children }: { children: React.ReactNode })
/>
</head>
<body className={cn("min-h-screen bg-background font-sans antialiased", inter.className)}>
<I18nProvider>
<I18nProvider locale={locale}>
<PreferencesProvider>
<ClientLayout>{children}</ClientLayout>
</PreferencesProvider>

View File

@@ -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}</>;
}

View File

@@ -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