- Update [slug]/page.tsx to always include locale in canonical URL
- Update by-oil/page.tsx to use consistent locale prefix
- Update by-concern/page.tsx to use consistent locale prefix
- All canonical URLs now match actual URLs: /{locale}/solutions/{slug}
110 lines
3.3 KiB
TypeScript
110 lines
3.3 KiB
TypeScript
import {
|
|
getOilForConcernPageBySlug,
|
|
getAllSolutionSlugs,
|
|
getLocalizedString,
|
|
getLocalizedKeywords
|
|
} from "@/lib/programmatic-seo/dataLoader";
|
|
import { getProducts, filterOutBundles } from "@/lib/saleor";
|
|
import { OilForConcernPageTemplate } from "@/components/programmatic-seo/OilForConcernPage";
|
|
import { FAQSchema } from "@/components/programmatic-seo/FAQSchema";
|
|
import { isValidLocale, DEFAULT_LOCALE, type Locale } from "@/lib/i18n/locales";
|
|
import type { Metadata } from "next";
|
|
import { notFound } from "next/navigation";
|
|
|
|
interface PageProps {
|
|
params: Promise<{ locale: string; slug: string }>;
|
|
}
|
|
|
|
export async function generateStaticParams() {
|
|
return await getAllSolutionSlugs();
|
|
}
|
|
|
|
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || "https://manoonoils.com";
|
|
|
|
export async function generateMetadata({ params }: PageProps): Promise<Metadata> {
|
|
const { locale, slug } = await params;
|
|
const validLocale = isValidLocale(locale) ? locale : DEFAULT_LOCALE;
|
|
const page = await getOilForConcernPageBySlug(slug, validLocale);
|
|
|
|
if (!page) {
|
|
return {
|
|
title: "Page Not Found",
|
|
};
|
|
}
|
|
|
|
const metaTitle = getLocalizedString(page.metaTitle, validLocale);
|
|
const metaDescription = getLocalizedString(page.metaDescription, validLocale);
|
|
const keywords = getLocalizedKeywords(page.seoKeywords, validLocale);
|
|
const localePrefix = `/${validLocale}`;
|
|
const canonicalUrl = `${baseUrl}${localePrefix}/solutions/${slug}`;
|
|
|
|
return {
|
|
title: metaTitle,
|
|
description: metaDescription,
|
|
keywords: keywords.join(", "),
|
|
alternates: {
|
|
canonical: canonicalUrl,
|
|
languages: {
|
|
"sr": `${baseUrl}/sr/solutions/${page.localizedSlugs.sr}`,
|
|
"en": `${baseUrl}/en/solutions/${page.localizedSlugs.en}`,
|
|
"de": `${baseUrl}/de/solutions/${page.localizedSlugs.de}`,
|
|
"fr": `${baseUrl}/fr/solutions/${page.localizedSlugs.fr}`,
|
|
},
|
|
},
|
|
openGraph: {
|
|
title: metaTitle,
|
|
description: metaDescription,
|
|
type: "article",
|
|
url: canonicalUrl,
|
|
images: [{
|
|
url: `${baseUrl}/og-image.jpg`,
|
|
width: 1200,
|
|
height: 630,
|
|
alt: metaTitle,
|
|
}],
|
|
locale: validLocale,
|
|
},
|
|
twitter: {
|
|
card: "summary_large_image",
|
|
title: metaTitle,
|
|
description: metaDescription,
|
|
images: [`${baseUrl}/og-image.jpg`],
|
|
},
|
|
};
|
|
}
|
|
|
|
export default async function SolutionPage({ params }: PageProps) {
|
|
const { locale, slug } = await params;
|
|
const validLocale = isValidLocale(locale) ? locale : DEFAULT_LOCALE;
|
|
const [page, allProducts] = await Promise.all([
|
|
getOilForConcernPageBySlug(slug, validLocale),
|
|
getProducts(validLocale === "sr" ? "SR" : "EN", 20)
|
|
]);
|
|
|
|
if (!page) {
|
|
notFound();
|
|
}
|
|
|
|
// Filter out bundle products (2x, 3x versions) - only show original 4 products
|
|
const products = filterOutBundles(allProducts).slice(0, 4);
|
|
|
|
const basePath = `/${validLocale}`;
|
|
|
|
const faqQuestions = page.faqs.map((faq) => ({
|
|
question: getLocalizedString(faq.question, validLocale),
|
|
answer: getLocalizedString(faq.answer, validLocale),
|
|
}));
|
|
|
|
return (
|
|
<>
|
|
<FAQSchema questions={faqQuestions} />
|
|
<OilForConcernPageTemplate
|
|
page={page}
|
|
locale={validLocale as Locale}
|
|
basePath={basePath}
|
|
products={products}
|
|
/>
|
|
</>
|
|
);
|
|
}
|