From 28b96a8dc0c2c00325d6e0bb8c12ab1fab22af73 Mon Sep 17 00:00:00 2001 From: Alexander Bocken Date: Fri, 1 May 2026 13:01:25 +0200 Subject: [PATCH] feat(i18n): bootstrap faith namespace + migrate layout, homepage, apologetik MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three-locale faith dictionary lands at src/lib/i18n/faith/{de,en,la}.ts with the same satisfies-based completeness enforcement we use for fitness, cospend, and calendar. faithI18n.ts is the slim shim — exports m, FaithLang, FaithKey, plus the URL-slug helpers (langFromFaithSlug, faithSlugFromLang, prayersSlug, rosarySlug, calendarSlug, apologetikSlug) needed because faith routes do bidirectional slug ↔ locale mapping that the other namespaces don't. [faithLang]/+layout.svelte and +page.svelte fully migrated. The isEnglish/isLatin derived flag dance collapses into a single typed `lang`; ten inline ternaries per file (display labels and slug selection) become t.key lookups or slug-helper calls. The "DE" badge condition for non-German faith locales tightened from `isEnglish || isLatin` to `lang !== 'de'`. Apologetik latin-fallback hops through the helpers instead of inline matchers. Apologetik pages get the shared-label cut: all four pages (contra, contra detail, pro, pro detail) now use t.objections, t.evidences, t.alex_pick, t.objection_label, t.answered_by, t.voices_answering, t.arguments_title, t.positive_case from the dict. Page-specific marketing copy (the per-page heading/lede/eyebrow object literals) stays inline — those strings live in exactly one place each, the structure is already readable, and pulling them into a shared dict would be noise. Also: ImageUpload.svelte was the one stray cospend t() caller the earlier codemod missed (it lives at lib/components/, outside the codemod's --root scope). Now uses t.key with `as CospendLang` cast. --- package.json | 2 +- src/lib/components/ImageUpload.svelte | 21 +++--- src/lib/i18n/faith/de.ts | 23 ++++++ src/lib/i18n/faith/en.ts | 23 ++++++ src/lib/i18n/faith/la.ts | 23 ++++++ src/lib/js/faithI18n.ts | 72 +++++++++++++++++++ .../[faithLang=faithLang]/+layout.svelte | 37 +++++----- src/routes/[faithLang=faithLang]/+page.svelte | 52 ++++++-------- .../contra/+page.svelte | 24 +++---- .../contra/[argId]/[[archId]]/+page.svelte | 18 ++--- .../pro/+page.svelte | 10 ++- .../pro/[posArgId]/[[voiceId]]/+page.svelte | 14 ++-- 12 files changed, 224 insertions(+), 95 deletions(-) create mode 100644 src/lib/i18n/faith/de.ts create mode 100644 src/lib/i18n/faith/en.ts create mode 100644 src/lib/i18n/faith/la.ts create mode 100644 src/lib/js/faithI18n.ts diff --git a/package.json b/package.json index 9ac55fd6..250f6c77 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "homepage", - "version": "1.54.2", + "version": "1.55.0", "private": true, "type": "module", "scripts": { diff --git a/src/lib/components/ImageUpload.svelte b/src/lib/components/ImageUpload.svelte index 48ada74f..dd54441d 100644 --- a/src/lib/components/ImageUpload.svelte +++ b/src/lib/components/ImageUpload.svelte @@ -1,5 +1,5 @@ - {labels.title} - Bocken - + {t.title} - Bocken + -

{labels.title}

+

{t.title}

- {labels.description} + {t.description}

-

{labels.prayers}

+

{t.prayers}

@@ -116,11 +106,11 @@ C251.417,184.249,273.196,208.938,257.227,213.294z"/> -

{labels.rosary}

+

{t.rosary}

{#if eastertide} - {isLatin ? 'Tempore' : isEnglish ? 'In season' : 'Zur Zeit'} + {t.in_season}

Regína Cæli

@@ -131,16 +121,16 @@ {/if} - {#if isEnglish || isLatin}DE{/if} + {#if lang !== 'de'}DE{/if}

Katechese

-

{labels.apologetics}

+

{t.apologetics}

-

{labels.calendar}

+

{t.calendar}

diff --git a/src/routes/[faithLang=faithLang]/[apologetikSlug=apologetikSlug]/contra/+page.svelte b/src/routes/[faithLang=faithLang]/[apologetikSlug=apologetikSlug]/contra/+page.svelte index 19c0548a..b8978288 100644 --- a/src/routes/[faithLang=faithLang]/[apologetikSlug=apologetikSlug]/contra/+page.svelte +++ b/src/routes/[faithLang=faithLang]/[apologetikSlug=apologetikSlug]/contra/+page.svelte @@ -4,11 +4,15 @@ import CaseTabs from '$lib/components/faith/CaseTabs.svelte'; import ApologetikToc from '$lib/components/faith/ApologetikToc.svelte'; + import { m, type FaithLang } from '$lib/js/faithI18n'; + let { data } = $props(); const faithLang = $derived(data?.faithLang ?? 'faith'); const slug = $derived(faithLang === 'faith' ? 'apologetics' : 'apologetik'); - const isLatin = $derived(data?.lang === 'la'); - const isGerman = $derived(data?.lang === 'de'); + const lang = $derived((data?.lang ?? 'en') as FaithLang); + const t = $derived(m[lang]); + const isLatin = $derived(lang === 'la'); + const isGerman = $derived(lang === 'de'); const ARCHETYPES = $derived(data.archetypes); const ARGUMENTS = $derived(data.args); @@ -79,18 +83,10 @@ ? 'Dreiundzwanzig Einwände, wie sie ein Atheist erheben mag, je in mehreren Stimmen beantwortet.' : 'Twenty-three objections an atheist might raise, each answered in several voices.' ); - const tocLabel = $derived( - isLatin ? 'Obiectiones' : isGerman ? 'Einwände' : 'Objections' - ); - const legendTitle = $derived( - isLatin ? 'Voces respondentes' : isGerman ? 'Die antwortenden Stimmen' : 'The voices that answer' - ); - const objectionLabel = $derived( - isLatin ? 'OBIECTIO' : isGerman ? 'EINWAND' : 'OBJECTION' - ); - const answeredByLabel = $derived( - isLatin ? 'Respondetur a' : isGerman ? 'Beantwortet von' : 'Answered by' - ); + const tocLabel = $derived(t.objections); + const legendTitle = $derived(t.voices_answering); + const objectionLabel = $derived(t.objection_label); + const answeredByLabel = $derived(t.answered_by); const filterLabels = $derived( isLatin ? { filteringBy: 'Filtrum:', showAll: 'omnia ostendere' } diff --git a/src/routes/[faithLang=faithLang]/[apologetikSlug=apologetikSlug]/contra/[argId]/[[archId]]/+page.svelte b/src/routes/[faithLang=faithLang]/[apologetikSlug=apologetikSlug]/contra/[argId]/[[archId]]/+page.svelte index 4d6231c2..f7e523f3 100644 --- a/src/routes/[faithLang=faithLang]/[apologetikSlug=apologetikSlug]/contra/[argId]/[[archId]]/+page.svelte +++ b/src/routes/[faithLang=faithLang]/[apologetikSlug=apologetikSlug]/contra/[argId]/[[archId]]/+page.svelte @@ -2,21 +2,21 @@ import { resolve } from '$app/paths'; import ApologetikToc from '$lib/components/faith/ApologetikToc.svelte'; + import { m, type FaithLang } from '$lib/js/faithI18n'; + let { data } = $props(); const faithLang = $derived(data?.faithLang ?? 'faith'); const slug = $derived(faithLang === 'faith' ? 'apologetics' : 'apologetik'); - const isLatin = $derived(data?.lang === 'la'); - const isGerman = $derived(data?.lang === 'de'); + const lang = $derived((data?.lang ?? 'en') as FaithLang); + const t = $derived(m[lang]); + const isLatin = $derived(lang === 'la'); + const isGerman = $derived(lang === 'de'); const arg = $derived(data.argument); const ARCHETYPES = $derived(data.archetypes); const alexPicks = $derived(data.alexPicks ?? []); - const alexPickLabel = $derived( - isLatin ? 'Alexandri delectus' : isGerman ? "Alex' Wahl" : "Alex's pick" - ); + const alexPickLabel = $derived(t.alex_pick); - const tocLabel = $derived( - isLatin ? 'Obiectiones' : isGerman ? 'Einwände' : 'Objections' - ); + const tocLabel = $derived(t.objections); const tocItems = $derived( data.args.map((a) => ({ id: a.id, @@ -88,7 +88,7 @@ - {arg.title} · {isLatin ? 'Apologia' : isGerman ? 'Apologetik' : 'Arguments'} · bocken.org + {arg.title} · {t.arguments_title} · bocken.org diff --git a/src/routes/[faithLang=faithLang]/[apologetikSlug=apologetikSlug]/pro/+page.svelte b/src/routes/[faithLang=faithLang]/[apologetikSlug=apologetikSlug]/pro/+page.svelte index ab82bb8d..ce266c11 100644 --- a/src/routes/[faithLang=faithLang]/[apologetikSlug=apologetikSlug]/pro/+page.svelte +++ b/src/routes/[faithLang=faithLang]/[apologetikSlug=apologetikSlug]/pro/+page.svelte @@ -5,11 +5,15 @@ import CaseTabs from '$lib/components/faith/CaseTabs.svelte'; import ApologetikToc from '$lib/components/faith/ApologetikToc.svelte'; + import { m, type FaithLang } from '$lib/js/faithI18n'; + let { data } = $props(); const faithLang = $derived(data?.faithLang ?? 'faith'); const slug = $derived(faithLang === 'faith' ? 'apologetics' : 'apologetik'); - const isLatin = $derived(data?.lang === 'la'); - const isGerman = $derived(data?.lang === 'de'); + const lang = $derived((data?.lang ?? 'en') as FaithLang); + const t = $derived(m[lang]); + const isLatin = $derived(lang === 'la'); + const isGerman = $derived(lang === 'de'); const POS_VOICES = $derived(data.voices); const POS_LAYERS = $derived(data.layers); @@ -129,7 +133,7 @@ }) ); const tocLabel = $derived( - isLatin ? 'Argumenta' : isGerman ? 'Belege' : 'Evidences' + t.evidences ); diff --git a/src/routes/[faithLang=faithLang]/[apologetikSlug=apologetikSlug]/pro/[posArgId]/[[voiceId]]/+page.svelte b/src/routes/[faithLang=faithLang]/[apologetikSlug=apologetikSlug]/pro/[posArgId]/[[voiceId]]/+page.svelte index c1c1fc1c..a6a8f6be 100644 --- a/src/routes/[faithLang=faithLang]/[apologetikSlug=apologetikSlug]/pro/[posArgId]/[[voiceId]]/+page.svelte +++ b/src/routes/[faithLang=faithLang]/[apologetikSlug=apologetikSlug]/pro/[posArgId]/[[voiceId]]/+page.svelte @@ -2,11 +2,15 @@ import { resolve } from '$app/paths'; import ApologetikToc from '$lib/components/faith/ApologetikToc.svelte'; + import { m, type FaithLang } from '$lib/js/faithI18n'; + let { data } = $props(); const faithLang = $derived(data?.faithLang ?? 'faith'); const slug = $derived(faithLang === 'faith' ? 'apologetics' : 'apologetik'); - const isLatin = $derived(data?.lang === 'la'); - const isGerman = $derived(data?.lang === 'de'); + const lang = $derived((data?.lang ?? 'en') as FaithLang); + const t = $derived(m[lang]); + const isLatin = $derived(lang === 'la'); + const isGerman = $derived(lang === 'de'); const arg = $derived(data.argument); const POS_VOICES = $derived(data.voices); const POS_LAYERS = $derived(data.layers); @@ -20,9 +24,7 @@ ? { natural: 'Übernatürlich', theism: 'Theismus', christianity: 'Christentum' } : { natural: 'Supernatural', theism: 'Theism', christianity: 'Christianity' } ); - const tocLabel = $derived( - isLatin ? 'Argumenta' : isGerman ? 'Belege' : 'Evidences' - ); + const tocLabel = $derived(t.evidences); const tocItems = $derived( POS_ARGUMENTS.map((a) => ({ id: a.id, @@ -94,7 +96,7 @@ - {arg.title} · {isLatin ? 'Argumenta pro' : isGerman ? 'Positives' : 'Positive case'} · bocken.org + {arg.title} · {t.positive_case} · bocken.org