fix(i18n): map gallery + hero + floorplan images to real filenames; force-DE on legal pages
- home: map 9/12 gallery items to real filenames (Wohnzimmer-1 -> wohnzimmer2.png, Badezimmer-1 -> Bad.jpg, etc.); remove 3 items whose source images are missing - home: hero-bg.jpg -> Außenansicht-2.webp (file exists) - home: floorplan image -> /bilder/grundrisse/<name>.png (subdir + correct name) - layout: og:image fallback Aussenansicht-2.webp (ASCII) -> Außenansicht-2.png (UTF-8) - layout: hero-bg.jpg fallback -> Außenansicht-2.png (UTF-8) - Controller::render(): add $forceLocale param for legal pages - ImpressumController / DatenschutzController: force 'de' (TMG §5 / GDPR) so <html lang=de> is emitted regardless of cookie
This commit is contained in:
@@ -25,10 +25,13 @@ abstract class Controller
|
|||||||
* Render a view inside a layout.
|
* Render a view inside a layout.
|
||||||
*
|
*
|
||||||
* @param array<string,mixed> $data
|
* @param array<string,mixed> $data
|
||||||
|
* @param string|null $forceLocale If set, overrides the locale resolved from
|
||||||
|
* cookie/Accept-Language for this render. Used by legal pages (Impressum,
|
||||||
|
* Datenschutz) that must be served in German only by German law.
|
||||||
*/
|
*/
|
||||||
protected function render(string $view, array $data = [], string $layout = 'main'): void
|
protected function render(string $view, array $data = [], string $layout = 'main', ?string $forceLocale = null): void
|
||||||
{
|
{
|
||||||
$locale = LocaleController::current();
|
$locale = $forceLocale ?? LocaleController::current();
|
||||||
$i18n = static fn (string $key, array $params = []): string => I18n::t($key, $params, $locale);
|
$i18n = static fn (string $key, array $params = []): string => I18n::t($key, $params, $locale);
|
||||||
|
|
||||||
$globals = [
|
$globals = [
|
||||||
|
|||||||
@@ -11,17 +11,18 @@ class DatenschutzController extends Controller
|
|||||||
{
|
{
|
||||||
public function index(): void
|
public function index(): void
|
||||||
{
|
{
|
||||||
$locale = LocaleController::current();
|
// Legal pages (Datenschutzerklärung) must be served in German only by GDPR / German law.
|
||||||
|
// Force German locale for render() so <html lang="de"> + German meta are emitted
|
||||||
|
// regardless of cookie/Accept-Language.
|
||||||
$this->render('datenschutz/index', [
|
$this->render('datenschutz/index', [
|
||||||
'pageTitle' => I18n::t('legal.privacy_h1', [], $locale) . ' – ' . I18n::t('site.title', [], $locale),
|
'pageTitle' => I18n::t('legal.privacy_h1', [], 'de') . ' – ' . I18n::t('site.title', [], 'de'),
|
||||||
'pageDescription' => I18n::t('legal.privacy_h1', [], $locale) . ' – ' . I18n::t('site.title', [], $locale),
|
'pageDescription' => I18n::t('legal.privacy_h1', [], 'de') . ' – ' . I18n::t('site.title', [], 'de'),
|
||||||
'robots' => 'noindex',
|
'robots' => 'noindex',
|
||||||
'canonical' => I18n::t('site.canonical_base', [], $locale) . '/datenschutz',
|
'canonical' => I18n::t('site.canonical_base', [], 'de') . '/datenschutz',
|
||||||
'ogLocale' => Locale::toOgLocale($locale),
|
'ogLocale' => Locale::toOgLocale('de'),
|
||||||
'ogUrl' => I18n::t('site.canonical_base', [], $locale) . '/datenschutz',
|
'ogUrl' => I18n::t('site.canonical_base', [], 'de') . '/datenschutz',
|
||||||
'ogTitle' => I18n::t('legal.privacy_h1', [], $locale),
|
'ogTitle' => I18n::t('legal.privacy_h1', [], 'de'),
|
||||||
'ogDescription' => I18n::t('legal.privacy_h1', [], $locale),
|
'ogDescription' => I18n::t('legal.privacy_h1', [], 'de'),
|
||||||
]);
|
], 'main', 'de');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,17 +11,18 @@ class ImpressumController extends Controller
|
|||||||
{
|
{
|
||||||
public function index(): void
|
public function index(): void
|
||||||
{
|
{
|
||||||
$locale = LocaleController::current();
|
// Legal pages (Impressum) must be served in German only by German law (TMG §5).
|
||||||
|
// Force German locale for render() so <html lang="de"> + German meta are emitted
|
||||||
|
// regardless of cookie/Accept-Language.
|
||||||
$this->render('impressum/index', [
|
$this->render('impressum/index', [
|
||||||
'pageTitle' => I18n::t('legal.imprint_h1', [], $locale) . ' – ' . I18n::t('site.title', [], $locale),
|
'pageTitle' => I18n::t('legal.imprint_h1', [], 'de') . ' – ' . I18n::t('site.title', [], 'de'),
|
||||||
'pageDescription' => I18n::t('legal.imprint_h1', [], $locale) . ' – ' . I18n::t('site.title', [], $locale),
|
'pageDescription' => I18n::t('legal.imprint_h1', [], 'de') . ' – ' . I18n::t('site.title', [], 'de'),
|
||||||
'robots' => 'noindex',
|
'robots' => 'noindex',
|
||||||
'canonical' => I18n::t('site.canonical_base', [], $locale) . '/impressum',
|
'canonical' => I18n::t('site.canonical_base', [], 'de') . '/impressum',
|
||||||
'ogLocale' => Locale::toOgLocale($locale),
|
'ogLocale' => Locale::toOgLocale('de'),
|
||||||
'ogUrl' => I18n::t('site.canonical_base', [], $locale) . '/impressum',
|
'ogUrl' => I18n::t('site.canonical_base', [], 'de') . '/impressum',
|
||||||
'ogTitle' => I18n::t('legal.imprint_h1', [], $locale),
|
'ogTitle' => I18n::t('legal.imprint_h1', [], 'de'),
|
||||||
'ogDescription' => I18n::t('legal.imprint_h1', [], $locale),
|
'ogDescription' => I18n::t('legal.imprint_h1', [], 'de'),
|
||||||
]);
|
], 'main', 'de');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,22 +15,22 @@ declare(strict_types=1);
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
$gridItems = [
|
$gridItems = [
|
||||||
['img' => 'bilder/Außenansicht-2.png', 'key' => 'gallery.exterior', 'alt' => 'gallery.alt.exterior', 'class' => 'span-2 row-2'],
|
// NOTE: image filenames reflect the actual files in public/bilder/ on the server.
|
||||||
['img' => 'bilder/Wohnzimmer-1.png', 'key' => 'gallery.living', 'alt' => 'gallery.alt.living', 'class' => 'span-2 row-1'],
|
// 3 items were removed (gästezimmer / wohnbereich / wohnbereich-detail)
|
||||||
['img' => 'bilder/Küche-1.png', 'key' => 'gallery.kitchen', 'alt' => 'gallery.alt.kitchen', 'class' => ''],
|
// because no matching files exist in the image inventory.
|
||||||
['img' => 'bilder/Schlafzimmer-1.png','key' => 'gallery.bedroom', 'alt' => 'gallery.alt.bedroom', 'class' => ''],
|
['img' => 'bilder/Außenansicht-2.png', 'key' => 'gallery.exterior', 'alt' => 'gallery.alt.exterior', 'class' => 'span-2 row-2'],
|
||||||
['img' => 'bilder/Badezimmer-1.png', 'key' => 'gallery.bath', 'alt' => 'gallery.alt.bath', 'class' => ''],
|
['img' => 'bilder/wohnzimmer2.png', 'key' => 'gallery.living', 'alt' => 'gallery.alt.living', 'class' => 'span-2 row-1'],
|
||||||
['img' => 'bilder/Kinderzimmer-1-1.png', 'key' => 'gallery.kid1', 'alt' => 'gallery.alt.kid1', 'class' => ''],
|
['img' => 'bilder/Küche 1.jpg', 'key' => 'gallery.kitchen', 'alt' => 'gallery.alt.kitchen', 'class' => ''],
|
||||||
['img' => 'bilder/Kinderzimmer-2.png','key' => 'gallery.kid2', 'alt' => 'gallery.alt.kid2', 'class' => ''],
|
['img' => 'bilder/schlafzimmer.png', 'key' => 'gallery.bedroom', 'alt' => 'gallery.alt.bedroom', 'class' => ''],
|
||||||
['img' => 'bilder/Kinderzimmer-Detail.png','key' => 'gallery.kid_detail', 'alt' => 'gallery.alt.kid_detail', 'class' => 'span-2 row-1'],
|
['img' => 'bilder/Bad.jpg', 'key' => 'gallery.bath', 'alt' => 'gallery.alt.bath', 'class' => ''],
|
||||||
['img' => 'bilder/Gästezimmer.png', 'key' => 'gallery.guest', 'alt' => 'gallery.alt.guest', 'class' => ''],
|
['img' => 'bilder/Kinderzimmer 2.jpg', 'key' => 'gallery.kid1', 'alt' => 'gallery.alt.kid1', 'class' => ''],
|
||||||
['img' => 'bilder/Wohnbereich.png', 'key' => 'gallery.area1', 'alt' => 'gallery.alt.living', 'class' => ''],
|
['img' => 'bilder/Kinderzimmer 3.jpg', 'key' => 'gallery.kid2', 'alt' => 'gallery.alt.kid2', 'class' => ''],
|
||||||
['img' => 'bilder/Wohnbereich-Detail.png', 'key' => 'gallery.area2', 'alt' => 'gallery.alt.living', 'class' => ''],
|
['img' => 'bilder/kinderzimmer 2 2.webp', 'key' => 'gallery.kid_detail', 'alt' => 'gallery.alt.kid_detail', 'class' => 'span-2 row-1'],
|
||||||
['img' => 'bilder/Außenansicht-1.png','key' => 'gallery.area3', 'alt' => 'gallery.alt.exterior', 'class' => 'span-2 row-1'],
|
['img' => 'bilder/Außenansicht-2.png', 'key' => 'gallery.area3', 'alt' => 'gallery.alt.exterior', 'class' => 'span-2 row-1'],
|
||||||
];
|
];
|
||||||
?>
|
?>
|
||||||
<header class="hero" id="hero">
|
<header class="hero" id="hero">
|
||||||
<img src="/bilder/hero-bg.jpg" alt="" class="hero-bg" id="heroBg" loading="eager" decoding="async" fetchpriority="high">
|
<img src="/bilder/Außenansicht-2.webp" alt="" class="hero-bg" id="heroBg" loading="eager" decoding="async" fetchpriority="high">
|
||||||
<div class="hero-content" id="heroContent">
|
<div class="hero-content" id="heroContent">
|
||||||
<span class="hero-tag"><?= htmlspecialchars($t('hero.tag'), ENT_QUOTES) ?></span>
|
<span class="hero-tag"><?= htmlspecialchars($t('hero.tag'), ENT_QUOTES) ?></span>
|
||||||
<h1 class="hero-h1">
|
<h1 class="hero-h1">
|
||||||
@@ -105,6 +105,13 @@ $gridItems = [
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
|
$floorImageMap = [
|
||||||
|
'eg' => 'bilder/grundrisse/EG.png',
|
||||||
|
'og1' => 'bilder/grundrisse/OG 1 2.png',
|
||||||
|
'og2' => 'bilder/grundrisse/OG 2 grundriss.png',
|
||||||
|
'attic' => 'bilder/grundrisse/Dachboden unten.png',
|
||||||
|
];
|
||||||
|
|
||||||
$floors = [
|
$floors = [
|
||||||
['id' => 'eg', 'titleKey' => 'floors.eg.title', 'areaKey' => 'floors.eg.area', 'altKey' => 'floors.alt.eg',
|
['id' => 'eg', 'titleKey' => 'floors.eg.title', 'areaKey' => 'floors.eg.area', 'altKey' => 'floors.alt.eg',
|
||||||
'rooms' => [
|
'rooms' => [
|
||||||
@@ -148,7 +155,7 @@ $gridItems = [
|
|||||||
<span class="floor-area"><?= htmlspecialchars($t($floor['areaKey']), ENT_QUOTES) ?></span>
|
<span class="floor-area"><?= htmlspecialchars($t($floor['areaKey']), ENT_QUOTES) ?></span>
|
||||||
</summary>
|
</summary>
|
||||||
<div class="floor-body">
|
<div class="floor-body">
|
||||||
<img src="/bilder/grundriss-<?= htmlspecialchars($floor['id'], ENT_QUOTES) ?>.png"
|
<img src="/<?= htmlspecialchars($floorImageMap[$floor['id']] ?? 'bilder/grundrisse/EG.png', ENT_QUOTES) ?>"
|
||||||
alt="<?= htmlspecialchars($t($floor['altKey']), ENT_QUOTES) ?>"
|
alt="<?= htmlspecialchars($t($floor['altKey']), ENT_QUOTES) ?>"
|
||||||
loading="lazy" decoding="async"
|
loading="lazy" decoding="async"
|
||||||
class="floor-plan-img">
|
class="floor-plan-img">
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ $canonical = $canonical ?? $canonicalBase . ($currentPath === '/' ? '
|
|||||||
$siteName = I18n::t('site.name', [], $locale);
|
$siteName = I18n::t('site.name', [], $locale);
|
||||||
$ogTitle = $openGraph['ogTitle'] ?? $title;
|
$ogTitle = $openGraph['ogTitle'] ?? $title;
|
||||||
$ogDescription = $openGraph['ogDescription'] ?? $description;
|
$ogDescription = $openGraph['ogDescription'] ?? $description;
|
||||||
$ogImage = $openGraph['ogImage'] ?? 'https://haus-schleusingen.de/bilder/Aussenansicht-2.webp';
|
$ogImage = $openGraph['ogImage'] ?? 'https://haus-schleusingen.de/bilder/Außenansicht-2.png';
|
||||||
$ogUrl = $openGraph['ogUrl'] ?? $canonical;
|
$ogUrl = $openGraph['ogUrl'] ?? $canonical;
|
||||||
$hreflangs = Locale::hreflangAlternates($currentPath === '/' ? '/' : $currentPath, $canonicalBase);
|
$hreflangs = Locale::hreflangAlternates($currentPath === '/' ? '/' : $currentPath, $canonicalBase);
|
||||||
|
|
||||||
@@ -72,7 +72,7 @@ $navItems = [
|
|||||||
<meta property="og:description" content="<?= htmlspecialchars($ogDescription ?? $pageDescription ?? $t('site.description'), 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: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: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) ?>">
|
<meta property="og:image" content="<?= htmlspecialchars($ogImage ?? ($t('site.canonical_base') . '/bilder/Außenansicht-2.png'), ENT_QUOTES) ?>">
|
||||||
|
|
||||||
<?php if (isset($structuredData)): ?>
|
<?php if (isset($structuredData)): ?>
|
||||||
<script type="application/ld+json"><?= $structuredData ?></script>
|
<script type="application/ld+json"><?= $structuredData ?></script>
|
||||||
|
|||||||
Reference in New Issue
Block a user