From da389cc3370c45fa805becdbf11ea73e3a8ded23 Mon Sep 17 00:00:00 2001 From: maximus <ten.maksim97@gmail.com> Date: Fri, 14 Oct 2022 14:12:24 +0300 Subject: [PATCH] added localiazation --- public/locales/ru/translation.json | 43 ++++++++++++++++++- src/components/Cards/CategoryCard.tsx | 7 +-- .../sections/FeaturedArticlesCards.tsx | 4 +- .../sections/FeaturedArticlesCategories.tsx | 21 +++++---- .../sections/FeaturedAuthorsCards.tsx | 13 +++--- .../MainPage/sections/MainSection.tsx | 18 +++++--- src/components/SearchResultsSection.tsx | 8 ++-- src/components/parts/Footer.tsx | 28 ++++++------ src/components/search/SearchBar.tsx | 4 ++ src/core/helpers.ts | 4 ++ src/pages/MainPage.tsx | 1 - src/pages/SearchResultsPage.tsx | 2 +- 12 files changed, 109 insertions(+), 44 deletions(-) diff --git a/public/locales/ru/translation.json b/public/locales/ru/translation.json index e474311..961208e 100755 --- a/public/locales/ru/translation.json +++ b/public/locales/ru/translation.json @@ -83,5 +83,46 @@ "signIn": "Вход", "signUp": "Регистрация" } + }, + "footer": { + "accountSettings": "Настройки аккаунта", + "about": "О scipaper", + "help": "Помощь", + "contactUs": "Контакты", + "allRightsReserved": "Все права защищены", + "termsOfUse": "Правила использования", + "privacyPolicy": "Политика конфиденциальности", + "coockiesPolicy": "Политика использования coockies", + "supportedBy": "Создано" + }, + "mainPage": { + "title": "Библиотека научных статей с бесплатным доступом", + "search": "Поиск", + "article_one": "статьи", + "article_few": "статей", + "article_many": "статей", + "advancedSearch": "Расширенный поиск", + "featuredArticles": { + "title": "Популярные статьи", + "descriptionPart1": "Выберете интересующую вас ", + "descriptionPart2": "научную категорию", + "categories": { + "Medical": "Медицина", + "TechnicsAndTechlonogies": "Техника и технологии", + "Fundamental": "Естественые", + "Humanitarian": "Гуманитарные", + "Agricultural": "Аuрокультурa", + "Social": "Социальные" + } + }, + "featuredAuthors": "Популярные авторы", + "more": "Больше", + "showAll": "Показать все" + }, + "searchResults": { + "title": "Результаты поиска", + "totalResults":"Всего найдено", + "nothingFound": "Ничего не найдено" } -} \ No newline at end of file + +} diff --git a/src/components/Cards/CategoryCard.tsx b/src/components/Cards/CategoryCard.tsx index 0edeca8..172e9e9 100755 --- a/src/components/Cards/CategoryCard.tsx +++ b/src/components/Cards/CategoryCard.tsx @@ -3,7 +3,7 @@ import { SVGMedicine } from "../icons"; import Typography from "components/typography/Typography"; import { Button } from "components/Button/Button"; import classNames from "classnames"; -import { JsxElement } from "typescript"; +import { useTranslation } from "react-i18next"; type Props = { count?: number; @@ -13,6 +13,7 @@ type Props = { } & Omit<React.ComponentPropsWithoutRef<"div">, "">; function CategoryCard({ count, title, iconChild, className, ...props }: Props) { + const [t, i18next] = useTranslation() const iconChildStyle = "h-7 fill-gray-500 stroke-gray-500 group-focus:fill-blue-600 group-active:fill-blue-600 group-focus:stroke-blue-600 group-active:stroke-blue-600"; @@ -34,7 +35,7 @@ function CategoryCard({ count, title, iconChild, className, ...props }: Props) { fontWeightVariant="bold" className="text-sm leading-6 min-w-max group-active:text-blue-600 group-focus:text-blue-600" > - {title} + {t(title)} </Typography> </div> <div className="max-w-max "> @@ -42,7 +43,7 @@ function CategoryCard({ count, title, iconChild, className, ...props }: Props) { fontWeightVariant="normal" className="text-xs text-gray-500 group-active:text-blue-600 group-focus:text-blue-600" > - {count} Items + {count} {t("mainPage.article", {count: count}).toString()} </Typography> </div> </div> diff --git a/src/components/MainPage/sections/FeaturedArticlesCards.tsx b/src/components/MainPage/sections/FeaturedArticlesCards.tsx index 890add1..bfb2a07 100755 --- a/src/components/MainPage/sections/FeaturedArticlesCards.tsx +++ b/src/components/MainPage/sections/FeaturedArticlesCards.tsx @@ -31,6 +31,7 @@ import "swiper/css/pagination"; import "swiper/css/navigation"; // import "./styles.css"; import "swiper/css"; +import { useTranslation } from "react-i18next"; /* -------------------------------------------------------------------------- */ /* Article mock data */ /* -------------------------------------------------------------------------- */ @@ -97,6 +98,7 @@ const FeaturedArticlesCards = () => { const navigationPrevRef = useRef(null); const navigationNextRef = useRef(null); const paginationRef = useRef(null); + const [t, i18next] = useTranslation() return ( <div className="slider-wrapper articles"> @@ -168,7 +170,7 @@ const FeaturedArticlesCards = () => { <Card.CardAction href={Articale.Link}> <Link to="*"> <Typography className="text-blue-500 font-bold"> - Read More + {t("mainPage.more")} </Typography> </Link> <SVGCaretRight className="fill-blue-500 w-4 h-4" /> diff --git a/src/components/MainPage/sections/FeaturedArticlesCategories.tsx b/src/components/MainPage/sections/FeaturedArticlesCategories.tsx index 21dafc0..30e0758 100755 --- a/src/components/MainPage/sections/FeaturedArticlesCategories.tsx +++ b/src/components/MainPage/sections/FeaturedArticlesCategories.tsx @@ -9,22 +9,25 @@ import { SVGTechnicsAndTechology, SVGFundamental, } from "components/icons"; +import { useTranslation} from "react-i18next"; const categories = [ - { id: 1, title: "Medical", count: 5617813, icon: <SVGMedicine /> }, + { id: 1, title: "mainPage.featuredArticles.categories.Medical", count: 5617813, icon: <SVGMedicine /> }, { id: 2, - title: "Technics and Technology", + title: "mainPage.featuredArticles.categories.TechnicsAndTechlonogies", count: 5617813, icon: <SVGTechnicsAndTechology />, }, - { id: 3, title: "Fundamental", count: 5617813, icon: <SVGFundamental /> }, - { id: 4, title: "Humanitarian", count: 5617813, icon: <SVGHumanitarian /> }, - { id: 5, title: "Agricultural", count: 5617813, icon: <SVGAgricultural /> }, - { id: 6, title: "Social", count: 5617813, icon: <SVGSocials /> }, + { id: 3, title: "mainPage.featuredArticles.categories.Fundamental", count: 5617813, icon: <SVGFundamental /> }, + { id: 4, title: "mainPage.featuredArticles.categories.Humanitarian", count: 5617813, icon: <SVGHumanitarian /> }, + { id: 5, title: "mainPage.featuredArticles.categories.Agricultural", count: 5617813, icon: <SVGAgricultural /> }, + { id: 6, title: "mainPage.featuredArticles.categories.Social", count: 5617813, icon: <SVGSocials /> }, ]; export function FeaturedArticlesCategories() { + const [t, i18next] = useTranslation(); + const categoryCards = useMemo( () => categories.map((category) => ( @@ -45,11 +48,11 @@ export function FeaturedArticlesCategories() { fontWeightVariant="semibold" className="text-3xl mb-2" > - Featured articles + {t("mainPage.featuredArticles.title")} </Typography> <Typography htmlTag="h2" className="text-base text-gray-500"> - Select the category of science <br className="visible sm:hidden" /> - you are interested in + {t("mainPage.featuredArticles.descriptionPart1")}<br className="visible sm:hidden" /> + {t("mainPage.featuredArticles.descriptionPart2")} </Typography> </div> <div className="py-8 px-10 flex md:flex justify-start md:justify-center md:flex-wrap overflow-x-scroll md:overflow-hidden snap-x scroll-smooth overscroll-x-contain"> diff --git a/src/components/MainPage/sections/FeaturedAuthorsCards.tsx b/src/components/MainPage/sections/FeaturedAuthorsCards.tsx index 91acd31..965a243 100755 --- a/src/components/MainPage/sections/FeaturedAuthorsCards.tsx +++ b/src/components/MainPage/sections/FeaturedAuthorsCards.tsx @@ -17,12 +17,9 @@ import "swiper/css/navigation"; // import "./styles.css"; import "swiper/css"; -/* -------------------------------------------------------------------------- */ -/* Icons */ -/* -------------------------------------------------------------------------- */ import { ReactComponent as SVGCaretRight } from "assets/svg/caret-right.svg"; import Link from "../../typography/Link"; - +import { useTranslation } from "react-i18next"; /* -------------------------------------------------------------------------- */ /* Variables */ /* -------------------------------------------------------------------------- */ @@ -73,10 +70,12 @@ if (authors.length == 2) { * Featured authors component to display ... */ export default function FeaturedAuthorsCards(): JSX.Element { + const [t, i18next] = useTranslation(); + return ( <div> {/* The Title of Featured Authors section */} - <Heading className="text-center my-8">Featured Authors</Heading> + <Heading className="text-center my-8 text-3xl font-semibold">{t("mainPage.featuredAuthors")}</Heading> {/* Featured Authors section */} <div className="slider-wrapper Authors"> @@ -134,7 +133,7 @@ export default function FeaturedAuthorsCards(): JSX.Element { <Card.CardAction href={card.Link}> <Link className="text-blue-500 font-bold" to="*"> - See More + {t('mainPage.more')} </Link> <SVGCaretRight className="fill-blue-500 w-4 h-4" /> </Card.CardAction> @@ -188,7 +187,7 @@ export default function FeaturedAuthorsCards(): JSX.Element { </div> <Button emphasis="high" className="font-bold m-auto my-8"> - Show All + {t("mainPage.showAll")} </Button> </div> ); diff --git a/src/components/MainPage/sections/MainSection.tsx b/src/components/MainPage/sections/MainSection.tsx index dc9b3b2..60caa7b 100755 --- a/src/components/MainPage/sections/MainSection.tsx +++ b/src/components/MainPage/sections/MainSection.tsx @@ -2,24 +2,32 @@ /* Imports */ /* -------------------------------------------------------------------------- */ import React from "react"; +import {t as nextT} from "i18next"; +import { useTranslation } from "react-i18next"; import { SearchBar } from "../../search/SearchBar"; +import { formatNumber } from "core/helpers"; export default function MainSection() { + const { t, i18n } = useTranslation(); + const amountArticles = 4202020 + + + return ( <section className="bg-main bg-center bg-cover bg-origin-border bg-no-repeat min-h-[100vh] py-32 px-2 sm:px-6 md:px-6 lg:px-0 items-center flex justify-center "> <div className="flex-col"> <div className="m-auto text-center font-bold text-4xl "> - Scientific Library with Free Access + {t("mainPage.title")} </div> <div className="flex flex-row items-center justify-center space-x-3 pt-2"> - <div className=" text-2xl text-gray-400">Search</div> - <div className=" text-3xl text-blue-500">320 455</div> - <div className=" text-2xl text-gray-400">Items</div> + <div className=" text-2xl text-gray-400">{t("mainPage.search")}</div> + <div className=" text-3xl text-blue-500">{formatNumber(amountArticles)}</div> + <div className=" text-2xl text-gray-400">{nextT("mainPage.article", {count: amountArticles}).toString()}</div> </div> <div className="max-w-xl m-auto pt-16 "> <SearchBar /> <div className="mt-7 pr-1 text-right font-semibold text-sm"> - Advanced Search + {t("mainPage.advancedSearch")} </div> </div> </div> diff --git a/src/components/SearchResultsSection.tsx b/src/components/SearchResultsSection.tsx index dfa9b22..26a3d8d 100644 --- a/src/components/SearchResultsSection.tsx +++ b/src/components/SearchResultsSection.tsx @@ -4,10 +4,12 @@ import { useSearchStoreImplementation } from "searchResults/data/searchStoreImpl import { useSearchViewModel } from "../searchResults/controller/searchResultsViewModel"; import { ArticleSearchResult } from "./ArticleSearchResult"; import { Loader } from "./Loader/Loader"; +import { useTranslation } from "react-i18next"; export const SearchResultSection = () => { const store = useSearchStoreImplementation(); const { searchResults, isLoading } = useSearchViewModel(store); + const [t, i18next] = useTranslation() function getResults() { if (searchResults === undefined || searchResults?.data.length === 0) { @@ -16,7 +18,7 @@ export const SearchResultSection = () => { fontWeightVariant="semibold" className="text-xl w-full text-center items-center py-3" > - Nothing found. + {t("searchResults.nothingFound")}. </Typography> ); } else { @@ -31,10 +33,10 @@ export const SearchResultSection = () => { <div className="p-4 md:px-6 md:py-8"> <div className="pb-2"> <Typography fontWeightVariant="semibold" className="text-3xl"> - Search Results + {t("searchResults.title")} </Typography> <Typography className="text-gray-300 text-sm"> - Total results: {searchResults?.meta.total} + {t("searchResults.totalResults")}: {searchResults?.meta.total} </Typography> </div> <hr className="w-full border-gray-100" /> diff --git a/src/components/parts/Footer.tsx b/src/components/parts/Footer.tsx index dda5474..fdcb3af 100755 --- a/src/components/parts/Footer.tsx +++ b/src/components/parts/Footer.tsx @@ -6,29 +6,29 @@ import Typography from "components/typography/Typography"; import { SVGFacebook, SVGInstagram, SVGCircle } from "components/icons"; import { RouterLink } from "components/typography/RouterLink"; import Link from "components/typography/Link"; +import { useTranslation } from "react-i18next"; /* -------------------------------------------------------------------------- */ /* Define consts */ /* -------------------------------------------------------------------------- */ - const mainLinks = [ - { label: "account settings", url: "/account/settings", disabled: false }, - { label: "about freeland", url: "/about", disabled: false }, - { label: "help", url: "/help", disabled: false }, - { label: "contact us", url: "/contact-us", disabled: false }, + { label: "footer.accountSettings", url: "/account/settings", disabled: false }, + { label: "footer.about", url: "/about", disabled: false }, + { label: "footer.help", url: "/help", disabled: false }, + { label: "footer.contactUs", url: "/contact-us", disabled: false }, ]; const secondaryLinks = [ - { index: 1, label: "Terms of Use", url: "/terms-of-use", disabled: false }, + { index: 1, label: "footer.termsOfUse", url: "/terms-of-use", disabled: false }, { index: 2, - label: "Privacy Policy", + label: "footer.privacyPolicy", url: "/privacy-policy", disabled: false, }, { index: 3, - label: "Cookies Policy", + label: "footer.coockiesPolicy", url: "/cookies-policy", disabled: false, }, @@ -48,6 +48,8 @@ const circleDivider = ( /* -------------------------------------------------------------------------- */ export function Footer() { + + const { t, i18n } = useTranslation(); /* -------------------------- Part with main links -------------------------- */ const mainLinksPart = useMemo( () => @@ -59,7 +61,7 @@ export function Footer() { to={link.url} > <Typography className="" fontWeightVariant="semibold" htmlTag="p"> - {link.label.toUpperCase()} + {t(link.label).toUpperCase()} </Typography> </RouterLink> )), @@ -72,7 +74,7 @@ export function Footer() { <div className="flex flex-row items-center"> {link.index != 1 && circleDivider} <Link key={link.url} disabled={link.disabled} to={link.url}> - {link.label} + {t(link.label) } </Link> </div> )), @@ -88,7 +90,7 @@ export function Footer() { <div className="sm:col-span-1"> <Link to="*"> <Typography className="text-2xl" fontWeightVariant="semibold"> - Freeland + Scipaper </Typography> </Link> </div> @@ -108,13 +110,13 @@ export function Footer() { <section className="w-full flex flex-col md:flex-row text-gray-500 text-xs justify-between"> <div className="flex flex-col md:flex-row justify-center items-center"> <Typography> - @ Copyright 2022 Freeland - All rights reserved + @ Copyright 2022 Freeland - {t("footer.allRightsReserved")} </Typography> <div className="hidden md:flex">{circleDivider}</div> <div className="flex flex-row items-center">{secondaryLinksPart}</div> </div> <div className="flex flex-row justify-center md:justify-end"> - Supported by + {t("footer.supportedBy")} <Typography className="ml-1 lg:ml-2" fontWeightVariant="bold"> Comfortel </Typography> diff --git a/src/components/search/SearchBar.tsx b/src/components/search/SearchBar.tsx index 563d8d6..813b100 100644 --- a/src/components/search/SearchBar.tsx +++ b/src/components/search/SearchBar.tsx @@ -4,6 +4,7 @@ import SearchInput from "./SearchInput"; import { Button } from "components/Button/Button"; import { SVGSearch } from "components/icons"; import Link from "components/typography/Link"; +import { useTranslation } from "react-i18next"; type Props = { @@ -15,6 +16,8 @@ type Props = { export function SearchBar({ className }: Props) { const [onSelected, setOnSelected] = useState(""); // Selected item from response list + const { t, i18n } = useTranslation(); + const searchResolver = (item: any) => { setOnSelected(item.caption); @@ -31,6 +34,7 @@ export function SearchBar({ className }: Props) { onSelected={searchResolver} className="w-full" inGroup={true} + placeHolder={t("mainPage.search") + "..."} /> </div> </div> diff --git a/src/core/helpers.ts b/src/core/helpers.ts index 812e24c..c655cd5 100755 --- a/src/core/helpers.ts +++ b/src/core/helpers.ts @@ -10,4 +10,8 @@ export const handleScrollTo = (e: React.MouseEvent<HTMLAnchorElement>) => { export function capitalization (str: string) { return str.substring(0,1).toUpperCase() + str.substring(1); +} + +export function formatNumber(num: number) { + return num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1 '); } \ No newline at end of file diff --git a/src/pages/MainPage.tsx b/src/pages/MainPage.tsx index 83b5614..ec6bb1b 100755 --- a/src/pages/MainPage.tsx +++ b/src/pages/MainPage.tsx @@ -20,7 +20,6 @@ export default function MainPage({ className }: Props) { <FeaturedArticlesCategories></FeaturedArticlesCategories> <FeaturedArticlesCards></FeaturedArticlesCards> <FeaturedAuthorsCards></FeaturedAuthorsCards> - <BottomBarAcceptCookies></BottomBarAcceptCookies> </BaseLayout> </div> ); diff --git a/src/pages/SearchResultsPage.tsx b/src/pages/SearchResultsPage.tsx index b4c937d..ca4e486 100644 --- a/src/pages/SearchResultsPage.tsx +++ b/src/pages/SearchResultsPage.tsx @@ -19,7 +19,7 @@ export const SearchResultsPage = () => { <SearchResultSection /> </ColumnLayout.Main> <ColumnLayout.Right> - <div className="h-98 bg-blue-200 w-[300px]">right bar</div> + <div className="w-[300px]"></div> </ColumnLayout.Right> </ColumnLayout> </BaseLayout>