From b9d91c8f402bfefcb4d69676c90765f60c89be4b Mon Sep 17 00:00:00 2001 From: Codex Agent Date: Thu, 22 Jan 2026 09:07:46 +0100 Subject: [PATCH] Improve marketing language switcher --- public/lang/de/marketing.json | 4 + public/lang/en/marketing.json | 4 + resources/js/layouts/mainWebsite.tsx | 207 +++++++++++++++++++++++---- resources/lang/de/marketing.json | 6 +- resources/lang/en/marketing.json | 6 +- 5 files changed, 194 insertions(+), 33 deletions(-) diff --git a/public/lang/de/marketing.json b/public/lang/de/marketing.json index 04f1aca..2ad5fba 100644 --- a/public/lang/de/marketing.json +++ b/public/lang/de/marketing.json @@ -504,6 +504,10 @@ "contact": "Kontakt", "discover_packages": "Packages entdecken", "language": "Sprache", + "language_de": "Deutsch", + "language_en": "English", + "language_changed": "{{language}} ausgewählt", + "language": "Sprache", "open_menu": "Menü öffnen", "close_menu": "Menü schließen", "cta_demo": "Jetzt ausprobieren", diff --git a/public/lang/en/marketing.json b/public/lang/en/marketing.json index 496e25f..f4cb975 100644 --- a/public/lang/en/marketing.json +++ b/public/lang/en/marketing.json @@ -494,6 +494,10 @@ "contact": "Contact", "discover_packages": "Discover Packages", "language": "Language", + "language_de": "Deutsch", + "language_en": "English", + "language_changed": "{{language}} selected", + "language": "Language", "open_menu": "Open menu", "close_menu": "Close menu", "cta_demo": "Try it now", diff --git a/resources/js/layouts/mainWebsite.tsx b/resources/js/layouts/mainWebsite.tsx index a57c9ec..26d2dd1 100644 --- a/resources/js/layouts/mainWebsite.tsx +++ b/resources/js/layouts/mainWebsite.tsx @@ -8,6 +8,7 @@ import { useAppearance } from '@/hooks/use-appearance'; import { Button } from '@/components/ui/button'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuTrigger } from '@/components/ui/dropdown-menu'; import { MoreHorizontal, Sun, Moon, Languages, LayoutDashboard, LogOut, LogIn } from 'lucide-react'; +import toast from 'react-hot-toast'; interface MarketingLayoutProps { children: React.ReactNode; @@ -136,9 +137,44 @@ const MarketingLayout: React.FC = ({ children, title }) => return acc; }, {}); + const orderedLocales = useMemo(() => { + const preferredOrder = ['de', 'en']; + return [...supportedLocales].sort((a, b) => { + const aIndex = preferredOrder.indexOf(a); + const bIndex = preferredOrder.indexOf(b); + if (aIndex === -1 && bIndex === -1) return a.localeCompare(b); + if (aIndex === -1) return 1; + if (bIndex === -1) return -1; + return aIndex - bIndex; + }); + }, [supportedLocales]); + + const resolveLanguageLabel = (code: string) => { + if (code === 'de') { + return t('nav.language_de', 'Deutsch'); + } + if (code === 'en') { + return t('nav.language_en', 'English'); + } + return code.toUpperCase(); + }; + + const languageOptions = useMemo(() => orderedLocales.map((code) => ({ + code, + label: resolveLanguageLabel(code), + })), [orderedLocales, t]); + + const useInlineLocaleToggle = supportedLocales.length === 2; + const handleLocaleChange = (nextLocale: string) => { + if (nextLocale === activeLocale) { + setMobileMenuOpen(false); + return; + } + const targetPath = localizedPath(relativePath, nextLocale); const targetUrl = `${targetPath}${rawQuery ? `?${rawQuery}` : ''}`; + const nextLabel = resolveLanguageLabel(nextLocale); setMobileMenuOpen(false); router.visit(targetUrl, { @@ -146,10 +182,47 @@ const MarketingLayout: React.FC = ({ children, title }) => preserveState: false, onSuccess: () => { i18n.changeLanguage(nextLocale); + toast.success(t('nav.language_changed', '{{language}} selected', { language: nextLabel })); }, }); }; + const FlagDe = () => ( + + ); + + const FlagEn = () => ( + + ); + + const resolveFlag = (code: string) => { + if (code === 'de') { + return ; + } + if (code === 'en') { + return ; + } + return null; + }; + return ( <> @@ -232,6 +305,36 @@ const MarketingLayout: React.FC = ({ children, title }) => ))}
+ {useInlineLocaleToggle && ( +
+ {languageOptions.map((option) => { + const isActive = option.code === activeLocale; + return ( + + ); + })} +
+ )}
- - + {useInlineLocaleToggle ? ( +
+

+ {t('nav.language', 'Sprache')} +

+
+ {languageOptions.map((option) => { + const isActive = option.code === activeLocale; + return ( + + ); + })} +
+
+ ) : ( + <> + + + + )}
diff --git a/resources/lang/de/marketing.json b/resources/lang/de/marketing.json index e75e81c..49b2f3e 100644 --- a/resources/lang/de/marketing.json +++ b/resources/lang/de/marketing.json @@ -421,7 +421,11 @@ "blog": "Blog", "packages": "Pakete", "contact": "Kontakt", - "discover_packages": "Pakete entdecken" + "discover_packages": "Pakete entdecken", + "language": "Sprache", + "language_de": "Deutsch", + "language_en": "English", + "language_changed": "{{language}} ausgewählt" }, "footer": { "company": "S.E.B. Fotografie", diff --git a/resources/lang/en/marketing.json b/resources/lang/en/marketing.json index f3509c6..b91f59b 100644 --- a/resources/lang/en/marketing.json +++ b/resources/lang/en/marketing.json @@ -421,7 +421,11 @@ "blog": "Blog", "packages": "Packages", "contact": "Contact", - "discover_packages": "Discover Packages" + "discover_packages": "Discover Packages", + "language": "Language", + "language_de": "Deutsch", + "language_en": "English", + "language_changed": "{{language}} selected" }, "footer": { "company": "S.E.B. Fotografie",