144 lines
6.9 KiB
PHP
144 lines
6.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* @var string $content Page body (rendered by the controller)
|
|
* @var string $locale Current locale code (e.g. 'de')
|
|
* @var callable $t Translation helper
|
|
* @var callable $locale_switcher Returns the locale switcher HTML
|
|
* @var string|null $pageTitle Optional page title override
|
|
* @var string|null $pageDescription Optional meta description override
|
|
* @var string|null $canonical Optional canonical URL override
|
|
* @var string|null $robots Optional robots meta override
|
|
* @var array<string,string>|null $openGraph OG meta map: ogTitle, ogDescription, ogImage, ogUrl
|
|
* @var string|null $structuredData JSON-LD blob
|
|
* @var string|null $extraCss Optional inline CSS
|
|
*/
|
|
|
|
use App\Core\I18n;
|
|
use App\Core\Locale;
|
|
|
|
$currentPath = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH) ?: '/';
|
|
$ogLocale = Locale::toOgLocale($locale);
|
|
$title = $pageTitle ?? I18n::t('site.title', [], $locale);
|
|
$description = $pageDescription ?? I18n::t('site.description', [], $locale);
|
|
$canonicalBase = I18n::t('site.canonical_base', [], $locale);
|
|
$canonical = $canonical ?? $canonicalBase . ($currentPath === '/' ? '/' : $currentPath);
|
|
$siteName = I18n::t('site.name', [], $locale);
|
|
$ogTitle = $openGraph['ogTitle'] ?? $title;
|
|
$ogDescription = $openGraph['ogDescription'] ?? $description;
|
|
$ogImage = $openGraph['ogImage'] ?? 'https://haus-schleusingen.de/bilder/Aussenansicht-2.webp';
|
|
$ogUrl = $openGraph['ogUrl'] ?? $canonical;
|
|
$hreflangs = Locale::hreflangAlternates($currentPath === '/' ? '/' : $currentPath, $canonicalBase);
|
|
|
|
$homeUrl = $canonicalBase . '/';
|
|
$isHome = $currentPath === '/' || $currentPath === '';
|
|
$isImpr = $currentPath === '/impressum';
|
|
$isPriv = $currentPath === '/datenschutz';
|
|
|
|
$navItems = [
|
|
['href' => '/#galerie', 'label' => 'nav.gallery', 'active' => false],
|
|
['href' => '/#grundriss','label' => 'nav.layout', 'active' => false],
|
|
['href' => '/#miete', 'label' => 'nav.rent', 'active' => false],
|
|
['href' => '/#lage', 'label' => 'nav.location', 'active' => false],
|
|
];
|
|
?>
|
|
<!doctype html>
|
|
<html lang="<?= htmlspecialchars($locale, ENT_QUOTES) ?>">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title><?= htmlspecialchars($title) ?></title>
|
|
<meta name="description" content="<?= htmlspecialchars($description) ?>" />
|
|
<?php if (isset($robots)): ?>
|
|
<meta name="robots" content="<?= htmlspecialchars($robots) ?>" />
|
|
<?php endif; ?>
|
|
<link rel="canonical" href="<?= htmlspecialchars($canonical) ?>" />
|
|
|
|
<?php foreach ($hreflangs as $alt): ?>
|
|
<link rel="alternate" hreflang="<?= htmlspecialchars($alt['hreflang']) ?>" href="<?= htmlspecialchars($alt['href']) ?>" />
|
|
<?php endforeach; ?>
|
|
|
|
<link rel="icon" type="image/png" sizes="32x32" href="/bilder/favicon/favicon-32x32.png">
|
|
<link rel="icon" type="image/png" sizes="16x16" href="/bilder/favicon/favicon-16x16.png">
|
|
<link rel="icon" type="image/x-icon" href="/bilder/favicon/favicon.ico">
|
|
<link rel="apple-touch-icon" sizes="180x180" href="/bilder/favicon/apple-touch-icon.png">
|
|
<link rel="manifest" href="/bilder/favicon/site.webmanifest">
|
|
|
|
<meta property="og:type" content="<?= htmlspecialchars($ogType ?? 'website', ENT_QUOTES) ?>">
|
|
<meta property="og:url" content="<?= htmlspecialchars($ogUrl ?? $canonical ?? ($t('site.canonical_base') . '/'), ENT_QUOTES) ?>">
|
|
<meta property="og:title" content="<?= htmlspecialchars($ogTitle ?? $pageTitle ?? $t('site.title'), ENT_QUOTES) ?>">
|
|
<meta property="og:description" content="<?= htmlspecialchars($ogDescription ?? $pageDescription ?? $t('site.description'), ENT_QUOTES) ?>">
|
|
<meta property="og:locale" content="<?= htmlspecialchars($ogLocale ?? Locale::toOgLocale($locale), ENT_QUOTES) ?>">
|
|
<meta property="og:site_name" content="<?= htmlspecialchars($ogSiteName ?? $t('site.name'), ENT_QUOTES) ?>">
|
|
<meta property="og:image" content="<?= htmlspecialchars($ogImage ?? ($t('site.canonical_base') . '/bilder/hero-bg.jpg'), ENT_QUOTES) ?>">
|
|
|
|
<?php if (isset($structuredData)): ?>
|
|
<script type="application/ld+json"><?= $structuredData ?></script>
|
|
<?php endif; ?>
|
|
|
|
<link rel="stylesheet" href="/fonts/fonts.css" />
|
|
<link rel="stylesheet" href="/css/haus-schleusingen.css" />
|
|
<?php if (isset($extraCss)): ?>
|
|
<style><?= $extraCss ?></style>
|
|
<?php endif; ?>
|
|
</head>
|
|
<body>
|
|
<a class="skip-link" href="#main"><?= htmlspecialchars($t('nav.skip'), ENT_QUOTES) ?></a>
|
|
|
|
<nav id="navbar" class="scrolled" aria-label="<?= htmlspecialchars($t('nav.main'), ENT_QUOTES) ?>">
|
|
<div class="nav-logo">
|
|
<a href="<?= htmlspecialchars($homeUrl) ?>">
|
|
<span class="logo-icon" aria-hidden="true">🏠</span>
|
|
<span class="logo-text"><?= htmlspecialchars($siteName) ?></span>
|
|
</a>
|
|
</div>
|
|
|
|
<ul class="nav-links" role="list">
|
|
<?php foreach ($navItems as $item): ?>
|
|
<li>
|
|
<a href="<?= htmlspecialchars($item['href']) ?>"><?= htmlspecialchars($t($item['label']), ENT_QUOTES) ?></a>
|
|
</li>
|
|
<?php endforeach; ?>
|
|
</ul>
|
|
|
|
<?= $locale_switcher($currentPath) ?>
|
|
|
|
<a class="nav-cta" href="/#kontakt"><?= htmlspecialchars($t('nav.cta'), ENT_QUOTES) ?></a>
|
|
|
|
<button class="nav-hamburger" type="button" aria-expanded="false" aria-controls="navMobile" aria-label="<?= htmlspecialchars($t('nav.toggle'), ENT_QUOTES) ?>">
|
|
<span></span>
|
|
</button>
|
|
|
|
<div id="navMobile" class="nav-mobile-overlay" hidden></div>
|
|
</nav>
|
|
|
|
<main id="main" tabindex="-1">
|
|
<?= $content ?>
|
|
</main>
|
|
|
|
<footer>
|
|
<div class="footer-logo">
|
|
<span class="logo-icon" aria-hidden="true">🏠</span>
|
|
<span><?= htmlspecialchars($t('footer.address'), ENT_QUOTES) ?></span>
|
|
</div>
|
|
<div class="footer-links">
|
|
<a href="/impressum"<?= $isImpr ? ' aria-current="page"' : '' ?>><?= htmlspecialchars($t('footer.imprint'), ENT_QUOTES) ?></a>
|
|
<a href="/datenschutz"<?= $isPriv ? ' aria-current="page"' : '' ?>><?= htmlspecialchars($t('footer.privacy'), ENT_QUOTES) ?></a>
|
|
</div>
|
|
<div class="footer-bottom">© <?= date('Y') ?> <?= htmlspecialchars($siteName) ?></div>
|
|
</footer>
|
|
|
|
<div id="lightbox" class="lightbox" role="dialog" aria-modal="true" aria-label="<?= htmlspecialchars($t('lightbox.aria'), ENT_QUOTES) ?>">
|
|
<button id="lightboxClose" class="lightbox-close" type="button" aria-label="<?= htmlspecialchars($t('lightbox.close'), ENT_QUOTES) ?>">×</button>
|
|
<div class="lightbox-content">
|
|
<img id="lightboxImg" class="lightbox-img" alt="" />
|
|
<div id="lightboxCaption" class="lightbox-caption"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="/js/haus-schleusingen.js"></script>
|
|
</body>
|
|
</html>
|