diff --git a/frontend/jest.config.js b/frontend/jest.config.js index c2c411f..b27cb26 100644 --- a/frontend/jest.config.js +++ b/frontend/jest.config.js @@ -10,8 +10,10 @@ const customJestConfig = { setupFilesAfterEnv: ['/jest.setup.js'], testEnvironment: 'jest-environment-jsdom', moduleNameMapper: { + '^next-intl$': '/tests/__mocks__/next-intl.tsx', '^next-intl/routing$': '/tests/__mocks__/next-intl-routing.tsx', '^next-intl/navigation$': '/tests/__mocks__/next-intl-navigation.tsx', + '^@/components/i18n$': '/tests/__mocks__/components-i18n.tsx', '^@/(.*)$': '/src/$1', }, testMatch: ['/tests/**/*.test.ts', '/tests/**/*.test.tsx'], diff --git a/frontend/messages/en.json b/frontend/messages/en.json index 179f935..63e3904 100644 --- a/frontend/messages/en.json +++ b/frontend/messages/en.json @@ -161,5 +161,11 @@ "maxLength": "Maximum {count} characters allowed", "pattern": "Invalid format", "passwordMismatch": "Passwords do not match" + }, + "locale": { + "en": "English", + "it": "Italian", + "switchLanguage": "Switch language", + "currentLanguage": "Current language" } } diff --git a/frontend/messages/it.json b/frontend/messages/it.json index 85a9754..dd1c414 100644 --- a/frontend/messages/it.json +++ b/frontend/messages/it.json @@ -161,5 +161,11 @@ "maxLength": "Massimo {count} caratteri consentiti", "pattern": "Formato non valido", "passwordMismatch": "Le password non corrispondono" + }, + "locale": { + "en": "Inglese", + "it": "Italiano", + "switchLanguage": "Cambia lingua", + "currentLanguage": "Lingua corrente" } } diff --git a/frontend/src/components/admin/Breadcrumbs.tsx b/frontend/src/components/admin/Breadcrumbs.tsx index 53e58fc..516c1f8 100644 --- a/frontend/src/components/admin/Breadcrumbs.tsx +++ b/frontend/src/components/admin/Breadcrumbs.tsx @@ -25,6 +25,7 @@ export function Breadcrumbs() { const pathname = usePathname(); // Generate breadcrumb items from pathname + // Note: usePathname() from next-intl returns path WITHOUT locale prefix const generateBreadcrumbs = (): BreadcrumbItem[] => { const segments = pathname.split('/').filter(Boolean); const breadcrumbs: BreadcrumbItem[] = []; diff --git a/frontend/src/components/home/Header.tsx b/frontend/src/components/home/Header.tsx index a2b6f5f..fa9fdd9 100644 --- a/frontend/src/components/home/Header.tsx +++ b/frontend/src/components/home/Header.tsx @@ -10,6 +10,7 @@ import { Link } from '@/lib/i18n/routing'; import { Menu, X, Github, Star } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Sheet, SheetContent, SheetTrigger } from '@/components/ui/sheet'; +import { LocaleSwitcher } from '@/components/i18n'; interface HeaderProps { onOpenDemoModal: () => void; @@ -63,6 +64,9 @@ export function Header({ onOpenDemoModal }: HeaderProps) { + {/* Locale Switcher */} + + {/* CTAs */} + + + {routing.locales.map((loc) => ( + handleLocaleChange(loc)} + className="cursor-pointer gap-2" + > + + ))} + + + ); +} diff --git a/frontend/src/components/i18n/index.ts b/frontend/src/components/i18n/index.ts new file mode 100644 index 0000000..cadda4d --- /dev/null +++ b/frontend/src/components/i18n/index.ts @@ -0,0 +1,6 @@ +/** + * i18n Components + * Exports internationalization-related components + */ + +export { LocaleSwitcher } from './LocaleSwitcher'; diff --git a/frontend/src/components/layout/Header.tsx b/frontend/src/components/layout/Header.tsx index 14475cb..d30226d 100644 --- a/frontend/src/components/layout/Header.tsx +++ b/frontend/src/components/layout/Header.tsx @@ -23,6 +23,7 @@ import { Avatar, AvatarFallback } from '@/components/ui/avatar'; import { Settings, LogOut, User, Shield } from 'lucide-react'; import { cn } from '@/lib/utils'; import { ThemeToggle } from '@/components/theme'; +import { LocaleSwitcher } from '@/components/i18n'; /** * Get user initials for avatar @@ -92,9 +93,10 @@ export function Header() { - {/* Right side - Theme toggle and user menu */} + {/* Right side - Theme toggle, locale switcher, and user menu */}
+