feat(landing): translate landing page copy (Landing i18n namespace)

The landing page was hardcoded English, so switching languages had no
visible effect on it — added a "Landing" namespace to both message
catalogs and wired src/app/page.tsx up via getTranslations, matching
the pattern already used by other server-rendered pages.
This commit is contained in:
admin committed 2026-08-11 20:09:13 +02:00
1 parent 0da56a2aef
commit f899ed5f7c
3 files changed
+52 -29

No files matched your search

+18
View File
@@ -500,5 +500,23 @@
"confirm": "Blockieren",
"successToast": "Du hast {petName} blockiert",
"errorToast": "Tier konnte nicht blockiert werden. Bitte versuch es erneut."
},
"Landing": {
"tagline": "Wo Haustiere die Stars sind. Profile, Beiträge und Storys — gemacht für Hunde, Katzen und Vögel.",
"getStarted": "Jetzt loslegen",
"logIn": "Anmelden",
"previewAlt": "Der PawFeed-Feed mit Tierbeiträgen von Noctis und Bubi",
"featuresHeading": "Gebaut für das Tier, nicht den Menschen",
"feature1Title": "Nicht Menschen, sondern Tiere sind das Profil",
"feature1Body": "Jeder Hund, jede Katze, jeder Vogel bekommt eine eigene Identität — eigene Beiträge, Follower und eine eigene Story, getrennt vom Besitzer.",
"feature2Title": "Beiträge, Storys & Kurzvideos",
"feature2Body": "Fotos, Kurzvideos und 24-Stunden-Storys — alles rund um das, was dein Tier gerade erlebt.",
"feature3Title": "Gesundheits-Tracking",
"feature3Body": "Gewichtsverlauf, Tierarztbesuche und Impfungen an einem Ort — per privatem Link mit dem Tierarzt teilbar.",
"feature4Title": "Nachrichten von Tier zu Tier",
"feature4Body": "Direktnachrichten laufen zwischen den Tieren, nicht den Besitzern — passend zum Aufbau der ganzen Plattform.",
"footerImpressum": "Impressum",
"footerDatenschutz": "Datenschutz",
"footerAgb": "AGB"
}
}
+18
View File
@@ -500,5 +500,23 @@
"confirm": "Block",
"successToast": "You've blocked {petName}",
"errorToast": "Couldn't block this pet. Please try again."
},
"Landing": {
"tagline": "Where pets are the stars. Profiles, posts, and stories — built for dogs, cats, and birds.",
"getStarted": "Get started",
"logIn": "Log in",
"previewAlt": "The PawFeed feed, showing pet posts from Noctis and Bubi",
"featuresHeading": "Built for the pet, not the person",
"feature1Title": "Pets, not humans, are the profile",
"feature1Body": "Every dog, cat, or bird gets its own identity — its own posts, followers, and story, separate from its owner's.",
"feature2Title": "Posts, stories & short video",
"feature2Body": "Photos, short-form video, and 24-hour stories — all built around what your pet is up to.",
"feature3Title": "Health tracking",
"feature3Body": "Weight logs, vet visits, and vaccine records in one place — shareable with a vet via a private link.",
"feature4Title": "Pet-to-pet messaging",
"feature4Body": "Direct messages happen between pets, not owners — matching how the whole platform is built.",
"footerImpressum": "Imprint",
"footerDatenschutz": "Privacy Policy",
"footerAgb": "Terms"
}
}
+16 -29
View File
@@ -1,8 +1,9 @@
import { auth } from "@clerk/nextjs/server";
import { getTranslations } from "next-intl/server";
import { redirect } from "next/navigation";
import Link from "next/link";
import Image from "next/image";
import { PawPrint, Sparkles, HeartPulse, MessageCircle, Images } from "lucide-react";
import { PawPrint, HeartPulse, MessageCircle, Images } from "lucide-react";
import { LanguageSwitcher } from "@/components/i18n/LanguageSwitcher";
/**
@@ -21,27 +22,13 @@ export default async function RootPage() {
const { userId } = await auth();
if (userId) redirect("/feed");
const t = await getTranslations("Landing");
const features = [
{
icon: PawPrint,
title: "Pets, not humans, are the profile",
body: "Every dog, cat, or bird gets its own identity — its own posts, followers, and story, separate from its owner's.",
},
{
icon: Images,
title: "Posts, stories & short video",
body: "Photos, short-form video, and 24-hour stories — all built around what your pet is up to.",
},
{
icon: HeartPulse,
title: "Health tracking",
body: "Weight logs, vet visits, and vaccine records in one place — shareable with a vet via a private link.",
},
{
icon: MessageCircle,
title: "Pet-to-pet messaging",
body: "Direct messages happen between pets, not owners — matching how the whole platform is built.",
},
{ icon: PawPrint, title: t("feature1Title"), body: t("feature1Body") },
{ icon: Images, title: t("feature2Title"), body: t("feature2Body") },
{ icon: HeartPulse, title: t("feature3Title"), body: t("feature3Body") },
{ icon: MessageCircle, title: t("feature4Title"), body: t("feature4Body") },
] as const;
return (
@@ -71,7 +58,7 @@ export default async function RootPage() {
</h1>
<p className="mx-auto mt-5 max-w-lg text-xl font-medium text-orange-50 sm:mx-0 sm:text-2xl">
Where pets are the stars. Profiles, posts, and stories — built for dogs, cats, and birds.
{t("tagline")}
</p>
<div className="mt-10 flex flex-col justify-center gap-3 sm:flex-row sm:justify-start">
@@ -79,13 +66,13 @@ export default async function RootPage() {
href="/sign-up"
className="inline-flex items-center justify-center rounded-xl bg-white px-7 py-3.5 text-base font-semibold text-orange-600 shadow-lg transition-colors hover:bg-orange-50"
>
Get started
{t("getStarted")}
</Link>
<Link
href="/log-in"
className="inline-flex items-center justify-center rounded-xl border-2 border-white/70 px-7 py-3.5 text-base font-semibold text-white transition-colors hover:bg-white/10"
>
Log in
{t("logIn")}
</Link>
</div>
</div>
@@ -104,7 +91,7 @@ export default async function RootPage() {
<div className="relative aspect-[16/10] w-full bg-muted">
<Image
src="/app-preview-feed.jpg"
alt="The PawFeed feed, showing pet posts from Noctis and Bubi"
alt={t("previewAlt")}
fill
sizes="(min-width: 768px) 896px, 100vw"
className="object-cover object-left-top"
@@ -119,7 +106,7 @@ export default async function RootPage() {
<section className="bg-muted/30 px-6 py-20 sm:px-10">
<div className="mx-auto max-w-5xl">
<h2 className="text-center text-3xl font-bold tracking-tight text-foreground sm:text-4xl">
Built for the pet, not the person
{t("featuresHeading")}
</h2>
<div className="mt-14 grid gap-8 sm:grid-cols-2 lg:grid-cols-4">
{features.map(({ icon: Icon, title, body }) => (
@@ -140,9 +127,9 @@ export default async function RootPage() {
<div className="mx-auto flex max-w-5xl flex-col items-center justify-between gap-4 text-sm text-muted-foreground sm:flex-row">
<span>© {new Date().getFullYear()} PawFeed</span>
<nav className="flex gap-5">
<Link href="/impressum" className="hover:text-foreground">Impressum</Link>
<Link href="/datenschutz" className="hover:text-foreground">Datenschutz</Link>
<Link href="/nutzungsbedingungen" className="hover:text-foreground">AGB</Link>
<Link href="/impressum" className="hover:text-foreground">{t("footerImpressum")}</Link>
<Link href="/datenschutz" className="hover:text-foreground">{t("footerDatenschutz")}</Link>
<Link href="/nutzungsbedingungen" className="hover:text-foreground">{t("footerAgb")}</Link>
</nav>
</div>
</footer>