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

@@ -2,15 +2,16 @@
import { motion } from "framer-motion";
import { useState } from "react";
import { useTranslations } from "next-intl";
import { ArrowRight } from "lucide-react";
export default function NewsletterSection() {
const t = useTranslations("Newsletter");
const [email, setEmail] = useState("");
const [status, setStatus] = useState<"idle" | "success" | "error">("idle");
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
// TODO: Connect to newsletter service
setStatus("success");
setEmail("");
};
@@ -26,9 +27,7 @@ export default function NewsletterSection() {
transition={{ duration: 0.6 }}
className="font-serif italic text-4xl lg:text-5xl xl:text-[3.5rem] text-[#1A1A1A] tracking-tight leading-[1.1] mb-6"
>
Get 10% off your
<br />
first order
{t("stayConnected")}
</motion.h2>
<motion.p
@@ -38,8 +37,7 @@ export default function NewsletterSection() {
transition={{ duration: 0.6, delay: 0.1 }}
className="text-[#4A4A4A] mb-8"
>
Join the ManoonOils community and receive exclusive offers,
skincare tips, and early access to new products.
{t("newsletterText")}
</motion.p>
<motion.form
@@ -54,7 +52,7 @@ export default function NewsletterSection() {
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Enter your email"
placeholder={t("emailPlaceholder")}
required
className="flex-1 px-4 py-3 border border-[#1A1A1A]/10 rounded-[4px] text-sm focus:outline-none focus:border-[#1A1A1A]/30 transition-colors"
/>
@@ -62,7 +60,7 @@ export default function NewsletterSection() {
type="submit"
className="inline-flex items-center justify-center gap-2 bg-[#1A1A1A] text-white px-6 py-3 text-sm font-medium hover:bg-[#1A1A1A]/90 transition-colors rounded-[4px]"
>
Subscribe
{t("subscribe")}
<ArrowRight className="w-4 h-4" />
</button>
</motion.form>
@@ -73,7 +71,7 @@ export default function NewsletterSection() {
animate={{ opacity: 1 }}
className="text-sm text-emerald-600 mt-4"
>
Thank you! Check your email for your discount code.
Hvala vam! Proverite email za vaš kod za popust.
</motion.p>
)}
@@ -84,11 +82,10 @@ export default function NewsletterSection() {
transition={{ duration: 0.6, delay: 0.3 }}
className="text-xs text-[#4A4A4A]/60 mt-4"
>
By subscribing, you agree to our Privacy Policy. Unsubscribe
anytime.
Prijavom prihvatate našu Politiku privatnosti. Možete se odjaviti bilo kada.
</motion.p>
</div>
</div>
</section>
);
}
}