import JsonLd from '@/components/JsonLd'; import { SITE_URL } from '@/lib/schema'; import ProductSidebar from '@/components/ProductSidebar'; import ProductTabs from '@/components/ProductTabs'; import ProductTechnicalData from '@/components/ProductTechnicalData'; import RelatedProducts from '@/components/RelatedProducts'; import DatasheetDownload from '@/components/DatasheetDownload'; import { Badge, Card, Container, Heading, Section } from '@/components/ui'; import { getDatasheetPath } from '@/lib/datasheets'; import { getAllProducts, getProductBySlug } from '@/lib/products'; import { mapFileSlugToTranslated, mapSlugToFileSlug } from '@/lib/slugs'; import { Metadata } from 'next'; import { getTranslations, setRequestLocale } from 'next-intl/server'; import { getProductOGImageMetadata } from '@/lib/metadata'; import Image from 'next/image'; import Link from 'next/link'; import { notFound, redirect } from 'next/navigation'; import ProductEngagementTracker from '@/components/analytics/ProductEngagementTracker'; import MDXContent from '@/components/MDXContent'; interface ProductPageProps { params: Promise<{ locale: string; slug: string[]; }>; } export async function generateMetadata({ params }: ProductPageProps): Promise { const { locale, slug } = await params; const productSlug = slug[slug.length - 1]; const t = await getTranslations('Products'); // Check if it's a category page const categories = [ 'low-voltage-cables', 'medium-voltage-cables', 'high-voltage-cables', 'solar-cables', ]; const fileSlug = await mapSlugToFileSlug(productSlug, locale); if (categories.includes(fileSlug)) { const categoryKey = fileSlug .replace(/-cables$/, '') .replace(/-([a-z])/g, (g) => g[1].toUpperCase()); const categoryTitle = t.has(`categories.${categoryKey}.title`) ? t(`categories.${categoryKey}.title`) : fileSlug; const categoryDesc = t.has(`categories.${categoryKey}.description`) ? t(`categories.${categoryKey}.description`) : ''; return { title: categoryTitle, description: categoryDesc, alternates: { canonical: `${SITE_URL}/${locale}/${await mapFileSlugToTranslated('products', locale)}/${await mapFileSlugToTranslated(fileSlug, locale)}`, languages: { de: `${SITE_URL}/de/${await mapFileSlugToTranslated('products', 'de')}/${await mapFileSlugToTranslated(fileSlug, 'de')}`, en: `${SITE_URL}/en/${await mapFileSlugToTranslated('products', 'en')}/${await mapFileSlugToTranslated(fileSlug, 'en')}`, 'x-default': `${SITE_URL}/en/${await mapFileSlugToTranslated('products', 'en')}/${await mapFileSlugToTranslated(fileSlug, 'en')}`, }, }, }; } const fileSlugs = await Promise.all(slug.map((s) => mapSlugToFileSlug(s, locale))); const getLocalizedPath = async (lang: string) => { const parts = await Promise.all([ mapFileSlugToTranslated('products', lang), ...fileSlugs.map((fs) => mapFileSlugToTranslated(fs, lang)), ]); return parts.join('/'); }; const product = await getProductBySlug(productSlug, locale); if (!product) return {}; const currentLocalePath = await getLocalizedPath(locale); return { title: product.frontmatter.title, description: product.frontmatter.description, alternates: { canonical: `${SITE_URL}/${locale}/${currentLocalePath}`, languages: { de: `${SITE_URL}/de/${await getLocalizedPath('de')}`, en: `${SITE_URL}/en/${await getLocalizedPath('en')}`, 'x-default': `${SITE_URL}/en/${await getLocalizedPath('en')}`, }, }, openGraph: { title: product.frontmatter.title, description: product.frontmatter.description, type: 'website', url: `${SITE_URL}/${locale}/${currentLocalePath}`, images: getProductOGImageMetadata(productSlug, product.frontmatter.title, locale), }, twitter: { card: 'summary_large_image', title: product.frontmatter.title, description: product.frontmatter.description, }, }; } export default async function ProductPage({ params }: ProductPageProps) { const { locale, slug } = await params; setRequestLocale(locale); const productSlug = slug[slug.length - 1]; const t = await getTranslations('Products'); const productsSlug = await mapFileSlugToTranslated('products', locale); const categories = [ 'low-voltage-cables', 'medium-voltage-cables', 'high-voltage-cables', 'solar-cables', ]; const fileSlugs = await Promise.all(slug.map((s) => mapSlugToFileSlug(s, locale))); const translatedSlugsForLocale = await Promise.all( fileSlugs.map((fs) => mapFileSlugToTranslated(fs, locale)), ); // If the requested slugs don't exactly match the translated slugs for the current locale // (i.e. if the user used the static language switcher but kept the original locale's slugs) if (slug.join('/') !== translatedSlugsForLocale.join('/')) { redirect(`/${locale}/${productsSlug}/${translatedSlugsForLocale.join('/')}`); } const fileSlug = fileSlugs[fileSlugs.length - 1]; if (categories.includes(fileSlug)) { const allProducts = await getAllProducts(locale); const categoryKey = fileSlug .replace(/-cables$/, '') .replace(/-([a-z])/g, (g) => g[1].toUpperCase()); const categoryTitle = t.has(`categories.${categoryKey}.title`) ? t(`categories.${categoryKey}.title`) : fileSlug; const filteredProducts = allProducts.filter((p) => { const firstCat = p.frontmatter.categories[0] || ''; const normalizedCat = firstCat.toLowerCase().replace(/\s+/g, '-'); let pFileSlug = 'low-voltage-cables'; if (normalizedCat === 'hochspannungskabel' || normalizedCat === 'high-voltage-cables') pFileSlug = 'high-voltage-cables'; else if ( normalizedCat === 'mittelspannungskabel' || normalizedCat === 'medium-voltage-cables' ) pFileSlug = 'medium-voltage-cables'; else if ( normalizedCat === 'solarkabel' || normalizedCat === 'solar-cables' || normalizedCat === 'solar' ) pFileSlug = 'solar-cables'; return pFileSlug === fileSlug; }); const productsWithTranslatedSlugs = await Promise.all( filteredProducts.map(async (p) => ({ ...p, translatedSlug: await mapFileSlugToTranslated(p.slug, locale), })), ); return (
{categoryTitle}
{productsWithTranslatedSlugs.map((product) => (
{product.frontmatter.images?.[0] && ( <> {product.frontmatter.title}
)}
{product.frontmatter.categories.map((cat, i) => ( {cat} ))}

{product.frontmatter.title}

{product.frontmatter.description}

{t('details')}
))}
); } const product = await getProductBySlug(productSlug, locale); if (!product) { notFound(); } let technicalItems = []; try { const tabMatch = typeof product.content === 'string' && product.content.match(//s); if (tabMatch && tabMatch[1]) { const data = JSON.parse(tabMatch[1]); technicalItems = data.technicalItems || []; } } catch (e) { // Ignore JSON parse errors for AST } const datasheetPath = getDatasheetPath(productSlug, locale); const isFallback = (product.frontmatter as any).isFallback; const categorySlug = slug[0]; const categoryFileSlug = await mapSlugToFileSlug(categorySlug, locale); const categoryKey = categoryFileSlug .replace(/-cables$/, '') .replace(/-([a-z])/g, (g) => g[1].toUpperCase()); const categoryTitle = t.has(`categories.${categoryKey}.title`) ? t(`categories.${categoryKey}.title`) : categoryFileSlug; let descriptionContent = typeof product.content === 'string' ? product.content : ''; let technicalContent = ''; if (typeof product.content === 'string') { const tabBlockMatch = product.content.match(//s); if (tabBlockMatch) { descriptionContent = product.content.replace(tabBlockMatch[0], ''); technicalContent = tabBlockMatch[0]; } } const sidebar = ( ); return (
{/* Product Hero */}
{/* Background Decorative Elements */}
{isFallback && (
{t('englishVersion')}
)}
{product.frontmatter.categories.map((cat, idx) => ( {cat} ))}
{product.frontmatter.title}

{product.frontmatter.description}

{/* Large Product Image Section */} {product.frontmatter.images && product.frontmatter.images.length > 0 && (
{product.frontmatter.title} {/* Subtle reflection/shadow effect */}
{product.frontmatter.images.length > 1 && (
{product.frontmatter.images.slice(0, 5).map((img, idx) => (
))}
)}
)}
{/* Description Area Next to Sidebar */}
{descriptionContent ? ( ) : product.frontmatter.description ? (

{product.frontmatter.description}

) : null} {product.application && (
)}
{/* Sidebar Column */}
{sidebar}
{/* Full-width Technical Data Below */}
{/* Datasheet Download Section */} {categoryFileSlug === 'medium-voltage-cables' && datasheetPath && (

{t('downloadDatasheet')}

)} {/* Structured Data (Hidden) */} ({ '@type': 'PropertyValue', name: item.label, value: item.value, })), category: product.frontmatter.categories.join(', '), mainEntityOfPage: { '@type': 'WebPage', '@id': `${SITE_URL}/${locale}/${await mapFileSlugToTranslated('products', locale)}/${slug.join('/')}`, }, } as any } />
{/* Related Products Section */}
); }