refactor: centralize locale constants to prevent breaking changes
Created src/lib/i18n/locales.ts as single source of truth for: - SUPPORTED_LOCALES array - LOCALE_COOKIE name - DEFAULT_LOCALE - LOCALE_CONFIG (labels, flags, Saleor locale mapping) - Helper functions (isValidLocale, getSaleorLocale, getLocaleFromPath) Updated all files to use centralized constants: - middleware.ts - Header.tsx - ProductCard.tsx - sitemap.ts - root layout and locale layout - routing.ts Benefits: - Adding new locale only requires updating ONE file (locales.ts) - No more hardcoded locale lists scattered across codebase - Cookie name defined in one place - Type-safe locale validation
This commit is contained in:
@@ -9,11 +9,8 @@ import { useTranslations } from "next-intl";
|
||||
import { useSaleorCheckoutStore } from "@/stores/saleorCheckoutStore";
|
||||
import { User, ShoppingBag, Menu, X, Globe } from "lucide-react";
|
||||
import CartDrawer from "@/components/cart/CartDrawer";
|
||||
|
||||
const LOCALES = [
|
||||
{ code: "sr", label: "Srpski", flag: "🇷🇸" },
|
||||
{ code: "en", label: "English", flag: "🇬🇧" },
|
||||
] as const;
|
||||
import { SUPPORTED_LOCALES, LOCALE_COOKIE, LOCALE_CONFIG, isValidLocale } from "@/lib/i18n/locales";
|
||||
import type { Locale } from "@/lib/i18n/locales";
|
||||
|
||||
interface HeaderProps {
|
||||
locale?: string;
|
||||
@@ -29,9 +26,7 @@ export default function Header({ locale = "sr" }: HeaderProps) {
|
||||
const { getLineCount, toggleCart, initCheckout } = useSaleorCheckoutStore();
|
||||
|
||||
const itemCount = getLineCount();
|
||||
const localePath = `/${locale}`;
|
||||
|
||||
const currentLocale = LOCALES.find((l) => l.code === locale) || LOCALES[0];
|
||||
const currentLocale = isValidLocale(locale) ? LOCALE_CONFIG[locale] : LOCALE_CONFIG.sr;
|
||||
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
@@ -48,7 +43,11 @@ export default function Header({ locale = "sr" }: HeaderProps) {
|
||||
setLangDropdownOpen(false);
|
||||
return;
|
||||
}
|
||||
document.cookie = `NEXT_LOCALE=${newLocale}; path=/; max-age=31536000`;
|
||||
if (!isValidLocale(newLocale)) {
|
||||
setLangDropdownOpen(false);
|
||||
return;
|
||||
}
|
||||
document.cookie = `${LOCALE_COOKIE}=${newLocale}; path=/; max-age=31536000`;
|
||||
const pathWithoutLocale = pathname.replace(/^\/(sr|en|de|fr)/, "") || "/";
|
||||
const newPath = `/${newLocale}${pathWithoutLocale}`;
|
||||
window.location.replace(newPath);
|
||||
@@ -115,7 +114,7 @@ export default function Header({ locale = "sr" }: HeaderProps) {
|
||||
))}
|
||||
</nav>
|
||||
|
||||
<Link href={localePath || "/"} className="flex-shrink-0 lg:absolute lg:left-1/2 lg:-translate-x-1/2">
|
||||
<Link href={`/${locale}`} className="flex-shrink-0 lg:absolute lg:left-1/2 lg:-translate-x-1/2">
|
||||
<Image
|
||||
src="https://minio-api.nodecrew.me/manoon-media/2024/09/cropped-manoon-logo_256x-1-1.png"
|
||||
alt="ManoonOils"
|
||||
@@ -144,16 +143,16 @@ export default function Header({ locale = "sr" }: HeaderProps) {
|
||||
exit={{ opacity: 0, y: -10 }}
|
||||
className="absolute right-0 top-full mt-1 bg-white border border-[#e5e5e5] shadow-lg rounded-md overflow-hidden z-50"
|
||||
>
|
||||
{LOCALES.map((loc) => (
|
||||
{SUPPORTED_LOCALES.map((loc) => (
|
||||
<button
|
||||
key={loc.code}
|
||||
onClick={() => switchLocale(loc.code)}
|
||||
key={loc}
|
||||
onClick={() => switchLocale(loc)}
|
||||
className={`flex items-center gap-2 px-4 py-2 text-sm hover:bg-black/5 transition-colors w-full text-left ${
|
||||
loc.code === locale ? "bg-black/5 font-medium" : ""
|
||||
loc === locale ? "bg-black/5 font-medium" : ""
|
||||
}`}
|
||||
>
|
||||
<span>{loc.flag}</span>
|
||||
<span>{loc.label}</span>
|
||||
<span>{LOCALE_CONFIG[loc].flag}</span>
|
||||
<span>{LOCALE_CONFIG[loc].label}</span>
|
||||
</button>
|
||||
))}
|
||||
</motion.div>
|
||||
@@ -195,7 +194,7 @@ export default function Header({ locale = "sr" }: HeaderProps) {
|
||||
>
|
||||
<div className="container h-full flex flex-col">
|
||||
<div className="flex items-center justify-between h-[72px]">
|
||||
<Link href={localePath || "/"} onClick={() => setMobileMenuOpen(false)}>
|
||||
<Link href={`/${locale}`} onClick={() => setMobileMenuOpen(false)}>
|
||||
<Image
|
||||
src="https://minio-api.nodecrew.me/manoon-media/2024/09/cropped-manoon-logo_256x-1-1.png"
|
||||
alt="ManoonOils"
|
||||
@@ -260,4 +259,4 @@ export default function Header({ locale = "sr" }: HeaderProps) {
|
||||
<CartDrawer />
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user