101 lines
2.8 KiB
TypeScript
101 lines
2.8 KiB
TypeScript
import {NextIntlClientProvider} from 'next-intl';
|
|
import {getMessages, getTranslations} from 'next-intl/server';
|
|
import '../../styles/globals.css';
|
|
import Header from '@/components/Header';
|
|
import Footer from '@/components/Footer';
|
|
import UmamiScript from '@/components/analytics/UmamiScript';
|
|
import AnalyticsProvider from '@/components/analytics/AnalyticsProvider';
|
|
import { Metadata, Viewport } from 'next';
|
|
import JsonLd from '@/components/JsonLd';
|
|
import { getOrganizationSchema, SITE_URL } from '@/lib/schema';
|
|
|
|
export async function generateMetadata({params: {locale}}: {params: {locale: string}}): Promise<Metadata> {
|
|
const t = await getTranslations({locale, namespace: 'Index.meta'});
|
|
|
|
return {
|
|
title: {
|
|
default: t('title'),
|
|
template: `%s | KLZ Cables`
|
|
},
|
|
description: t('description'),
|
|
metadataBase: new URL('https://klz-cables.com'),
|
|
icons: {
|
|
icon: '/favicon.ico',
|
|
apple: '/apple-touch-icon.png',
|
|
},
|
|
alternates: {
|
|
canonical: `/${locale}`,
|
|
languages: {
|
|
'de': '/de',
|
|
'en': '/en',
|
|
'x-default': '/en',
|
|
},
|
|
},
|
|
openGraph: {
|
|
type: 'website',
|
|
locale: locale === 'de' ? 'de_DE' : 'en_US',
|
|
url: `https://klz-cables.com/${locale}`,
|
|
siteName: 'KLZ Cables',
|
|
title: t('title'),
|
|
description: t('description'),
|
|
},
|
|
twitter: {
|
|
card: 'summary_large_image',
|
|
title: t('title'),
|
|
description: t('description'),
|
|
},
|
|
robots: {
|
|
index: true,
|
|
follow: true,
|
|
googleBot: {
|
|
index: true,
|
|
follow: true,
|
|
'max-video-preview': -1,
|
|
'max-image-preview': 'large',
|
|
'max-snippet': -1,
|
|
},
|
|
},
|
|
};
|
|
}
|
|
|
|
export const viewport: Viewport = {
|
|
width: 'device-width',
|
|
initialScale: 1,
|
|
maximumScale: 1,
|
|
userScalable: false,
|
|
viewportFit: 'cover',
|
|
themeColor: '#001a4d',
|
|
};
|
|
|
|
export default async function LocaleLayout({
|
|
children,
|
|
params: {locale}
|
|
}: {
|
|
children: React.ReactNode;
|
|
params: {locale: string};
|
|
}) {
|
|
// Providing all messages to the client
|
|
// side is the easiest way to get started
|
|
const messages = await getMessages();
|
|
|
|
return (
|
|
<html lang={locale} className="scroll-smooth overflow-x-hidden">
|
|
<body className="flex flex-col min-h-screen font-sans selection:bg-accent selection:text-primary-dark antialiased overflow-x-hidden">
|
|
<NextIntlClientProvider messages={messages} locale={locale}>
|
|
{/* Loads Umami only when NEXT_PUBLIC_UMAMI_WEBSITE_ID is set */}
|
|
<UmamiScript />
|
|
|
|
<Header />
|
|
<main className="flex-grow animate-fade-in overflow-visible">
|
|
{children}
|
|
</main>
|
|
<Footer />
|
|
|
|
{/* Sends pageviews for client-side navigations */}
|
|
<AnalyticsProvider />
|
|
</NextIntlClientProvider>
|
|
</body>
|
|
</html>
|
|
);
|
|
}
|