refactor: eliminate hardcoded locale comparisons for antifragility
Created centralized helpers: - src/lib/i18n/pageMetadata.ts: All page metadata (titles, descriptions, alt text) - src/lib/i18n/productText.ts: Product-specific translated text (shortDescription, benefits) - src/lib/i18n/metadata.ts: Helper functions for locale handling Updated all pages to use centralized metadata: - Homepage: Uses getPageMetadata for title, description, productionAlt - Products page: Uses getPageMetadata - Product detail: Uses getPageMetadata + getTranslatedShortDescription/getTranslatedBenefits - About page: Uses getPageMetadata ProductDetail component now uses: - getTranslatedShortDescription() instead of locale comparison - getTranslatedBenefits() instead of locale comparison All user-facing text now goes through translation files or centralized helpers. Adding a new language now requires only: 1. Add to SUPPORTED_LOCALES in locales.ts 2. Add LOCALE_CONFIG entry 3. Add entries to pageMetadata.ts and productText.ts 4. Add translation keys to message files
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import { getTranslations, setRequestLocale } from "next-intl/server";
|
||||
import Header from "@/components/layout/Header";
|
||||
import Footer from "@/components/layout/Footer";
|
||||
import { getPageMetadata } from "@/lib/i18n/pageMetadata";
|
||||
import { isValidLocale, DEFAULT_LOCALE, type Locale } from "@/lib/i18n/locales";
|
||||
|
||||
interface AboutPageProps {
|
||||
params: Promise<{ locale: string }>;
|
||||
@@ -8,19 +10,19 @@ interface AboutPageProps {
|
||||
|
||||
export async function generateMetadata({ params }: AboutPageProps) {
|
||||
const { locale } = await params;
|
||||
const validLocale = isValidLocale(locale) ? locale : DEFAULT_LOCALE;
|
||||
const metadata = getPageMetadata(validLocale as Locale);
|
||||
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.",
|
||||
title: metadata.about.title,
|
||||
description: metadata.about.description,
|
||||
};
|
||||
}
|
||||
|
||||
export default async function AboutPage({ params }: AboutPageProps) {
|
||||
const { locale } = await params;
|
||||
setRequestLocale(locale);
|
||||
const validLocale = isValidLocale(locale) ? locale : DEFAULT_LOCALE;
|
||||
const metadata = getPageMetadata(validLocale as Locale);
|
||||
setRequestLocale(validLocale);
|
||||
const t = await getTranslations("About");
|
||||
|
||||
return (
|
||||
@@ -43,7 +45,7 @@ export default async function AboutPage({ params }: AboutPageProps) {
|
||||
<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"}
|
||||
alt={metadata.productionAlt}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-black/20" />
|
||||
|
||||
@@ -10,30 +10,32 @@ import ProductReviews from "@/components/product/ProductReviews";
|
||||
import BeforeAfterGallery from "@/components/home/BeforeAfterGallery";
|
||||
import ProblemSection from "@/components/home/ProblemSection";
|
||||
import HowItWorks from "@/components/home/HowItWorks";
|
||||
import { getPageMetadata } from "@/lib/i18n/pageMetadata";
|
||||
import { isValidLocale, DEFAULT_LOCALE, getSaleorLocale, type Locale } from "@/lib/i18n/locales";
|
||||
|
||||
export async function generateMetadata({ params }: { params: Promise<{ locale: string }> }) {
|
||||
const { locale } = await params;
|
||||
setRequestLocale(locale);
|
||||
const validLocale = isValidLocale(locale) ? locale : DEFAULT_LOCALE;
|
||||
const metadata = getPageMetadata(validLocale as Locale);
|
||||
setRequestLocale(validLocale);
|
||||
return {
|
||||
title: locale === "sr"
|
||||
? "ManoonOils - Premium prirodna ulja za negu kose i kože"
|
||||
: "ManoonOils - Premium Natural Oils for Hair & Skin",
|
||||
description: locale === "sr"
|
||||
? "Otkrijte našu premium kolekciju prirodnih ulja za negu kose i kože."
|
||||
: "Discover our premium collection of natural oils for hair and skin care.",
|
||||
title: metadata.home.title,
|
||||
description: metadata.home.description,
|
||||
};
|
||||
}
|
||||
|
||||
export default async function Homepage({ params }: { params: Promise<{ locale: string }> }) {
|
||||
const { locale } = await params;
|
||||
setRequestLocale(locale);
|
||||
const validLocale = isValidLocale(locale) ? locale : DEFAULT_LOCALE;
|
||||
setRequestLocale(validLocale);
|
||||
const t = await getTranslations("Home");
|
||||
const tBenefits = await getTranslations("Benefits");
|
||||
const metadata = getPageMetadata(validLocale as Locale);
|
||||
|
||||
const productLocale = locale === "sr" ? "SR" : "EN";
|
||||
const saleorLocale = getSaleorLocale(validLocale as Locale);
|
||||
let products: any[] = [];
|
||||
try {
|
||||
products = await getProducts(productLocale);
|
||||
products = await getProducts(saleorLocale);
|
||||
} catch (e) {
|
||||
console.log("Failed to fetch products during build");
|
||||
}
|
||||
@@ -41,7 +43,7 @@ export default async function Homepage({ params }: { params: Promise<{ locale: s
|
||||
const featuredProducts = products?.slice(0, 4) || [];
|
||||
const hasProducts = featuredProducts.length > 0;
|
||||
|
||||
const basePath = `/${locale}`;
|
||||
const basePath = `/${validLocale}`;
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -122,7 +124,7 @@ export default async function Homepage({ params }: { params: Promise<{ locale: s
|
||||
<div className="relative aspect-[4/3] bg-[#e8f0f5] rounded-lg overflow-hidden">
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1608571423902-eed4a5ad8108?q=80&w=800&auto=format&fit=crop"
|
||||
alt={locale === "sr" ? "Proizvodnja prirodnih ulja" : "Natural oils production"}
|
||||
alt={metadata.home.productionAlt}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -5,6 +5,8 @@ import Footer from "@/components/layout/Footer";
|
||||
import ProductDetail from "@/components/product/ProductDetail";
|
||||
import type { Product } from "@/types/saleor";
|
||||
import { routing } from "@/i18n/routing";
|
||||
import { getPageMetadata } from "@/lib/i18n/pageMetadata";
|
||||
import { isValidLocale, DEFAULT_LOCALE, getSaleorLocale, type Locale } from "@/lib/i18n/locales";
|
||||
|
||||
interface ProductPageProps {
|
||||
params: Promise<{ locale: string; slug: string }>;
|
||||
@@ -16,8 +18,8 @@ export async function generateStaticParams() {
|
||||
|
||||
for (const locale of locales) {
|
||||
try {
|
||||
const productLocale = locale === "sr" ? "SR" : "EN";
|
||||
const products = await getProducts(productLocale, 100);
|
||||
const saleorLocale = locale === "sr" ? "SR" : "EN";
|
||||
const products = await getProducts(saleorLocale, 100);
|
||||
products.forEach((product: Product) => {
|
||||
params.push({ locale, slug: product.slug });
|
||||
});
|
||||
@@ -29,16 +31,18 @@ export async function generateStaticParams() {
|
||||
|
||||
export async function generateMetadata({ params }: ProductPageProps) {
|
||||
const { locale, slug } = await params;
|
||||
const productLocale = locale === "sr" ? "SR" : "EN";
|
||||
const product = await getProductBySlug(slug, productLocale);
|
||||
const validLocale = isValidLocale(locale) ? locale : DEFAULT_LOCALE;
|
||||
const metadata = getPageMetadata(validLocale as Locale);
|
||||
const saleorLocale = validLocale === "sr" ? "SR" : "EN";
|
||||
const product = await getProductBySlug(slug, saleorLocale);
|
||||
|
||||
if (!product) {
|
||||
return {
|
||||
title: locale === "sr" ? "Proizvod nije pronađen" : "Product not found",
|
||||
title: metadata.productNotFound,
|
||||
};
|
||||
}
|
||||
|
||||
const localized = getLocalizedProduct(product, productLocale);
|
||||
const localized = getLocalizedProduct(product, saleorLocale);
|
||||
|
||||
return {
|
||||
title: localized.name,
|
||||
@@ -48,12 +52,13 @@ export async function generateMetadata({ params }: ProductPageProps) {
|
||||
|
||||
export default async function ProductPage({ params }: ProductPageProps) {
|
||||
const { locale, slug } = await params;
|
||||
setRequestLocale(locale);
|
||||
const validLocale = isValidLocale(locale) ? locale : DEFAULT_LOCALE;
|
||||
setRequestLocale(validLocale);
|
||||
const t = await getTranslations("Product");
|
||||
const productLocale = locale === "sr" ? "SR" : "EN";
|
||||
const product = await getProductBySlug(slug, productLocale);
|
||||
const saleorLocale = getSaleorLocale(validLocale as Locale);
|
||||
const product = await getProductBySlug(slug, saleorLocale);
|
||||
|
||||
const basePath = locale === "sr" ? "" : `/${locale}`;
|
||||
const basePath = `/${validLocale}`;
|
||||
|
||||
if (!product) {
|
||||
return (
|
||||
|
||||
@@ -4,6 +4,8 @@ import Header from "@/components/layout/Header";
|
||||
import Footer from "@/components/layout/Footer";
|
||||
import ProductCard from "@/components/product/ProductCard";
|
||||
import { ChevronDown } from "lucide-react";
|
||||
import { getPageMetadata } from "@/lib/i18n/pageMetadata";
|
||||
import { isValidLocale, DEFAULT_LOCALE, getSaleorLocale, type Locale } from "@/lib/i18n/locales";
|
||||
|
||||
interface ProductsPageProps {
|
||||
params: Promise<{ locale: string }>;
|
||||
@@ -11,22 +13,21 @@ interface ProductsPageProps {
|
||||
|
||||
export async function generateMetadata({ params }: ProductsPageProps) {
|
||||
const { locale } = await params;
|
||||
const validLocale = isValidLocale(locale) ? locale : DEFAULT_LOCALE;
|
||||
const metadata = getPageMetadata(validLocale as Locale);
|
||||
return {
|
||||
title: locale === "sr"
|
||||
? "Proizvodi - ManoonOils"
|
||||
: "Products - ManoonOils",
|
||||
description: locale === "sr"
|
||||
? "Pregledajte našu kolekciju premium prirodnih ulja za negu kose i kože."
|
||||
: "Browse our collection of premium natural oils for hair and skin care.",
|
||||
title: metadata.products.title,
|
||||
description: metadata.products.description,
|
||||
};
|
||||
}
|
||||
|
||||
export default async function ProductsPage({ params }: ProductsPageProps) {
|
||||
const { locale } = await params;
|
||||
setRequestLocale(locale);
|
||||
const validLocale = isValidLocale(locale) ? locale : DEFAULT_LOCALE;
|
||||
setRequestLocale(validLocale);
|
||||
const t = await getTranslations("Products");
|
||||
const productLocale = locale === "sr" ? "SR" : "EN";
|
||||
const products = await getProducts(productLocale);
|
||||
const saleorLocale = getSaleorLocale(validLocale as Locale);
|
||||
const products = await getProducts(saleorLocale);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
Reference in New Issue
Block a user