translate to en

This commit is contained in:
Batyr 2025-02-03 18:31:49 +05:00
parent 2db321a479
commit 78e95cab9c
19 changed files with 456 additions and 125 deletions

View File

@ -8,7 +8,9 @@ import {
} from "../ui/sheet";
import { Link } from "react-router-dom";
import { Button } from "../ui/button";
import { navData, navData2 } from "./header";
import { navData } from "@/data/header.data";
import { useTranslate } from "@/hooks/use-translate";
import { useLangStore } from "@/store/lang";
interface Props {
className?: string;
@ -16,6 +18,7 @@ interface Props {
export const Burger: FC<Props> = () => {
const [open, setOpen] = useState(false);
const lang = useLangStore((state) => state.lang);
return (
<Sheet onOpenChange={() => setOpen(!open)} open={open}>
@ -50,7 +53,7 @@ export const Burger: FC<Props> = () => {
<hr className="border-slate-500/20 my-8" />
<div className="flex flex-col gap-6">
{navData.concat(navData2).map((item) => (
{navData[useTranslate(lang)].data.map((item) => (
<Link
onClick={() => setOpen(false)}
className="h-10 text-on_surface"

View File

@ -1,8 +1,10 @@
import { FC } from "react";
import { Container } from "./";
import { Logo } from "../shared";
import { Language, useLangStore } from "@/store/lang";
export const Footer: FC = () => {
const lang = useLangStore((state) => state.lang);
return (
<footer className="py-5 bg-primary">
<Container className="flex flex-col gap-6">
@ -19,7 +21,9 @@ export const Footer: FC = () => {
<hr className="border-white/50" />
<h5 className="text-base text-center normal text-white">
©2025 Все права защищены
{lang === Language.RU
? "©2025 Все права защищены"
: "All rights reserved"}
</h5>
</Container>
</footer>

View File

@ -4,34 +4,13 @@ import { MapPin, Smartphone } from "lucide-react";
import { Link } from "react-router-dom";
import { Button } from "../ui/button";
import { Logo } from "../shared";
export const navData = [
{
title: "Медиа",
link: "",
},
{
title: "Контакты",
link: "/contacts",
},
];
export const navData2 = [
{
title: "О выставке",
link: "/about",
},
{
title: "Посетителям",
link: "",
},
{
title: "Экспонентам",
link: "",
},
];
import { useLangStore } from "@/store/lang";
import { navData } from "@/data/header.data";
import { useTranslate } from "@/hooks/use-translate";
export const Header: FC = () => {
const lang = useLangStore((state) => state.lang);
return (
<header>
<div className="h-12 hidden lg:flex bg-sur text-surface-bg items-center overflow-hidden">
@ -39,11 +18,17 @@ export const Header: FC = () => {
<div className="gap-8 flex items-center justify-between">
<div className="flex items-center gap-2">
<MapPin />
<h4 className="text-sm">Ашхабад, Туркменистан</h4>
<h4 className="text-sm">
{lang === "ru"
? "Ашхабад, Туркменистан"
: "Ashgabat, Turkmenistan"}
</h4>
</div>
<nav className="flex items-center gap-6">
{navData.map(({ title, link }) => (
{navData[useTranslate(lang)].data
.slice(0, 2)
.map(({ title, link }) => (
<Link className="py-2" key={title} to={link}>
{title}
</Link>
@ -70,8 +55,14 @@ export const Header: FC = () => {
</Link>
<nav className="lg:flex hidden items-center gap-6 text-white">
{navData2.map(({ title, link }) => (
<Link key={title} to={link} className="flex items-center gap-2">
{navData[useTranslate(lang)].data
.slice(2, 5)
.map(({ title, link }) => (
<Link
key={title}
to={link}
className="flex items-center gap-2"
>
{title} <img src="/chevron.svg" />
</Link>
))}
@ -93,7 +84,7 @@ export const Header: FC = () => {
size={"sm"}
className="bg-white text-primary hover:bg-white/90"
>
Официальная поддержка
{lang === "ru" ? "Официальная поддержка" : "Official Support"}
</Button>
</Link>
@ -103,7 +94,7 @@ export const Header: FC = () => {
size={"sm"}
className="bg-teritary text-white hover:bg-teritary/90"
>
Стать спонсором{" "}
{lang === "ru" ? "Стать спонсором" : "Become a sponsor"}
</Button>
</Link>
</div>

View File

@ -1,22 +1,25 @@
import { cn } from "@/lib/utils";
import { FC } from "react";
import { times } from "../home/home-time";
import { Container } from "@/components/layout";
import { TimeCard } from "../";
import { useTranslate } from "@/hooks/use-translate";
import { useLangStore } from "@/store/lang";
import { times } from "@/data/home-time.data";
interface Props {
className?: string;
}
export const AboutTime: FC<Props> = ({ className }) => {
const lang = useLangStore((state) => state.lang);
return (
<section
className={cn("bg-bg_surface_container py-10 md:py-[160px]", className)}
>
<Container>
<h3 className="h2 mb-6">Время выставки</h3>
<h2 className="h2 mb-6">{times[useTranslate(lang)].title}</h2>
<div className="flex flex-col md:flex-row items-center gap-6">
{times.map((item) => (
{times[useTranslate(lang)].data.map((item) => (
<TimeCard
bottomClassName="!bg-white rounded-b-[2px]"
{...item}

View File

@ -4,6 +4,9 @@ import { Link } from "react-router-dom";
import useEmblaCarousel from "embla-carousel-react";
import { Container } from "@/components/layout";
import { AboutCard } from "../about-card";
import { aboutData } from "@/data/home-about.data";
import { useTranslate } from "@/hooks/use-translate";
import { Language, useLangStore } from "@/store/lang";
const data = [
{
@ -26,13 +29,14 @@ const data = [
export const HomeAbout: FC = () => {
const [ebmblaRef] = useEmblaCarousel();
const lang = useLangStore((state) => state.lang);
return (
<section>
<Container className="flex flex-col gap-6">
<div className="text-center">
<h2 className="h2 md:mb-3 mb-6 text-left sm:text-center">
Выставка-ярмарка «TurkmenTextile Expo 2025» в Ашхабаде{" "}
Выставка-ярмарка «TurkmenTextile Expo 2025» в Ашхабаде
</h2>
<p className="md:text-base text-sm normal text-left sm:text-center text-[#454545]">
Глобальная выставка и ярмарка текстиля и моды, которая объединит
@ -46,7 +50,7 @@ export const HomeAbout: FC = () => {
<div ref={ebmblaRef} className="embla overflow-hidden">
<div className="flex embla__container items-center gap-6">
{data.map((item) => (
{aboutData[useTranslate(lang)].data.map((item) => (
<AboutCard
key={item.text}
{...item}
@ -56,7 +60,11 @@ export const HomeAbout: FC = () => {
</div>
</div>
<Link to="/about" className="mx-auto">
<Button variant={"outline"}>Подробнее о выставке</Button>
<Button variant={"outline"}>
{lang === Language.RU
? "Подробнее о выставке"
: "More about the exhibition"}
</Button>
</Link>
</Container>
</section>

View File

@ -4,29 +4,13 @@ import { Link } from "react-router-dom";
import { Button } from "@/components/ui/button";
import { Container } from "@/components/layout";
import { useMediaQuery } from "usehooks-ts";
export const btns = [
{
title: "План выставки",
link: "https://turkmentextile.turkmenexpo.com/app/storage/app/media/Floor%20plan/floor%20plan.pdf",
blank: true,
},
{
title: "Забронировать стенд",
link: "/stend-form",
},
{
title: "Список участников ",
link: "",
},
{
title: "B2B | B2G встречи",
link: "/B2B-B2G",
},
];
import { btns } from "@/data/home-hero.data";
import { useTranslate } from "@/hooks/use-translate";
import { useLangStore } from "@/store/lang";
export const HomeHero: FC = () => {
const [embalRef] = useEmblaCarousel();
const lang = useLangStore((state) => state.lang);
const lg = useMediaQuery("(min-width: 1024px)");
const md = useMediaQuery("(min-width: 768px)");
@ -52,7 +36,7 @@ export const HomeHero: FC = () => {
</div>
<Container className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 items-center gap-6 text-2xl">
{btns.map(({ title, link, blank }) => (
{btns[useTranslate(lang)].data.map(({ title, link, blank }) => (
<Link
target={blank ? "_blank" : ""}
key={title}

View File

@ -2,10 +2,14 @@ import { FC, useCallback, useEffect, useState } from "react";
import useEmblaCarousel from "embla-carousel-react";
import { Container } from "@/components/layout";
import { EmblaDots, OfferCard } from "../";
import { offersData } from "@/data/home-offers.data";
import { useTranslate } from "@/hooks/use-translate";
import { useLangStore } from "@/store/lang";
export const HomeOffers: FC = () => {
const [emblaRef, emblaApi] = useEmblaCarousel({ align: "start" });
const [activeIndex, setActiveIndex] = useState(0);
const lang = useLangStore((state) => state.lang);
const scrollTo = useCallback(
(index: number) => {
@ -34,22 +38,9 @@ export const HomeOffers: FC = () => {
<Container>
<div ref={emblaRef} className="embla ">
<div className="mb-2 flex gap-6 embla__container">
<OfferCard
btnText="Скачать путеводитель"
img="/offer-1.png"
className="embla__slide flex-[0_0_300px] md:flex-[0_0_600px]"
title="Гостиницы, трансфер, визы"
link="https://turkmentextile.turkmenexpo.com/app/storage/app/media/travel_guide/Travel_guide_ru.pdf"
text="По вопросам размещения в гостиницах, визовой поддержки, транспортного и экскурсионного обслуживания Вы можете ознакомиться с путеводителем"
/>
<OfferCard
btnText="Скачать план выставки"
link="https://turkmentextile.turkmenexpo.com/app/storage/app/media/Floor%20plan/floor%20plan.pdf"
img="/offer-2.png"
className="embla__slide flex-[0_0_300px] md:flex-[0_0_600px]"
title="Ознакомьтесь с планом выставки TurkmenTextile Expo 2025"
text="Как выбрать лучшее место на выставке? Вы всегда должны помнить, что удачное расположение выставочной экспозиции повышает Ваши шансы привлечь внимание Ваших потенциальных клиентов"
/>
{offersData[useTranslate(lang)].data.map((item) => (
<OfferCard {...item} key={item.title} />
))}
</div>
<EmblaDots

View File

@ -1,6 +1,9 @@
import { FC } from "react";
import { ThemeCard } from "../theme-card";
import { Container } from "@/components/layout";
import { useLangStore } from "@/store/lang";
import { homeTheme } from "@/data/home-theme.data";
import { useTranslate } from "@/hooks/use-translate";
export const themes = [
{
@ -38,15 +41,16 @@ export const themes = [
];
export const HomeTheme: FC = () => {
const lang = useLangStore((state) => state.lang);
return (
<section className="">
<Container>
<h2 className="h2 mb-10 text-center">
Тематические направления выставки
{homeTheme[useTranslate(lang)].title}
</h2>
<div className="grid md:grid-cols-4 grid-cols-2 gap-6">
{themes.map((item) => (
{homeTheme[useTranslate(lang)].data.map((item) => (
<ThemeCard
key={item.title}
{...item}

View File

@ -4,65 +4,40 @@ import { Button } from "@/components/ui/button";
import { Link } from "react-router-dom";
import { Container } from "@/components/layout";
import { ContactCard, TimeCard } from "../";
import { useTranslate } from "@/hooks/use-translate";
import { Language, useLangStore } from "@/store/lang";
import { times } from "@/data/home-time.data";
import { contacts } from "@/data/contacts.data";
interface Props {
className?: string;
}
export const times = [
{
name: "Монтаж выставки",
date: "12 мая 10 июня 2025 года",
},
{
name: "Работа",
date: "1113 июня 2025 года",
},
{
name: "Демонтаж",
date: "1314 июня 2025 года",
},
];
const contacts = [
{
title: "contact@turkmenexpo.com",
subtitle: "Адрес электронной почты",
img: "/contacts/home/mail.svg",
},
{
title: "здание ТПП Туркменистана",
subtitle: "Адрес выставки",
img: "/contacts/home/location.svg",
},
{
title: "+99371871812; 99363719588",
subtitle: "Контактный номер",
img: "/contacts/home/mobile.svg",
},
];
export const HomeTime: FC<Props> = ({ className }) => {
const lang = useLangStore((state) => state.lang);
return (
<section className={cn("bg-surface_high pt-10 pb-20", className)}>
<Container>
<h2 className="h2 mb-10">Время выставки</h2>
<h2 className="h2 mb-6">{times[useTranslate(lang)].title}</h2>
<div className="flex flex-col gap-6">
<div className="flex flex-col md:flex-row items-center gap-6">
{times.map((item) => (
{times[useTranslate(lang)].data.map((item) => (
<TimeCard {...item} key={item.name} className="w-full" />
))}
</div>
<div className="md:p-10 pt-16 flex flex-col md:flex-row items-center gap-6">
{contacts.map((item) => (
{contacts[useTranslate(lang)].data.map((item) => (
<ContactCard {...item} key={item.title} className="w-full" />
))}
</div>
<Link to="/stend-form" className="md:w-fit w-full mx-auto">
<Button className="w-full">Забронируйте стенд </Button>
<Button className="w-full">
{lang === Language.RU ? "Забронируйте стенд" : "Book a stand"}
</Button>
</Link>
</div>
</Container>

41
src/data/contacts.data.ts Normal file
View File

@ -0,0 +1,41 @@
export const contacts = [
{
data: [
{
title: "contact@turkmenexpo.com",
subtitle: "Адрес электронной почты",
img: "/contacts/home/mail.svg",
},
{
title: "здание ТПП Туркменистана",
subtitle: "Адрес выставки",
img: "/contacts/home/location.svg",
},
{
title: "+99371871812; 99363719588",
subtitle: "Контактный номер",
img: "/contacts/home/mobile.svg",
},
],
},
{
data: [
{
title: "contact@turkmenexpo.com",
subtitle: "E-mail Address",
img: "/contacts/home/mail.svg",
},
{
title: "здание ТПП Туркменистана",
subtitle: "Exhibition address",
img: "/contacts/home/location.svg",
},
{
title: "+99371871812; 99363719588",
subtitle: "Contact Number",
img: "/contacts/home/mobile.svg",
},
],
},
];

55
src/data/header.data.ts Normal file
View File

@ -0,0 +1,55 @@
import { Language } from "@/store/lang";
export const navData = [
{
lang: Language.RU,
data: [
{
title: "Медиа",
link: "",
},
{
title: "Контакты",
link: "/contacts",
},
{
title: "О выставке",
link: "/about",
},
{
title: "Посетителям",
link: "",
},
{
title: "Экспонентам",
link: "",
},
],
},
{
lang: Language.EN,
data: [
{
title: "Media",
link: "",
},
{
title: "Contacts",
link: "/contacts",
},
{
title: "About exhibition",
link: "/about",
},
{
title: "To the Visitors",
link: "",
},
{
title: "To the Exhibitors",
link: "",
},
],
},
];

View File

@ -0,0 +1,43 @@
export const aboutData = [
{
data: [
{
nums: "8,400 m²",
text: "выставочной площади",
},
{
nums: "10000+",
text: "Посетители посетят выставку",
},
{
nums: "100+",
text: "Экспоненты из более чем 30 стран",
},
{
nums: "80%",
text: "Участники принимают участие в принятии решений о закупках",
},
],
},
{
data: [
{
nums: "8,400 m²",
text: "Of the exhibition area",
},
{
nums: "10000+",
text: "Visitors and specialists attend the exhibition",
},
{
nums: "100+",
text: "More than 100 exhibitors from 30 countries ",
},
{
nums: "80%",
text: "Visitors are involved in procurement decisions",
},
],
},
];

View File

@ -0,0 +1,49 @@
import { Language } from "@/store/lang";
export const btns = [
{
lang: Language.RU,
data: [
{
title: "План выставки",
link: "https://turkmentextile.turkmenexpo.com/app/storage/app/media/Floor%20plan/floor%20plan.pdf",
blank: true,
},
{
title: "Забронировать стенд",
link: "/stend-form",
},
{
title: "Список участников",
link: "",
},
{
title: "B2B | B2G встречи",
link: "/B2B-B2G",
},
],
},
{
lang: Language.EN,
data: [
{
title: "Floor Plan",
link: "https://itse.turkmenexpo.com/app/storage/app/media/Floor%20plan/Floor%20plan.pdf",
blank: true,
},
{
title: "Book a stand",
link: "/stend-form",
},
{
title: "Participants list",
link: "/",
},
{
title: "B2B | B2G meetings",
link: "/B2B-B2G",
},
],
},
];

View File

@ -0,0 +1,41 @@
export const offersData = [
{
data: [
{
img: "/offer-1.png",
title: "Гостиницы, трансфер, визы",
btnText: "Скачать путеводитель",
text: "По вопросам размещения в гостиницах, визовой поддержки, транспортного и экскурсионного обслуживания Вы можете ознакомиться с путеводителем",
link: "https://turkmentextile.turkmenexpo.com/app/storage/app/media/travel_guide/Travel_guide_ru.pdf",
},
{
img: "/offer-2.png",
title: "Ознакомьтесь с планом выставки TurkmenTextile Expo 2025",
btnText: "Скачать план выставки",
text: `Как выбрать лучшее место на выставке? Вы всегда должны помнить, что удачное расположение выставочной экспозиции повышает Ваши шансы привлечь внимание Ваших потенциальных клиентов`,
link: "https://turkmentextile.turkmenexpo.com/app/storage/app/media/Floor%20plan/floor%20plan.pdf",
},
],
},
{
data: [
{
img: "/offer-2.png",
title: "Hotels, transfers, visa",
btnText: "Download the Travel guide",
text: `Regarding hotel accommodation, visa support,
transportation and excursion services you can check out the Travel guide`,
link: "https://turkmentextile.turkmenexpo.com/app/storage/app/media/travel_guide/Travel_guide_ru.pdf",
},
{
img: "/offer-2.png",
title: "Check out the Turkmen Textile 2025 Exhibition plan ",
btnText: "Download the Floor plan",
text: `How to choose the best place in the exhibition?
You should always remember that the good location of the exhibition increases your chance to attract the attention of your potential customers`,
link: "https://turkmentextile.turkmenexpo.com/app/storage/app/media/Floor%20plan/floor%20plan.pdf",
},
],
},
];

View File

@ -0,0 +1,79 @@
export const homeTheme = [
{
h1: "Тематические направления выставки",
data: [
{
title: "Пищевая продукция и сельское хозяйство",
img: "/theme/1.svg",
},
{
title: "Товары и услуги",
img: "/theme/2.svg",
},
{
title: "E-commerce",
img: "/theme/3.svg",
},
{
title: "Волокна, текстиль и одежда",
img: "/theme/4.svg",
},
{
title: "Продукция промышленного производства",
img: "/theme/5.svg",
},
{
title: "Профессиональные услуги",
img: "/theme/6.svg",
},
{
title: "Ремесленные производства",
img: "/theme/7.svg",
},
{
title: "Креативные индустрии",
img: "/theme/8.svg",
},
],
},
{
title: "Thematic areas of the exhibition",
data: [
{
title: "Пищевая продукция и сельское хозяйство",
img: "/theme/1.svg",
},
{
title: "Товары и услуги",
img: "/theme/2.svg",
},
{
title: "E-commerce",
img: "/theme/3.svg",
},
{
title: "Волокна, текстиль и одежда",
img: "/theme/4.svg",
},
{
title: "Продукция промышленного производства",
img: "/theme/5.svg",
},
{
title: "Профессиональные услуги",
img: "/theme/6.svg",
},
{
title: "Ремесленные производства",
img: "/theme/7.svg",
},
{
title: "Креативные индустрии",
img: "/theme/8.svg",
},
],
},
];

View File

@ -0,0 +1,37 @@
export const times = [
{
title: "Время выставки",
data: [
{
name: "Монтаж выставки",
date: "12 мая 10 июня 2025 года",
},
{
name: "Работа",
date: "1113 июня 2025 года",
},
{
name: "Демонтаж",
date: "1314 июня 2025 года",
},
],
},
{
title: "Exhibition time",
data: [
{
name: "Exhibition assembly",
date: "1 — 27 april 2025",
},
{
name: "Exhibition days",
date: "29 — 1 may 2025",
},
{
name: "Exhibition dismantling",
date: "1 — 2 may 2025",
},
],
},
];

View File

@ -0,0 +1,5 @@
import { Language } from "@/store/lang";
export const useTranslate = (lang: Language): number => {
return lang === Language.RU ? 0 : 1;
};

View File

@ -8,13 +8,15 @@ import {
} from "@/components/shared";
import { useScrollTop } from "@/hooks/use-scroll-top";
import { cn } from "@/lib/utils";
import { Language, useLangStore } from "@/store/lang";
export default function About() {
useScrollTop();
const lang = useLangStore((state) => state.lang);
return (
<div className={cn("")}>
<Cover title="О выставке" />
<Cover title={lang === Language.RU ? "О выставке" : "About exhibition"} />
<AboutInfo />
<AboutThemes />

16
src/store/lang.ts Normal file
View File

@ -0,0 +1,16 @@
import { create } from "zustand";
export enum Language {
EN = "en",
RU = "ru",
}
export interface LangState {
lang: Language;
setLang: (lang: Language) => void;
}
export const useLangStore = create<LangState>()((set) => ({
lang: Language.EN,
setLang: (lang) => set({ lang }),
}));