Created centralized helpers: - src/lib/i18n/pageMetadata.ts: All page metadata (titles, descriptions, alt text) - src/lib/i18n/productText.ts: Product-specific translated text (shortDescription, benefits) - src/lib/i18n/metadata.ts: Helper functions for locale handling Updated all pages to use centralized metadata: - Homepage: Uses getPageMetadata for title, description, productionAlt - Products page: Uses getPageMetadata - Product detail: Uses getPageMetadata + getTranslatedShortDescription/getTranslatedBenefits - About page: Uses getPageMetadata ProductDetail component now uses: - getTranslatedShortDescription() instead of locale comparison - getTranslatedBenefits() instead of locale comparison All user-facing text now goes through translation files or centralized helpers. Adding a new language now requires only: 1. Add to SUPPORTED_LOCALES in locales.ts 2. Add LOCALE_CONFIG entry 3. Add entries to pageMetadata.ts and productText.ts 4. Add translation keys to message files
130 lines
4.8 KiB
TypeScript
130 lines
4.8 KiB
TypeScript
import { getTranslations, setRequestLocale } from "next-intl/server";
|
|
import Header from "@/components/layout/Header";
|
|
import Footer from "@/components/layout/Footer";
|
|
import { getPageMetadata } from "@/lib/i18n/pageMetadata";
|
|
import { isValidLocale, DEFAULT_LOCALE, type Locale } from "@/lib/i18n/locales";
|
|
|
|
interface AboutPageProps {
|
|
params: Promise<{ locale: string }>;
|
|
}
|
|
|
|
export async function generateMetadata({ params }: AboutPageProps) {
|
|
const { locale } = await params;
|
|
const validLocale = isValidLocale(locale) ? locale : DEFAULT_LOCALE;
|
|
const metadata = getPageMetadata(validLocale as Locale);
|
|
return {
|
|
title: metadata.about.title,
|
|
description: metadata.about.description,
|
|
};
|
|
}
|
|
|
|
export default async function AboutPage({ params }: AboutPageProps) {
|
|
const { locale } = await params;
|
|
const validLocale = isValidLocale(locale) ? locale : DEFAULT_LOCALE;
|
|
const metadata = getPageMetadata(validLocale as Locale);
|
|
setRequestLocale(validLocale);
|
|
const t = await getTranslations("About");
|
|
|
|
return (
|
|
<>
|
|
<Header locale={locale} />
|
|
<main className="min-h-screen bg-white">
|
|
<div className="pt-[104px]">
|
|
<div className="container py-12 md:py-16">
|
|
<div className="max-w-2xl mx-auto text-center">
|
|
<span className="text-xs uppercase tracking-[0.2em] text-[#666666] mb-3 block">
|
|
{t("subtitle")}
|
|
</span>
|
|
<h1 className="text-4xl md:text-5xl font-medium tracking-tight">
|
|
{t("title")}
|
|
</h1>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="relative h-[400px] md:h-[500px] overflow-hidden">
|
|
<img
|
|
src="https://images.unsplash.com/photo-1608571423902-eed4a5ad8108?q=80&w=2000&auto=format&fit=crop"
|
|
alt={metadata.productionAlt}
|
|
className="w-full h-full object-cover"
|
|
/>
|
|
<div className="absolute inset-0 bg-black/20" />
|
|
</div>
|
|
|
|
<section className="py-16 md:py-24">
|
|
<div className="container">
|
|
<div className="max-w-3xl mx-auto">
|
|
<div className="mb-16">
|
|
<p className="text-xl md:text-2xl text-[#1a1a1a] leading-relaxed mb-8">
|
|
{t("intro")}
|
|
</p>
|
|
<p className="text-[#666666] leading-relaxed">
|
|
{t("intro2")}
|
|
</p>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 md:gap-12 mb-16">
|
|
<div className="p-6 bg-[#f8f9fa]">
|
|
<h3 className="text-lg font-medium mb-3">
|
|
{t("naturalIngredients")}
|
|
</h3>
|
|
<p className="text-[#666666] text-sm leading-relaxed">
|
|
{t("naturalIngredientsDesc")}
|
|
</p>
|
|
</div>
|
|
<div className="p-6 bg-[#f8f9fa]">
|
|
<h3 className="text-lg font-medium mb-3">
|
|
{t("crueltyFree")}
|
|
</h3>
|
|
<p className="text-[#666666] text-sm leading-relaxed">
|
|
{t("crueltyFreeDesc")}
|
|
</p>
|
|
</div>
|
|
<div className="p-6 bg-[#f8f9fa]">
|
|
<h3 className="text-lg font-medium mb-3">
|
|
{t("sustainablePackaging")}
|
|
</h3>
|
|
<p className="text-[#666666] text-sm leading-relaxed">
|
|
{t("sustainablePackagingDesc")}
|
|
</p>
|
|
</div>
|
|
<div className="p-6 bg-[#f8f9fa]">
|
|
<h3 className="text-lg font-medium mb-3">
|
|
{t("handcraftedQuality")}
|
|
</h3>
|
|
<p className="text-[#666666] text-sm leading-relaxed">
|
|
{t("handcraftedQualityDesc")}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="text-center py-12 border-t border-b border-[#e5e5e5]">
|
|
<span className="text-caption text-[#666666] mb-4 block">
|
|
{t("mission")}
|
|
</span>
|
|
<blockquote className="text-2xl md:text-3xl font-medium tracking-tight">
|
|
“{t("missionQuote")}”
|
|
</blockquote>
|
|
</div>
|
|
|
|
<div className="mt-16">
|
|
<h2 className="text-2xl font-medium mb-6">
|
|
{t("handmadeTitle")}
|
|
</h2>
|
|
<p className="text-[#666666] leading-relaxed mb-6">
|
|
{t("handmadeText1")}
|
|
</p>
|
|
<p className="text-[#666666] leading-relaxed">
|
|
{t("handmadeText2")}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
<div className="pt-16">
|
|
<Footer locale={locale} />
|
|
</div>
|
|
</>
|
|
);
|
|
} |