Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
57 lines
2.7 KiB
TypeScript
57 lines
2.7 KiB
TypeScript
import '@barev/ui/styles.css';
|
|
import '../landing.css';
|
|
import { createT, isLocale, LOCALES, type Locale } from '@barev/i18n';
|
|
import type { Metadata, Viewport } from 'next';
|
|
import { Noto_Sans_Armenian, Onest, Rubik } from 'next/font/google';
|
|
import { notFound } from 'next/navigation';
|
|
import type { ReactNode } from 'react';
|
|
|
|
const rubik = Rubik({ subsets: ['latin', 'cyrillic'], weight: ['400', '500', '700', '800'], style: ['normal', 'italic'], variable: '--font-rubik', display: 'swap' });
|
|
const onest = Onest({ subsets: ['latin', 'cyrillic'], weight: ['400', '500', '600'], variable: '--font-onest', display: 'swap' });
|
|
const armenian = Noto_Sans_Armenian({ subsets: ['armenian'], weight: ['400', '600', '700'], variable: '--font-armenian', display: 'swap', preload: false });
|
|
|
|
const SITE = process.env.LANDING_URL ?? 'http://localhost:3000';
|
|
|
|
export function generateStaticParams() {
|
|
return LOCALES.map((locale) => ({ locale }));
|
|
}
|
|
|
|
export const viewport: Viewport = { themeColor: '#FBF6EE', width: 'device-width', initialScale: 1 };
|
|
|
|
/** LND-4: SEO-мета на каждом языке и hreflang */
|
|
export async function generateMetadata({ params }: { params: Promise<{ locale: string }> }): Promise<Metadata> {
|
|
const { locale } = await params;
|
|
if (!isLocale(locale)) return {};
|
|
const t = createT(locale);
|
|
// по умолчанию — заголовок и описание главной (страницы задают свои)
|
|
const title = t('landing.home.metaTitle');
|
|
const description = t('landing.home.metaDescription');
|
|
return {
|
|
metadataBase: new URL(SITE),
|
|
title,
|
|
description,
|
|
alternates: {
|
|
canonical: `/${locale}`,
|
|
languages: Object.fromEntries([...LOCALES.map((l) => [l, `/${l}`]), ['x-default', '/ru']]),
|
|
},
|
|
openGraph: { title, description, locale, type: 'website', siteName: 'Barev Club' },
|
|
twitter: { card: 'summary_large_image' },
|
|
// подтверждение прав в Search Console, Яндекс Вебмастере и Bing — коды из .env (можно и через DNS)
|
|
verification: {
|
|
google: process.env.GOOGLE_SITE_VERIFICATION || undefined,
|
|
yandex: process.env.YANDEX_VERIFICATION || undefined,
|
|
other: process.env.BING_SITE_VERIFICATION ? { 'msvalidate.01': process.env.BING_SITE_VERIFICATION } : undefined,
|
|
},
|
|
};
|
|
}
|
|
|
|
export default async function LocaleLayout({ children, params }: { children: ReactNode; params: Promise<{ locale: string }> }) {
|
|
const { locale } = await params;
|
|
if (!isLocale(locale)) notFound();
|
|
return (
|
|
<html lang={locale as Locale} className={`${rubik.variable} ${onest.variable} ${armenian.variable}`}>
|
|
<body>{children}</body>
|
|
</html>
|
|
);
|
|
}
|