feat: implement locale-aware routing with [locale] dynamic segments
Some checks failed
Build and Deploy / build (push) Has been cancelled

WARNING: This change breaks existing SEO URLs for Serbian locale.

Changes:
- Migrated from separate locale folders (src/app/en/, src/app/de/, etc.)
  to [locale] dynamic segments (src/app/[locale]/)
- Serbian is now at /sr/ instead of / (root)
- English at /en/, German at /de/, French at /fr/
- All components updated to generate locale-aware links
- Root / now redirects to /sr (307 temporary redirect)

SEO Impact:
- Previously indexed Serbian URLs (/, /products, /about, /contact)
  will now return 404 or redirect to /sr/* URLs
- This is a breaking change for SEO - Serbian pages should ideally
  remain at root (/) with only non-default locales getting prefix
- Consider implementing 301 redirects from old URLs to maintain
  search engine rankings

Technical Notes:
- next-intl v4 with [locale] structure requires ALL locales to
  have the prefix (cannot have default locale at root)
- Alternative approach would be separate folder structure per locale
This commit is contained in:
Unchained
2026-03-23 20:59:33 +02:00
parent 5bd1a0f167
commit 92b6c830e1
47 changed files with 2175 additions and 2881 deletions

View File

@@ -0,0 +1,128 @@
import { getTranslations, setRequestLocale } from "next-intl/server";
import Header from "@/components/layout/Header";
import Footer from "@/components/layout/Footer";
interface AboutPageProps {
params: Promise<{ locale: string }>;
}
export async function generateMetadata({ params }: AboutPageProps) {
const { locale } = await params;
return {
title: locale === "sr"
? "O nama - ManoonOils"
: "About - ManoonOils",
description: locale === "sr"
? "Saznajte više o ManoonOils - naša priča, misija i posvećenost prirodnoj lepoti."
: "Learn more about ManoonOils - our story, mission, and commitment to natural beauty.",
};
}
export default async function AboutPage({ params }: AboutPageProps) {
const { locale } = await params;
setRequestLocale(locale);
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={locale === "sr" ? "Proizvodnja prirodnih ulja" : "Natural oils production"}
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">
&ldquo;{t("missionQuote")}&rdquo;
</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>
</>
);
}