From 7b1c7e277f5741f26dc1edee513d77e835e79870 Mon Sep 17 00:00:00 2001 From: NazarBaraban Date: Thu, 14 Sep 2023 23:34:15 +0300 Subject: [PATCH 1/7] create localization and first variant of selector --- package.json | 2 ++ src/components/Card.tsx | 18 +++++----- src/components/CategoryCard.tsx | 8 +++-- src/components/CheckoutModal.tsx | 12 ++++--- src/components/Footer.tsx | 13 ++++--- src/components/Header.tsx | 18 ++++++---- src/components/LanguageSelector.tsx | 54 +++++++++++++++++++++++++++++ src/index.tsx | 1 + src/localization/i18n.js | 29 ++++++++++++++++ src/localization/locales/en.json | 54 +++++++++++++++++++++++++++++ src/localization/locales/ja.json | 52 +++++++++++++++++++++++++++ src/localization/locales/uk.json | 54 +++++++++++++++++++++++++++++ src/pages/BurgerMenu.tsx | 10 +++--- src/pages/CartPage.tsx | 24 +++++++++---- src/pages/CatalogPage.tsx | 46 ++++++++++++------------ src/pages/ContactsPage.tsx | 5 ++- src/pages/FavouritesPage.tsx | 8 +++-- src/pages/HomePage.tsx | 12 ++++--- src/pages/NotFoundPage.tsx | 16 +++++---- src/pages/ProductPage.tsx | 26 +++++++------- 20 files changed, 375 insertions(+), 87 deletions(-) create mode 100644 src/components/LanguageSelector.tsx create mode 100644 src/localization/i18n.js create mode 100644 src/localization/locales/en.json create mode 100644 src/localization/locales/ja.json create mode 100644 src/localization/locales/uk.json diff --git a/package.json b/package.json index 525988e..5b9a0fd 100644 --- a/package.json +++ b/package.json @@ -13,9 +13,11 @@ "@types/react-dom": "^18.2.7", "axios": "^1.5.0", "classnames": "^2.3.2", + "i18next": "^23.4.6", "react": "^18.2.0", "react-dom": "^18.2.0", "react-hot-toast": "^2.4.1", + "react-i18next": "^13.2.2", "react-icons": "^4.10.1", "react-redux": "^8.1.2", "react-router-dom": "^6.15.0", diff --git a/src/components/Card.tsx b/src/components/Card.tsx index 87df973..e632995 100644 --- a/src/components/Card.tsx +++ b/src/components/Card.tsx @@ -1,18 +1,19 @@ import classNames from 'classnames'; import { useState } from 'react'; -import { FiHeart } from 'react-icons/fi'; +import toast from 'react-hot-toast'; +import { useTranslation } from 'react-i18next'; import { FaHeart } from 'react-icons/fa'; +import { FiHeart } from 'react-icons/fi'; +import { NavLink } from 'react-router-dom'; import { addItemToCart, - useAppDispatch, toggleFavourite, + useAppDispatch, useAppSelector, } from '../redux'; +import { IProduct } from '../types/Product'; import { Button } from './Button'; import { ProductProperties } from './ProductProperties'; -import { IProduct } from '../types/Product'; -import toast from 'react-hot-toast'; -import { NavLink } from 'react-router-dom'; type Props = { product: IProduct; @@ -24,6 +25,7 @@ export const Card = ({ product, isFetching }: Props) => { const { items } = useAppSelector((state) => state.cart); const dispatch = useAppDispatch(); const [favorite, setFavorite] = useState(false); + const { t } = useTranslation(); const isFavourite = (id: string) => favouriteItems.some((item) => item._id === id); @@ -52,7 +54,7 @@ export const Card = ({ product, isFetching }: Props) => { const handleAddToCart = () => { if (items.some(({ id }) => id === product._id)) { - toast.error('This product is already in your cart'); + toast.error(t('toTheCartError')); return; } @@ -69,7 +71,7 @@ export const Card = ({ product, isFetching }: Props) => { }; dispatch(addItemToCart(itemData)); - toast.success('Successfully added to your cart!'); + toast.success(t('toTheCart')); }; return ( @@ -116,7 +118,7 @@ export const Card = ({ product, isFetching }: Props) => {

- Your payment was successfull + {t('successfulPayment')}

- Thank you for shopping with us! + {t('thanksForOrder')}

- Your order has been placed + {t('orderPlaced')}

- +
)} diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx index 35ec0fc..776e3fa 100644 --- a/src/components/Footer.tsx +++ b/src/components/Footer.tsx @@ -1,8 +1,11 @@ +import { useTranslation } from 'react-i18next'; +import { FiChevronUp } from 'react-icons/fi'; import { NavLink } from 'react-router-dom'; import logo from '../assets/images/logo.svg'; -import { FiChevronUp } from 'react-icons/fi'; export const Footer = () => { + const { t } = useTranslation(); + const handleClickToTop = () => { window.scrollTo({ top: 0, @@ -29,7 +32,7 @@ export const Footer = () => { className="duration-150 select-none uppercase text-secondary-light dark:text-secondary-dark font-extrabold text-xs hover:text-primary-light dark:hover:text-primary-dark active:text-primary-light dark:active:text-primary-dark focus:text-primary-light dark:focus:text-primary-dark font-Mont" href="#" > - Github + GitHub @@ -38,7 +41,7 @@ export const Footer = () => { className="duration-150 select-none uppercase text-secondary-light dark:text-secondary-dark font-extrabold text-xs hover:text-primary-light dark:hover:text-primary-dark active:text-primary-light dark:active:text-primary-dark focus:text-primary-light dark:focus:text-primary-dark font-Mont" to="/contacts" > - Contacts + {t('contacts')} @@ -47,7 +50,7 @@ export const Footer = () => { className="duration-150 select-none uppercase text-secondary-light dark:text-secondary-dark font-extrabold text-xs hover:text-primary-light dark:hover:text-primary-dark active:text-primary-light dark:active:text-primary-dark focus:text-primary-light dark:focus:text-primary-dark font-Mont" href="#" > - Rights + {t('rights')} @@ -56,7 +59,7 @@ export const Footer = () => {

- Back to top + {t('backToTop')}

{ const { favouriteItems } = useAppSelector((state) => state.favourites); @@ -21,6 +16,14 @@ export const Header: React.FC = () => { const { pathname } = useLocation(); const [menuIsOpen, setMenuIsOpen] = useState(false); const iconColor = classNames('dark:text-primary-dark'); + const { t } = useTranslation(); + + const navLinks = [ + { name: t('home'), path: '/' }, + { name: t('phones'), path: 'phones' }, + { name: t('tablets'), path: 'tablets' }, + { name: t('accessories'), path: 'accessories' }, + ]; const handleOpenMenu = () => setMenuIsOpen((prev) => !prev); @@ -58,6 +61,7 @@ export const Header: React.FC = () => {
+
{ + const { t, i18n } = useTranslation(); + const [isMenuOpen, setIsMenuOpen] = useState(false); + + const toggleMenu = () => { + setIsMenuOpen(!isMenuOpen); + }; + + const changeLanguage = (language: string | undefined) => { + i18n.changeLanguage(language); + setIsMenuOpen(false); + }; + + return ( +
+ + {isMenuOpen && ( +
+
+ + + +
+
+ )} +
+ ); +}; + +export default LanguageSelector; diff --git a/src/index.tsx b/src/index.tsx index 6bd43e5..7149daa 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -3,6 +3,7 @@ import { Provider } from 'react-redux'; import './index.css'; import { Root } from './Root'; import { store } from './redux'; +import './localization/i18n'; const root = ReactDOM.createRoot( document.getElementById('root') as HTMLElement, diff --git a/src/localization/i18n.js b/src/localization/i18n.js new file mode 100644 index 0000000..f2ae1a8 --- /dev/null +++ b/src/localization/i18n.js @@ -0,0 +1,29 @@ +import i18n from 'i18next'; +import { initReactI18next } from 'react-i18next'; + +import translationEN from './locales/en.json'; +import translationUK from './locales/uk.json'; +import translationJA from './locales/ja.json'; + +i18n + .use(initReactI18next) + .init({ + resources: { + en: { + translation: translationEN, + }, + uk: { + translation: translationUK, + }, + ja: { + translation: translationJA, + }, + }, + lng: 'en', + fallbackLng: 'en', + interpolation: { + escapeValue: false, + }, + }); + +export default i18n; diff --git a/src/localization/locales/en.json b/src/localization/locales/en.json new file mode 100644 index 0000000..f1717be --- /dev/null +++ b/src/localization/locales/en.json @@ -0,0 +1,54 @@ +{ + "home": "Home", + "phones": "Phones", + "tablets": "Tablets", + "accessories": "Accessories", + "title": "Welcome to Nice Gadgets store!", + "newModels": "Brand new models", + "addToCart": "Add to cart", + "toTheCart": "Successfully added to your cart!", + "toTheCartError": "This product is already in your cart", + "addedToCart": "Added to cart", + "shopByCategory": "Shop by category", + "mobilePhones": "Mobile phones", + "hotPrices": "Hot prices", + "contacts": "Contacts", + "rights": "Rights", + "backToTop": "Back to top", + "model": "model", + "modeli": "models", + "models": "models", + "sortBy": "Sort by", + "newest": "Newest", + "oldest": "Oldest", + "itemsOnPage": "Items on page", + "runOutOfProducts": "Sorry, we ran out of these products", + "back": "Back", + "availableColors": "Available colors", + "selectCapacity": "Select capacity", + "about": "About", + "techSpecs": "Tech specs", + "recomended": "Recomended", + "favourites": "Favourites", + "noFavourites": "You don't have favourite products", + "cart": "Cart", + "emptyCart": "Your cart is empty", + "startShopping": "Start shopping now!", + "totalFor": "Total for", + "item": "item", + "itemu": "items", + "items": "items", + "checkout": "Checkout", + "successfulPayment": "Your payment was successfull", + "thanksForOrder": "Thank you for shopping with us!", + "orderPlaced": "Your order has been placed", + "backHome": "Back to Home", + "pageNotFound": "Page not found", + "movedOrDeleted": "Most likely, this page has been moved or deleted", + "addressMistake": "You may have made a mistake when entering the address", + "checkAgain": "Please check it again", + "takeMeHome": "Take me home", + "contactSupport": "Contact support", + "ourTeam": "Our Team", + "language": "Language" +} diff --git a/src/localization/locales/ja.json b/src/localization/locales/ja.json new file mode 100644 index 0000000..4fc04b2 --- /dev/null +++ b/src/localization/locales/ja.json @@ -0,0 +1,52 @@ +{ + "home": "ホーム", + "phones": "スマートフォン", + "tablets": "タブレット", + "accessories": "アクセサリー", + "title": "ナイスガジェットストアへようこそ!", + "newModels": "ブランド新しいモデル", + "addToCart": "カートに追加", + "toTheCart": "カートに追加しました!", + "toTheCartError": "この製品はすでにカートにあります", + "addedToCart": "カートに追加されました", + "shopByCategory": "カテゴリー別にショッピング", + "mobilePhones": "モバイルフォン", + "hotPrices": "ホットプライス", + "contacts": "お問い合わせ", + "rights": "権利", + "backToTop": "トップに戻る", + "model": "モデル", + "modeli": "モデル", + "models": "モデル", + "sortBy": "並び替え", + "newest": "新着", + "oldest": "最古", + "itemsOnPage": "ページ上のアイテム", + "runOutOfProducts": "申し訳ありませんが、これらの製品は品切れです", + "back": "戻る", + "availableColors": "利用可能な色", + "selectCapacity": "容量を選択", + "about": "について", + "techSpecs": "技術仕様", + "recomended": "おすすめ", + "favourites": "お気に入り", + "noFavourites": "お気に入りの製品はありません", + "cart": "カート", + "emptyCart": "カートは空です", + "startShopping": "今すぐショッピングを始める!", + "totalFor": "合計金額", + "items": "アイテム", + "checkout": "チェックアウト", + "successfulPayment": "お支払いが成功しました", + "thanksForOrder": "お買い物いただきありがとうございます!", + "orderPlaced": "ご注文が完了しました", + "backHome": "ホームに戻る", + "pageNotFound": "ページが見つかりません", + "movedOrDeleted": "おそらく、このページは移動または削除されました", + "addressMistake": "アドレスを入力する際に誤りがあるかもしれません", + "checkAgain": "もう一度確認してください", + "takeMeHome": "ホームに戻る", + "contactSupport": "サポートにお問い合わせ", + "ourTeam": "チーム", + "language": "言語" +} diff --git a/src/localization/locales/uk.json b/src/localization/locales/uk.json new file mode 100644 index 0000000..dec2cf9 --- /dev/null +++ b/src/localization/locales/uk.json @@ -0,0 +1,54 @@ +{ + "home": "Головна", + "phones": "Смартфони", + "tablets": "Планшети", + "accessories": "Аксесуари", + "title": "Ласкаво просимо до Nice Gadgets!", + "newModels": "Нові моделі", + "addToCart": "Додати в кошик", + "toTheCart": "Успішно додано до вашого кошика!", + "toTheCartError": "Цей товар вже є у вашому кошику", + "addedToCart": "Додано до кошика", + "shopByCategory": "Купуйте за категоріями", + "mobilePhones": "Мобільні телефони", + "hotPrices": "Гарячі ціни", + "contacts": "Контакти", + "rights": "Всі права захищені", + "backToTop": "Повернутися наверх", + "model": "модель", + "modeli": "моделі", + "models": "моделей", + "sortBy": "Сортувати за", + "newest": "Найновіші", + "oldest": "Найстаріші", + "itemsOnPage": "Товарів на сторінці", + "runOutOfProducts": "На жаль, цього товару більше немає в наявності", + "back": "Назад", + "availableColors": "Доступні кольори", + "selectCapacity": "Оберіть об'єм", + "about": "Про нас", + "techSpecs": "Технічні характеристики", + "recomended": "Також може сподобатись", + "favourites": "Обрані", + "noFavourites": "У вас немає улюблених товарів", + "cart": "Кошик", + "emptyCart": "Ваш кошик порожній", + "startShopping": "Почніть покупки зараз!", + "totalFor": "Загалом за", + "items": "товарів", + "item": "товар", + "itemu": "товари", + "checkout": "Оформити замовлення", + "successfulPayment": "Ваш платіж пройшов успішно", + "thanksForOrder": "Дякуємо за покупки в нашому магазині!", + "orderPlaced": "Ваше замовлення прийнято", + "backHome": "Повернутися на головну", + "pageNotFound": "Сторінку не знайдено", + "movedOrDeleted": "Можливо, цю сторінку перемістили або видалили", + "addressMistake": "Можливо, ви допустили помилку при введенні адреси", + "checkAgain": "Будь ласка, перевірте її ще раз", + "takeMeHome": "Повернути мене додому", + "contactSupport": "Зв'яжіться з підтримкою", + "ourTeam": "Наша Команда", + "language": "Мова" +} diff --git a/src/pages/BurgerMenu.tsx b/src/pages/BurgerMenu.tsx index 3e2d668..0bec4ca 100644 --- a/src/pages/BurgerMenu.tsx +++ b/src/pages/BurgerMenu.tsx @@ -2,10 +2,12 @@ import { FiHeart, FiShoppingBag } from 'react-icons/fi'; import { NavLink } from 'react-router-dom'; import { ItemCounter } from '../components/ItemCounter'; import { useAppSelector } from '../redux'; +import { useTranslation } from 'react-i18next'; const BurgerMenu = () => { const { favouriteItems } = useAppSelector((state) => state.favourites); const { items } = useAppSelector((state) => state.cart); + const { t } = useTranslation(); return (
@@ -14,25 +16,25 @@ const BurgerMenu = () => { to="/" className="block py-2 mt-4 leading-tight text-center text-secondary-light dark:text-secondary-dark text-xs uppercase tracking-widest transition-colors hover:text-primary-light dark:hover:text-primary-dark" > -

home

+

{t('home')}

-

phones

+

{t('phones')}

-

tablets

+

{t('tablets')}

-

accessories

+

{t('accessories')}

diff --git a/src/pages/CartPage.tsx b/src/pages/CartPage.tsx index 300506c..b77bbfc 100644 --- a/src/pages/CartPage.tsx +++ b/src/pages/CartPage.tsx @@ -1,22 +1,34 @@ import classNames from 'classnames'; import { useState } from 'react'; +import { useTranslation } from 'react-i18next'; import { NavLink } from 'react-router-dom'; +import BreadCrumb from '../components/BreadCrumb'; import { Button } from '../components/Button'; import CartItem from '../components/CartItem'; import { CheckoutModal } from '../components/CheckoutModal'; import { clearCart, useAppDispatch, useAppSelector } from '../redux'; import { getTotalProductsCost } from '../utils/getTotalCost'; import { getTotalItemsCount } from '../utils/getTotalItemsCount'; -import BreadCrumb from '../components/BreadCrumb'; const CartPage = () => { const { items: cartItems } = useAppSelector((state) => state.cart); const [showModal, setShowModal] = useState(false); const dispatch = useAppDispatch(); + const { t } = useTranslation(); const totalCost = getTotalProductsCost(cartItems); const totalItemsCount = getTotalItemsCount(cartItems); + let itemCounter; + + if (totalItemsCount === 1) { + itemCounter = `${t('totalFor')} ${totalItemsCount} ${t('item')}`; + } else if (totalItemsCount >= 2 && totalItemsCount <= 4) { + itemCounter = `${t('totalFor')} ${totalItemsCount} ${t('itemu')}`; + } else { + itemCounter = `${t('totalFor')} ${totalItemsCount} ${t('items')}`; + } + const handlePaymentSuccess = () => { localStorage.removeItem('cart-items'); dispatch(clearCart()); @@ -42,7 +54,7 @@ const CartPage = () => {

- Cart + {t('cart')}

@@ -59,17 +71,17 @@ const CartPage = () => { {`${totalCost}$`}
- {`Total for ${totalItemsCount} items`} + {itemCounter}
- +
) : ( <> -

Your cart is empty

+

{t('emptyCart')}

- Start shopping now! + {t('startShopping')} )} diff --git a/src/pages/CatalogPage.tsx b/src/pages/CatalogPage.tsx index 9313e06..a08686d 100644 --- a/src/pages/CatalogPage.tsx +++ b/src/pages/CatalogPage.tsx @@ -9,17 +9,7 @@ import Pagination from '../components/Pagination'; import { useGetProductsQuery } from '../redux/api/productApi'; import { CatalogTitle } from '../types/PageTitle'; import { IProduct } from '../types/Product'; - -const sortOptions = [ - { - value: 'Newest', - label: 'Newest', - }, - { - value: 'Oldest', - label: 'Oldest', - }, -]; +import { useTranslation } from 'react-i18next'; const perPageOptions = [ { @@ -36,13 +26,8 @@ const perPageOptions = [ }, ]; -const title: CatalogTitle = { - '/phones': 'Mobile phones', - '/tablets': 'Tablets', - '/accessories': 'Accessories', -}; - const CatalogPage: React.FC = () => { + const { t } = useTranslation(); const { pathname } = useLocation(); const [searchParams] = useSearchParams(); const currentPage = Number(searchParams.get('page')) || 1; @@ -60,9 +45,26 @@ const CatalogPage: React.FC = () => { type: pathname.slice(1), }); + const title: CatalogTitle = { + '/phones': t('mobilePhones'), + '/tablets': t('tablets'), + '/accessories': t('accessories'), + }; + + const sortOptions = [ + { + value: `${t('newest')}`, + label: `${t('newest')}`, + }, + { + value: `${t('oldest')}`, + label: `${t('oldest')}`, + }, + ]; + const total = products ? products.totalProducts : 0; - const modelCounter = total === 1 ? `${total} model` : `${total} models`; + const modelCounter = total === 1 ? `${total} ${t('models')}` : `${total} ${t('models')}`; const handlePageNumber = (pageNo: number) => { searchParams.set('page', pageNo.toString()); @@ -76,7 +78,7 @@ const CatalogPage: React.FC = () => {

- {title[pathname as keyof CatalogTitle]} + {t(title[pathname as keyof CatalogTitle])}

@@ -87,7 +89,7 @@ const CatalogPage: React.FC = () => {

@@ -95,7 +97,7 @@ const CatalogPage: React.FC = () => {
@@ -112,7 +114,7 @@ const CatalogPage: React.FC = () => { )) ) : (

- Sorry, we ran out of these products + {t('runOutOfProducts')}

)}
diff --git a/src/pages/ContactsPage.tsx b/src/pages/ContactsPage.tsx index 75ad46f..09e1579 100644 --- a/src/pages/ContactsPage.tsx +++ b/src/pages/ContactsPage.tsx @@ -1,8 +1,11 @@ +import { useTranslation } from 'react-i18next'; import BreadCrumb from '../components/BreadCrumb'; import ContactCard from '../components/ContactCard'; import { contacts } from '../utils/contacts'; const ContactsPage = () => { + const { t } = useTranslation(); + return (

- Our Team + {t('ourTeam')}

diff --git a/src/pages/FavouritesPage.tsx b/src/pages/FavouritesPage.tsx index ffa459c..ca2e924 100644 --- a/src/pages/FavouritesPage.tsx +++ b/src/pages/FavouritesPage.tsx @@ -1,9 +1,11 @@ +import { useTranslation } from 'react-i18next'; import BreadCrumb from '../components/BreadCrumb'; import { Card } from '../components/Card'; import { useAppSelector } from '../redux'; const FavouritesPage = () => { const { favouriteItems } = useAppSelector((state) => state.favourites); + const { t } = useTranslation(); return (
@@ -11,13 +13,13 @@ const FavouritesPage = () => {

- Favourites + {t('favourites')}

{favouriteItems.length ? ( <>

- {`${favouriteItems.length} items`} + {`${favouriteItems.length} ${t('items')}`}

{favouriteItems.map((pr) => ( @@ -26,7 +28,7 @@ const FavouritesPage = () => {
) : ( -

You don't have favourite products

+

{t('noFavourites')}

)}
); diff --git a/src/pages/HomePage.tsx b/src/pages/HomePage.tsx index 529755f..9b8e1af 100644 --- a/src/pages/HomePage.tsx +++ b/src/pages/HomePage.tsx @@ -1,3 +1,4 @@ +import { useTranslation } from 'react-i18next'; import { Navigation, Pagination } from 'swiper'; import 'swiper/css'; import 'swiper/css/navigation'; @@ -10,15 +11,16 @@ const HomePage = () => { const phonesImage = require('../assets/images/phones-category.png'); const tabletsImage = require('../assets/images/tablets-category.png'); const accessoriesoneImage = require('../assets/images/accessories-category.png'); + const { t } = useTranslation(); return (

- Welcome to Nice Gadgets store! + {t('title')}

{
- +

- Shop by category + {t('shopByCategory')}

@@ -71,7 +73,7 @@ const HomePage = () => {
- +
); }; diff --git a/src/pages/NotFoundPage.tsx b/src/pages/NotFoundPage.tsx index 7a39867..225f7e3 100644 --- a/src/pages/NotFoundPage.tsx +++ b/src/pages/NotFoundPage.tsx @@ -1,4 +1,8 @@ +import { useTranslation } from 'react-i18next'; + const NotFoundPage = () => { + const { t } = useTranslation(); + return (
@@ -8,25 +12,25 @@ const NotFoundPage = () => { className="mx-auto w-[250px] mb-4 mt-[-100px]" />

- Page not found + {t('pageNotFound')}

- Most likely, this page has been moved or deleted -
You may have made a mistake when entering the address -
Please check it again + {t('movedOrDeleted')} +
{t('addressMistake')} +
{t('checkAgain')}

- Take me home + {t('takeMeHome')} - Contact support + {('contactSupport')}
diff --git a/src/pages/ProductPage.tsx b/src/pages/ProductPage.tsx index 1e0248e..00fa838 100644 --- a/src/pages/ProductPage.tsx +++ b/src/pages/ProductPage.tsx @@ -1,5 +1,7 @@ +import classNames from 'classnames'; import { useState } from 'react'; import { toast } from 'react-hot-toast'; +import { useTranslation } from 'react-i18next'; import { FaHeart } from 'react-icons/fa'; import { FiChevronLeft, FiHeart } from 'react-icons/fi'; import { NavLink, useLocation, useParams } from 'react-router-dom'; @@ -19,7 +21,6 @@ import { } from '../redux'; import { useGetProductByIdQuery } from '../redux/api/productApi'; import { IDescription } from '../types/Description'; -import classNames from 'classnames'; const ProductPage = () => { const { productId } = useParams(); @@ -32,6 +33,7 @@ const ProductPage = () => { const { data, isError, isLoading, isFetching } = useGetProductByIdQuery( productId!, ); + const { t } = useTranslation(); const route = pathname.split('/')[1]; const isFavourite = favouriteItems.some((item) => item._id === data?._id); @@ -75,13 +77,13 @@ const ProductPage = () => { const handleAddToCart = () => { if (items.some(({ id }) => id === data?._id)) { - toast.error('This product is already in your cart'); + toast.error(t('toTheCartError')); return; } dispatch(addItemToCart(itemData)); - toast.success('Successfully added to your cart!'); + toast.success(t('toTheCart')); }; return ( @@ -103,7 +105,7 @@ const ProductPage = () => { > - Back + {t('back')}

@@ -140,7 +142,7 @@ const ProductPage = () => {
-

Available colors

+

{t('availableColors')}

{data?.colorsAvailable.map((color) => ( @@ -156,7 +158,7 @@ const ProductPage = () => {

- Select capacity + {t('selectCapacity')}

{data?.capacityAvailable && @@ -184,7 +186,7 @@ const ProductPage = () => { onClick={handleAddToCart} outline={!!isAddedToCart} > - {isAddedToCart ? 'Added to cart' : 'Add to cart'} + {isAddedToCart ? t('addedToCart') : t('addToCart')}
{isMenuOpen && ( -
+
{isMenuOpen && (
From acfdf39f3eaeef35238b3f88c6ba0ae2ca1c71b5 Mon Sep 17 00:00:00 2001 From: NazarBaraban Date: Fri, 15 Sep 2023 11:42:57 +0300 Subject: [PATCH 5/7] little fix --- src/components/LanguageSelector.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/LanguageSelector.tsx b/src/components/LanguageSelector.tsx index 69248bb..8b6559d 100644 --- a/src/components/LanguageSelector.tsx +++ b/src/components/LanguageSelector.tsx @@ -16,11 +16,13 @@ const LanguageSelector = () => { }; return ( -
+
From 41b394c020818091bf2a491d735f107c3581e00a Mon Sep 17 00:00:00 2001 From: NazarBaraban Date: Fri, 15 Sep 2023 11:43:46 +0300 Subject: [PATCH 6/7] test --- src/components/LanguageSelector.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/LanguageSelector.tsx b/src/components/LanguageSelector.tsx index 8b6559d..8ae0c52 100644 --- a/src/components/LanguageSelector.tsx +++ b/src/components/LanguageSelector.tsx @@ -17,8 +17,8 @@ const LanguageSelector = () => { return (
{isMenuOpen && (
-
- +
+ {languageCodes.map((code, index) => ( - -
+ ))} +
)}