diff --git a/src/components/layout/footer/FooterInfo.tsx b/src/components/layout/footer/FooterInfo.tsx
index 33cc8cc..6f5b81f 100644
--- a/src/components/layout/footer/FooterInfo.tsx
+++ b/src/components/layout/footer/FooterInfo.tsx
@@ -1,9 +1,11 @@
+'use client';
+
import { appConstants } from '@/assets/constants';
import images from '@/assets/images/images';
import { Icon, IconName } from '@/components/uikit/icons';
-import { t } from '@/locales/translates';
import Image from 'next/image';
import Link from 'next/link';
+import { useTranslations } from 'next-intl';
export default function FooterInfo({
withLogo,
@@ -12,6 +14,8 @@ export default function FooterInfo({
withLogo?: boolean;
className?: string;
}) {
+ const t = useTranslations();
+
return (
)}
-
{t('footer_slogan') as string}
+
{t('footer_slogan')}
{appConstants.socials.map((social) => (
void;
}
-const links = [routeFactory.home, routeFactory.about, routeFactory.contact];
-
export default function HamburgerMenu({ isOpen, onClose }: Props) {
const pathname = usePathname();
+ const params = useParams();
+ const locale = params.locale as string;
+ const t = useTranslations();
const menuRef = useRef
(null);
+ // Generate links dynamically with current locale and translations
+ const routes = routeFactory(t, locale);
+ const links = [routes.home, routes.about, routes.contact];
+
useEffect(() => {
function handleClickOutside(event: MouseEvent) {
if (menuRef.current && !menuRef.current.contains(event.target as Node)) {
@@ -50,7 +55,7 @@ export default function HamburgerMenu({ isOpen, onClose }: Props) {
className="relative z-10 flex h-full w-80 max-w-full flex-col bg-black p-5 text-white"
>
-
+
- {title as string}
+ {title}
);
})}
diff --git a/src/components/layout/header/index.tsx b/src/components/layout/header/index.tsx
index 56cb87f..2917b3d 100644
--- a/src/components/layout/header/index.tsx
+++ b/src/components/layout/header/index.tsx
@@ -1,15 +1,20 @@
+'use client';
+
import images from '@/assets/images/images';
import Navbar from '../navbar';
import Button, { IconButton } from '@/components/uikit/button';
-import { t } from '@/locales/translates';
import { Icon } from '@/components/uikit/icons';
+import { useTranslations } from 'next-intl';
export default function Header() {
+ const t = useTranslations();
+
const bannerFooter = [
- t('com_home_Banner_link1') as string,
- t('com_home_Banner_link2') as string,
- t('com_home_Banner_link3') as string,
+ t('com_home_Banner_link1'),
+ t('com_home_Banner_link2'),
+ t('com_home_Banner_link3'),
];
+
return (
@@ -45,14 +53,14 @@ export default function AboutTopInfo() {
- {t('com_about_info_description') as string}
+ {t('com_about_info_description')}
@@ -61,8 +69,8 @@ export default function AboutTopInfo() {
))}
-
diff --git a/src/components/pages/home/HomeStorySection.tsx b/src/components/pages/home/HomeStorySection.tsx
index 2c2ce69..aee83cb 100644
--- a/src/components/pages/home/HomeStorySection.tsx
+++ b/src/components/pages/home/HomeStorySection.tsx
@@ -1,24 +1,28 @@
+'use client';
+
import images from '@/assets/images/images';
import SectionTitle from '@/components/layout/sectionTitle';
-import { t } from '@/locales/translates';
import Image from 'next/image';
+import { useTranslations } from 'next-intl';
export default function HomeStorySection({
className = '',
}: {
className?: string;
}) {
+ const t = useTranslations();
+
const statisticsData = [
{
- title: t('com_home_story_projects_count') as string,
+ title: t('com_home_story_projects_count'),
count: '10K',
},
{
- title: t('com_home_story_customer_count') as string,
+ title: t('com_home_story_customer_count'),
count: '500',
},
{
- title: t('com_home_story_experience') as string,
+ title: t('com_home_story_experience'),
count: '25',
},
];
@@ -27,9 +31,9 @@ export default function HomeStorySection({
{[images.homeBanner, images.aboutImg_1].map((e, i) => (
@@ -53,7 +57,7 @@ export default function HomeStorySection({
- {t('com_home_story_description') as string}
+ {t('com_home_story_description')}
diff --git a/src/components/pages/home/Products.tsx b/src/components/pages/home/Products.tsx
index fed9350..9763939 100644
--- a/src/components/pages/home/Products.tsx
+++ b/src/components/pages/home/Products.tsx
@@ -1,14 +1,22 @@
import images from '@/assets/images/images';
import SectionTitle from '@/components/layout/sectionTitle';
-import { t } from '@/locales/translates';
import type { IProductCategoryCardProps } from '../productCategories/productCategoryCard.d';
import { getProductCategories } from '@/services/products';
import Link from 'next/link';
import routeFactory from '@/assets/constants/routeFactory';
+import { getTranslations } from 'next-intl/server';
+import { ILayoutLocaleParams } from '@/models/layout';
+import { TLocales } from '@/locales/translates';
-export default async function HomePageProducts() {
+interface Props {
+ locale: TLocales;
+}
+
+export default async function HomePageProducts({ locale }: Props) {
+ const t = await getTranslations({ locale });
const productCategories: IProductCategoryCardProps[] =
await getProductCategories();
+ const routes = routeFactory(t, locale);
return (
@@ -19,12 +27,12 @@ export default async function HomePageProducts() {
- {t('com_home_products_description') as string}
+ {t('com_home_products_description')}
@@ -32,16 +40,17 @@ export default async function HomePageProducts() {
{productCategories.map((category, index) => (
-
+
{category.title}
- {`Includes ${category.typesCount} Products`}
+ {t('com_products_category_types_count', {
+ count: category.typesCount,
+ })}
diff --git a/src/components/pages/productCategories/ProductCategoryCard.tsx b/src/components/pages/productCategories/ProductCategoryCard.tsx
index 1c304b8..31da85a 100644
--- a/src/components/pages/productCategories/ProductCategoryCard.tsx
+++ b/src/components/pages/productCategories/ProductCategoryCard.tsx
@@ -1,9 +1,12 @@
+'use client';
+
import { Icon } from '@/components/uikit/icons';
import type { IProductCategoryCardProps } from './productCategoryCard.d';
import AchievementTextBox from '@/components/layout/achievementTextBox';
-import { t } from '@/locales/translates';
import Button from '@/components/uikit/button';
import routeFactory from '@/assets/constants/routeFactory';
+import { useTranslations } from 'next-intl';
+import { useParams } from 'next/navigation';
export default function ProductsCategoryCard({
icon,
@@ -13,6 +16,11 @@ export default function ProductsCategoryCard({
bestForTitle,
id,
}: IProductCategoryCardProps) {
+ const t = useTranslations();
+ const params = useParams();
+ const locale = params.locale as string;
+ const routes = routeFactory(t, locale);
+
return (
@@ -22,22 +30,18 @@ export default function ProductsCategoryCard({
- {t('com_products_category_show_all_CTA') as string}
+ {t('com_products_category_show_all_CTA')}
diff --git a/src/components/pages/productCategories/ProductCategoryCardInProducts.tsx b/src/components/pages/productCategories/ProductCategoryCardInProducts.tsx
index ab25f98..ddacd78 100644
--- a/src/components/pages/productCategories/ProductCategoryCardInProducts.tsx
+++ b/src/components/pages/productCategories/ProductCategoryCardInProducts.tsx
@@ -1,7 +1,9 @@
+'use client';
+
import AchievementTextBox from '@/components/layout/achievementTextBox';
import type { IProductCategoryCardProps } from './productCategoryCard.d';
-import { t } from '@/locales/translates';
import { Icon } from '@/components/uikit/icons';
+import { useTranslations } from 'next-intl';
export default function ProductCategoryCardInProducts({
productCategory,
@@ -10,6 +12,8 @@ export default function ProductCategoryCardInProducts({
productCategory: IProductCategoryCardProps;
className?: string;
}) {
+ const t = useTranslations();
+
return (
- {
- t('com_products_products_category_title', {
- title: productCategory.title,
- }) as string
- }
+ {t('com_products_products_category_title', {
+ title: productCategory.title,
+ })}
{
+ // Typically corresponds to the `[locale]` segment
+ const requested = await requestLocale;
+ const locale = hasLocale(routing.locales, requested)
+ ? requested
+ : routing.defaultLocale;
+
+ return {
+ locale,
+ messages: (await import(`../../messages/${locale}.json`)).default,
+ };
+});
diff --git a/src/i18n/routing.ts b/src/i18n/routing.ts
new file mode 100644
index 0000000..afd6614
--- /dev/null
+++ b/src/i18n/routing.ts
@@ -0,0 +1,12 @@
+import { defineRouting } from 'next-intl/routing';
+
+export const routing = defineRouting({
+ locales: ['en', 'fa'],
+ defaultLocale: 'en',
+ pathnames: {
+ '/': '/',
+ '/pathnames': {
+ fa: '/pfadnamen',
+ },
+ },
+});
diff --git a/src/locales/translates.ts b/src/locales/translates.ts
index 6b0f35b..5fe47e4 100644
--- a/src/locales/translates.ts
+++ b/src/locales/translates.ts
@@ -58,7 +58,7 @@ export const translates = (
export const t = (
key: keyof Translates,
dynamicValue?: Record,
-) => translates(key, dynamicValue);
+) => '';
export type TLocales = 'en' | 'fa';
diff --git a/src/middleware.ts b/src/middleware.ts
new file mode 100644
index 0000000..f46db49
--- /dev/null
+++ b/src/middleware.ts
@@ -0,0 +1,8 @@
+import createMiddleware from 'next-intl/middleware';
+import { routing } from './i18n/routing';
+
+export default createMiddleware(routing);
+
+export const config = {
+ matcher: '/((?!api|trpc|_next|_vercel|.*\\..*).*)',
+};
diff --git a/src/models/layout.d.ts b/src/models/layout.d.ts
new file mode 100644
index 0000000..526e0c8
--- /dev/null
+++ b/src/models/layout.d.ts
@@ -0,0 +1,3 @@
+export interface ILayoutLocaleParams {
+ locale: TLocales;
+}