make search component bilingual
All checks were successful
CI / update (push) Successful in 12s

This commit is contained in:
2025-12-26 21:47:34 +01:00
parent 715f86d26d
commit 3215c87fad
11 changed files with 29 additions and 23 deletions

View File

@@ -5,6 +5,7 @@
export let icons export let icons
export let active_icon export let active_icon
export let routePrefix = '/rezepte' export let routePrefix = '/rezepte'
export let lang = 'de'
</script> </script>
<style> <style>
@@ -73,7 +74,7 @@
{/each} {/each}
</div> </div>
<section> <section>
<Search icon={active_icon}></Search> <Search icon={active_icon} {lang}></Search>
</section> </section>
<section> <section>
<slot name=recipes></slot> <slot name=recipes></slot>

View File

@@ -2,16 +2,19 @@
import {onMount} from "svelte"; import {onMount} from "svelte";
import { browser } from '$app/environment'; import { browser } from '$app/environment';
import "$lib/css/nordtheme.css"; import "$lib/css/nordtheme.css";
// Filter props for different contexts // Filter props for different contexts
export let category = null; let { category = null, tag = null, icon = null, season = null, favoritesOnly = false, lang = 'de' } = $props();
export let tag = null;
export let icon = null; const isEnglish = $derived(lang === 'en');
export let season = null; const searchResultsUrl = $derived(isEnglish ? '/recipes/search' : '/rezepte/search');
export let favoritesOnly = false; const labels = $derived({
export let searchResultsUrl = '/rezepte/search'; placeholder: isEnglish ? 'Search...' : 'Suche...',
searchTitle: isEnglish ? 'Search' : 'Suchen',
let searchQuery = ''; clearTitle: isEnglish ? 'Clear search' : 'Sucheintrag löschen'
});
let searchQuery = $state('');
// Build search URL with current filters // Build search URL with current filters
function buildSearchUrl(query) { function buildSearchUrl(query) {
@@ -190,15 +193,15 @@ scale: 0.8 0.8;
{#if season}<input type="hidden" name="season" value={season} />{/if} {#if season}<input type="hidden" name="season" value={season} />{/if}
{#if favoritesOnly}<input type="hidden" name="favorites" value="true" />{/if} {#if favoritesOnly}<input type="hidden" name="favorites" value="true" />{/if}
<input type="text" id="search" name="q" placeholder="Suche..." bind:value={searchQuery}> <input type="text" id="search" name="q" placeholder={labels.placeholder} bind:value={searchQuery}>
<!-- Submit button (visible by default, hidden when JS loads) --> <!-- Submit button (visible by default, hidden when JS loads) -->
<button type="submit" id="submit-search" class="search-button" style="display: flex;"> <button type="submit" id="submit-search" class="search-button" style="display: flex;">
<svg xmlns="http://www.w3.org/2000/svg" class="ionicon" viewBox="0 0 512 512" style="width: 100%; height: 100%;"><title>Suchen</title><path d="M221.09 64a157.09 157.09 0 10157.09 157.09A157.1 157.1 0 00221.09 64z" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"></path><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="32" d="m338.29 338.29 105.25 105.25"></path></svg> <svg xmlns="http://www.w3.org/2000/svg" class="ionicon" viewBox="0 0 512 512" style="width: 100%; height: 100%;"><title>{labels.searchTitle}</title><path d="M221.09 64a157.09 157.09 0 10157.09 157.09A157.1 157.1 0 00221.09 64z" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"></path><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="32" d="m338.29 338.29 105.25 105.25"></path></svg>
</button> </button>
<!-- Clear button (hidden by default, shown when JS loads) --> <!-- Clear button (hidden by default, shown when JS loads) -->
<button type="button" id="clear-search" class="search-button js-only" style="display: none;" on:click={clearSearch}> <button type="button" id="clear-search" class="search-button js-only" style="display: none;" on:click={clearSearch}>
<svg xmlns="http://www.w3.org/2000/svg" class="ionicon" viewBox="0 0 512 512"><title>Sucheintrag löschen</title><path d="M135.19 390.14a28.79 28.79 0 0021.68 9.86h246.26A29 29 0 00432 371.13V140.87A29 29 0 00403.13 112H156.87a28.84 28.84 0 00-21.67 9.84v0L46.33 256l88.86 134.11z" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="32"></path><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M336.67 192.33L206.66 322.34M336.67 322.34L206.66 192.33M336.67 192.33L206.66 322.34M336.67 322.34L206.66 192.33"></path></svg> <svg xmlns="http://www.w3.org/2000/svg" class="ionicon" viewBox="0 0 512 512"><title>{labels.clearTitle}</title><path d="M135.19 390.14a28.79 28.79 0 0021.68 9.86h246.26A29 29 0 00432 371.13V140.87A29 29 0 00403.13 112H156.87a28.84 28.84 0 00-21.67 9.84v0L46.33 256l88.86 134.11z" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="32"></path><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M336.67 192.33L206.66 322.34M336.67 322.34L206.66 192.33M336.67 192.33L206.66 322.34M336.67 322.34L206.66 192.33"></path></svg>
</button> </button>
</form> </form>

View File

@@ -6,6 +6,7 @@
let month : number; let month : number;
export let active_index; export let active_index;
export let routePrefix = '/rezepte'; export let routePrefix = '/rezepte';
export let lang = 'de';
</script> </script>
<style> <style>
@@ -42,7 +43,7 @@ a.month:hover,
{/each} {/each}
</div> </div>
<section> <section>
<Search season={active_index + 1}></Search> <Search season={active_index + 1} {lang}></Search>
</section> </section>
<section> <section>
<slot name=recipes></slot> <slot name=recipes></slot>

View File

@@ -49,7 +49,7 @@ h1{
<h1>{labels.title}</h1> <h1>{labels.title}</h1>
<p class=subheading>{labels.subheading}</p> <p class=subheading>{labels.subheading}</p>
<Search></Search> <Search lang={data.lang}></Search>
<MediaScroller title={labels.inSeason}> <MediaScroller title={labels.inSeason}>
{#each data.season as recipe} {#each data.season as recipe}

View File

@@ -17,7 +17,7 @@
} }
</style> </style>
<h1>{label} <q>{data.category}</q>:</h1> <h1>{label} <q>{data.category}</q>:</h1>
<Search category={data.category}></Search> <Search category={data.category} lang={data.lang}></Search>
<section> <section>
<Recipes> <Recipes>
{#each rand_array(data.recipes) as recipe} {#each rand_array(data.recipes) as recipe}

View File

@@ -61,7 +61,7 @@ h1{
{/if} {/if}
</p> </p>
<Search favoritesOnly={true}></Search> <Search favoritesOnly={true} lang={data.lang}></Search>
{#if data.error} {#if data.error}
<p class="empty-state">{labels.errorLoading} {data.error}</p> <p class="empty-state">{labels.errorLoading} {data.error}</p>

View File

@@ -8,7 +8,7 @@
let { data }: { data: PageData } = $props(); let { data }: { data: PageData } = $props();
import { rand_array } from '$lib/js/randomize'; import { rand_array } from '$lib/js/randomize';
</script> </script>
<IconLayout icons={data.icons} active_icon={data.icon} routePrefix="/{data.recipeLang}"> <IconLayout icons={data.icons} active_icon={data.icon} routePrefix="/{data.recipeLang}" lang={data.lang}>
<Recipes slot=recipes> <Recipes slot=recipes>
{#each rand_array(data.season) as recipe} {#each rand_array(data.season) as recipe}
<Card {recipe} icon_override=true isFavorite={recipe.isFavorite} showFavoriteIndicator={!!data.session?.user} routePrefix="/{data.recipeLang}"></Card> <Card {recipe} icon_override=true isFavorite={recipe.isFavorite} showFavoriteIndicator={!!data.session?.user} routePrefix="/{data.recipeLang}"></Card>

View File

@@ -70,6 +70,7 @@
icon={data.filters.icon} icon={data.filters.icon}
season={data.filters.season} season={data.filters.season}
favoritesOnly={data.filters.favoritesOnly} favoritesOnly={data.filters.favoritesOnly}
lang={data.lang}
/> />
{#if data.error} {#if data.error}

View File

@@ -16,7 +16,7 @@
: ["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"]);
</script> </script>
<SeasonLayout active_index={current_month-1} {months} routePrefix="/{data.recipeLang}"> <SeasonLayout active_index={current_month-1} {months} routePrefix="/{data.recipeLang}" lang={data.lang}>
<Recipes slot=recipes> <Recipes slot=recipes>
{#each rand_array(data.season) as recipe} {#each rand_array(data.season) as recipe}
<Card {recipe} {current_month} isFavorite={recipe.isFavorite} showFavoriteIndicator={!!data.session?.user} routePrefix="/{data.recipeLang}"></Card> <Card {recipe} {current_month} isFavorite={recipe.isFavorite} showFavoriteIndicator={!!data.session?.user} routePrefix="/{data.recipeLang}"></Card>

View File

@@ -14,7 +14,7 @@
import { rand_array } from '$lib/js/randomize'; import { rand_array } from '$lib/js/randomize';
</script> </script>
<SeasonLayout active_index={data.month -1} {months} routePrefix="/{data.recipeLang}"> <SeasonLayout active_index={data.month -1} {months} routePrefix="/{data.recipeLang}" lang={data.lang}>
<Recipes slot=recipes> <Recipes slot=recipes>
{#each rand_array(data.season) as recipe} {#each rand_array(data.season) as recipe}
<Card {recipe} icon_override=true isFavorite={recipe.isFavorite} showFavoriteIndicator={!!data.session?.user} routePrefix="/{data.recipeLang}"></Card> <Card {recipe} icon_override=true isFavorite={recipe.isFavorite} showFavoriteIndicator={!!data.session?.user} routePrefix="/{data.recipeLang}"></Card>

View File

@@ -17,7 +17,7 @@
} }
</style> </style>
<h1>{label} <q>{data.tag}</q>:</h1> <h1>{label} <q>{data.tag}</q>:</h1>
<Search tag={data.tag}></Search> <Search tag={data.tag} lang={data.lang}></Search>
<section> <section>
<Recipes> <Recipes>
{#each rand_array(data.recipes) as recipe} {#each rand_array(data.recipes) as recipe}