diff --git a/package.json b/package.json index 17b14a2..28a150a 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ }, "dependencies": { "@radix-ui/react-dialog": "1.0.5", - "@radix-ui/react-dropdown-menu": "2.0.6", + "@radix-ui/react-dropdown-menu": "^2.1.6", "@radix-ui/react-progress": "^1.1.2", "@radix-ui/react-slot": "1.0.2", "@radix-ui/react-toast": "1.1.5", @@ -19,16 +19,19 @@ "@types/mongoose": "5.11.97", "bcrypt": "^5.1.1", "class-variance-authority": "^0.7.0", - "clsx": "2.1.0", - "lucide-react": "0.323.0", + "clsx": "^2.1.1", + "i18next": "^24.2.2", + "i18next-browser-languagedetector": "^8.0.4", + "lucide-react": "^0.476.0", "mongoose": "8.1.0", "next": "14.1.0", "next-auth": "4.24.5", "next-themes": "0.2.1", "react": "18.2.0", "react-dom": "18.2.0", + "react-i18next": "^15.4.1", "sharp": "0.33.2", - "tailwind-merge": "2.2.1", + "tailwind-merge": "^3.0.2", "tailwindcss-animate": "1.0.7", "zod": "3.22.4" }, diff --git a/src/app/layout.tsx b/src/app/layout.tsx index ee518a4..af7ae6c 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -4,6 +4,8 @@ import "@/styles/globals.css"; import { cn } from "@/lib/utils"; import ClientLayout from "@/components/layout/ClientLayout"; import { PreferencesProvider } from "@/contexts/PreferencesContext"; +import { I18nProvider } from "@/components/providers/I18nProvider"; +import "@/i18n/i18n"; // Import i18next configuration const inter = Inter({ subsets: ["latin"] }); @@ -114,9 +116,11 @@ export default function RootLayout({ children }: { children: React.ReactNode }) /> - - {children} - + + + {children} + + ); diff --git a/src/app/login/LoginContent.tsx b/src/app/login/LoginContent.tsx index 2de8157..3e87c0d 100644 --- a/src/app/login/LoginContent.tsx +++ b/src/app/login/LoginContent.tsx @@ -3,6 +3,7 @@ import { LoginForm } from "@/components/auth/LoginForm"; import { RegisterForm } from "@/components/auth/RegisterForm"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { useTranslate } from "@/hooks/useTranslate"; interface LoginContentProps { searchParams: { @@ -12,6 +13,7 @@ interface LoginContentProps { } export function LoginContent({ searchParams }: LoginContentProps) { + const { t } = useTranslate(); const defaultTab = searchParams.tab || "login"; return ( @@ -41,25 +43,20 @@ export function LoginContent({ searchParams }: LoginContentProps) {
-

- Profitez de vos BD, mangas et comics préférés avec une expérience de lecture moderne - et fluide. -

+

{t("login.description")}

-

Bienvenue sur StripStream

-

- Connectez-vous ou créez un compte pour commencer -

+

{t("login.title")}

+

{t("login.subtitle")}

- Connexion - Inscription + {t("login.tabs.login")} + {t("login.tabs.register")} diff --git a/src/components/LanguageSelector.tsx b/src/components/LanguageSelector.tsx new file mode 100644 index 0000000..eb7a239 --- /dev/null +++ b/src/components/LanguageSelector.tsx @@ -0,0 +1,43 @@ +"use client"; + +import { useTranslation } from "react-i18next"; +import { Button } from "@/components/ui/button"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { Languages } from "lucide-react"; + +export default function LanguageSelector() { + const { t, i18n } = useTranslation("common"); + + const handleLanguageChange = (newLocale: string) => { + i18n.changeLanguage(newLocale); + }; + + return ( + + + + + + handleLanguageChange("fr")} + className={i18n.language === "fr" ? "bg-accent" : ""} + > + {t("language.fr")} + + handleLanguageChange("en")} + className={i18n.language === "en" ? "bg-accent" : ""} + > + {t("language.en")} + + + + ); +} diff --git a/src/components/home/HeroSection.tsx b/src/components/home/HeroSection.tsx index 1d1f401..758ba30 100644 --- a/src/components/home/HeroSection.tsx +++ b/src/components/home/HeroSection.tsx @@ -1,4 +1,7 @@ +"use client"; + import { Cover } from "@/components/ui/cover"; +import { useTranslate } from "@/hooks/useTranslate"; interface OptimizedHeroSeries { id: string; @@ -12,6 +15,8 @@ interface HeroSectionProps { } export function HeroSection({ series }: HeroSectionProps) { + const { t } = useTranslate(); + // console.log("HeroSection - Séries reçues:", { // count: series?.length || 0, // firstSeries: series?.[0], @@ -29,7 +34,7 @@ export function HeroSection({ series }: HeroSectionProps) { @@ -43,10 +48,10 @@ export function HeroSection({ series }: HeroSectionProps) { {/* Contenu */}

- Bienvenue sur StripStream + {t("home.hero.title")}

- Votre bibliothèque numérique pour lire vos BD, mangas et comics préférés. + {t("home.hero.subtitle")}

diff --git a/src/components/home/HomeContent.tsx b/src/components/home/HomeContent.tsx index 6f30f95..3c285f1 100644 --- a/src/components/home/HomeContent.tsx +++ b/src/components/home/HomeContent.tsx @@ -1,9 +1,12 @@ +"use client"; + import { HeroSection } from "./HeroSection"; import { MediaRow } from "./MediaRow"; import { KomgaBook, KomgaSeries } from "@/types/komga"; import { RefreshButton } from "@/components/library/RefreshButton"; import { History, Sparkles, Clock, LibraryBig, BookOpen } from "lucide-react"; import { HomeData } from "@/lib/services/home.service"; +import { useTranslate } from "@/hooks/useTranslate"; interface HomeContentProps { data: HomeData; @@ -11,6 +14,8 @@ interface HomeContentProps { } export function HomeContent({ data, refreshHome }: HomeContentProps) { + const { t } = useTranslate(); + // Vérification des données pour le debug // console.log("HomeContent - Données reçues:", { // ongoingCount: data.ongoing?.length || 0, @@ -51,7 +56,7 @@ export function HomeContent({ data, refreshHome }: HomeContentProps) { return (
-

Accueil

+

{t("home.title")}

{/* Hero Section - Afficher uniquement si nous avons des séries en cours */} @@ -63,7 +68,7 @@ export function HomeContent({ data, refreshHome }: HomeContentProps) {
{data.ongoing && data.ongoing.length > 0 && ( } /> @@ -71,7 +76,7 @@ export function HomeContent({ data, refreshHome }: HomeContentProps) { {data.ongoingBooks && data.ongoingBooks.length > 0 && ( } /> @@ -79,7 +84,7 @@ export function HomeContent({ data, refreshHome }: HomeContentProps) { {data.onDeck && data.onDeck.length > 0 && ( } /> @@ -87,7 +92,7 @@ export function HomeContent({ data, refreshHome }: HomeContentProps) { {data.latestSeries && data.latestSeries.length > 0 && ( } /> @@ -95,7 +100,7 @@ export function HomeContent({ data, refreshHome }: HomeContentProps) { {data.recentlyRead && data.recentlyRead.length > 0 && ( } /> diff --git a/src/components/layout/Header.tsx b/src/components/layout/Header.tsx index 316586e..53e55fd 100644 --- a/src/components/layout/Header.tsx +++ b/src/components/layout/Header.tsx @@ -1,5 +1,6 @@ import { Menu, Moon, Sun } from "lucide-react"; import { useTheme } from "next-themes"; +import LanguageSelector from "@/components/LanguageSelector"; interface HeaderProps { onToggleSidebar: () => void; @@ -33,7 +34,8 @@ export function Header({ onToggleSidebar }: HeaderProps) {
-