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,38 +1,45 @@
"use client";
import Link from "next/link";
import Image from "next/image";
import { Instagram, Facebook } from "lucide-react";
import { useTranslations } from "next-intl";
const footerLinks = {
shop: [
{ label: "All Products", href: "/products" },
{ label: "Hair Care", href: "/products" },
{ label: "Skin Care", href: "/products" },
{ label: "Gift Sets", href: "/products" },
],
about: [
{ label: "Our Story", href: "/about" },
{ label: "Process", href: "/about" },
{ label: "Sustainability", href: "/about" },
],
help: [
{ label: "FAQ", href: "/contact" },
{ label: "Shipping", href: "/contact" },
{ label: "Returns", href: "/contact" },
{ label: "Contact Us", href: "/contact" },
],
};
interface FooterProps {
locale?: string;
}
export default function Footer() {
export default function Footer({ locale = "sr" }: FooterProps) {
const t = useTranslations("Footer");
const currentYear = new Date().getFullYear();
const localePath = `/${locale}`;
const footerLinks = {
shop: [
{ label: t("allProducts"), href: `${localePath}/products` },
{ label: t("hairCare"), href: `${localePath}/products` },
{ label: t("skinCare"), href: `${localePath}/products` },
{ label: t("giftSets"), href: `${localePath}/products` },
],
about: [
{ label: t("ourStory"), href: `${localePath}/about` },
{ label: t("process"), href: `${localePath}/about` },
{ label: t("sustainability"), href: `${localePath}/about` },
],
help: [
{ label: t("faq"), href: `${localePath}/contact` },
{ label: t("shipping"), href: `${localePath}/contact` },
{ label: t("returns"), href: `${localePath}/contact` },
{ label: t("contactUs"), href: `${localePath}/contact` },
],
};
return (
<footer className="bg-white border-t border-[#e5e5e5]">
{/* Main Footer */}
<div className="container py-16 lg:py-20">
<div className="grid grid-cols-1 lg:grid-cols-12 gap-12 lg:gap-8">
{/* Brand Column */}
<div className="lg:col-span-4">
<Link href="/" className="inline-block mb-6">
<Link href={localePath} className="inline-block mb-6">
<Image
src="https://minio-api.nodecrew.me/manoon-media/2024/09/cropped-manoon-logo_256x-1-1.png"
alt="ManoonOils"
@@ -42,9 +49,8 @@ export default function Footer() {
/>
</Link>
<p className="text-[#666666] text-sm leading-relaxed max-w-xs mb-6">
Premium natural oils for hair and skin care. Handcrafted with love using traditional methods.
{t("brandDescription")}
</p>
{/* Social Links */}
<div className="flex items-center gap-4">
<a
href="https://instagram.com"
@@ -67,13 +73,11 @@ export default function Footer() {
</div>
</div>
{/* Links Columns - All aligned at top */}
<div className="lg:col-span-8">
<div className="grid grid-cols-2 md:grid-cols-3 gap-8">
{/* Shop */}
<div className="flex flex-col">
<h4 className="text-xs uppercase tracking-[0.15em] font-medium mb-5 text-[#1a1a1a]">
Shop
{t("shop")}
</h4>
<ul className="space-y-3">
{footerLinks.shop.map((link) => (
@@ -89,10 +93,9 @@ export default function Footer() {
</ul>
</div>
{/* About */}
<div className="flex flex-col">
<h4 className="text-xs uppercase tracking-[0.15em] font-medium mb-5 text-[#1a1a1a]">
About
{t("about")}
</h4>
<ul className="space-y-3">
{footerLinks.about.map((link) => (
@@ -108,10 +111,9 @@ export default function Footer() {
</ul>
</div>
{/* Help */}
<div className="flex flex-col">
<h4 className="text-xs uppercase tracking-[0.15em] font-medium mb-5 text-[#1a1a1a]">
Help
{t("help")}
</h4>
<ul className="space-y-3">
{footerLinks.help.map((link) => (
@@ -131,18 +133,15 @@ export default function Footer() {
</div>
</div>
{/* Bottom Bar */}
<div className="border-t border-[#e5e5e5]">
<div className="container py-6">
<div className="flex flex-col md:flex-row items-center justify-between gap-4">
{/* Copyright */}
<p className="text-xs text-[#999999]">
&copy; {currentYear} ManoonOils. All rights reserved.
&copy; {currentYear} ManoonOils. {t("allRights")}
</p>
{/* Payment Methods */}
<div className="flex items-center gap-3">
<span className="text-xs text-[#999999]">We accept:</span>
<span className="text-xs text-[#999999]">{t("weAccept")}</span>
<div className="flex items-center gap-2">
<span className="text-xs font-medium text-[#666666] px-2 py-1 border border-[#e5e5e5] rounded">
Visa
@@ -160,4 +159,4 @@ export default function Footer() {
</div>
</footer>
);
}
}