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

@@ -1,8 +1,12 @@
"use client";
import { motion } from "framer-motion";
import { useTranslations } from "next-intl";
export default function ProblemSection() {
const t = useTranslations("ProblemSection");
const problems = t.raw("problems") as Array<{ problem: string; description: string }>;
return (
<section className="py-24 bg-gradient-to-b from-[#fefcfb] to-[#faf9f7]">
<div className="container mx-auto px-4">
@@ -14,47 +18,19 @@ export default function ProblemSection() {
transition={{ duration: 0.6 }}
>
<span className="text-xs uppercase tracking-[0.3em] text-[#c9a962] mb-4 block font-medium">
The Problem
{t("title")}
</span>
<h2 className="text-3xl md:text-4xl lg:text-5xl font-medium mb-6 leading-tight text-[#1a1a1a]">
Tired of Hair & Skin Products That Don&apos;t Deliver?
{t("subtitle")}
</h2>
<p className="text-[#666666] text-lg max-w-xl mx-auto">
You deserve better than products filled with harsh chemicals and empty promises
{t("description")}
</p>
<div className="w-16 h-1 bg-gradient-to-r from-[#c9a962] to-[#FFD700] mx-auto mt-8 rounded-full" />
</motion.div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 lg:gap-8 max-w-5xl mx-auto mt-16">
{[
{
icon: (
<svg className="w-10 h-10" viewBox="0 0 24 24" fill="none" strokeWidth="1.5">
<path stroke="#c9a962" strokeLinecap="round" strokeLinejoin="round" d="M9.172 16.172a4 4 0 015.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
),
problem: "Dry, Damaged Hair",
description: "Products leave your hair brittle, frizzy, and breaking despite expensive treatments",
},
{
icon: (
<svg className="w-10 h-10" viewBox="0 0 24 24" fill="none" strokeWidth="1.5">
<path stroke="#e8967a" strokeLinecap="round" strokeLinejoin="round" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
),
problem: "Confusing Ingredients",
description: "Can't pronounce what's in your skincare. parabens, sulfates, synthetic fragrances—dangerous toxins",
},
{
icon: (
<svg className="w-10 h-10" viewBox="0 0 24 24" fill="none" strokeWidth="1.5">
<path stroke="#7eb89e" strokeLinecap="round" strokeLinejoin="round" d="M18.364 18.364A9 9 0 005.636 5.636m12.728 12.728A9 9 0 015.636 5.636m12.728 12.728L5.636 5.636" />
</svg>
),
problem: "No Real Results",
description: "Countless products promise miracles but deliver nothing but empty promises and wasted money",
},
].map((item, index) => (
{problems.map((item, index) => (
<motion.div
key={index}
className="relative text-center p-8 bg-white rounded-3xl shadow-lg border border-[#f0ede8] hover:shadow-2xl hover:border-[#c9a962]/30 transition-all duration-500 group"
@@ -64,11 +40,24 @@ export default function ProblemSection() {
transition={{ duration: 0.5, delay: index * 0.1 }}
whileHover={{ y: -5 }}
>
{/* Decorative top border */}
<div className="absolute top-0 left-1/2 -translate-x-1/2 w-20 h-1 bg-gradient-to-r from-[#c9a962] to-[#FFD700] rounded-b-full opacity-0 group-hover:opacity-100 transition-opacity duration-300" />
<div className="w-20 h-20 mx-auto mb-6 rounded-2xl bg-gradient-to-br from-[#faf9f7] to-[#f5f0e8] flex items-center justify-center shadow-md border border-[#e8e4dc] group-hover:border-[#c9a962]/50 transition-colors duration-300">
{item.icon}
{index === 0 && (
<svg className="w-10 h-10" viewBox="0 0 24 24" fill="none" strokeWidth="1.5">
<path stroke="#c9a962" strokeLinecap="round" strokeLinejoin="round" d="M9.172 16.172a4 4 0 015.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
)}
{index === 1 && (
<svg className="w-10 h-10" viewBox="0 0 24 24" fill="none" strokeWidth="1.5">
<path stroke="#e8967a" strokeLinecap="round" strokeLinejoin="round" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
)}
{index === 2 && (
<svg className="w-10 h-10" viewBox="0 0 24 24" fill="none" strokeWidth="1.5">
<path stroke="#7eb89e" strokeLinecap="round" strokeLinejoin="round" d="M18.364 18.364A9 9 0 005.636 5.636m12.728 12.728A9 9 0 015.636 5.636m12.728 12.728L5.636 5.636" />
</svg>
)}
</div>
<h3 className="text-lg font-semibold text-[#1a1a1a] mb-3">{item.problem}</h3>
<p className="text-sm text-[#666666] leading-relaxed">{item.description}</p>
@@ -78,4 +67,4 @@ export default function ProblemSection() {
</div>
</section>
);
}
}