['en' => '/contact'], '/contact' => ['de' => '/kontakt'], '/so-funktionierts' => ['en' => '/how-it-works'], '/how-it-works' => ['de' => '/so-funktionierts'], '/anlaesse' => ['en' => '/occasions'], '/anlaesse/hochzeit' => ['en' => '/occasions/wedding'], '/anlaesse/geburtstag' => ['en' => '/occasions/birthday'], '/anlaesse/firmenevent' => ['en' => '/occasions/corporate-event'], '/anlaesse/konfirmation' => ['en' => '/occasions/confirmation'], '/occasions/wedding' => ['de' => '/anlaesse/hochzeit'], '/occasions/birthday' => ['de' => '/anlaesse/geburtstag'], '/occasions/corporate-event' => ['de' => '/anlaesse/firmenevent'], '/occasions/confirmation' => ['de' => '/anlaesse/konfirmation'], ]; $rewrites = $map[$normalized] ?? []; return $rewrites[$locale] ?? $normalized; }; $determinePreferredLocale = static function (Request $request) use ($supportedLocales): string { $sessionLocale = $request->session()->get('preferred_locale'); if ($sessionLocale && in_array($sessionLocale, $supportedLocales, true)) { return $sessionLocale; } $headerLocale = $request->getPreferredLanguage($supportedLocales); if ($headerLocale && in_array($headerLocale, $supportedLocales, true)) { return $headerLocale; } return $supportedLocales[0] ?? 'de'; }; Route::prefix('{locale}') ->where(['locale' => $localePattern]) ->group(function () { Route::get('/', [MarketingController::class, 'index'])->name('marketing.home'); Route::middleware('guest')->group(function () { Route::get('/login', [AuthenticatedSessionController::class, 'create']); Route::post('/login', [AuthenticatedSessionController::class, 'store']); Route::get('/register', [RegisteredUserController::class, 'create']); Route::post('/register', [RegisteredUserController::class, 'store']); }); Route::get('/contact', [MarketingController::class, 'contactView']) ->name('marketing.contact'); Route::post('/contact', [MarketingController::class, 'contact']) ->middleware(['throttle:contact-form', ProtectAgainstSpam::class]) ->name('marketing.contact.submit'); Route::get('/kontakt', [MarketingController::class, 'contactView']) ->name('kontakt'); Route::post('/kontakt', [MarketingController::class, 'contact']) ->middleware(['throttle:contact-form', ProtectAgainstSpam::class]) ->name('kontakt.submit'); Route::get('/blog', [MarketingController::class, 'blogIndex'])->name('blog'); Route::get('/blog/{slug}', [MarketingController::class, 'blogShow'])->name('blog.show'); Route::get('/packages', [MarketingController::class, 'packagesIndex'])->name('packages'); Route::get('/anlaesse/{type}', [MarketingController::class, 'occasionsType'])->name('anlaesse.type'); Route::get('/occasions/{type}', [MarketingController::class, 'occasionsType']) ->name('occasions.type'); Route::get('/so-funktionierts', [MarketingController::class, 'howItWorks']) ->where('locale', 'de'); Route::get('/how-it-works', [MarketingController::class, 'howItWorks']) ->where('locale', 'en') ->name('marketing.how-it-works'); Route::get('/demo', [MarketingController::class, 'demo'])->name('demo'); Route::get('/success/{packageId?}', [MarketingController::class, 'success'])->name('marketing.success'); Route::get('/gutschein', [MarketingController::class, 'giftVouchers'])->name('marketing.gift-voucher.de'); Route::get('/gift-card', [MarketingController::class, 'giftVouchers'])->name('marketing.gift-voucher.en'); Route::get('/gift-vouchers/{voucher}/print', GiftVoucherPrintController::class) ->middleware('signed') ->name('marketing.gift-vouchers.print'); Route::middleware('auth')->group(function () { Route::get('/voucher-status', fn () => Inertia::render('marketing/GiftVoucherStatus')) ->name('marketing.gift-voucher.status'); }); Route::get('/impressum', [LegalPageController::class, 'show']) ->defaults('slug', 'impressum') ->name('impressum'); Route::get('/imprint', [LegalPageController::class, 'show']) ->where('locale', 'en') ->defaults('slug', 'impressum') ->name('imprint'); Route::get('/datenschutz', [LegalPageController::class, 'show']) ->defaults('slug', 'datenschutz') ->name('datenschutz'); Route::get('/privacy', [LegalPageController::class, 'show']) ->where('locale', 'en') ->defaults('slug', 'datenschutz') ->name('privacy'); Route::get('/agb', [LegalPageController::class, 'show']) ->defaults('slug', 'agb') ->name('agb'); Route::get('/terms', [LegalPageController::class, 'show']) ->where('locale', 'en') ->defaults('slug', 'agb') ->name('terms'); Route::get('/widerrufsbelehrung', [LegalPageController::class, 'show']) ->defaults('slug', 'widerrufsbelehrung') ->name('widerrufsbelehrung'); Route::get('/withdrawal', [LegalPageController::class, 'show']) ->where('locale', 'en') ->defaults('slug', 'widerrufsbelehrung') ->name('withdrawal'); Route::get('/buy/{packageId}', [MarketingController::class, 'buyPackages']) ->name('buy.packages') ->defaults('locale', config('app.locale', 'de')); if (config('checkout.enabled')) { Route::get('/{checkoutSlug}/{package}', [CheckoutController::class, 'show']) ->where('checkoutSlug', 'bestellen|checkout') ->name('checkout.show'); } else { Route::get('/{checkoutSlug}/{package}', function (string $locale, string $checkoutSlug, string $package) { $resolvedPackage = Package::query()->find($package); if (! $resolvedPackage) { return redirect() ->route('packages', ['locale' => $locale]) ->with('error', __('marketing.packages.package_not_found')); } return redirect()->route('packages', [ 'locale' => $locale, 'highlight' => $resolvedPackage->slug, ]); }) ->where('checkoutSlug', 'bestellen|checkout') ->name('checkout.show'); } Route::middleware('auth')->group(function () { Route::get('/profile', [ProfileController::class, 'index']) ->name('marketing.profile.index'); Route::get('/widerruf', [WithdrawalController::class, 'show']) ->where('locale', 'de') ->name('marketing.withdrawal.confirm.de'); Route::post('/widerruf', [WithdrawalController::class, 'confirm']) ->where('locale', 'de') ->name('marketing.withdrawal.confirm.submit.de'); Route::get('/withdrawal/confirm', [WithdrawalController::class, 'show']) ->where('locale', 'en') ->name('marketing.withdrawal.confirm.en'); Route::post('/withdrawal/confirm', [WithdrawalController::class, 'confirm']) ->where('locale', 'en') ->name('marketing.withdrawal.confirm.submit.en'); }); Route::fallback(function () { return Inertia::render('marketing/NotFound', [ 'requestedPath' => request()->path(), ])->toResponse(request())->setStatusCode(404); }); }); Route::get('/', function (Request $request) use ($determinePreferredLocale) { $locale = $determinePreferredLocale($request); return redirect("/{$locale}", 302); })->name('home'); Route::get('/contact', function (Request $request) use ($determinePreferredLocale, $rewritePath) { $locale = $determinePreferredLocale($request); $path = $rewritePath('/contact', $locale); return redirect("/{$locale}".($path === '/' ? '' : $path), 301); }); Route::get('/kontakt', function (Request $request) use ($determinePreferredLocale, $rewritePath) { $locale = $determinePreferredLocale($request); $path = $rewritePath('/kontakt', $locale); return redirect("/{$locale}".($path === '/' ? '' : $path), 301); }); Route::get('/so-funktionierts', function (Request $request) use ($determinePreferredLocale, $rewritePath) { $locale = $determinePreferredLocale($request); $path = $rewritePath('/so-funktionierts', $locale); return redirect("/{$locale}{$path}", 301); }); Route::get('/how-it-works', function (Request $request) use ($determinePreferredLocale, $rewritePath) { $locale = $determinePreferredLocale($request); $path = $rewritePath('/how-it-works', $locale); return redirect("/{$locale}{$path}", 301); }); Route::get('/blog', function (Request $request) use ($determinePreferredLocale) { $locale = $determinePreferredLocale($request); return redirect("/{$locale}/blog", 301); }); Route::get('/blog/{slug}', function (Request $request, string $slug) use ($determinePreferredLocale) { $locale = $determinePreferredLocale($request); return redirect("/{$locale}/blog/{$slug}", 301); }); Route::get('/packages', function (Request $request) use ($determinePreferredLocale) { $locale = $determinePreferredLocale($request); return redirect("/{$locale}/packages", 301); }); Route::get('/anlaesse/{type}', function (Request $request, string $type) use ($determinePreferredLocale, $rewritePath) { $locale = $determinePreferredLocale($request); $path = $rewritePath("/anlaesse/{$type}", $locale); return redirect("/{$locale}{$path}", 301); }); Route::get('/occasions/{type}', function (Request $request, string $type) use ($determinePreferredLocale, $rewritePath) { $locale = $determinePreferredLocale($request); $path = $rewritePath("/occasions/{$type}", $locale); return redirect("/{$locale}{$path}", 301); }); Route::get('/demo', function (Request $request) use ($determinePreferredLocale) { $locale = $determinePreferredLocale($request); return redirect("/{$locale}/demo", 301); }); Route::get('/marketing/login', function (Request $request) use ($determinePreferredLocale) { $locale = $determinePreferredLocale($request); $destination = "/{$locale}/login"; $query = $request->getQueryString(); return redirect($query ? "{$destination}?{$query}" : $destination, 302); })->name('marketing.login'); Route::get('/success/{packageId?}', function (Request $request, ?int $packageId = null) use ($determinePreferredLocale) { $locale = $determinePreferredLocale($request); $path = "/{$locale}/success"; if ($packageId !== null) { $path .= "/{$packageId}"; } return redirect($path, 301); }); Route::get('/buy/{packageId}', function (Request $request, int $packageId) use ($determinePreferredLocale) { $locale = $determinePreferredLocale($request); return redirect("/{$locale}/buy/{$packageId}", 301); }); Route::get('/dashboard', DashboardController::class) ->middleware(['auth']) ->name('dashboard'); Route::middleware('auth')->group(function () { Route::get('/profile', [ProfileController::class, 'index']) ->name('profile.index'); Route::post('/profile/data-exports', [ProfileDataExportController::class, 'store']) ->name('profile.data-exports.store'); Route::get('/profile/data-exports/{export}', [ProfileDataExportController::class, 'download']) ->name('profile.data-exports.download'); Route::delete('/profile/account', [ProfileAccountController::class, 'destroy']) ->name('profile.account.destroy'); }); Route::middleware('auth:super_admin')->group(function () { Route::get('/super-admin/data-exports/{export}/download', [SuperAdminDataExportController::class, 'download']) ->name('superadmin.data-exports.download'); }); Route::prefix('event-admin')->group(function () { $renderAdmin = fn () => view('admin'); $authAdmin = TenantAdminAuthController::class; // Public routes (auth check inside controller) Route::get('/auth/callback', $renderAdmin)->name('tenant.admin.auth.callback'); Route::get('/login', $renderAdmin)->name('tenant.admin.login'); Route::get('/auth/google', [TenantAdminGoogleController::class, 'redirect']) ->name('tenant.admin.google.redirect'); Route::get('/auth/google/callback', [TenantAdminGoogleController::class, 'callback']) ->name('tenant.admin.google.callback'); // Protected routes (auth check inside controller) Route::get('/logout', $authAdmin)->name('tenant.admin.logout'); Route::get('/dashboard', $authAdmin)->name('tenant.admin.dashboard'); Route::get('/{view?}', $renderAdmin) ->where('view', '.*') ->name('tenant.admin.app'); }); Route::view('/event', 'guest')->name('guest.pwa.landing'); Route::view('/g/{token}', 'guest')->where('token', '.*')->name('guest.gallery'); Route::view('/show/{token}', 'guest')->where('token', '.*')->name('guest.live-show'); Route::view('/e/{token}/{path?}', 'guest') ->where('token', '.*') ->where('path', '.*') ->name('guest.event'); Route::view('/share/{slug}', 'guest') ->where('slug', '[A-Za-z0-9]+') ->name('guest.share'); Route::middleware('auth')->group(function () { Route::get('/tenant/events/{event}/photos/archive', EventPhotoArchiveController::class) ->name('tenant.events.photos.archive'); }); Route::get('/purchase-wizard/{package}', function (Request $request, string $package) use ($determinePreferredLocale) { $locale = $determinePreferredLocale($request); $resolvedPackage = Package::query()->find($package); if (! $resolvedPackage) { return redirect() ->route('packages', ['locale' => $locale]) ->with('error', __('marketing.packages.package_not_found')); } return redirect()->to(CheckoutRoutes::wizardUrl($resolvedPackage, $locale), 301); }); Route::get('/checkout/{package}', function (Request $request, string $package) use ($determinePreferredLocale) { $locale = $determinePreferredLocale($request); $resolvedPackage = Package::query()->find($package); if (! $resolvedPackage) { return redirect() ->route('packages', ['locale' => $locale]) ->with('error', __('marketing.packages.package_not_found')); } return redirect()->to(CheckoutRoutes::wizardUrl($resolvedPackage, $locale), 301); }); Route::post('/checkout/login', [CheckoutController::class, 'login'])->name('checkout.login'); Route::post('/checkout/register', [CheckoutController::class, 'register'])->name('checkout.register'); Route::get('/checkout/auth/google', [CheckoutGoogleController::class, 'redirect'])->name('checkout.google.redirect'); Route::get('/checkout/auth/google/callback', [CheckoutGoogleController::class, 'callback'])->name('checkout.google.callback'); Route::post('/checkout/track-abandoned', [CheckoutController::class, 'trackAbandonedCheckout'])->name('checkout.track-abandoned'); Route::post('/set-locale', [LocaleController::class, 'set'])->name('set-locale'); Route::middleware('auth')->group(function () { Route::post('/checkout/free-activate', [CheckoutController::class, 'activateFree'])->name('checkout.free-activate'); Route::get('/checkout/session/{session}/status', [CheckoutController::class, 'sessionStatus']) ->whereUuid('session') ->name('checkout.session.status'); Route::post('/checkout/session/{session}/confirm', [CheckoutController::class, 'confirmSession']) ->whereUuid('session') ->name('checkout.session.confirm'); Route::post('/paddle/create-checkout', [PaddleCheckoutController::class, 'create'])->name('paddle.checkout.create'); }); Route::get('/paddle/return', \App\Http\Controllers\PaddleReturnController::class) ->name('paddle.return'); Route::post('/paddle/webhook', [PaddleWebhookController::class, 'handle']) ->withoutMiddleware([\Illuminate\Foundation\Http\Middleware\ValidateCsrfToken::class]) ->middleware('throttle:paddle-webhook') ->name('paddle.webhook');