feat: add page titles to recipe and glaube routes
All checks were successful
CI / update (push) Successful in 1m20s

- Add titles to category, tag, icon, season routes
- Add bilingual support (German/English) for recipe route titles
- Use consistent "Bocken Recipes" / "Bocken Rezepte" branding
- Change English tagline from "Bocken's Recipes" to "Bocken Recipes"
- Add titles to /glaube and /glaube/gebete pages
- Make tips-and-tricks page language-aware
This commit is contained in:
2026-01-20 19:54:09 +01:00
parent e366b44bba
commit ab2a6c9158
12 changed files with 81 additions and 6 deletions

View File

@@ -98,7 +98,7 @@
season: isEnglish ? 'Season:' : 'Saison:', season: isEnglish ? 'Season:' : 'Saison:',
keywords: isEnglish ? 'Keywords:' : 'Stichwörter:', keywords: isEnglish ? 'Keywords:' : 'Stichwörter:',
lastModified: isEnglish ? 'Last modified:' : 'Letzte Änderung:', lastModified: isEnglish ? 'Last modified:' : 'Letzte Änderung:',
title: isEnglish ? "Bocken's Recipes" : "Bocken'sche Rezepte" title: isEnglish ? "Bocken Recipes" : "Bocken'sche Rezepte"
}); });
</script> </script>
<style> <style>

View File

@@ -7,9 +7,14 @@
const isEnglish = $derived(data.lang === 'en'); const isEnglish = $derived(data.lang === 'en');
const labels = $derived({ const labels = $derived({
title: isEnglish ? 'Categories' : 'Kategorien' title: isEnglish ? 'Categories' : 'Kategorien',
siteTitle: isEnglish ? 'Bocken Recipes' : 'Bocken Rezepte'
}); });
</script> </script>
<svelte:head>
<title>{labels.title} - {labels.siteTitle}</title>
</svelte:head>
<style> <style>
h1 { h1 {
text-align: center; text-align: center;

View File

@@ -9,6 +9,7 @@
const isEnglish = $derived(data.lang === 'en'); const isEnglish = $derived(data.lang === 'en');
const label = $derived(isEnglish ? 'Recipes in Category' : 'Rezepte in Kategorie'); const label = $derived(isEnglish ? 'Recipes in Category' : 'Rezepte in Kategorie');
const siteTitle = $derived(isEnglish ? 'Bocken Recipes' : 'Bocken Rezepte');
// Search state // Search state
let matchedRecipeIds = $state(new Set()); let matchedRecipeIds = $state(new Set());
@@ -34,6 +35,11 @@
font-size: 3em; font-size: 3em;
} }
</style> </style>
<svelte:head>
<title>{data.category} - {siteTitle}</title>
</svelte:head>
<h1>{label} <q>{data.category}</q>:</h1> <h1>{label} <q>{data.category}</q>:</h1>
<Search category={data.category} lang={data.lang} recipes={data.recipes} isLoggedIn={!!data.session?.user} onSearchResults={handleSearchResults}></Search> <Search category={data.category} lang={data.lang} recipes={data.recipes} isLoggedIn={!!data.session?.user} onSearchResults={handleSearchResults}></Search>
<section> <section>

View File

@@ -7,7 +7,17 @@
import Card from '$lib/components/Card.svelte'; import Card from '$lib/components/Card.svelte';
import Search from '$lib/components/Search.svelte'; import Search from '$lib/components/Search.svelte';
let { data } = $props<{ data: PageData }>(); let { data } = $props<{ data: PageData }>();
const isEnglish = $derived(data.lang === 'en');
const labels = $derived({
title: isEnglish ? 'Icons' : 'Icons',
siteTitle: isEnglish ? 'Bocken Recipes' : 'Bocken Rezepte'
});
</script> </script>
<svelte:head>
<title>{labels.title} - {labels.siteTitle}</title>
</svelte:head>
<style> <style>
a{ a{
font-family: "Noto Color Emoji", emoji, sans-serif; font-family: "Noto Color Emoji", emoji, sans-serif;

View File

@@ -8,6 +8,9 @@
let { data } = $props<{ data: PageData }>(); let { data } = $props<{ data: PageData }>();
import { rand_array } from '$lib/js/randomize'; import { rand_array } from '$lib/js/randomize';
const isEnglish = $derived(data.lang === 'en');
const siteTitle = $derived(isEnglish ? 'Bocken Recipes' : 'Bocken Rezepte');
// Search state // Search state
let matchedRecipeIds = $state(new Set()); let matchedRecipeIds = $state(new Set());
let hasActiveSearch = $state(false); let hasActiveSearch = $state(false);
@@ -26,6 +29,11 @@
return data.season.filter(r => matchedRecipeIds.has(r._id)); return data.season.filter(r => matchedRecipeIds.has(r._id));
}); });
</script> </script>
<svelte:head>
<title>{data.icon} - {siteTitle}</title>
</svelte:head>
<IconLayout icons={data.icons} active_icon={data.icon} routePrefix="/{data.recipeLang}" lang={data.lang} recipes={data.season} isLoggedIn={!!data.session?.user} onSearchResults={handleSearchResults}> <IconLayout icons={data.icons} active_icon={data.icon} routePrefix="/{data.recipeLang}" lang={data.lang} recipes={data.season} isLoggedIn={!!data.session?.user} onSearchResults={handleSearchResults}>
{#snippet recipesSlot()} {#snippet recipesSlot()}
<Recipes> <Recipes>

View File

@@ -14,6 +14,10 @@
const months = $derived(isEnglish const months = $derived(isEnglish
? ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"] ? ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"]); : ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"]);
const labels = $derived({
title: isEnglish ? 'In Season' : 'Saisonal',
siteTitle: isEnglish ? 'Bocken Recipes' : 'Bocken Rezepte'
});
// Search state // Search state
let matchedRecipeIds = $state(new Set()); let matchedRecipeIds = $state(new Set());
@@ -34,6 +38,10 @@
}); });
</script> </script>
<svelte:head>
<title>{labels.title} - {labels.siteTitle}</title>
</svelte:head>
<SeasonLayout active_index={current_month-1} {months} routePrefix="/{data.recipeLang}" lang={data.lang} recipes={data.season} isLoggedIn={!!data.session?.user} onSearchResults={handleSearchResults}> <SeasonLayout active_index={current_month-1} {months} routePrefix="/{data.recipeLang}" lang={data.lang} recipes={data.season} isLoggedIn={!!data.session?.user} onSearchResults={handleSearchResults}>
{#snippet recipesSlot()} {#snippet recipesSlot()}
<Recipes> <Recipes>

View File

@@ -11,6 +11,8 @@
const months = $derived(isEnglish const months = $derived(isEnglish
? ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"] ? ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"]); : ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"]);
const siteTitle = $derived(isEnglish ? 'Bocken Recipes' : 'Bocken Rezepte');
const currentMonth = $derived(months[data.month - 1]);
import { rand_array } from '$lib/js/randomize'; import { rand_array } from '$lib/js/randomize';
@@ -32,6 +34,11 @@
return data.season.filter(r => matchedRecipeIds.has(r._id)); return data.season.filter(r => matchedRecipeIds.has(r._id));
}); });
</script> </script>
<svelte:head>
<title>{currentMonth} - {siteTitle}</title>
</svelte:head>
<SeasonLayout active_index={data.month -1} {months} routePrefix="/{data.recipeLang}" lang={data.lang} recipes={data.season} onSearchResults={handleSearchResults}> <SeasonLayout active_index={data.month -1} {months} routePrefix="/{data.recipeLang}" lang={data.lang} recipes={data.season} onSearchResults={handleSearchResults}>
{#snippet recipesSlot()} {#snippet recipesSlot()}
<Recipes> <Recipes>

View File

@@ -7,9 +7,14 @@
const isEnglish = $derived(data.lang === 'en'); const isEnglish = $derived(data.lang === 'en');
const labels = $derived({ const labels = $derived({
title: isEnglish ? 'Keywords' : 'Stichwörter' title: isEnglish ? 'Keywords' : 'Stichwörter',
siteTitle: isEnglish ? 'Bocken Recipes' : 'Bocken Rezepte'
}); });
</script> </script>
<svelte:head>
<title>{labels.title} - {labels.siteTitle}</title>
</svelte:head>
<style> <style>
h1 { h1 {
font-size: 3rem; font-size: 3rem;

View File

@@ -9,6 +9,7 @@
const isEnglish = $derived(data.lang === 'en'); const isEnglish = $derived(data.lang === 'en');
const label = $derived(isEnglish ? 'Recipes with Keyword' : 'Rezepte mit Stichwort'); const label = $derived(isEnglish ? 'Recipes with Keyword' : 'Rezepte mit Stichwort');
const siteTitle = $derived(isEnglish ? 'Bocken Recipes' : 'Bocken Rezepte');
// Search state // Search state
let matchedRecipeIds = $state(new Set()); let matchedRecipeIds = $state(new Set());
@@ -34,6 +35,11 @@
font-size: 2em; font-size: 2em;
} }
</style> </style>
<svelte:head>
<title>{data.tag} - {siteTitle}</title>
</svelte:head>
<h1>{label} <q>{data.tag}</q>:</h1> <h1>{label} <q>{data.tag}</q>:</h1>
<Search tag={data.tag} lang={data.lang} recipes={data.recipes} isLoggedIn={!!data.session?.user} onSearchResults={handleSearchResults}></Search> <Search tag={data.tag} lang={data.lang} recipes={data.recipes} isLoggedIn={!!data.session?.user} onSearchResults={handleSearchResults}></Search>
<section> <section>

View File

@@ -2,6 +2,16 @@
import type { PageData } from './$types'; import type { PageData } from './$types';
import AddButton from '$lib/components/AddButton.svelte'; import AddButton from '$lib/components/AddButton.svelte';
import Converter from './Converter.svelte'; import Converter from './Converter.svelte';
let { data } = $props<{ data: PageData }>();
const isEnglish = $derived(data.lang === 'en');
const labels = $derived({
title: isEnglish ? 'Tips & Tricks' : 'Tipps & Tricks',
siteTitle: isEnglish ? 'Bocken Recipes' : 'Bocken Rezepte',
description: isEnglish
? "A constantly growing collection of recipes from Bocken's kitchen."
: 'Eine stetig wachsende Ansammlung an Rezepten aus der Bockenschen Küche.'
});
</script> </script>
<style> <style>
h1{ h1{
@@ -18,15 +28,15 @@ h1{
} }
</style> </style>
<svelte:head> <svelte:head>
<title>Bocken Rezepte</title> <title>{labels.title} - {labels.siteTitle}</title>
<meta name="description" content="Eine stetig wachsende Ansammlung an Rezepten aus der Bockenschen Küche." /> <meta name="description" content="{labels.description}" />
<meta property="og:image" content="https://bocken.org/static/rezepte/thumb/ragu_aus_rindsrippen.webp" /> <meta property="og:image" content="https://bocken.org/static/rezepte/thumb/ragu_aus_rindsrippen.webp" />
<meta property="og:image:secure_url" content="https://bocken.org/static/rezepte/thumb/ragu_aus_rindsrippen.webp" /> <meta property="og:image:secure_url" content="https://bocken.org/static/rezepte/thumb/ragu_aus_rindsrippen.webp" />
<meta property="og:image:type" content="image/webp" /> <meta property="og:image:type" content="image/webp" />
<meta property="og:image:alt" content="Pasta al Ragu mit Linguine" /> <meta property="og:image:alt" content="Pasta al Ragu mit Linguine" />
</svelte:head> </svelte:head>
<h1>Tipps & Tricks</h1> <h1>{labels.title}</h1>
<div class=content> <div class=content>
<h2>Trockenhefe vs. Frischhefe</h2> <h2>Trockenhefe vs. Frischhefe</h2>

View File

@@ -1,6 +1,11 @@
<script> <script>
import LinksGrid from '$lib/components/LinksGrid.svelte'; import LinksGrid from '$lib/components/LinksGrid.svelte';
</script> </script>
<svelte:head>
<title>Glaube - Bocken</title>
<meta name="description" content="Gebete und ein interaktiver Rosenkranz zum katholischen Glauben." />
</svelte:head>
<style> <style>
h1{ h1{
text-align: center; text-align: center;

View File

@@ -19,6 +19,11 @@
// Create language context for prayer components // Create language context for prayer components
createLanguageContext(); createLanguageContext();
</script> </script>
<svelte:head>
<title>Gebete - Bocken</title>
<meta name="description" content="Katholische Gebete auf Deutsch und Latein." />
</svelte:head>
<style> <style>
.ccontainer{ .ccontainer{
margin: auto; margin: auto;