feat(i18n): add internationalization support with i18next

- Add i18next and related dependencies for translation support
- Create locale files for English and Farsi languages
- Implement i18n configuration and provider in layout
- Set up route factory and constants for internationalized routes
- Remove test button components and simplify main page
This commit is contained in:
2025-05-31 16:41:12 +03:30
parent b8c3ebcee3
commit cb77aef586
15 changed files with 270 additions and 59 deletions
+17
View File
@@ -0,0 +1,17 @@
// ... existing imports ...
async function getData() {
// Simulate a delay to show server-side data fetching
await new Promise((resolve) => setTimeout(resolve, 1000));
return { message: 'This data was fetched on the server!' };
}
export default async function Home() {
const data = await getData();
return (
<main className="flex min-h-screen flex-col items-center justify-between p-24 text-gray-300">
ssss
</main>
);
}
+7 -17
View File
@@ -1,16 +1,8 @@
import type { Metadata } from 'next';
import { Geist, Geist_Mono } from 'next/font/google';
import './globals.css';
const geistSans = Geist({
variable: '--font-geist-sans',
subsets: ['latin'],
});
const geistMono = Geist_Mono({
variable: '--font-geist-mono',
subsets: ['latin'],
});
import { I18nextProvider } from 'react-i18next';
import i18n from '../config/i18n';
export const metadata: Metadata = {
title: 'Create Next App',
@@ -19,16 +11,14 @@ export const metadata: Metadata = {
export default function RootLayout({
children,
}: Readonly<{
}: {
children: React.ReactNode;
}>) {
}) {
return (
<html lang="en">
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
{children}
</body>
<I18nextProvider i18n={i18n}>
<body>{children}</body>
</I18nextProvider>
</html>
);
}
+1 -39
View File
@@ -1,5 +1,4 @@
// ... existing imports ...
import Button from '../components/Button'; // Adjust the import path if necessary
async function getData() {
// Simulate a delay to show server-side data fetching
@@ -12,44 +11,7 @@ export default async function Home() {
return (
<main className="flex min-h-screen flex-col items-center justify-between p-24 text-gray-300">
<div className="z-10 w-full max-w-5xl items-center justify-between font-mono text-sm lg:flex">
<p className="fixed left-0 top-0 flex w-full justify-center border-b border-gray-300 bg-gradient-to-b from-zinc-200 pb-6 pt-8 backdrop-blur-2xl dark:border-neutral-800 dark:bg-zinc-800/30 dark:from-inherit lg:static lg:w-auto lg:rounded-xl lg:border lg:bg-gray-200 lg:p-4 lg:dark:bg-zinc-800/30">
{data.message}
</p>
</div>
<div className="mt-8 flex gap-4">
<Button>Default Button</Button>
<Button disabled>Disabled Button</Button>
<Button loading>Loading Button</Button>
<Button endIcon={<span></span>}>Button with Icon</Button>
</div>
<div className="mt-8 flex flex-col gap-4">
<h3>Standard Buttons:</h3>
<div className="flex gap-4">
<Button>Default Button</Button>
<Button disabled>Disabled Button</Button>
<Button loading>Loading Button</Button>
<Button endIcon={<span></span>}>Button with Icon</Button>
</div>
<h3>Sized Buttons:</h3>
<div className="flex gap-4 items-center">
<Button size="small">Small Button</Button>
<Button size="medium">Medium Button</Button>
<Button size="large">Large Button</Button>
</div>
<h3>Icon Buttons:</h3>
<div className="flex gap-4 items-center">
<Button iconOnly endIcon={<span></span>} size="small" />
<Button iconOnly endIcon={<span></span>} size="medium" />
<Button iconOnly endIcon={<span></span>} size="large" />
<Button iconOnly endIcon={<span></span>} disabled size="medium" />
<Button iconOnly endIcon={<span></span>} loading size="medium" />
</div>
</div>
ssss
</main>
);
}
+17
View File
@@ -0,0 +1,17 @@
// ... existing imports ...
async function getData() {
// Simulate a delay to show server-side data fetching
await new Promise((resolve) => setTimeout(resolve, 1000));
return { message: 'This data was fetched on the server!' };
}
export default async function Home() {
const data = await getData();
return (
<main className="flex min-h-screen flex-col items-center justify-between p-24 text-gray-300">
ssss
</main>
);
}
+17
View File
@@ -0,0 +1,17 @@
// ... existing imports ...
async function getData() {
// Simulate a delay to show server-side data fetching
await new Promise((resolve) => setTimeout(resolve, 1000));
return { message: 'This data was fetched on the server!' };
}
export default async function Home() {
const data = await getData();
return (
<main className="flex min-h-screen flex-col items-center justify-between p-24 text-gray-300">
ssss
</main>
);
}
+5
View File
@@ -0,0 +1,5 @@
import { quickLinks } from './quickLinks.const';
export const footerMenu = {
quickLinks,
};
@@ -0,0 +1,7 @@
import { appConstants } from '..';
export const quickLinks = [
{
title: appConstants.routeFactory.home.title,
},
] as any[];
+7
View File
@@ -0,0 +1,7 @@
import { footerMenu } from './footerMenu';
import routeFactory from './routeFactory';
export const appConstants = {
routeFactory,
footerMenu,
};
@@ -0,0 +1,13 @@
import { useTranslation } from 'react-i18next';
const { t } = useTranslation('routes');
export default {
home: {
title: t('home'),
route: () => '/',
},
about: {
title: t('about'),
route: () => '/about',
},
};
+19
View File
@@ -0,0 +1,19 @@
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import Backend from 'i18next-http-backend';
i18n
.use(Backend)
.use(initReactI18next)
.init({
fallbackLng: 'en',
debug: false,
interpolation: {
escapeValue: false,
},
backend: {
loadPath: '/locales/{{lng}}/{{ns}}.json',
}
});
export default i18n;