i18n(faith): migrate streak components, BibleModal, katechese notices
Adds streak/angelus and Bible-modal keys to the faith dictionary, plus the three-fragment "this catechesis is only available in German" notice used by both katechese pages. Pluralization for day/days handled by two explicit keys (day_singular/day_plural) chosen at the call site — Latin's "Dies" is invariant so both keys hold the same string. StreakCounter and AngelusStreakCounter collapse their per-component labels objects into direct t.foo lookups; the rosary page's BibleModal call site now passes the typed `lang` derived value (was data.lang as plain string, didn't satisfy the tightened FaithLang prop type). BibleModal isn't actually used in Latin context, but the dict requires every key in every locale, so reasonable Latin equivalents got filled in for completeness.
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "homepage",
|
||||
"version": "1.55.0",
|
||||
"version": "1.55.1",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -5,6 +5,7 @@ import StreakAura from '$lib/components/faith/StreakAura.svelte';
|
||||
import Coffee from '@lucide/svelte/icons/coffee';
|
||||
import Sun from '@lucide/svelte/icons/sun';
|
||||
import Moon from '@lucide/svelte/icons/moon';
|
||||
import { m, type FaithLang } from '$lib/js/faithI18n';
|
||||
import { tick, onMount } from 'svelte';
|
||||
|
||||
let burst = $state(false);
|
||||
@@ -13,14 +14,13 @@ let selectedSlot = $state<TimeSlot>('morning');
|
||||
|
||||
interface Props {
|
||||
streakData?: { streak: number; lastComplete: string | null; todayPrayed: number; todayDate: string | null } | null;
|
||||
lang?: 'de' | 'en' | 'la';
|
||||
lang?: FaithLang;
|
||||
isLoggedIn?: boolean;
|
||||
}
|
||||
|
||||
let { streakData = null, lang = 'de', isLoggedIn = false }: Props = $props();
|
||||
|
||||
const isEnglish = $derived(lang === 'en');
|
||||
const isLatin = $derived(lang === 'la');
|
||||
const t = $derived(m[lang]);
|
||||
|
||||
// Display values: store when available, SSR fallback
|
||||
const displayStreak = $derived(store?.streak ?? streakData?.streak ?? 0);
|
||||
@@ -52,20 +52,12 @@ const slots: { key: TimeSlot; icon: typeof Coffee; color: string }[] = [
|
||||
{ key: 'evening', icon: Moon, color: 'var(--nord15)' }
|
||||
];
|
||||
|
||||
const labels = $derived({
|
||||
days: isLatin ? 'Dies' : isEnglish ? (displayStreak === 1 && !showFraction ? 'Day' : 'Days') : (displayStreak === 1 && !showFraction ? 'Tag' : 'Tage'),
|
||||
pray: isLatin ? 'Oravi' : isEnglish ? 'Prayed' : 'Gebetet',
|
||||
done: isLatin ? 'Hodie completa' : isEnglish ? 'Done today' : 'Heute fertig',
|
||||
morning: isLatin ? 'Mane' : isEnglish ? 'Morning' : 'Morgens',
|
||||
noon: isLatin ? 'Meridie' : isEnglish ? 'Noon' : 'Mittags',
|
||||
evening: isLatin ? 'Vespere' : isEnglish ? 'Evening' : 'Abends',
|
||||
ariaLabel: isLatin ? 'Orationem notatam fac' : isEnglish ? 'Mark prayer as prayed' : 'Gebet als gebetet markieren'
|
||||
});
|
||||
const dayLabel = $derived(displayStreak === 1 && !showFraction ? t.day_singular : t.day_plural);
|
||||
|
||||
const slotLabels: Record<TimeSlot, string> = $derived({
|
||||
morning: labels.morning,
|
||||
noon: labels.noon,
|
||||
evening: labels.evening
|
||||
morning: t.morning,
|
||||
noon: t.noon,
|
||||
evening: t.evening
|
||||
});
|
||||
|
||||
function isSlotPrayed(slot: TimeSlot): boolean {
|
||||
@@ -105,7 +97,7 @@ async function pray() {
|
||||
{displayStreak}{#if showFraction}<span class="fraction"><span class="num">{partialCount}</span><span class="slash">/</span><span class="den">3</span></span>{/if}
|
||||
</span>
|
||||
</StreakAura>
|
||||
<span class="streak-label">{labels.days}</span>
|
||||
<span class="streak-label">{dayLabel}</span>
|
||||
</div>
|
||||
|
||||
<div class="prayer-controls">
|
||||
@@ -132,12 +124,12 @@ async function pray() {
|
||||
class="pray-button"
|
||||
type="submit"
|
||||
disabled={todayComplete || selectedSlotPrayed}
|
||||
aria-label={labels.ariaLabel}
|
||||
aria-label={t.mark_prayer}
|
||||
>
|
||||
{#if todayComplete}
|
||||
{labels.done}
|
||||
{t.done_today}
|
||||
{:else}
|
||||
{labels.pray}
|
||||
{t.prayed}
|
||||
{/if}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import type { VerseData } from '$lib/data/mysteryDescriptions';
|
||||
import { m, type FaithLang } from '$lib/js/faithI18n';
|
||||
|
||||
let {
|
||||
reference = '',
|
||||
@@ -11,11 +12,11 @@
|
||||
reference?: string,
|
||||
title?: string,
|
||||
verseData?: VerseData | null,
|
||||
lang?: string,
|
||||
lang?: FaithLang,
|
||||
onClose: () => void
|
||||
} = $props();
|
||||
|
||||
const isEnglish = $derived(lang === 'en');
|
||||
const t = $derived(m[lang]);
|
||||
|
||||
// svelte-ignore state_referenced_locally
|
||||
let book: string = $state(verseData?.book || '');
|
||||
@@ -25,7 +26,7 @@
|
||||
let verses: Array<{ verse: number; text: string }> = $state(verseData?.verses || []);
|
||||
let loading = $state(false);
|
||||
// svelte-ignore state_referenced_locally
|
||||
let error = $state(verseData ? '' : (lang === 'en' ? 'No verse data available' : 'Keine Versdaten verfügbar'));
|
||||
let error = $state(verseData ? '' : m[lang].no_verse_data);
|
||||
|
||||
function handleBackdropClick(event: MouseEvent) {
|
||||
if (event.target === event.currentTarget) {
|
||||
@@ -57,7 +58,7 @@
|
||||
{/if}
|
||||
<p class="modal-reference">{reference}</p>
|
||||
</div>
|
||||
<button class="close-button" onclick={onClose} aria-label={isEnglish ? 'Close' : 'Schliessen'}>
|
||||
<button class="close-button" onclick={onClose} aria-label={t.close}>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<line x1="18" y1="6" x2="6" y2="18"></line>
|
||||
<line x1="6" y1="6" x2="18" y2="18"></line>
|
||||
@@ -67,7 +68,7 @@
|
||||
|
||||
<div class="modal-body">
|
||||
{#if loading}
|
||||
<p class="loading">{isEnglish ? 'Loading...' : 'Lädt...'}</p>
|
||||
<p class="loading">{t.loading}</p>
|
||||
{:else if error}
|
||||
<p class="error">{error}</p>
|
||||
{:else if verses.length > 0}
|
||||
@@ -80,7 +81,7 @@
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
<p class="error">{isEnglish ? 'No verses found' : 'Keine Verse gefunden'}</p>
|
||||
<p class="error">{t.no_verses_found}</p>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { browser } from '$app/environment';
|
||||
import { getRosaryStreak } from '$lib/stores/rosaryStreak.svelte';
|
||||
import StreakAura from '$lib/components/faith/StreakAura.svelte';
|
||||
import { m, type FaithLang } from '$lib/js/faithI18n';
|
||||
import { tick, onMount } from 'svelte';
|
||||
|
||||
let burst = $state(false);
|
||||
@@ -9,26 +10,19 @@ let streak = $state<ReturnType<typeof getRosaryStreak> | null>(null);
|
||||
|
||||
interface Props {
|
||||
streakData?: { length: number; lastPrayed: string | null } | null;
|
||||
lang?: 'de' | 'en' | 'la';
|
||||
lang?: FaithLang;
|
||||
isLoggedIn?: boolean;
|
||||
}
|
||||
|
||||
let { streakData = null, lang = 'de', isLoggedIn = false }: Props = $props();
|
||||
|
||||
const isEnglish = $derived(lang === 'en');
|
||||
const t = $derived(m[lang]);
|
||||
|
||||
// Derive display values: use store when available, fall back to server data for SSR
|
||||
let displayLength = $derived(streak?.length ?? streakData?.length ?? 0);
|
||||
let prayedToday = $derived(streak?.prayedToday ?? (streakData?.lastPrayed === new Date().toISOString().split('T')[0]));
|
||||
|
||||
// Labels need to come after displayLength since they depend on it
|
||||
const isLatin = $derived(lang === 'la');
|
||||
const labels = $derived({
|
||||
days: isLatin ? (displayLength === 1 ? 'Dies' : 'Dies') : isEnglish ? (displayLength === 1 ? 'Day' : 'Days') : (displayLength === 1 ? 'Tag' : 'Tage'),
|
||||
prayed: isLatin ? 'Oravi' : isEnglish ? 'Prayed' : 'Gebetet',
|
||||
prayedToday: isLatin ? 'Hodie oravi' : isEnglish ? 'Prayed today' : 'Heute gebetet',
|
||||
ariaLabel: isLatin ? 'Orationem notatam fac' : isEnglish ? 'Mark prayer as prayed' : 'Gebet als gebetet markieren'
|
||||
});
|
||||
const dayLabel = $derived(displayLength === 1 ? t.day_singular : t.day_plural);
|
||||
|
||||
// Initialize store on mount (client-side only)
|
||||
// Init with server data BEFORE assigning to streak, so displayLength
|
||||
@@ -50,7 +44,7 @@ async function pray() {
|
||||
<div class="streak-container" class:no-js-hidden={!isLoggedIn}>
|
||||
<div class="streak-display">
|
||||
<StreakAura value={displayLength} {burst} />
|
||||
<span class="streak-label">{labels.days}</span>
|
||||
<span class="streak-label">{dayLabel}</span>
|
||||
</div>
|
||||
<form method="POST" action="?/pray" onsubmit={(e) => { e.preventDefault(); pray(); }
|
||||
}>
|
||||
@@ -58,12 +52,12 @@ async function pray() {
|
||||
class="streak-button"
|
||||
type="submit"
|
||||
disabled={prayedToday}
|
||||
aria-label={labels.ariaLabel}
|
||||
aria-label={t.mark_prayer}
|
||||
>
|
||||
{#if prayedToday}
|
||||
{labels.prayedToday}
|
||||
{t.prayed_today}
|
||||
{:else}
|
||||
{labels.prayed}
|
||||
{t.prayed}
|
||||
{/if}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
@@ -19,5 +19,27 @@ export const de = {
|
||||
alex_pick: "Alex' Wahl",
|
||||
arguments_title: 'Apologetik',
|
||||
evidences: 'Belege',
|
||||
positive_case: 'Positives'
|
||||
positive_case: 'Positives',
|
||||
|
||||
// Streak counters (rosary, angelus)
|
||||
day_singular: 'Tag',
|
||||
day_plural: 'Tage',
|
||||
prayed: 'Gebetet',
|
||||
prayed_today: 'Heute gebetet',
|
||||
mark_prayer: 'Gebet als gebetet markieren',
|
||||
done_today: 'Heute fertig',
|
||||
morning: 'Morgens',
|
||||
noon: 'Mittags',
|
||||
evening: 'Abends',
|
||||
|
||||
// Bible modal
|
||||
close: 'Schliessen',
|
||||
loading: 'Lädt…',
|
||||
no_verses_found: 'Keine Verse gefunden',
|
||||
no_verse_data: 'Keine Versdaten verfügbar',
|
||||
|
||||
// Language-availability notice (catechesis is German-only)
|
||||
only_german_pre: 'Diese Katechese ist nur auf ',
|
||||
only_german_link: 'Deutsch',
|
||||
only_german_post: ' verfügbar.'
|
||||
} as const;
|
||||
|
||||
@@ -19,5 +19,27 @@ export const en = {
|
||||
alex_pick: "Alex's pick",
|
||||
arguments_title: 'Arguments',
|
||||
evidences: 'Evidences',
|
||||
positive_case: 'Positive case'
|
||||
positive_case: 'Positive case',
|
||||
|
||||
// Streak counters
|
||||
day_singular: 'Day',
|
||||
day_plural: 'Days',
|
||||
prayed: 'Prayed',
|
||||
prayed_today: 'Prayed today',
|
||||
mark_prayer: 'Mark prayer as prayed',
|
||||
done_today: 'Done today',
|
||||
morning: 'Morning',
|
||||
noon: 'Noon',
|
||||
evening: 'Evening',
|
||||
|
||||
// Bible modal
|
||||
close: 'Close',
|
||||
loading: 'Loading…',
|
||||
no_verses_found: 'No verses found',
|
||||
no_verse_data: 'No verse data available',
|
||||
|
||||
// Language-availability notice (catechesis is German-only)
|
||||
only_german_pre: 'This catechesis is only available in ',
|
||||
only_german_link: 'German',
|
||||
only_german_post: '.'
|
||||
} as const satisfies Record<keyof typeof de, string>;
|
||||
|
||||
@@ -19,5 +19,27 @@ export const la = {
|
||||
alex_pick: 'Alexandri delectus',
|
||||
arguments_title: 'Apologia',
|
||||
evidences: 'Argumenta',
|
||||
positive_case: 'Argumenta pro'
|
||||
positive_case: 'Argumenta pro',
|
||||
|
||||
// Streak counters — Latin "Dies" is invariant
|
||||
day_singular: 'Dies',
|
||||
day_plural: 'Dies',
|
||||
prayed: 'Oravi',
|
||||
prayed_today: 'Hodie oravi',
|
||||
mark_prayer: 'Orationem notatam fac',
|
||||
done_today: 'Hodie completa',
|
||||
morning: 'Mane',
|
||||
noon: 'Meridie',
|
||||
evening: 'Vespere',
|
||||
|
||||
// Bible modal — not used in Latin context but the dict requires every key
|
||||
close: 'Claude',
|
||||
loading: 'Carico…',
|
||||
no_verses_found: 'Versus non inventi',
|
||||
no_verse_data: 'Nulli versus praesto',
|
||||
|
||||
// Language-availability notice (catechesis is German-only)
|
||||
only_german_pre: 'Haec catechesis tantum in ',
|
||||
only_german_link: 'lingua Germanica',
|
||||
only_german_post: ' praesto est.'
|
||||
} as const satisfies Record<keyof typeof de, string>;
|
||||
|
||||
@@ -1156,5 +1156,5 @@ h1 {
|
||||
|
||||
<!-- Bible citation modal -->
|
||||
{#if showModal}
|
||||
<BibleModal reference={selectedReference} title={selectedTitle} verseData={selectedVerseData} lang={data.lang} onClose={() => showModal = false} />
|
||||
<BibleModal reference={selectedReference} title={selectedTitle} verseData={selectedVerseData} {lang} onClose={() => showModal = false} />
|
||||
{/if}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
<script>
|
||||
import { resolve } from '$app/paths';
|
||||
import LinksGrid from '$lib/components/LinksGrid.svelte';
|
||||
import { m } from '$lib/js/faithI18n';
|
||||
/** @typedef {import('$lib/js/faithI18n').FaithLang} FaithLang */
|
||||
let { data } = $props();
|
||||
const isGerman = $derived(data.lang === 'de');
|
||||
const isLatin = $derived(data.lang === 'la');
|
||||
const lang = $derived(/** @type {FaithLang} */ (data.lang));
|
||||
const t = $derived(m[lang]);
|
||||
const isGerman = $derived(lang === 'de');
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
@@ -49,7 +52,7 @@
|
||||
|
||||
<h1>Katechese</h1>
|
||||
{#if !isGerman}
|
||||
<p class="lang-notice">{isLatin ? 'Haec catechesis tantum in ' : 'This catechesis is only available in '}<a href={resolve('/glaube/katechese')}>{isLatin ? 'lingua Germanica' : 'German'}</a>{isLatin ? ' praesto est.' : '.'}</p>
|
||||
<p class="lang-notice">{t.only_german_pre}<a href={resolve('/glaube/katechese')}>{t.only_german_link}</a>{t.only_german_post}</p>
|
||||
{/if}
|
||||
<p>
|
||||
Aufgearbeitete Lehrinhalte aus dem Glaubenskurs von P. Martin Ramm FSSP.
|
||||
|
||||
@@ -5,10 +5,12 @@
|
||||
import ArrowLeft from '@lucide/svelte/icons/arrow-left';
|
||||
import { page } from '$app/state';
|
||||
import ApologetikToc from '$lib/components/faith/ApologetikToc.svelte';
|
||||
import { m, langFromFaithSlug } from '$lib/js/faithI18n';
|
||||
/** @type {number | string | null} */
|
||||
let expanded = $state(null);
|
||||
const isGerman = $derived(page.url.pathname.startsWith('/glaube'));
|
||||
const isLatin = $derived(page.url.pathname.startsWith('/fides'));
|
||||
const lang = $derived(langFromFaithSlug(page.url.pathname.split('/')[1]));
|
||||
const t = $derived(m[lang]);
|
||||
const isGerman = $derived(lang === 'de');
|
||||
|
||||
/** @param {number | string} id */
|
||||
function toggle(id) {
|
||||
@@ -93,7 +95,7 @@
|
||||
</header>
|
||||
|
||||
{#if !isGerman}
|
||||
<p class="lang-notice">{isLatin ? 'Haec catechesis tantum in ' : 'This catechesis is only available in '}<a href={resolve('/glaube/katechese/zehn-gebote')}>{isLatin ? 'lingua Germanica' : 'German'}</a>{isLatin ? ' praesto est.' : '.'}</p>
|
||||
<p class="lang-notice">{t.only_german_pre}<a href={resolve('/glaube/katechese/zehn-gebote')}>{t.only_german_link}</a>{t.only_german_post}</p>
|
||||
{/if}
|
||||
|
||||
<section id="ursprung">
|
||||
|
||||
Reference in New Issue
Block a user