Import source: src/app/[locale]/layout
Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality.
This commit is contained in:
@@ -0,0 +1,83 @@
|
|||||||
|
import { NextIntlClientProvider } from 'next-intl';
|
||||||
|
import { getMessages, getTranslations } from 'next-intl/server';
|
||||||
|
import { Inter, Vazirmatn } from 'next/font/google';
|
||||||
|
import { routing } from '@/i18n/routing';
|
||||||
|
import { notFound } from 'next/navigation';
|
||||||
|
import '@/app/globals.css';
|
||||||
|
|
||||||
|
const inter = Inter({
|
||||||
|
subsets: ['latin'],
|
||||||
|
variable: '--font-sans',
|
||||||
|
});
|
||||||
|
|
||||||
|
const vazirmatn = Vazirmatn({
|
||||||
|
subsets: ['arabic'],
|
||||||
|
variable: '--font-farsi',
|
||||||
|
});
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
children: React.ReactNode;
|
||||||
|
params: Promise<{ locale?: string }>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function generateMetadata({ params }: { params: Promise<{ locale?: string }> }) {
|
||||||
|
const { locale = 'en' } = await params;
|
||||||
|
const t = await getTranslations({ locale, namespace: 'Metadata' });
|
||||||
|
return {
|
||||||
|
title: t('title'),
|
||||||
|
description: t('description'),
|
||||||
|
alternates: {
|
||||||
|
canonical: locale === 'en' ? 'https://arsamsabbagh.ir/' : 'https://arsamsabbagh.ir/fa',
|
||||||
|
languages: {
|
||||||
|
en: 'https://arsamsabbagh.ir/',
|
||||||
|
fa: 'https://arsamsabbagh.ir/fa',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function LocaleLayout({ children, params }: Props) {
|
||||||
|
const { locale = 'en' } = await params;
|
||||||
|
|
||||||
|
|
||||||
|
// Validate that the incoming `locale` parameter is valid
|
||||||
|
if (!routing.locales.includes(locale as any)) {
|
||||||
|
notFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get messages for the locale
|
||||||
|
const messages = await getMessages();
|
||||||
|
|
||||||
|
const direction = locale === 'fa' ? 'rtl' : 'ltr';
|
||||||
|
|
||||||
|
// Inline script to prevent theme flash
|
||||||
|
const themeScript = `
|
||||||
|
(function() {
|
||||||
|
try {
|
||||||
|
var theme = localStorage.getItem('theme');
|
||||||
|
if (theme === 'dark' || (!theme && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
||||||
|
document.documentElement.classList.add('dark');
|
||||||
|
} else {
|
||||||
|
document.documentElement.classList.remove('dark');
|
||||||
|
}
|
||||||
|
} catch (e) {}
|
||||||
|
})();
|
||||||
|
`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<html
|
||||||
|
lang={locale}
|
||||||
|
dir={direction}
|
||||||
|
className={`${inter.variable} ${vazirmatn.variable} scroll-smooth`}
|
||||||
|
>
|
||||||
|
<head>
|
||||||
|
<script dangerouslySetInnerHTML={{ __html: themeScript }} />
|
||||||
|
</head>
|
||||||
|
<body className="bg-warm-white dark:bg-near-black text-charcoal dark:text-warm-white/90 antialiased transition-colors duration-300 font-sans">
|
||||||
|
<NextIntlClientProvider messages={messages}>
|
||||||
|
{children}
|
||||||
|
</NextIntlClientProvider>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user