diff --git a/src/app/onboarding/pet/page.tsx b/src/app/onboarding/pet/page.tsx index eccc6f5..2b53747 100644 --- a/src/app/onboarding/pet/page.tsx +++ b/src/app/onboarding/pet/page.tsx @@ -9,6 +9,7 @@ import { Button } from "@/components/ui/button"; import { useActivePet } from "@/context/ActivePetContext"; import { OnboardingGuidelines } from "@/components/legal/OnboardingGuidelines"; import { UploadConsent } from "@/components/legal/UploadConsent"; +import { LanguageSwitcher } from "@/components/i18n/LanguageSwitcher"; /** * Onboarding pet page — /onboarding/pet @@ -32,55 +33,41 @@ export default function OnboardingPetPage() { const [guidelinesAcknowledged, setGuidelinesAcknowledged] = useState(false); const [uploadConsentGiven, setUploadConsentGiven] = useState(false); + let content: React.ReactNode; + if (!guidelinesAcknowledged) { - return ( - - setGuidelinesAcknowledged(true)} /> - - ); - } - - if (!uploadConsentGiven) { - return ( - - setUploadConsentGiven(true)} /> - - ); - } - - if (createdPetId) { - return ( - - - - {t("addPhoto")} - {t("addPhotoDesc")} - - - {}} /> - - - router.push(`/pets/${createdPetId}`)} - > - {t("done")} - - router.push(`/pets/${createdPetId}`)} - > - {t("skipForNow")} - - + content = setGuidelinesAcknowledged(true)} />; + } else if (!uploadConsentGiven) { + content = setUploadConsentGiven(true)} />; + } else if (createdPetId) { + content = ( + + + {t("addPhoto")} + {t("addPhotoDesc")} - - ); - } - return ( - + {}} /> + + + router.push(`/pets/${createdPetId}`)} + > + {t("done")} + + router.push(`/pets/${createdPetId}`)} + > + {t("skipForNow")} + + + + ); + } else { + content = ( {t("addFirstPet")} {t("addFirstPetDesc")} @@ -92,6 +79,15 @@ export default function OnboardingPetPage() { }} /> + ); + } + + return ( + + + + + {content} ); } diff --git a/src/i18n/request.ts b/src/i18n/request.ts index 3e5b72e..41cf638 100644 --- a/src/i18n/request.ts +++ b/src/i18n/request.ts @@ -1,16 +1,35 @@ import { getRequestConfig } from "next-intl/server"; -import { cookies } from "next/headers"; +import { cookies, headers } from "next/headers"; export const LOCALES = ["en", "de"] as const; export type Locale = (typeof LOCALES)[number]; export const defaultLocale: Locale = "en"; +/** + * Picks the first Accept-Language entry (browsers already send these in + * preference order) whose primary subtag matches a supported locale. Used + * only when the visitor has never set NEXT_LOCALE — e.g. a fresh sign-up + * mid-onboarding, which has no in-app language switcher available yet. + */ +function localeFromAcceptLanguage(acceptLanguage: string | null): Locale | null { + if (!acceptLanguage) return null; + const tags = acceptLanguage + .split(",") + .map((part) => part.split(";")[0].trim().split("-")[0].toLowerCase()); + const match = tags.find((tag) => (LOCALES as readonly string[]).includes(tag)); + return (match as Locale) ?? null; +} + export default getRequestConfig(async () => { const cookieStore = await cookies(); const raw = cookieStore.get("NEXT_LOCALE")?.value ?? ""; - const locale: Locale = (LOCALES as readonly string[]).includes(raw) - ? (raw as Locale) - : defaultLocale; + let locale: Locale; + if ((LOCALES as readonly string[]).includes(raw)) { + locale = raw as Locale; + } else { + const headerStore = await headers(); + locale = localeFromAcceptLanguage(headerStore.get("accept-language")) ?? defaultLocale; + } return { locale,
{t("addPhotoDesc")}
{t("addFirstPetDesc")}