From f45565802a11eb4947d3a080a2d7199be9b27407 Mon Sep 17 00:00:00 2001 From: filipKovachev Date: Tue, 19 Nov 2024 00:30:15 +0200 Subject: [PATCH 1/3] fix avatar, translate app add files add two other files split messages, adjust switch widht translate remaining parts of the app fix home and footer fix ts errors --- .../src/components/FilterComponent.tsx | 3 +- .../src/data/mesagges.ts | 106 ++++ .../src/pages/AllProductsListView.tsx | 2 +- .../src/pages/Home.tsx | 2 +- .../package-lock.json | 2 +- .../src/components/AdminView.tsx | 31 +- .../src/components/AllProductsListView.tsx | 166 +++--- .../src/components/CardHolder.tsx | 29 +- .../src/components/CardsList.tsx | 170 +++--- .../src/components/CategoryList.tsx | 142 +++-- .../src/components/Contacts.tsx | 144 ++--- .../src/components/ContactsRadioButtons.tsx | 45 +- .../src/components/FilterComponent.tsx | 146 +++--- .../src/components/Footer.tsx | 196 ++++--- .../src/components/Header.tsx | 235 ++++++--- .../src/components/Home.tsx | 255 +++++---- .../src/components/PaymentDetails.tsx | 186 ++++--- .../src/components/ProductCard.tsx | 70 ++- .../src/components/ProductDetails.tsx | 90 ++-- .../src/components/ShoppingCartList.tsx | 175 ++++--- .../src/components/Testemonials.tsx | 137 +++-- .../src/components/ThankYou.tsx | 66 ++- .../src/data/listData.tsx | 459 +++++++++------- .../src/data/messages/en.ts | 492 +++++++++++++++++ .../src/data/messages/es.ts | 495 ++++++++++++++++++ .../src/data/messages/fr.ts | 447 ++++++++++++++++ .../src/data/types.ts | 25 +- .../src/helpers/languageStore.ts | 14 + .../src/layouts/Layout.astro | 2 +- .../src/pages/product/[id].astro | 12 +- .../src/pages/thankyou.astro | 4 + 31 files changed, 3267 insertions(+), 1081 deletions(-) create mode 100644 examples/ecommerce-jewellery-store/src/data/mesagges.ts create mode 100644 examples/kendo-react-e-commerce-astro-app/src/data/messages/en.ts create mode 100644 examples/kendo-react-e-commerce-astro-app/src/data/messages/es.ts create mode 100644 examples/kendo-react-e-commerce-astro-app/src/data/messages/fr.ts create mode 100644 examples/kendo-react-e-commerce-astro-app/src/helpers/languageStore.ts diff --git a/examples/ecommerce-jewellery-store/src/components/FilterComponent.tsx b/examples/ecommerce-jewellery-store/src/components/FilterComponent.tsx index 8d5ea4ad..6ce9c055 100644 --- a/examples/ecommerce-jewellery-store/src/components/FilterComponent.tsx +++ b/examples/ecommerce-jewellery-store/src/components/FilterComponent.tsx @@ -135,5 +135,4 @@ export const FilterComponent: React.FC = ({ updateUI }) => ); -}; - +}; \ No newline at end of file diff --git a/examples/ecommerce-jewellery-store/src/data/mesagges.ts b/examples/ecommerce-jewellery-store/src/data/mesagges.ts new file mode 100644 index 00000000..cd17b2b6 --- /dev/null +++ b/examples/ecommerce-jewellery-store/src/data/mesagges.ts @@ -0,0 +1,106 @@ +export const messages = { + en: { + title: "Vilora Jewelry", + subtitle: "We offer exquisite jewelry, each showcasing timeless elegance", + buttonText: "See Collections", + bestsellersTitle: "Our Bestsellers", + bestsellersSubtitle: "Enjoy an excellent selection of fine jewelry", + timelessTitle: "Timeless Classics", + timelessSubtitle: "Get our unique handmade collections", + timelessContent: "Jewelry enhances style and adds elegance, with each piece telling a unique story.", + fineJewelryTitle: "Fine Jewelry", + fineJewelrySubtitle: "Get our unique handmade collections", + fineJewelryContent: "Jewelry elevates one's style and brings sophistication, with every piece narrating a distinct tale.", + ringsTitle: "Our Rings", + ringsSubtitle: "Enjoy an excellent selection of fine rings", + watchesTitle: "Our Watches", + watchesSubtitle: "Enjoy an excellent selection of watches", + servicesTitle: "Services", + servicesSubtitle: "Explore expert repairs to elevate your experience", + servicesContent: "Vilora provides services like custom designs, repairs, and appraisals to enhance the customer experience.", + filterLabel: "Filter:", + sortByLabel: "Sort by:", + clearFiltersButton: "Clear Filters", + categoryPlaceholder: "Category", + materialPlaceholder: "Material", + categoriesData: ["Bracelets", "Rings", "Earrings", "Watches", "Necklaces"], + statusesData: ["Sale", "Recommended", "Must Have"], + materialsData: ["Gold", "Silver"], + addToCartButtonText: "Add to Cart", + shoppingCartTitle: "Shopping Cart", + backButtonText: "Back", + removeButtonText: "Remove", + emptyCartMessage: "Your shopping cart is empty.", + proceedToCheckoutButtonText: "Proceed to Checkout" + }, + es: { + title: "Joyería Vilora", + subtitle: "Ofrecemos joyería exquisita, cada una mostrando elegancia atemporal", + buttonText: "Ver Colecciones", + bestsellersTitle: "Nuestros Más Vendidos", + bestsellersSubtitle: "Disfruta de una excelente selección de joyas finas", + timelessTitle: "Clásicos Atemporales", + timelessSubtitle: "Obtén nuestras colecciones únicas hechas a mano", + timelessContent: "Las joyas mejoran el estilo y agregan elegancia, cada pieza cuenta una historia única.", + fineJewelryTitle: "Joyería Fina", + fineJewelrySubtitle: "Obtén nuestras colecciones únicas hechas a mano", + fineJewelryContent: "Las joyas elevan el estilo y aportan sofisticación, cada pieza narra una historia distinta.", + ringsTitle: "Nuestros Anillos", + ringsSubtitle: "Disfruta de una excelente selección de anillos finos", + watchesTitle: "Nuestros Relojes", + watchesSubtitle: "Disfruta de una excelente selección de relojes", + servicesTitle: "Servicios", + servicesSubtitle: "Explora reparaciones expertas para mejorar tu experiencia", + servicesContent: "Vilora ofrece servicios como diseños personalizados, reparaciones y tasaciones para mejorar la experiencia del cliente.", + filterLabel: "Filtrar:", + sortByLabel: "Ordenar por:", + clearFiltersButton: "Borrar filtros", + categoryPlaceholder: "Categoría", + materialPlaceholder: "Material", + categoriesData: ["Pulseras", "Anillos", "Pendientes", "Relojes", "Collares"], + statusesData: ["Oferta", "Recomendado", "Imprescindible"], + materialsData: ["Oro", "Plata"], + addToCartButtonText: "Agregar al Carrito", + shoppingCartTitle: "Carrito de Compras", + backButtonText: "Volver", + removeButtonText: "Eliminar", + emptyCartMessage: "Tu carrito está vacío.", + proceedToCheckoutButtonText: "Proceder al Pago" + }, + fr: { + title: "Bijoux Vilora", + subtitle: "Nous proposons des bijoux exquis, chacun illustrant une élégance intemporelle", + buttonText: "Voir les Collections", + bestsellersTitle: "Nos Meilleures Ventes", + bestsellersSubtitle: "Profitez d'une excellente sélection de bijoux fins", + timelessTitle: "Classiques Intemporels", + timelessSubtitle: "Découvrez nos collections artisanales uniques", + timelessContent: "Les bijoux subliment le style et ajoutent de l'élégance, chaque pièce raconte une histoire unique.", + fineJewelryTitle: "Bijoux Fins", + fineJewelrySubtitle: "Découvrez nos collections artisanales uniques", + fineJewelryContent: "Les bijoux rehaussent le style et apportent de la sophistication, chaque pièce raconte une histoire distincte.", + ringsTitle: "Nos Bagues", + ringsSubtitle: "Profitez d'une excellente sélection de bagues fines", + watchesTitle: "Nos Montres", + watchesSubtitle: "Profitez d'une excellente sélection de montres", + servicesTitle: "Services", + servicesSubtitle: "Explorez des réparations expertes pour enrichir votre expérience", + servicesContent: "Vilora propose des services tels que des designs personnalisés, des réparations et des expertises pour enrichir l'expérience client.", + filterLabel: "Filtrer :", + sortByLabel: "Trier par :", + clearFiltersButton: "Effacer les filtres", + categoryPlaceholder: "Catégorie", + materialPlaceholder: "Matériau", + categoriesData: ["Bracelets", "Bagues", "Boucles d'oreilles", "Montres", "Colliers"], + statusesData: ["Vente", "Recommandé", "Indispensable"], + materialsData: ["Or", "Argent"], + addToCartButtonText: "Ajouter au Panier", + shoppingCartTitle: "Panier", + backButtonText: "Retour", + removeButtonText: "Supprimer", + emptyCartMessage: "Votre panier est vide.", + proceedToCheckoutButtonText: "Passer à la caisse", + }, + }; + + export default messages; diff --git a/examples/ecommerce-jewellery-store/src/pages/AllProductsListView.tsx b/examples/ecommerce-jewellery-store/src/pages/AllProductsListView.tsx index 3dda0cdb..4db02eb7 100644 --- a/examples/ecommerce-jewellery-store/src/pages/AllProductsListView.tsx +++ b/examples/ecommerce-jewellery-store/src/pages/AllProductsListView.tsx @@ -108,4 +108,4 @@ export const AllProductsListView = () => { ); -}; +}; \ No newline at end of file diff --git a/examples/ecommerce-jewellery-store/src/pages/Home.tsx b/examples/ecommerce-jewellery-store/src/pages/Home.tsx index 1acf0bc0..889094ec 100644 --- a/examples/ecommerce-jewellery-store/src/pages/Home.tsx +++ b/examples/ecommerce-jewellery-store/src/pages/Home.tsx @@ -149,4 +149,4 @@ const Home: React.FC = () => { ); }; -export default Home; +export default Home; \ No newline at end of file diff --git a/examples/kendo-react-e-commerce-astro-app/package-lock.json b/examples/kendo-react-e-commerce-astro-app/package-lock.json index e613519f..87cfabd2 100644 --- a/examples/kendo-react-e-commerce-astro-app/package-lock.json +++ b/examples/kendo-react-e-commerce-astro-app/package-lock.json @@ -6916,4 +6916,4 @@ } } } -} +} \ No newline at end of file diff --git a/examples/kendo-react-e-commerce-astro-app/src/components/AdminView.tsx b/examples/kendo-react-e-commerce-astro-app/src/components/AdminView.tsx index 645e388b..bee8da1f 100644 --- a/examples/kendo-react-e-commerce-astro-app/src/components/AdminView.tsx +++ b/examples/kendo-react-e-commerce-astro-app/src/components/AdminView.tsx @@ -20,6 +20,17 @@ import { Button } from "@progress/kendo-react-buttons"; import { orderBy } from "@progress/kendo-data-query"; import { chartAreaStackedIcon } from "@progress/kendo-svg-icons"; import { sampleData } from "../data/shared-gd-sampleChartData"; +import { useStore } from "@nanostores/react"; +import { selectedLanguage } from "../helpers/languageStore"; +import enMessages from "../data/messages/en"; +import frMessages from "../data/messages/fr"; +import esMessages from "../data/messages/es"; + +const translations = { + en: enMessages, + fr: frMessages, + es: esMessages, +}; const DATA_ITEM_KEY = "ID"; const SELECTED_FIELD = "selected"; @@ -35,6 +46,8 @@ interface PageState { } const AdminView: React.FC = () => { + const language = useStore(selectedLanguage); + const t = translations[language]; const gridRef = React.useRef(null); const [selectedState, setSelectedState] = React.useState({}); const [sort, setSort] = React.useState<{ field: string; dir: "asc" | "desc" }[]>([ @@ -134,10 +147,10 @@ const AdminView: React.FC = () => { disabled={disabled} style={{ marginRight: "10px" }} > - Chart of Selected Data + {t.chartSelectedDataButton} { setSort(e.sort as { field: string; dir: "asc" | "desc" }[]); }} > - - - - - - - + + + + + + + {showChartWizard && ( diff --git a/examples/kendo-react-e-commerce-astro-app/src/components/AllProductsListView.tsx b/examples/kendo-react-e-commerce-astro-app/src/components/AllProductsListView.tsx index b2147553..10cd036a 100644 --- a/examples/kendo-react-e-commerce-astro-app/src/components/AllProductsListView.tsx +++ b/examples/kendo-react-e-commerce-astro-app/src/components/AllProductsListView.tsx @@ -1,94 +1,134 @@ -import * as React from "react"; +import React, { useState, useEffect, useCallback } from "react"; import { Layout } from "../components/Layout"; import { OrderedImgText } from "../components/OrderedImageCard"; import { CustomSection } from "../components/CustomizedSection"; -import { listData } from "../data/listData"; import { FilterComponent } from "../components/FilterComponent"; import { CardsList } from "../components/CardsList"; import { CategoryList } from "../components/CategoryList"; -import { CardDescriptor } from "../data/types"; -import { DataModel } from "../data/types"; - import { Breadcrumb } from "@progress/kendo-react-layout"; import { Button, ButtonGroup } from "@progress/kendo-react-buttons"; import { layout2By2Icon, gridLayoutIcon } from "@progress/kendo-svg-icons"; import { process, State } from "@progress/kendo-data-query"; +import getTranslatedListData from "../data/listData"; +import { useStore } from "@nanostores/react"; +import { selectedLanguage } from "../helpers/languageStore"; +import { loadMessages, LocalizationProvider } from "@progress/kendo-react-intl"; + +import enMessages from "../data/messages/en"; +import frMessages from "../data/messages/fr"; +import esMessages from "../data/messages/es"; + +loadMessages(enMessages, "en"); +loadMessages(frMessages, "fr"); +loadMessages(esMessages, "es"); + +const messages = { + en: enMessages, + fr: frMessages, + es: esMessages, +}; + +export const AllProductsListView: React.FC = () => { + const language = useStore(selectedLanguage); + const t = messages[language]; -export const AllProductsListView = () => { - const title = "Fine Selection"; - const subtitle = "Enjoy the real craftsmanship"; - const contentText = - "Jewelry is a meaningful form of self-expression that enhances personal style and adds beauty to any occasion."; - const order = "first"; + const [translatedData, setTranslatedData] = useState(() => getTranslatedListData()); + const [filteredData, setFilteredData] = useState(translatedData); + const [currentLayout, setCurrentLayout] = useState<"grid" | "list">("grid"); - const [data, setData] = React.useState(listData); + useEffect(() => { + const updatedData = getTranslatedListData(); + setTranslatedData(updatedData); + setFilteredData(updatedData); + }, [language]); - const updateUI = (newState: State) => { - const newData = process(listData, newState); - setData(newData.data); - }; + const updateUI = useCallback( + (newState: State) => { + const updatedData = process(translatedData, newState).data; + setFilteredData(updatedData); + }, + [translatedData] + ); - const cards: CardDescriptor[] = [ + const cards = [ { img: "/kendo-react/kendo-react-e-commerce-astro-app/necklace_1.jfif", - collectionText: 'Collection "SERENE"', + collectionText: t.collectionSerene, }, { img: "/kendo-react/kendo-react-e-commerce-astro-app/ring_1.jfif", - collectionText: 'Collection "AURELIA"', + collectionText: t.collectionAurelia, }, { img: "/kendo-react/kendo-react-e-commerce-astro-app/1111.jfif", - collectionText: 'Collection "RAVINA"', + collectionText: t.collectionRavina, }, ]; - const BreakcrumbData: DataModel[] = [ - { text: "Home" }, - { text: "Jewelry" }, + const breadcrumbData = [ + { text: t.breadcrumbHome }, + { text: t.breadcrumbJewelry }, ]; return ( - <> - -
- -
-
- - - - - - -
- - -
-
- - - - - - - + + <> + +
+ +
+
+ + + + + + + + +
+ + +
+
+ + + + + + + + + +
); }; -export default AllProductsListView \ No newline at end of file +export default AllProductsListView; diff --git a/examples/kendo-react-e-commerce-astro-app/src/components/CardHolder.tsx b/examples/kendo-react-e-commerce-astro-app/src/components/CardHolder.tsx index 2d3772c8..58d8ed6c 100644 --- a/examples/kendo-react-e-commerce-astro-app/src/components/CardHolder.tsx +++ b/examples/kendo-react-e-commerce-astro-app/src/components/CardHolder.tsx @@ -1,10 +1,31 @@ import { TextBox } from '@progress/kendo-react-inputs'; +import { useStore } from '@nanostores/react'; +import { selectedLanguage } from '../helpers/languageStore'; +import { loadMessages, LocalizationProvider } from '@progress/kendo-react-intl'; + +import enMessages from '../data/messages/en'; +import frMessages from '../data/messages/fr'; +import esMessages from '../data/messages/es'; + +loadMessages(enMessages, 'en'); +loadMessages(frMessages, 'fr'); +loadMessages(esMessages, 'es'); + +const messages = { + en: enMessages, + fr: frMessages, + es: esMessages, +}; + +const CardHolder = () => { + const language = useStore(selectedLanguage); + const t = messages[language] || messages['en']; -const CardNumber = () => { return ( - - + + + ); }; -export default CardNumber; +export default CardHolder; diff --git a/examples/kendo-react-e-commerce-astro-app/src/components/CardsList.tsx b/examples/kendo-react-e-commerce-astro-app/src/components/CardsList.tsx index be0df568..d213b9d1 100644 --- a/examples/kendo-react-e-commerce-astro-app/src/components/CardsList.tsx +++ b/examples/kendo-react-e-commerce-astro-app/src/components/CardsList.tsx @@ -1,90 +1,118 @@ -import { Badge, BadgeContainer } from "@progress/kendo-react-indicators"; -import { Button } from "@progress/kendo-react-buttons"; -import { cartIcon } from "@progress/kendo-svg-icons"; -import { CardListProps } from "../data/types"; +import React from 'react'; +import { Badge, BadgeContainer } from '@progress/kendo-react-indicators'; +import { Button } from '@progress/kendo-react-buttons'; +import { cartIcon } from '@progress/kendo-svg-icons'; +import { CardListProps } from '../data/types'; -export const CardsList = (props: CardListProps) => { +import { useStore } from '@nanostores/react'; +import { selectedLanguage } from '../helpers/languageStore'; +import { loadMessages, LocalizationProvider } from '@progress/kendo-react-intl'; + +import enMessages from '../data/messages/en'; +import frMessages from '../data/messages/fr'; +import esMessages from '../data/messages/es'; + +loadMessages(enMessages, 'en'); +loadMessages(frMessages, 'fr'); +loadMessages(esMessages, 'es'); + +const messages = { + en: enMessages, + fr: frMessages, + es: esMessages, +}; + +export const CardsList: React.FC = (props) => { + const language = useStore(selectedLanguage); + const t = messages[language] || messages['en']; const onButtonClick = (index: number) => { - window.location.href=`/kendo-react/kendo-react-e-commerce-astro-app/product/${index + 1}`; + window.location.href = `/kendo-react/kendo-react-e-commerce-astro-app/product/${ + index + 1 + }`; }; return ( -
- {props.data.map((item, index) => { - return ( -
- {item.status != null ? ( - + +
+ {props.data.map((item, index) => { + return ( +
+ {item.status ? ( + +
+ {item.status && ( + + {t.statuses[item.status] || item.status} + + )} +
+ ) : (
- - - {item.status} - - - ) : ( -
- )} -
-
{item.title}
-
- - {item.oldPrice && ( + )} +
+
{t[item.title] || item.title}
+
+ + {item.oldPrice && ( + {`$${item.oldPrice}`} + )} {`$${item.oldPrice}`} - )} - {`$${item.newPrice}`} - - - - + >{`$${item.newPrice}`} + + + + +
-
- ); - })} -
+ ); + })} +
+ ); }; + +export default CardsList; diff --git a/examples/kendo-react-e-commerce-astro-app/src/components/CategoryList.tsx b/examples/kendo-react-e-commerce-astro-app/src/components/CategoryList.tsx index 9164acd8..f9834873 100644 --- a/examples/kendo-react-e-commerce-astro-app/src/components/CategoryList.tsx +++ b/examples/kendo-react-e-commerce-astro-app/src/components/CategoryList.tsx @@ -1,58 +1,94 @@ +import React from 'react'; +import { CategoryListProps, CardDescriptor } from '../data/types'; +import { Button } from '@progress/kendo-react-buttons'; -import { CategoryListProps } from "../data/types"; -import { Button } from "@progress/kendo-react-buttons"; -import { CardDescriptor } from "../data/types"; +import { useStore } from '@nanostores/react'; +import { selectedLanguage } from '../helpers/languageStore'; +import { loadMessages, LocalizationProvider } from '@progress/kendo-react-intl'; -export const CategoryList: React.FC = ({ data, title, subtitle, colSpan = 4 }) => { +import enMessages from '../data/messages/en'; +import frMessages from '../data/messages/fr'; +import esMessages from '../data/messages/es'; - const onNavigate = (card: CardDescriptor) => { - console.log(card); - if (card.collectionText === `Collection \"AURELIA\"`) { - } +loadMessages(enMessages, 'en'); +loadMessages(frMessages, 'fr'); +loadMessages(esMessages, 'es'); + +const messages = { + en: enMessages, + fr: frMessages, + es: esMessages, +}; + +export const CategoryList: React.FC = ({ + data, + title, + subtitle, + colSpan = 4, +}) => { + const language = useStore(selectedLanguage); + const t = messages[language] || messages['en']; + + const onNavigate = (card: CardDescriptor) => { + if (card.collectionText === t.collectionAurelia) { + // Handle navigation } + }; + + return ( + + <> +
+ {title} +
+
+ {subtitle} +
+
+ {data.map((card, index) => { + return ( +
+ {t[card.collectionTextKey] + + {t[card.collectionTextKey] || card.collectionText} + +
+ +
+
+ ); + })} +
+ +
+ ); +}; - return ( - <> -
- {title} -
-
- {subtitle} -
-
- {data.map((card, index) => { - return ( -
- - - {card.collectionText} - -
- -
-
- ); - })} -
- - ); -} +export default CategoryList; diff --git a/examples/kendo-react-e-commerce-astro-app/src/components/Contacts.tsx b/examples/kendo-react-e-commerce-astro-app/src/components/Contacts.tsx index 2c88099e..eab84869 100644 --- a/examples/kendo-react-e-commerce-astro-app/src/components/Contacts.tsx +++ b/examples/kendo-react-e-commerce-astro-app/src/components/Contacts.tsx @@ -16,77 +16,99 @@ import { FieldWrapper, } from '@progress/kendo-react-form'; import { Label } from '@progress/kendo-react-labels'; +import { useStore } from '@nanostores/react'; +import { selectedLanguage } from '../helpers/languageStore'; +import { loadMessages, LocalizationProvider } from '@progress/kendo-react-intl'; + +import enMessages from '../data/messages/en'; +import frMessages from '../data/messages/fr'; +import esMessages from '../data/messages/es'; + +loadMessages(enMessages, 'en'); +loadMessages(frMessages, 'fr'); +loadMessages(esMessages, 'es'); + +const messages = { + en: enMessages, + fr: frMessages, + es: esMessages, +}; const Contacts: React.FC = () => { + const language = useStore(selectedLanguage); + const t = messages[language] || messages['en']; + const onSubmitClick = () => { window.location.href = "/kendo-react/kendo-react-e-commerce-astro-app/thankyou"; }; return ( - -
-
-
-

Get in touch

-

If you have any questions, contact us

-
( - -
- - - - - - - - - - - - -
-

Type of customer

- + + +
+
+
+

{t.getInTouchTitle}

+

{t.getInTouchSubtitle}

+ ( + +
+ + + + + + + + + + + + +
+

{t.typeOfCustomerLabel}

+ +
+ + + + + + + + + +
- - - - - - - - - - -
- - )} - /> - -
-
- Contacts + + )} + /> + +
+
+ {t.contactsImageAlt} +
-
- + + ); }; -export default Contacts; \ No newline at end of file +export default Contacts; diff --git a/examples/kendo-react-e-commerce-astro-app/src/components/ContactsRadioButtons.tsx b/examples/kendo-react-e-commerce-astro-app/src/components/ContactsRadioButtons.tsx index dedb46e9..7e2ecea0 100644 --- a/examples/kendo-react-e-commerce-astro-app/src/components/ContactsRadioButtons.tsx +++ b/examples/kendo-react-e-commerce-astro-app/src/components/ContactsRadioButtons.tsx @@ -1,10 +1,21 @@ - - import * as React from 'react'; - import { RadioButton, RadioButtonChangeEvent } from '@progress/kendo-react-inputs'; +import { useStore } from '@nanostores/react'; +import { selectedLanguage } from '../helpers/languageStore'; +import enMessages from '../data/messages/en'; +import frMessages from '../data/messages/fr'; +import esMessages from '../data/messages/es'; + +const translations = { + en: enMessages, + fr: frMessages, + es: esMessages, +}; + +const ContactsRadioButtons: React.FC = () => { + const language = useStore(selectedLanguage); + const t = translations[language]; -const ContactsRadioButtons: React.FC = () => { const [selectedValue, setSelectedValue] = React.useState('first'); const handleChange = React.useCallback( @@ -16,13 +27,31 @@ const ContactsRadioButtons: React.FC = () => { return (
- +
- +
- +
); } -export default ContactsRadioButtons; \ No newline at end of file +export default ContactsRadioButtons; diff --git a/examples/kendo-react-e-commerce-astro-app/src/components/FilterComponent.tsx b/examples/kendo-react-e-commerce-astro-app/src/components/FilterComponent.tsx index be0aad3f..85a97681 100644 --- a/examples/kendo-react-e-commerce-astro-app/src/components/FilterComponent.tsx +++ b/examples/kendo-react-e-commerce-astro-app/src/components/FilterComponent.tsx @@ -1,108 +1,94 @@ -import React, { useEffect, useState } from "react"; +import React, { useEffect, useState, useCallback } from "react"; import { MultiSelect, DropDownList } from "@progress/kendo-react-dropdowns"; import { SvgIcon } from "@progress/kendo-react-common"; import { filterIcon, sortAscIcon } from "@progress/kendo-svg-icons"; -import { FilterDescriptor, SortDescriptor, State } from "@progress/kendo-data-query"; +import { FilterDescriptor, State } from "@progress/kendo-data-query"; +import { useStore } from "@nanostores/react"; +import { selectedLanguage } from "../helpers/languageStore"; +import enMessages from "../data/messages/en"; +import frMessages from "../data/messages/fr"; +import esMessages from "../data/messages/es"; + +const translations = { + en: enMessages, + fr: frMessages, + es: esMessages, +}; -const chips: string[]= ["Bracelets", "Rings", "Earrings", "Watches", "Necklaces"]; -const statuses: string[] = ["Sale", "Recommended", "Must Have"]; -const materials: string[] = ["Gold", "Silver"]; +const getTranslations = (language: string) => { + return translations[language] || translations["en"]; +}; interface FilterComponentProps { updateUI: (state: State) => void; } export const FilterComponent: React.FC = ({ updateUI }) => { - const [categoryValue, setCategoryValue] = useState([]); - const [statusValue, setStatusValue] = useState("Recommended"); - const [materialValue, setMaterialValue] = useState("Material"); + const language = useStore(selectedLanguage); + const t = getTranslations(language); - useEffect(() => { - const params = new URLSearchParams(window.location.search); - const category = params.get("category"); - - if (category && category !== "All") { - setCategoryValue([category]); - applyCategoryFilter([category]); - } else { - setCategoryValue([]); - applyCategoryFilter([]); - } - }, []); - - const applyCategoryFilter = (categories: string[]) => { - if (categories.length === 0) { - updateUI({ filter: undefined, sort: undefined }); - return; - } + const [categoryValue, setCategoryValue] = useState([]); + const [statusValue, setStatusValue] = useState(t.statusesData[0]); + const [materialValue, setMaterialValue] = useState(t.materialPlaceholder); - const filters = categories.map((category) => ({ - field: "category", - operator: "eq", - value: category, - })); + const chips = t.categoriesData || []; + const statuses = t.statusesData || []; + const materials = t.materialsData || []; - const customCompositeFilters: State = { - filter: { - logic: "or", - filters, - }, - sort: undefined, - }; - - updateUI(customCompositeFilters); - }; + useEffect(() => { + setCategoryValue([]); + setStatusValue(t.statusesData[0]); + setMaterialValue(t.materialPlaceholder); + updateUI({ filter: undefined, sort: undefined }); + }, [language, t, updateUI]); - const onCategoryChange = (e: any) => { - setCategoryValue(e.value); - applyCategoryFilter(e.value); - }; + const applyFilters = useCallback(() => { + const filters: FilterDescriptor[] = []; - const onStatusChange = (e: any) => { - setStatusValue(e.value); + if (categoryValue.length > 0) { + filters.push({ + field: "category", + operator: "eq", + value: categoryValue[0], + }); + } - const newSorts: SortDescriptor[] = [ - { + if (statusValue !== t.statusesData[0]) { + filters.push({ field: "status", - dir: "desc", - }, - ]; - - const customCompositeFilters: State = { - filter: undefined, - sort: newSorts, - }; - - updateUI(customCompositeFilters); - }; - - const onMaterialChange = (e: any) => { - setMaterialValue(e.value); + operator: "eq", + value: statusValue, + }); + } - const newFilter: FilterDescriptor[] = [ - { + if (materialValue !== t.materialPlaceholder) { + filters.push({ field: "material", operator: "eq", - value: e.value, - }, - ]; + value: materialValue, + }); + } const customCompositeFilters: State = { - filter: { - logic: "or", - filters: newFilter, - }, + filter: filters.length > 0 ? { logic: "and", filters } : undefined, sort: undefined, }; updateUI(customCompositeFilters); - setCategoryValue([]); - }; + }, [categoryValue, statusValue, materialValue, t, updateUI]); + + useEffect(() => { + applyFilters(); + }, [categoryValue, statusValue, materialValue, applyFilters]); + + const onCategoryChange = (e: any) => setCategoryValue(e.value); + const onStatusChange = (e: any) => setStatusValue(e.value); + const onMaterialChange = (e: any) => setMaterialValue(e.value); const clearFilters = () => { setCategoryValue([]); - setStatusValue("Recommended"); - setMaterialValue("Material"); + setStatusValue(t.statusesData[0]); + setMaterialValue(t.materialPlaceholder); updateUI({ filter: undefined, sort: undefined }); }; @@ -110,13 +96,13 @@ export const FilterComponent: React.FC = ({ updateUI }) =>
- Filter: + {t.filterLabel} @@ -127,14 +113,14 @@ export const FilterComponent: React.FC = ({ updateUI }) => - Sort by: + {t.sortByLabel}
); diff --git a/examples/kendo-react-e-commerce-astro-app/src/components/Footer.tsx b/examples/kendo-react-e-commerce-astro-app/src/components/Footer.tsx index 3e989e02..65b73bde 100644 --- a/examples/kendo-react-e-commerce-astro-app/src/components/Footer.tsx +++ b/examples/kendo-react-e-commerce-astro-app/src/components/Footer.tsx @@ -1,80 +1,152 @@ -import React from 'react'; -import { Button } from '@progress/kendo-react-buttons'; -import { SvgIcon } from '@progress/kendo-react-common'; -import { TextBox, InputSuffix, InputSeparator } from '@progress/kendo-react-inputs'; -import { Label } from '@progress/kendo-react-labels'; +import React from "react"; +import { Button } from "@progress/kendo-react-buttons"; +import { SvgIcon } from "@progress/kendo-react-common"; +import { + TextBox, + InputSuffix, + InputSeparator, +} from "@progress/kendo-react-inputs"; +import { Label } from "@progress/kendo-react-labels"; import { facebookIcon, linkedinIcon, twitterIcon, -} from '@progress/kendo-svg-icons'; +} from "@progress/kendo-svg-icons"; +import { useStore } from "@nanostores/react"; +import { selectedLanguage } from "../helpers/languageStore"; +import { + loadMessages, + LocalizationProvider, +} from "@progress/kendo-react-intl"; + +import enMessages from "../data/messages/en"; +import frMessages from "../data/messages/fr"; +import esMessages from "../data/messages/es"; + +const languages = { + en: enMessages, + fr: frMessages, + es: esMessages, +}; + +Object.keys(languages).forEach((lang) => { + loadMessages(languages[lang], lang); +}); const Footer: React.FC = () => { + const language = useStore(selectedLanguage); + + const t = languages[language] || languages["en"] || {}; + return ( -
-
-
- - Logo - -

We use cookies to improve your experience.

-

All rights reserved.

-

Subscribe to our Newsletter:

- - ( - - - - - )} - /> -

Follow us:

-
-

- Facebook + +

+
+
+ + Logo + +

+ {t.cookiesText}

-

- Twitter +

+ {t.rightsReservedText}

-

- LinkedIn +

+ {t.subscribeText}

+ + ( + + + + + )} + /> +

{t.followUsText}

+
+

+ Facebook +

+

+ Twitter +

+

+ LinkedIn +

+
-
- +
+

+ {t.customerCareTitle} +

+ {Array.isArray(t.customerCareLinks) && t.customerCareLinks.length > 0 ? ( + t.customerCareLinks.map((link: string, index: number) => ( + + {link} + + )) + ) : ( +

No links available.

+ )} +
- +
+

+ {t.ourCompanyTitle} +

+ {Array.isArray(t.ourCompanyLinks) && t.ourCompanyLinks.length > 0 ? ( + t.ourCompanyLinks.map((link: string, index: number) => ( + + {link} + + )) + ) : ( +

No links available.

+ )} +
-
-

Legal & Privacy

- Terms of Use - Conditions of Sale - Return Policy - Privacy Policy - Cookie Policy +
+

+ {t.legalPrivacyTitle} +

+ {Array.isArray(t.legalPrivacyLinks) && t.legalPrivacyLinks.length > 0 ? ( + t.legalPrivacyLinks.map((link: string, index: number) => ( + + {link} + + )) + ) : ( +

No links available.

+ )} +
-
-
+ + ); }; -export default Footer; +export default Footer; \ No newline at end of file diff --git a/examples/kendo-react-e-commerce-astro-app/src/components/Header.tsx b/examples/kendo-react-e-commerce-astro-app/src/components/Header.tsx index ef6dc7fb..36e2f567 100644 --- a/examples/kendo-react-e-commerce-astro-app/src/components/Header.tsx +++ b/examples/kendo-react-e-commerce-astro-app/src/components/Header.tsx @@ -1,31 +1,94 @@ -import React, { useState, useEffect } from "react"; -import { - Menu, - MenuSelectEvent, - MenuItemModel, -} from "@progress/kendo-react-layout"; +import React, { useCallback, useMemo, useEffect, useState } from "react"; +import { Menu, MenuSelectEvent, MenuItemModel } from "@progress/kendo-react-layout"; import { Button, DropDownButton } from "@progress/kendo-react-buttons"; import { SvgIcon } from "@progress/kendo-react-common"; -import { InputPrefix, InputSeparator, TextBox, Switch } from "@progress/kendo-react-inputs"; -import { searchIcon, userIcon, cartIcon, paletteIcon } from "@progress/kendo-svg-icons"; -import items from "../data/items"; -import themeItems from "../data/themeItems"; +import { + InputPrefix, + InputSeparator, + TextBox, + Switch, +} from "@progress/kendo-react-inputs"; import { AppBar, AppBarSection } from "@progress/kendo-react-layout"; +import { + searchIcon, + userIcon, + cartIcon, + paletteIcon, +} from "@progress/kendo-svg-icons"; import { isAdmin } from "../helpers/adminStore"; import { useStore } from "@nanostores/react"; +import { loadMessages, LocalizationProvider } from "@progress/kendo-react-intl"; +import themeItems from "../data/themeItems"; +import enMessages from "../data/messages/en"; +import frMessages from "../data/messages/fr"; +import esMessages from "../data/messages/es"; +import { selectedLanguage } from "../helpers/languageStore"; -interface CustomMenuItemModel extends MenuItemModel { - page?: string; +const messages = { + en: enMessages, + fr: frMessages, + es: esMessages, +}; + +Object.keys(messages).forEach((lang) => { + loadMessages(messages[lang], lang); +}); + +interface ExtendedMenuItemModel extends MenuItemModel { + category?: string; + url?: string; + code?: string; } const Header: React.FC = () => { const isAdminValue = useStore(isAdmin); + const language = useStore(selectedLanguage); + const t = messages[language]; - const [theme, setTheme] = useState(() => - typeof window !== "undefined" - ? localStorage.getItem("theme") || - "https://unpkg.com/@progress/kendo-theme-default@10.0.0/dist/default-main.css" - : "https://unpkg.com/@progress/kendo-theme-default@10.0.0/dist/default-main.css" + const menuItems = useMemo( + () => [ + { + text: t.menuHome, + url: "/kendo-react/kendo-react-e-commerce-astro-app/", + }, + { + text: t.menuJewelry, + items: [ + { text: t.menuBracelets, url: "/kendo-react/kendo-react-e-commerce-astro-app/products?category=Bracelets" }, + { text: t.menuRings, url: "/kendo-react/kendo-react-e-commerce-astro-app/products?category=Rings" }, + { text: t.menuEarrings, url: "/kendo-react/kendo-react-e-commerce-astro-app/products?category=Earrings" }, + { text: t.menuWatches, url: "/kendo-react/kendo-react-e-commerce-astro-app/products?category=Watches" }, + { text: t.menuAll, url: "/kendo-react/kendo-react-e-commerce-astro-app/products" }, + ], + }, + { + text: t.menuContacts, + url: "/kendo-react/kendo-react-e-commerce-astro-app/contacts", + }, + ], + [t] + ); + + const languageItems = useMemo( + () => [ + { + text: t.languageMenuTitle, + items: [ + { text: t.languageEnglish, code: "en" }, + { text: t.languageFrench, code: "fr" }, + { text: t.languageSpanish, code: "es" }, + ], + }, + ], + [t] + ); + + const [theme, setTheme] = useState( + () => + typeof window !== "undefined" + ? localStorage.getItem("theme") || + "https://unpkg.com/@progress/kendo-theme-default@10.0.0/dist/default-main.css" + : "https://unpkg.com/@progress/kendo-theme-default@10.0.0/dist/default-main.css" ); useEffect(() => { @@ -38,12 +101,10 @@ const Header: React.FC = () => { }, [theme]); const handleThemeChange = (event: any) => { - const selectedTheme = themeItems.find( - (item) => item.themeName === event.item.themeName - ); + const selectedTheme = themeItems.find((item) => item.themeName === event.item.themeName); if (selectedTheme) { - setTheme(selectedTheme.link); - localStorage.setItem("theme", selectedTheme.link); + setTheme(selectedTheme.link); + localStorage.setItem("theme", selectedTheme.link); } }; @@ -56,74 +117,82 @@ const Header: React.FC = () => { }; const handleMenuSelect = (event: MenuSelectEvent) => { - const selectedItem: CustomMenuItemModel = event.item; - - if (selectedItem.page) { - window.location.href = "/kendo-react/kendo-react-e-commerce-astro-app/" + selectedItem.page; - return; - } - - const selectedCategory = selectedItem.text; - if (selectedCategory === "All") { - window.location.href = `/kendo-react/kendo-react-e-commerce-astro-app/products`; - } else { - window.location.href = `/kendo-react/kendo-react-e-commerce-astro-app/products?category=${encodeURIComponent(selectedCategory)}`; + const selectedItem = event.item as ExtendedMenuItemModel; + if (selectedItem.url) { + window.location.href = selectedItem.url; } }; + const handleLanguageMenuSelect = useCallback( + (event: MenuSelectEvent) => { + const selectedLangCode = (event.item as ExtendedMenuItemModel).code; + if (selectedLangCode && messages[selectedLangCode]) { + selectedLanguage.set(selectedLangCode); + } + }, + [] + ); + return ( <> - - - - Logo + + + + Logo + + + + + ( + <> + + + + + + + + )} + style={{ width: 300 }} + /> + -
- -
-

Sub total

-

US Dollars

-

VAT

-

US Dollars

-

Shipping Method

-

Standard Free Delivery

-

Gift Wrapping

-

Included Gift Wrapping

-

Total

-

US Dollars

+ + )} + /> + +
+
+

{t.subTotalLabel}

+

{t.usDollarsLabel}

+

{t.vatLabel}

+

{t.usDollarsLabel}

+

{t.shippingMethodLabel}

+

{t.standardFreeDeliveryLabel}

+

{t.giftWrappingLabel}

+

{t.includedGiftWrappingLabel}

+

{t.totalLabel}

+

{t.usDollarsLabel}

+
- -
+ + ); }; diff --git a/examples/kendo-react-e-commerce-astro-app/src/components/ProductCard.tsx b/examples/kendo-react-e-commerce-astro-app/src/components/ProductCard.tsx index a9fbd971..02bb29a8 100644 --- a/examples/kendo-react-e-commerce-astro-app/src/components/ProductCard.tsx +++ b/examples/kendo-react-e-commerce-astro-app/src/components/ProductCard.tsx @@ -1,24 +1,46 @@ -import { Breadcrumb } from "@progress/kendo-react-layout"; -import { ProductCardProps } from "../data/types"; -import { NumericTextBox, Rating } from "@progress/kendo-react-inputs"; -import { Button } from "@progress/kendo-react-buttons"; +import React from 'react'; +import { Breadcrumb } from '@progress/kendo-react-layout'; +import { ProductCardProps } from '../data/types'; +import { NumericTextBox, Rating } from '@progress/kendo-react-inputs'; +import { Button } from '@progress/kendo-react-buttons'; + +import { useStore } from '@nanostores/react'; +import { selectedLanguage } from '../helpers/languageStore'; +import { loadMessages, LocalizationProvider } from '@progress/kendo-react-intl'; + +import enMessages from '../data/messages/en'; +import frMessages from '../data/messages/fr'; +import esMessages from '../data/messages/es'; + +loadMessages(enMessages, 'en'); +loadMessages(frMessages, 'fr'); +loadMessages(esMessages, 'es'); + +const messages = { + en: enMessages, + fr: frMessages, + es: esMessages, +}; + +export const ProductCard: React.FC = (props) => { + const language = useStore(selectedLanguage); + const t = messages[language] || messages['en']; -export const ProductCard = (props: ProductCardProps) => { return ( - <> +
@@ -26,44 +48,52 @@ export const ProductCard = (props: ProductCardProps) => {
- {props.title} -
{props.subtitle}
+ + {t[props.title] || props.title} + +
+ {t[props.subtitle] || props.subtitle} +
- {props.reviews} + {t.reviewsText.replace('{0}', props.reviews) || `${props.reviews} reviews`}
{`$${props.price}`}
-
{props.description}
+
+ {t[props.description] || props.description} +
-
- +
); }; + +export default ProductCard; diff --git a/examples/kendo-react-e-commerce-astro-app/src/components/ProductDetails.tsx b/examples/kendo-react-e-commerce-astro-app/src/components/ProductDetails.tsx index 4b4a9417..a1cc08fe 100644 --- a/examples/kendo-react-e-commerce-astro-app/src/components/ProductDetails.tsx +++ b/examples/kendo-react-e-commerce-astro-app/src/components/ProductDetails.tsx @@ -5,63 +5,87 @@ import { CategoryList } from '../components/CategoryList'; import { CustomSection } from '../components/CustomizedSection'; import { ListDataDescriptor, CardDescriptor } from '../data/types'; +import { useStore } from '@nanostores/react'; +import { selectedLanguage } from '../helpers/languageStore'; +import { loadMessages, LocalizationProvider } from '@progress/kendo-react-intl'; + +import enMessages from '../data/messages/en'; +import frMessages from '../data/messages/fr'; +import esMessages from '../data/messages/es'; + +loadMessages(enMessages, 'en'); +loadMessages(frMessages, 'fr'); +loadMessages(esMessages, 'es'); + +const messages = { + en: enMessages, + fr: frMessages, + es: esMessages, +}; + interface ProductDetailsProps { - id: string; - product: ListDataDescriptor; + id: string; + product: ListDataDescriptor; } export const ProductDetails: React.FC = ({ product }) => { + const language = useStore(selectedLanguage); + const t = messages[language] || messages['en']; + const handleAddToCart = () => { const existingCart = JSON.parse(localStorage.getItem('cart') || '[]'); const updatedCart = [...existingCart, product]; localStorage.setItem('cart', JSON.stringify(updatedCart)); - window.location.href = '/kendo-react/kendo-react-e-commerce-astro-app/shoppingcart'; + window.location.href = + '/kendo-react/kendo-react-e-commerce-astro-app/shoppingcart'; }; const data: CardDescriptor[] = [ { img: '/kendo-react/kendo-react-e-commerce-astro-app/homemadePinkDiamondRing.jpg', - collectionText: 'Handmade Pink Diamond Ring', + collectionText: t.handmadePinkDiamondRing, }, { img: '/kendo-react/kendo-react-e-commerce-astro-app/diamondRingPinkRuby.jpg', - collectionText: 'Diamond Ring with Pink Ruby', + collectionText: t.diamondRingWithPinkRuby, }, { img: '/kendo-react/kendo-react-e-commerce-astro-app/whiteSandDiamondRing.jpg', - collectionText: 'White Sand Diamond Ring', + collectionText: t.whiteSandDiamondRing, }, ]; return ( - <> - - - - - - + <> + + - - - + + + + + + + + ); }; diff --git a/examples/kendo-react-e-commerce-astro-app/src/components/ShoppingCartList.tsx b/examples/kendo-react-e-commerce-astro-app/src/components/ShoppingCartList.tsx index d8d5fb30..985d71ab 100644 --- a/examples/kendo-react-e-commerce-astro-app/src/components/ShoppingCartList.tsx +++ b/examples/kendo-react-e-commerce-astro-app/src/components/ShoppingCartList.tsx @@ -1,18 +1,36 @@ -import * as React from "react"; -import { - chevronLeftIcon, - trashIcon, -} from "@progress/kendo-svg-icons"; +import React, { useEffect, useState } from 'react'; +import { chevronLeftIcon, trashIcon } from '@progress/kendo-svg-icons'; -import { NumericTextBox } from "@progress/kendo-react-inputs"; -import { Button } from "@progress/kendo-react-buttons"; -import { Layout } from "./Layout"; +import { NumericTextBox } from '@progress/kendo-react-inputs'; +import { Button } from '@progress/kendo-react-buttons'; +import { Layout } from './Layout'; + +import { useStore } from '@nanostores/react'; +import { selectedLanguage } from '../helpers/languageStore'; +import { loadMessages, LocalizationProvider } from '@progress/kendo-react-intl'; + +import enMessages from '../data/messages/en'; +import frMessages from '../data/messages/fr'; +import esMessages from '../data/messages/es'; + +loadMessages(enMessages, 'en'); +loadMessages(frMessages, 'fr'); +loadMessages(esMessages, 'es'); + +const messages = { + en: enMessages, + fr: frMessages, + es: esMessages, +}; export const ShoppingCartList: React.FC = () => { - const [shoppingCart, setShoppingCart] = React.useState([]); + const language = useStore(selectedLanguage); + const t = messages[language] || messages['en']; + + const [shoppingCart, setShoppingCart] = useState([]); - React.useEffect(() => { - const storedCart = JSON.parse(localStorage.getItem("cart") || "[]"); + useEffect(() => { + const storedCart = JSON.parse(localStorage.getItem('cart') || '[]'); setShoppingCart(storedCart); }, []); @@ -22,89 +40,96 @@ export const ShoppingCartList: React.FC = () => { const onProceedClick = () => { window.location.href = "/kendo-react/kendo-react-e-commerce-astro-app/paymentdetails"; + window.location.href = '/products'; }; const updateQuantity = (index: number, value: number) => { const updatedCart = [...shoppingCart]; updatedCart[index].quantity = value; setShoppingCart(updatedCart); - localStorage.setItem("cart", JSON.stringify(updatedCart)); + localStorage.setItem('cart', JSON.stringify(updatedCart)); }; const removeItem = (index: number) => { const updatedCart = shoppingCart.filter((_, i) => i !== index); setShoppingCart(updatedCart); - localStorage.setItem("cart", JSON.stringify(updatedCart)); + localStorage.setItem('cart', JSON.stringify(updatedCart)); }; return ( - <> - -
- Shopping Cart -
-
- -
- - {shoppingCart.length > 0 ? ( - shoppingCart.map((item, index) => ( -
+ <> + +
+ {t.shoppingCartTitle} +
+
+
+ + {shoppingCart.length > 0 ? ( + shoppingCart.map((item, index) => ( +
-
- {item.title} - {`$${item.newPrice.toLocaleString()}`} - - - updateQuantity(index, e.value ?? item.quantity) - } - width={"118px"} - fillMode={"flat"} - /> - - + > + {item.title} +
+ {item.title} + {`$${item.newPrice.toLocaleString()}`} + + + updateQuantity(index, e.value ?? item.quantity) + } + width={'118px'} + fillMode={'flat'} + /> + + +
-
- )) - ) : ( -

Your shopping cart is empty.

- )} -
- {shoppingCart.length > 0 && ( - - + )) + ) : ( +

{t.emptyCartMessage}

+ )}
- )} - + {shoppingCart.length > 0 && ( + + + + )} + + ); }; diff --git a/examples/kendo-react-e-commerce-astro-app/src/components/Testemonials.tsx b/examples/kendo-react-e-commerce-astro-app/src/components/Testemonials.tsx index 14f9181a..e0a0d2c8 100644 --- a/examples/kendo-react-e-commerce-astro-app/src/components/Testemonials.tsx +++ b/examples/kendo-react-e-commerce-astro-app/src/components/Testemonials.tsx @@ -1,62 +1,95 @@ import { Avatar } from '@progress/kendo-react-layout'; import { Rating } from '@progress/kendo-react-inputs'; -import { TestemonialsDataDescriptor } from '../data/types'; +import { useStore } from '@nanostores/react'; +import { selectedLanguage } from '../helpers/languageStore'; +import { loadMessages, LocalizationProvider } from '@progress/kendo-react-intl'; -const testemonialsData: TestemonialsDataDescriptor[] = [ - { - image: '/kendo-react/kendo-react-e-commerce-astro-app/testemonials1.jpg', - name: "Erica Moore", - rating: 5, - description: "Vilora exceeded all my expectations! The craftsmanship of my diamond necklace is absolutely stunning, and the attention to detail is unparalleled. From the moment I placed my order to the day it arrived, the entire experience was flawless." - }, - { - image: '/kendo-react/kendo-react-e-commerce-astro-app/testemonials2.jpg', - name: "Kelvin Hettinger", - rating: 4.5, - description: "I couldn't be happier with my custom engagement ring from Vilora. The team helped me design the perfect piece, and the final result was even more beautiful than I imagined. Their service, quality, and dedication to excellence make Vilora my go-to for all fine jewelry." - }, - { - image: '/kendo-react/kendo-react-e-commerce-astro-app/testemonials3.jpg', - name: "Karen Brooks", - rating: 5, - description: "Vilora’s collection is nothing short of breathtaking. I recently purchased a white sapphire ring, and it’s become my favorite piece. The elegance and brilliance of the jewelry reflect their impeccable taste and high standards. Highly recommend!" - } +import enMessages from '../data/messages/en'; +import frMessages from '../data/messages/fr'; +import esMessages from '../data/messages/es'; + +loadMessages(enMessages, 'en'); +loadMessages(frMessages, 'fr'); +loadMessages(esMessages, 'es'); + +const messages = { + en: enMessages, + fr: frMessages, + es: esMessages, +}; + +const testemonialsData = [ + { + image: '/kendo-react/kendo-react-e-commerce-astro-app/testemonials1.jpg', + name: 'Erica Moore', + rating: 5, + description: + 'Vilora exceeded all my expectations! The craftsmanship of my diamond necklace is absolutely stunning, and the attention to detail is unparalleled. From the moment I placed my order to the day it arrived, the entire experience was flawless.', + }, + { + image: '/kendo-react/kendo-react-e-commerce-astro-app/testemonials2.jpg', + name: 'Kelvin Hettinger', + rating: 4.5, + description: + 'I couldn’t be happier with my custom engagement ring from Vilora. The team helped me design the perfect piece, and the final result was even more beautiful than I imagined. Their service, quality, and dedication to excellence make Vilora my go-to for all fine jewelry.', + }, + { + image: '/kendo-react/kendo-react-e-commerce-astro-app/testemonials3.jpg', + name: 'Karen Brooks', + rating: 5, + description: + 'Vilora’s collection is nothing short of breathtaking. I recently purchased a white sapphire ring, and it’s become my favorite piece. The elegance and brilliance of the jewelry reflect their impeccable taste and high standards. Highly recommend!', + }, ]; export const Testemonials = () => { - return ( -
-
-

Customers words

-

- What do they say about us? + const language = useStore(selectedLanguage); + const t = messages[language] || messages['en']; + + return ( + +

+
+

{t.testimonialsTitle || 'What Our Customers Say'}

+

+ {t.testimonialsSubtitle || 'Discover stories from our satisfied customers.'} +

+
+
+ {testemonialsData.map((item, index) => ( +
+
+
+ + {item.name} + +
+

+ {item.name}

+ +
+
+

{item.description}

+
-
- {testemonialsData.map((item, index) => ( -
-
-
- - - -
-

{item.name}

- -
-
-

- {item.description} -

-
-
- ))} -
+ ))}
- ); +
+ + ); }; + +export default Testemonials; diff --git a/examples/kendo-react-e-commerce-astro-app/src/components/ThankYou.tsx b/examples/kendo-react-e-commerce-astro-app/src/components/ThankYou.tsx index 2ddf7438..4a2b281b 100644 --- a/examples/kendo-react-e-commerce-astro-app/src/components/ThankYou.tsx +++ b/examples/kendo-react-e-commerce-astro-app/src/components/ThankYou.tsx @@ -1,32 +1,58 @@ import React from 'react'; -import { Layout } from "../components/Layout"; +import { Layout } from '../components/Layout'; import { BackgroundImage } from '../components/BackgroundImage'; -import { Button } from "@progress/kendo-react-buttons"; +import { Button } from '@progress/kendo-react-buttons'; + +import { useStore } from '@nanostores/react'; +import { selectedLanguage } from '../helpers/languageStore'; +import { loadMessages, LocalizationProvider } from '@progress/kendo-react-intl'; + +import enMessages from '../data/messages/en'; +import frMessages from '../data/messages/fr'; +import esMessages from '../data/messages/es'; + +loadMessages(enMessages, 'en'); +loadMessages(frMessages, 'fr'); +loadMessages(esMessages, 'es'); + +const messages = { + en: enMessages, + fr: frMessages, + es: esMessages, +}; const ThankYou: React.FC = () => { + const language = useStore(selectedLanguage); + const t = messages[language]; const onBacktoShoppingClick = () => { - window.location.href = "/kendo-react/kendo-react-e-commerce-astro-app/products"; + window.location.href = '/kendo-react/kendo-react-e-commerce-astro-app/products'; }; return ( - <> - - -
-

Thank You For Your Order!

-

You have submitted your order

- -
-
- + + <> + + +
+

{t.thankYouTitle}

+

{t.thankYouSubtitle}

+ +
+
+ +
); }; diff --git a/examples/kendo-react-e-commerce-astro-app/src/data/listData.tsx b/examples/kendo-react-e-commerce-astro-app/src/data/listData.tsx index 793ea6f7..0d3b2984 100644 --- a/examples/kendo-react-e-commerce-astro-app/src/data/listData.tsx +++ b/examples/kendo-react-e-commerce-astro-app/src/data/listData.tsx @@ -1,190 +1,273 @@ -import { ListDataDescriptor } from "./types.ts"; +import { ListDataDescriptor } from "./types"; +import enMessages from "../data/messages/en"; +import frMessages from "../data/messages/fr"; +import esMessages from "../data/messages/es"; -export const listData: ListDataDescriptor[] = [ - { - img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/diamondWeddingRing.png", - status: "sale", - title: "Diamond Wedding Ring", - category: "Rings", - material: "Silver", - oldPrice: 990, - newPrice: 890, - }, - { - img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/silverBraceletCross.png", - status: "recommended", - category: "Bracelets", - material: "Silver", - title: "Silver Bracelet with Cross", - oldPrice: null, - newPrice: 270, - }, - { - img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/pinkSilverBracelet.png", - status: null, - category: "Bracelets", - material: "Silver", - title: "Pink Silver Bracelet", - oldPrice: null, - newPrice: 460, - }, - { - img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/yellowGoldEarrings.png", - status: "sale", - category: "Earrings", - material: "Silver", - title: "Yellow Gold Earrings", - oldPrice: 500, - newPrice: 380, - }, - { - img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/necklace.png", - status: null, - category: "Necklaces", - material: "Silver", - title: "Silver Heart Necklace", - oldPrice: null, - newPrice: 400, - }, - { - img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/handmadeSilverEarrings.png", - status: null, - category: "Earrings", - material: "Silver", - title: "Handmade Silver Earrings", - oldPrice: null, - newPrice: 650, - }, - { - img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/diamondWeddingBands.png", - status: "recommended", - title: "Diamond Wedding Bands", - material: "Gold", - category: "Rings", - oldPrice: null, - newPrice: 4290, - }, - { - img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/casualSilverWatch.png", - status: null, - title: "Casual Silver Watch", - category: "Watches", - material: "Silver", - oldPrice: null, - newPrice: 390, - }, - { - img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/silverBraceletOnyx.png", - status: "sale", - title: "Silver Bracelet with Onyx", - material: "Silver", - category: "Bracelets", - oldPrice: 950, - newPrice: 770, - }, - { - img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/weddingBandsPearl.png", - status: "must have", - title: "Wedding Bands with Pearls", - material: "Gold", - category: "Rings", - oldPrice: null, - newPrice: 900, - }, - { - img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/silverWeddingBands.png", - status: null, - title: "Silver Wedding Bands", - material: "Silver", - category: "Rings", - oldPrice: null, - newPrice: 250, - }, - { - img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/handmadeYellowGoldRing.png", - status: null, - category: "Rings", - material: "Silver", - title: "Handmade Yellow Gold Ring", - oldPrice: null, - newPrice: 560, - }, - { - img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/diamondRingSapphire.png", - status: "must have", - title: "Diamond Ring with Sapphire", - category: "Rings", - material: "Gold", - oldPrice: null, - newPrice: 3590, - }, - { - img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/silverHeartBracelet.png", - status: null, - title: "Silver Heart Bracelet", - category: "Bracelets", - material: "Silver", - oldPrice: null, - newPrice: 430, - }, - { - img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/roseGoldEarringsOpal.png", - status: "Sale", - title: "Rose Gold Earrings with Opal", - category: "Earrings", - material: "Gold", - oldPrice: 850, - newPrice: 690, - }, - { - img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/silverBraceletTopaz.png", - status: null, - category: "Bracelets", - material: "Silver", - title: "Silver Bracelet with Topaz", - oldPrice: null, - newPrice: 580, - }, - { - img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/handmadeDiamongRing.png", - status: null, - category: "Rings", - material: "Gold", - title: "Handmade Diamond Ring", - oldPrice: null, - newPrice: 1100, - }, - { - img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/diamondRingRuby.png", - status: "must have", - category: "Rings", - material: "Gold", - title: "Diamond Ring with Ruby", - oldPrice: null, - newPrice: 5560, - }, - { - img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/stainlessSteelWatch.png", - status: null, - material: "Silver", - category: "Watches", - title: "Silver Watch", - oldPrice: null, - newPrice: 270, - }, - { - img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/goldEarringsGarnet.png", - status: null, - category: "Earrings", - material: "Gold", - title: "Gold Earrings with Garnet", - oldPrice: null, - newPrice: 270, - }, -].map((item, index) => ({ - ...item, - id: index + 1, - rating: Math.floor(Math.random() * 5) + 3, -})); +const translations = { + en: enMessages, + fr: frMessages, + es: esMessages, +}; -export default listData \ No newline at end of file +const getTranslations = (): typeof enMessages => { + let language = "en"; + + if (typeof window !== "undefined" && typeof localStorage !== "undefined") { + language = localStorage.getItem("selectedLanguage") || "en"; + } + + return translations[language] || translations["en"]; +}; + +export const getTranslatedListData = (): ListDataDescriptor[] => { + const t = getTranslations(); + + return [ + { + img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/diamondWeddingRing.png", + status: t.statuses.statusSale, + title: t.diamondWeddingRing, + titleKey: 'diamondWeddingRing', + category: t.categories.Rings, + categoryKey: 'Rings', + material: t.materials.materialSilver, + materialKey: 'materialSilver', + oldPrice: 990, + newPrice: 890, + }, + { + img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/silverBraceletCross.png", + status: t.statuses.statusRecommended, + title: t.silverBraceletWithCross, + titleKey: 'silverBraceletWithCross', + category: t.categories.Bracelets, + categoryKey: 'Bracelets', + material: t.materials.materialSilver, + materialKey: 'materialSilver', + oldPrice: null, + newPrice: 270, + }, + { + img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/pinkSilverBracelet.png", + status: null, + title: t.pinkSilverBracelet, + titleKey: 'pinkSilverBracelet', + category: t.categories.Bracelets, + categoryKey: 'Bracelets', + material: t.materials.materialSilver, + materialKey: 'materialSilver', + oldPrice: null, + newPrice: 460, + }, + { + img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/yellowGoldEarrings.png", + status: t.statuses.statusSale, + title: t.yellowGoldEarrings, + titleKey: 'yellowGoldEarrings', + category: t.categories.Earrings, + categoryKey: 'Earrings', + material: t.materials.materialGold, + materialKey: 'materialGold', + oldPrice: 500, + newPrice: 380, + }, + { + img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/necklace.png", + status: null, + title: t.silverHeartNecklace, + titleKey: 'silverHeartNecklace', + category: t.categories.Necklaces, + categoryKey: 'Necklaces', + material: t.materials.materialSilver, + materialKey: 'materialSilver', + oldPrice: null, + newPrice: 400, + }, + { + img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/handmadeSilverEarrings.png", + status: null, + title: t.handmadeSilverEarrings, + titleKey: 'handmadeSilverEarrings', + category: t.categories.Earrings, + categoryKey: 'Earrings', + material: t.materials.materialSilver, + materialKey: 'materialSilver', + oldPrice: null, + newPrice: 650, + }, + { + img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/diamondWeddingBands.png", + status: t.statuses.statusRecommended, + title: t.diamondWeddingBands, + titleKey: 'diamondWeddingBands', + category: t.categories.Rings, + categoryKey: 'Rings', + material: t.materials.materialGold, + materialKey: 'materialGold', + oldPrice: null, + newPrice: 4290, + }, + { + img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/casualSilverWatch.png", + status: null, + title: t.casualSilverWatch, + titleKey: 'casualSilverWatch', + category: t.categories.Watches, + categoryKey: 'Watches', + material: t.materials.materialSilver, + materialKey: 'materialSilver', + oldPrice: null, + newPrice: 390, + }, + { + img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/silverBraceletOnyx.png", + status: t.statuses.statusSale, + title: t.silverBraceletWithOnyx, + titleKey: 'silverBraceletWithOnyx', + category: t.categories.Bracelets, + categoryKey: 'Bracelets', + material: t.materials.materialSilver, + materialKey: 'materialSilver', + oldPrice: 950, + newPrice: 770, + }, + { + img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/weddingBandsPearl.png", + status: t.statuses.statusMustHave, + title: t.weddingBandsWithPearls, + titleKey: 'weddingBandsWithPearls', + category: t.categories.Rings, + categoryKey: 'Rings', + material: t.materials.materialGold, + materialKey: 'materialGold', + oldPrice: null, + newPrice: 900, + }, + { + img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/silverWeddingBands.png", + status: null, + title: t.silverWeddingBands, + titleKey: 'silverWeddingBands', + category: t.categories.Rings, + categoryKey: 'Rings', + material: t.materials.materialSilver, + materialKey: 'materialSilver', + oldPrice: null, + newPrice: 250, + }, + { + img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/handmadeYellowGoldRing.png", + status: null, + title: t.handmadeYellowGoldRing, + titleKey: 'handmadeYellowGoldRing', + category: t.categories.Rings, + categoryKey: 'Rings', + material: t.materials.materialGold, + materialKey: 'materialGold', + oldPrice: null, + newPrice: 560, + }, + { + img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/diamondRingSapphire.png", + status: t.statuses.statusMustHave, + title: t.diamondRingWithSapphire, + titleKey: 'diamondRingWithSapphire', + category: t.categories.Rings, + categoryKey: 'Rings', + material: t.materials.materialGold, + materialKey: 'materialGold', + oldPrice: null, + newPrice: 3590, + }, + { + img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/silverHeartBracelet.png", + status: null, + title: t.silverHeartBracelet, + titleKey: 'silverHeartBracelet', + category: t.categories.Bracelets, + categoryKey: 'Bracelets', + material: t.materials.materialSilver, + materialKey: 'materialSilver', + oldPrice: null, + newPrice: 430, + }, + { + img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/roseGoldEarringsOpal.png", + status: t.statuses.statusSale, + title: t.roseGoldEarringsWithOpal, + titleKey: 'roseGoldEarringsWithOpal', + category: t.categories.Earrings, + categoryKey: 'Earrings', + material: t.materials.materialGold, + materialKey: 'materialGold', + oldPrice: 850, + newPrice: 690, + }, + { + img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/silverBraceletTopaz.png", + status: null, + title: t.silverBraceletWithTopaz, + titleKey: 'silverBraceletWithTopaz', + category: t.categories.Bracelets, + categoryKey: 'Bracelets', + material: t.materials.materialSilver, + materialKey: 'materialSilver', + oldPrice: null, + newPrice: 580, + }, + { + img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/handmadeDiamondRing.png", + status: null, + title: t.handmadeDiamondRing, + titleKey: 'handmadeDiamondRing', + category: t.categories.Rings, + categoryKey: 'Rings', + material: t.materials.materialGold, + materialKey: 'materialGold', + oldPrice: null, + newPrice: 1100, + }, + { + img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/diamondRingRuby.png", + status: t.statuses.statusMustHave, + title: t.diamondRingWithRuby, + titleKey: 'diamondRingWithRuby', + category: t.categories.Rings, + categoryKey: 'Rings', + material: t.materials.materialGold, + materialKey: 'materialGold', + oldPrice: null, + newPrice: 5560, + }, + { + img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/stainlessSteelWatch.png", + status: null, + title: t.silverWatch, + titleKey: 'silverWatch', + category: t.categories.Watches, + categoryKey: 'Watches', + material: t.materials.materialSilver, + materialKey: 'materialSilver', + oldPrice: null, + newPrice: 270, + }, + { + img: "/kendo-react/kendo-react-e-commerce-astro-app/listViewImages/goldEarringsGarnet.png", + status: null, + title: t.goldEarringsWithGarnet, + titleKey: 'goldEarringsWithGarnet', + category: t.categories.Earrings, + categoryKey: 'Earrings', + material: t.materials.materialGold, + materialKey: 'materialGold', + oldPrice: null, + newPrice: 270, + }, + ].map((item, index) => ({ + ...item, + id: index + 1, + rating: Math.floor(Math.random() * 5) + 3, + })); +}; + +export default getTranslatedListData; diff --git a/examples/kendo-react-e-commerce-astro-app/src/data/messages/en.ts b/examples/kendo-react-e-commerce-astro-app/src/data/messages/en.ts new file mode 100644 index 00000000..326f2118 --- /dev/null +++ b/examples/kendo-react-e-commerce-astro-app/src/data/messages/en.ts @@ -0,0 +1,492 @@ +export const en = { + title: "Vilora Jewelry", + subtitle: "We offer exquisite jewelry, each showcasing timeless elegance", + buttonText: "See Collections", + searchPlaceholder: "Search", + addToCartButtonText: "Add to Cart", + adminLabel: "Admin", + clientLabel: "Client", + + languageMenuTitle: "Language", + languageEnglish: "English", + languageFrench: "French", + languageSpanish: "Spanish", + cookiesText: "We use cookies to improve your experience.", + rightsReservedText: "All rights reserved.", + subscribeText: "Subscribe to our Newsletter:", + emailPlaceholder: "Email", + subscribeButtonText: "Subscribe", + filterLabel: "Filter:", + sortByLabel: "Sort by:", + clearFiltersButton: "Clear Filters", + categoryPlaceholder: "Category", + materialPlaceholder: "Material", + categoriesData: ["Bracelets", "Rings", "Earrings", "Watches", "Necklaces"], + statusesData: ["Sale", "Recommended", "Must Have"], + materialsData: ["Gold", "Silver"], + followUsText: "Follow us:", + shoppingCartTitle: "Shopping Cart", + backButtonText: "Back", + whyChooseUs: "Why people choose us?", + returnPolicyTitle: "Return Policy", + returnPolicyContent: "You can return your items within 30 days for a full refund or exchange.", + includedGiftWrappingTitle: "Included Gift Wrapping", + includedGiftWrappingContent: "Add gift wrapping for a special touch, along with a personalized message for your loved ones.", + discountCodeTitle: "Discount Code Available", + discountCodeContent: "Apply your discount code at checkout to enjoy exclusive savings on your order.", + removeButtonText: "Remove", + emptyCartMessage: "Your shopping cart is empty.", + proceedToCheckoutButtonText: "Proceed to Checkout", + "radioButtons": { + "new": "New", + "existing": "Existing", + "justCurious": "Just curious" + }, + customerCareTitle: "Customer Care", + customerCareLinks: [ + "Contact Us", + "Shopping Online", + "Track Your Order", + "Shipping & Delivery", + "Orders & Payment", + "Help", + ], + ourCompanyTitle: "Our Company", + ourCompanyLinks: [ + "Prominent Locations", + "Careers", + "Corporate Responsibility", + "Sustainability", + "Society Care", + ], + legalPrivacyTitle: "Legal & Privacy", + legalPrivacyLinks: [ + "Terms of Use", + "Conditions of Sale", + "Return Policy", + "Privacy Policy", + "Cookie Policy", + ], + // Menu Translations + menuHome: "Home", + menuJewelry: "Jewelry", + menuContacts: "Contacts", + menuBracelets: "Bracelets", + menuRings: "Rings", + menuEarrings: "Earrings", + menuWatches: "Watches", + menuAll: "All", + // Other Translations + bestsellersTitle: "Our Bestsellers", + bestsellersSubtitle: "Enjoy an excellent selection of fine jewelry", + buyNowButtonText: "Buy Now", + timelessTitle: "Timeless Classics", + timelessSubtitle: "Get our unique handmade collections", + timelessContent: + "Jewelry enhances style and adds elegance, with each piece telling a unique story.", + fineJewelryTitle: "Fine Jewelry", + fineJewelrySubtitle: "Get our unique handmade collections", + fineJewelryContent: + "Jewelry elevates one's style and brings sophistication, with every piece narrating a distinct tale.", + ringsTitle: "Our Rings", + ringsSubtitle: "Enjoy an excellent selection of fine rings", + watchesTitle: "Our Watches", + watchesSubtitle: "Enjoy an excellent selection of watches", + watchesContent: + "High-end gold watches for men are the epitome of luxury, combining precision with sophisticated craftsmanship.", + servicesTitle: "Services", + servicesSubtitle: "Explore expert repairs to elevate your experience", + servicesContent: + "Vilora provides services like custom designs, repairs, and appraisals to enhance the customer experience.", + testimonialsTitle: "Customer Words", + testimonialsSubtitle: "What do they say about us?", + testimonialsData: [ + { + image: "/testemonials1.jpg", + name: "Erica Moore", + rating: 5, + description: + "Vilora exceeded all my expectations! The craftsmanship of my diamond necklace is absolutely stunning, and the attention to detail is unparalleled. From the moment I placed my order to the day it arrived, the entire experience was flawless.", + }, + { + image: "/testemonials2.jpg", + name: "Kelvin Hettinger", + rating: 4.5, + description: + "I couldn't be happier with my custom engagement ring from Vilora. The team helped me design the perfect piece, and the final result was even more beautiful than I imagined. Their service, quality, and dedication to excellence make Vilora my go-to for all fine jewelry.", + }, + { + image: "/testemonials3.jpg", + name: "Karen Brooks", + rating: 5, + description: + "Vilora’s collection is nothing short of breathtaking. I recently purchased a white sapphire ring, and it’s become my favorite piece. The elegance and brilliance of the jewelry reflect their impeccable taste and high standards. Highly recommend!", + }, + ], + // Contacts Page Translations + getInTouchTitle: "Get in touch", + getInTouchSubtitle: "If you have any questions, contact us", + fullNameLabel: "Full Name", + fullNamePlaceholder: "Enter your full name", + emailLabel: "Email", + phoneNumberLabel: "Phone Number", + typeOfCustomerLabel: "Type of customer", + dateLabel: "Date", + bookSlotButton: "Book a Slot", + contactsImageAlt: "Contacts", + // Thank You Page Translations + thankYouTitle: "Thank You For Your Order!", + thankYouSubtitle: "You have submitted your order", + backToShoppingButton: "Back to Shopping", + allProductsTitle: "Fine Selection", + allProductsSubtitle: "Enjoy the real craftsmanship", + allProductsContentText: + "Jewelry is a meaningful form of self-expression that enhances personal style and adds beauty to any occasion.", + collectionSerene: 'Collection "SERENE"', + collectionAurelia: 'Collection "AURELIA"', + chartSelectedDataButton: "Chart of Selected Data", + top3SalesButton: "Top 3 Sales per Category", + collectionRavina: 'Collection "RAVINA"', + ourCollectionsTitle: "Our Collections", + ourCollectionsSubtitle: "Enjoy an excellent selection of fine jewelry", + breadcrumbHome: "Home", + breadcrumbJewelry: "Jewelry", + buyButtonText: "Buy", + handmadePinkDiamondRing: "Handmade Pink Diamond Ring", + diamondRingWithPinkRuby: "Diamond Ring with Pink Ruby", + whiteSandDiamondRing: "White Sand Diamond Ring", + productSubtitle: "In Platinum with Natural Diamond", + productDescription: "Elegant wedding bands featuring lustrous pearls.", + reviewsText: "{0} reviews", + youMayAlsoLikeTitle: "You May Also Like", + youMayAlsoLikeSubtitle: "Enjoy an excellent selection of fine jewelry", + categories: { + Bracelets: "Bracelets", + Rings: "Rings", + Earrings: "Earrings", + Watches: "Watches", + Necklaces: "Necklaces", + }, + diamondWeddingRing: "Diamond Wedding Ring", + silverBraceletWithCross: "Silver Bracelet with Cross", + pinkSilverBracelet: "Pink Silver Bracelet", + yellowGoldEarrings: "Yellow Gold Earrings", + silverHeartNecklace: "Silver Heart Necklace", + handmadeSilverEarrings: "Handmade Silver Earrings", + diamondWeddingBands: "Diamond Wedding Bands", + casualSilverWatch: "Casual Silver Watch", + silverBraceletWithOnyx: "Silver Bracelet with Onyx", + weddingBandsWithPearls: "Wedding Bands with Pearls", + silverWeddingBands: "Silver Wedding Bands", + handmadeYellowGoldRing: "Handmade Yellow Gold Ring", + diamondRingWithSapphire: "Diamond Ring with Sapphire", + silverHeartBracelet: "Silver Heart Bracelet", + roseGoldEarringsWithOpal: "Rose Gold Earrings with Opal", + silverBraceletWithTopaz: "Silver Bracelet with Topaz", + handmadeDiamondRing: "Handmade Diamond Ring", + diamondRingWithRuby: "Diamond Ring with Ruby", + silverWatch: "Silver Watch", + goldEarringsWithGarnet: "Gold Earrings with Garnet", + statuses: { + statusSale: "Sale", + statusRecommended: "Recommended", + statusMustHave: "Must Have", + }, + materials: { + materialGold: "Gold", + materialSilver: "Silver", + }, + paymentDetailsTitle: "Payment Details", + paymentDetailsSubtitle: "Please, submit your payment details", + paymentMethodCreditCard: "Credit Card", + paymentMethodBankTransfer: "Bank Transfer", + paymentMethodApplePay: "Apple Pay", + cardNumberLabel: "Card Number", + expiryDateLabel: "Expiry Date", + cvvLabel: "CVV*", + cardHolderLabel: "Cardholder", + submitOrderButton: "Submit Order", + subTotalLabel: "Sub total", + usDollarsLabel: "US Dollars", + vatLabel: "VAT", + shippingMethodLabel: "Shipping Method", + standardFreeDeliveryLabel: "Standard Free Delivery", + giftWrappingLabel: "Gift Wrapping", + includedGiftWrappingLabel: "Included Gift Wrapping", + totalLabel: "Total", + grid: { + groupPanelEmpty: "Drag a column header and drop it here to group by that column", + noRecords: "No records available.", + pagerFirstPage: "Go to the first page", + pagerPreviousPage: "Go to the previous page", + productTitle: "Product", + nameTitle: "Name", + skuTitle: "SKU", + categoryTitle: "Category", + priceTitle: "Price", + quantityTitle: "Quantity", + totalSalesTitle: "Total Sales", + pagerNextPage: "Go to the next page", + pagerLastPage: "Go to the last page", + pagerPage: "Page", + pagerOf: "of", + pagerTotalPages: "{0}", + pagerItems: "items", + pagerInfo: "{0} - {1} of {2} items", + pagerItemsPerPage: "items per page", + filterEqOperator: "Is equal to", + filterNotEqOperator: "Is not equal to", + filterIsNullOperator: "Is null", + filterIsNotNullOperator: "Is not null", + filterIsEmptyOperator: "Is empty", + filterIsNotEmptyOperator: "Is not empty", + filterStartsWithOperator: "Starts with", + filterContainsOperator: "Contains", + filterNotContainsOperator: "Does not contain", + filterEndsWithOperator: "Ends with", + filterGteOperator: "Is greater than or equal to", + filterGtOperator: "Is greater than", + filterLteOperator: "Is less than or equal to", + filterLtOperator: "Is less than", + filterIsTrue: "Yes", + filterIsFalse: "No", + filterBooleanAll: "(All)", + filterAfterOrEqualOperator: "Is after or equal to", + filterAfterOperator: "Is after", + filterBeforeOperator: "Is before", + filterBeforeOrEqualOperator: "Is before or equal to", + filterSubmitButton: "Filter", + filterClearButton: "Clear filters", + filterAndLogic: "And", + filterOrLogic: "Or", + filterTitle: "Filter", + sortAscending: "Sort ascending", + sortDescending: "Sort descending", + searchPlaceholder: "Search", + filterCheckAll: "Check all", + pagerItemPerPage: "Items per page", + filterChooseOperator: "Choose operator", + filterSelectedItems: "selected items", + filterAriaLabel: "Filter", + sortAriaLabel: "Sortable", + groupColumn: "Group column", + groupExpand: "Expand group", + groupCollapse: "Collapse group", + groupPanelAriaLabel: "group panel", + ungroupColumn: "Ungroup column", + detailExpand: "Expand detail row", + detailCollapse: "Collapse detail row", + wizard: { + windowTitle: "Chart Preview", + exportButton: "Export", + exportPDF: "PDF File", + exportSVG: "SVG File", + exportPNG: "PNG File", + tabChart: "Chart", + tabData: "Data", + tabFormat: "Format", + barChart: "Bar Chart", + bar: "Bar", + stackedBar: "Stacked Bar", + "100stackedBar": "100% Stacked Bar", + pieChart: "Pie Chart", + pie: "Pie", + columnChart: "Column Chart", + column: "Column", + stackedColumn: "Stacked Column", + "100stackedColumn": "100% Stacked Column", + lineChart: "Line Chart", + line: "Line", + stackedLine: "Stacked Line", + "100stackedLine": "100% Stacked Line", + scatterChart: "Scatter Chart", + scatter: "Scatter", + configuration: "Configuration", + categoryAxis: "Category Axis", + xAxis: "X Axis", + valueAxis: "Value Axis", + series: "Series", + add: "Add", + chartArea: "Chart Area", + margins: "Margins", + auto: "Auto", + left: "Left", + right: "Right", + top: "Top", + bottom: "Bottom", + background: "Background Color", + title: "Title", + applyTo: "Apply to", + chartTitle: "Chart Title", + chartSubtitle: "Chart Subtitle", + font: "Font", + size: "Size", + color: "Color", + legend: "Legend", + showLegend: "Show Legend", + position: "Position", + labels: "Labels", + rotation: "Rotation", + reverseOrder: "Reverse Order", + valueAxisTitle: "Value Axis Title", + categoryAxisTitle: "Category Axis Title", + }, + chartWizard: { + window: { + title: "Chart Preview", + }, + export: { + button: "Export", + PDF: "PDF File", + SVG: "SVG File", + PNG: "PNG File", + }, + tab: { + chart: "Chart", + data: "Data", + format: "Format", + }, + chart: { + barChart: { + expandText: "Bar Chart", + bar: "Bar", + stackedBar: "Stacked Bar", + "100%stackedBar": "100% Stacked Bar", + }, + pieChart: { + expandText: "Pie Chart", + pie: "Pie", + }, + columnChart: { + expandText: "Column Chart", + column: "Column", + stackedColumn: "Stacked Column", + "100%stackedColumn": "100% Stacked Column", + }, + lineChart: { + expandText: "Line Chart", + line: "Line", + stackedLine: "Stacked Line", + "100%stackedLine": "100% Stacked Line", + }, + scatterChart: { + expandText: "Scatter Chart", + scatter: "Scatter", + }, + }, + data: { + configuration: { + expandText: "Configuration", + categoryAxis: "Category Axis", + xAxis: "X Axis", + valueAxis: "Value Axis", + series: { + title: "Series", + add: "Add", + }, + }, + }, + format: { + chartArea: { + expandText: "Chart Area", + margins: { + auto: "Auto", + left: "Left", + right: "Right", + top: "Top", + bottom: "Bottom", + }, + background: { + color: "Color", + }, + }, + title: { + expandText: "Title", + applyTo: "Apply to", + chartTitle: "Chart Title", + chartSubtitle: "Chart Subtitle", + label: "Title", + font: "Font", + fontPlaceholder: "(inherited font)", + size: "Size", + sizePlaceholder: "px", + color: "Color", + }, + series: { + expandText: "Series", + applyTo: "Apply to", + allSeries: "All Series", + color: "Color", + showLabels: "Show Labels", + }, + legend: { + expandText: "Legend", + showLegend: "Show Legend", + font: "Font", + fontPlaceholder: "(inherited font)", + size: "Size", + sizePlaceholder: "px", + color: "Color", + position: { + top: "Top", + bottom: "Bottom", + left: "Left", + right: "Right", + }, + }, + categoryAxis: { + expandText: "Category Axis", + title: { + expandText: "Title", + placeholder: "Axis Title", + font: "Font", + fontPlaceholder: "(inherited font)", + size: "Size", + sizePlaceholder: "px", + color: "Color", + }, + labels: { + text: "Labels", + font: "Font", + fontPlaceholder: "(inherited font)", + size: "Size", + sizePlaceholder: "px", + color: "Color", + rotation: { + text: "Rotation", + auto: "Auto", + }, + reverseOrder: "Reverse Order", + }, + }, + valueAxis: { + expandText: "Value Axis", + title: { + text: "Title", + placeholder: "Axis Title", + font: "Font", + fontPlaceholder: "(inherited font)", + size: "Size", + sizePlaceholder: "px", + color: "Color", + }, + labels: { + text: "Labels", + font: "Font", + fontPlaceholder: "(inherited font)", + size: "Size", + sizePlaceholder: "px", + color: "Color", + rotation: { + text: "Rotation", + auto: "Auto", + }, + }, + }, + }, + }, + }, +} + + +export default en \ No newline at end of file diff --git a/examples/kendo-react-e-commerce-astro-app/src/data/messages/es.ts b/examples/kendo-react-e-commerce-astro-app/src/data/messages/es.ts new file mode 100644 index 00000000..232aa5d6 --- /dev/null +++ b/examples/kendo-react-e-commerce-astro-app/src/data/messages/es.ts @@ -0,0 +1,495 @@ +export const es = { + title: "Joyería Vilora", + subtitle: + "Ofrecemos joyería exquisita, cada una mostrando elegancia atemporal", + buttonText: "Ver Colecciones", + searchPlaceholder: "Buscar", + addToCartButtonText: "Agregar al Carrito", + adminLabel: "Admin", + clientLabel: "Cliente", + languageMenuTitle: "Idioma", + languageEnglish: "Inglés", + languageFrench: "Francés", + languageSpanish: "Español", + cookiesText: "Usamos cookies para mejorar tu experiencia.", + rightsReservedText: "Todos los derechos reservados.", + subscribeText: "Suscríbete a nuestro boletín:", + emailPlaceholder: "Correo electrónico", + subscribeButtonText: "Suscribirse", + filterLabel: "Filtrar:", + sortByLabel: "Ordenar por:", + clearFiltersButton: "Borrar filtros", + categoryPlaceholder: "Categoría", + materialPlaceholder: "Material", + categoriesData: ["Pulseras", "Anillos", "Pendientes", "Relojes", "Collares"], + statusesData: ["Oferta", "Recomendado", "Imprescindible"], + materialsData: ["Oro", "Plata"], + whyChooseUs: "¿Por qué elegirnos?", + returnPolicyTitle: "Política de Devoluciones", + returnPolicyContent: "Puede devolver sus artículos dentro de los 30 días para obtener un reembolso completo o un cambio.", + includedGiftWrappingTitle: "Envoltorio de Regalo Incluido", + includedGiftWrappingContent: "Agregue un envoltorio de regalo para un toque especial, junto con un mensaje personalizado para sus seres queridos.", + discountCodeTitle: "Código de Descuento Disponible", + discountCodeContent: "Aplique su código de descuento al finalizar la compra para disfrutar de ahorros exclusivos en su pedido.", + followUsText: "Síguenos en:", + shoppingCartTitle: "Carrito de Compras", + backButtonText: "Volver", + removeButtonText: "Eliminar", + emptyCartMessage: "Tu carrito está vacío.", + proceedToCheckoutButtonText: "Proceder al Pago", + customerCareTitle: "Atención al Cliente", + "radioButtons": { + "new": "Nuevo", + "existing": "Existente", + "justCurious": "Solo curioso" + }, + customerCareLinks: [ + "Contáctanos", + "Compras en Línea", + "Rastrea tu Pedido", + "Envío y Entrega", + "Pedidos y Pago", + "Ayuda", + ], + ourCompanyTitle: "Nuestra Empresa", + ourCompanyLinks: [ + "Ubicaciones Destacadas", + "Carreras", + "Responsabilidad Corporativa", + "Sostenibilidad", + "Cuidado de la Sociedad", + ], + legalPrivacyTitle: "Legal y Privacidad", + legalPrivacyLinks: [ + "Términos de Uso", + "Condiciones de Venta", + "Política de Devoluciones", + "Política de Privacidad", + "Política de Cookies", + ], + // Menu Translations + menuHome: "Inicio", + menuJewelry: "Joyería", + menuContacts: "Contactos", + menuBracelets: "Pulseras", + menuRings: "Anillos", + menuEarrings: "Pendientes", + menuWatches: "Relojes", + menuAll: "Todo", + // Other Translations + bestsellersTitle: "Nuestros Más Vendidos", + bestsellersSubtitle: "Disfruta de una excelente selección de joyas finas", + buyNowButtonText: "Comprar Ahora", + timelessTitle: "Clásicos Atemporales", + timelessSubtitle: "Obtén nuestras colecciones únicas hechas a mano", + timelessContent: + "Las joyas mejoran el estilo y agregan elegancia, cada pieza cuenta una historia única.", + fineJewelryTitle: "Joyería Fina", + fineJewelrySubtitle: "Obtén nuestras colecciones únicas hechas a mano", + fineJewelryContent: + "Las joyas elevan el estilo y aportan sofisticación, cada pieza narra una historia distinta.", + ringsTitle: "Nuestros Anillos", + ringsSubtitle: "Disfruta de una excelente selección de anillos finos", + watchesTitle: "Nuestros Relojes", + watchesSubtitle: "Disfruta de una excelente selección de relojes", + watchesContent: + "Los relojes de oro de alta gama para hombres son el epítome del lujo, combinando precisión con una artesanía sofisticada.", + servicesTitle: "Servicios", + servicesSubtitle: "Explora reparaciones expertas para mejorar tu experiencia", + servicesContent: + "Vilora ofrece servicios como diseños personalizados, reparaciones y tasaciones para mejorar la experiencia del cliente.", + testimonialsTitle: "Palabras de los Clientes", + testimonialsSubtitle: "¿Qué dicen de nosotros?", + testimonialsData: [ + { + image: "/testemonials1.jpg", + name: "Erica Moore", + rating: 5, + description: + "¡Vilora superó todas mis expectativas! La artesanía de mi collar de diamantes es absolutamente impresionante, y la atención al detalle es inigualable. Desde el momento en que realicé mi pedido hasta el día que llegó, toda la experiencia fue impecable.", + }, + { + image: "/testemonials2.jpg", + name: "Kelvin Hettinger", + rating: 4.5, + description: + "No podría estar más feliz con mi anillo de compromiso personalizado de Vilora. El equipo me ayudó a diseñar la pieza perfecta, y el resultado final fue aún más hermoso de lo que imaginé. Su servicio, calidad y dedicación a la excelencia hacen de Vilora mi opción para todas las joyas finas.", + }, + { + image: "/testemonials3.jpg", + name: "Karen Brooks", + rating: 5, + description: + "La colección de Vilora es simplemente impresionante. Recientemente compré un anillo de zafiro blanco, y se ha convertido en mi pieza favorita. La elegancia y el brillo de las joyas reflejan su impecable gusto y altos estándares. ¡Altamente recomendado!", + }, + ], + // Contacts Page Translations + getInTouchTitle: "Ponte en contacto", + getInTouchSubtitle: "Si tienes alguna pregunta, contáctanos", + fullNameLabel: "Nombre completo", + fullNamePlaceholder: "Ingresa tu nombre completo", + emailLabel: "Correo electrónico", + phoneNumberLabel: "Número de teléfono", + typeOfCustomerLabel: "Tipo de cliente", + dateLabel: "Fecha", + bookSlotButton: "Reservar una cita", + contactsImageAlt: "Contactos", + // Thank You Page Translations + thankYouTitle: "¡Gracias por su pedido!", + thankYouSubtitle: "Ha enviado su pedido", + backToShoppingButton: "Volver a comprar", + allProductsTitle: "Selección Fina", + allProductsSubtitle: "Disfruta de la verdadera artesanía", + allProductsContentText: + "La joyería es una forma significativa de autoexpresión que mejora el estilo personal y agrega belleza a cualquier ocasión.", + collectionSerene: 'Colección "SERENE"', + chartSelectedDataButton: "Gráfico de datos seleccionados", + top3SalesButton: "Top 3 de ventas por categoría", + collectionAurelia: 'Colección "AURELIA"', + collectionRavina: 'Colección "RAVINA"', + ourCollectionsTitle: "Nuestras Colecciones", + ourCollectionsSubtitle: "Disfruta de una excelente selección de joyería fina", + breadcrumbHome: "Inicio", + breadcrumbJewelry: "Joyería", + buyButtonText: "Comprar", + handmadePinkDiamondRing: "Anillo de diamante rosa hecho a mano", + diamondRingWithPinkRuby: "Anillo de diamante con rubí rosa", + whiteSandDiamondRing: "Anillo de diamante de arena blanca", + productSubtitle: "En platino con diamante natural", + productDescription: "Elegantes alianzas con perlas lustrosas.", + reviewsText: "{0} reseñas", + youMayAlsoLikeTitle: "También te puede interesar", + youMayAlsoLikeSubtitle: "Disfruta de una excelente selección de joyería fina", + thankYou: { + title: "Thank You!", + subtitle: "Your order has been placed successfully.", + thankYouMessage: "Thank You For Your Order!", + orderSubmittedMessage: "You have submitted your order", + backToShopping: "Back to Shopping" + }, + categories: { + Bracelets: "Pulseras", + Rings: "Anillos", + Earrings: "Pendientes", + Watches: "Relojes", + Necklaces: "Collares", + }, + diamondWeddingRing: "Anillo de boda de diamante", + silverBraceletWithCross: "Pulsera de plata con cruz", + pinkSilverBracelet: "Pulsera de plata rosa", + yellowGoldEarrings: "Pendientes de oro amarillo", + silverHeartNecklace: "Collar de corazón de plata", + handmadeSilverEarrings: "Pendientes de plata hechos a mano", + diamondWeddingBands: "Anillos de boda de diamante", + casualSilverWatch: "Reloj casual de plata", + silverBraceletWithOnyx: "Pulsera de plata con ónix", + weddingBandsWithPearls: "Anillos de boda con perlas", + silverWeddingBands: "Anillos de boda de plata", + handmadeYellowGoldRing: "Anillo de oro amarillo hecho a mano", + diamondRingWithSapphire: "Anillo de diamante con zafiro", + silverHeartBracelet: "Pulsera de corazón de plata", + roseGoldEarringsWithOpal: "Pendientes de oro rosa con ópalo", + silverBraceletWithTopaz: "Pulsera de plata con topacio", + handmadeDiamondRing: "Anillo de diamante hecho a mano", + diamondRingWithRuby: "Anillo de diamante con rubí", + silverWatch: "Reloj de plata", + goldEarringsWithGarnet: "Pendientes de oro con granate", + statuses: { + statusSale: "Oferta", + statusRecommended: "Recomendado", + statusMustHave: "Imprescindible", + }, + materials: { + materialGold: "Oro", + materialSilver: "Plata", + }, + paymentDetailsTitle: "Detalles de Pago", + paymentDetailsSubtitle: "Por favor, ingrese sus detalles de pago", + paymentMethodCreditCard: "Tarjeta de Crédito", + paymentMethodBankTransfer: "Transferencia Bancaria", + paymentMethodApplePay: "Apple Pay", + cardNumberLabel: "Número de Tarjeta", + expiryDateLabel: "Fecha de Expiración", + cvvLabel: "CVV*", + cardHolderLabel: "Titular de la Tarjeta", + submitOrderButton: "Enviar Pedido", + subTotalLabel: "Subtotal", + usDollarsLabel: "Dólares EE.UU.", + vatLabel: "IVA", + shippingMethodLabel: "Método de Envío", + standardFreeDeliveryLabel: "Envío Estándar Gratuito", + giftWrappingLabel: "Envoltura de Regalo", + includedGiftWrappingLabel: "Envoltura de Regalo Incluida", + totalLabel: "Total", + grid: { + groupPanelEmpty: "Arrastra el encabezado de una columna y suéltalo aquí para agrupar por esa columna", + noRecords: "No hay registros disponibles.", + pagerFirstPage: "Ir a la primera página", + pagerPreviousPage: "Ir a la página anterior", + pagerNextPage: "Ir a la página siguiente", + pagerLastPage: "Ir a la última página", + pagerPage: "Página", + pagerOf: "de", + pagerTotalPages: "{0}", + pagerItems: "artículos", + productTitle: "Producto", + nameTitle: "Nombre", + skuTitle: "SKU", + categoryTitle: "Categoría", + priceTitle: "Precio", + quantityTitle: "Cantidad", + totalSalesTitle: "Ventas Totales", + pagerInfo: "{0} - {1} de {2} artículos", + pagerItemsPerPage: "artículos por página", + filterEqOperator: "Es igual a", + filterNotEqOperator: "No es igual a", + filterIsNullOperator: "Es nulo", + filterIsNotNullOperator: "No es nulo", + filterIsEmptyOperator: "Está vacío", + filterIsNotEmptyOperator: "No está vacío", + filterStartsWithOperator: "Comienza con", + filterContainsOperator: "Contiene", + filterNotContainsOperator: "No contiene", + filterEndsWithOperator: "Termina con", + filterGteOperator: "Mayor o igual que", + filterGtOperator: "Mayor que", + filterLteOperator: "Menor o igual que", + filterLtOperator: "Menor que", + filterIsTrue: "Sí", + filterIsFalse: "No", + filterBooleanAll: "(Todos)", + filterAfterOrEqualOperator: "Es posterior o igual a", + filterAfterOperator: "Es posterior a", + filterBeforeOperator: "Es anterior a", + filterBeforeOrEqualOperator: "Es anterior o igual a", + filterSubmitButton: "Filtrar", + filterClearButton: "Borrar filtros", + filterAndLogic: "Y", + filterOrLogic: "O", + filterTitle: "Filtrar", + sortAscending: "Orden ascendente", + sortDescending: "Orden descendente", + searchPlaceholder: "Buscar", + filterCheckAll: "Seleccionar todo", + filterAriaLabel: "Filtrar", + sortAriaLabel: "Ordenar", + groupColumn: "Columna de grupo", + groupExpand: "Expandir grupo", + groupCollapse: "Contraer grupo", + groupPanelAriaLabel: "Panel de agrupación", + ungroupColumn: "Desagrupar columna", + detailExpand: "Expandir detalle", + detailCollapse: "Contraer detalle", + }, + wizard: { + windowTitle: "Vista previa del gráfico", + exportButton: "Exportar", + exportPDF: "Archivo PDF", + exportSVG: "Archivo SVG", + exportPNG: "Archivo PNG", + tabChart: "Gráfico", + tabData: "Datos", + tabFormat: "Formato", + barChart: "Gráfico de barras", + bar: "Barra", + stackedBar: "Barras apiladas", + "100stackedBar": "Barras apiladas al 100%", + pieChart: "Gráfico circular", + pie: "Circular", + columnChart: "Gráfico de columnas", + column: "Columna", + stackedColumn: "Columnas apiladas", + "100stackedColumn": "Columnas apiladas al 100%", + lineChart: "Gráfico de líneas", + line: "Línea", + stackedLine: "Líneas apiladas", + "100stackedLine": "Líneas apiladas al 100%", + scatterChart: "Gráfico de dispersión", + scatter: "Dispersión", + configuration: "Configuración", + categoryAxis: "Eje de categorías", + xAxis: "Eje X", + valueAxis: "Eje de valores", + series: "Series", + add: "Agregar", + chartArea: "Área del gráfico", + margins: "Márgenes", + auto: "Auto", + left: "Izquierda", + right: "Derecha", + top: "Superior", + bottom: "Inferior", + background: "Color de fondo", + title: "Título", + applyTo: "Aplicar a", + chartTitle: "Título del gráfico", + chartSubtitle: "Subtítulo del gráfico", + font: "Fuente", + size: "Tamaño", + color: "Color", + legend: "Leyenda", + showLegend: "Mostrar leyenda", + position: "Posición", + labels: "Etiquetas", + rotation: "Rotación", + reverseOrder: "Orden inverso", + valueAxisTitle: "Título del eje de valores", + categoryAxisTitle: "Título del eje de categorías", + }, + chartWizard: { + window: { + title: "Vista previa del gráfico", + }, + export: { + button: "Exportar", + PDF: "Archivo PDF", + SVG: "Archivo SVG", + PNG: "Archivo PNG", + }, + tab: { + chart: "Gráfico", + data: "Datos", + format: "Formato", + }, + chart: { + barChart: { + expandText: "Gráfico de barras", + bar: "Barra", + stackedBar: "Barras apiladas", + "100%stackedBar": "Barras apiladas al 100%", + }, + pieChart: { + expandText: "Gráfico de pastel", + pie: "Pastel", + }, + columnChart: { + expandText: "Gráfico de columnas", + column: "Columna", + stackedColumn: "Columnas apiladas", + "100%stackedColumn": "Columnas apiladas al 100%", + }, + lineChart: { + expandText: "Gráfico de líneas", + line: "Línea", + stackedLine: "Líneas apiladas", + "100%stackedLine": "Líneas apiladas al 100%", + }, + scatterChart: { + expandText: "Gráfico de dispersión", + scatter: "Dispersión", + }, + }, + data: { + configuration: { + expandText: "Configuración", + categoryAxis: "Eje de categorías", + xAxis: "Eje X", + valueAxis: "Eje de valores", + series: { + title: "Series", + add: "Agregar", + }, + }, + }, + format: { + chartArea: { + expandText: "Área del gráfico", + margins: { + auto: "Auto", + left: "Izquierda", + right: "Derecha", + top: "Arriba", + bottom: "Abajo", + }, + background: { + color: "Color", + }, + }, + title: { + expandText: "Título", + applyTo: "Aplicar a", + chartTitle: "Título del gráfico", + chartSubtitle: "Subtítulo del gráfico", + label: "Título", + font: "Fuente", + fontPlaceholder: "(fuente heredada)", + size: "Tamaño", + sizePlaceholder: "px", + color: "Color", + }, + series: { + expandText: "Series", + applyTo: "Aplicar a", + allSeries: "Todas las series", + color: "Color", + showLabels: "Mostrar etiquetas", + }, + legend: { + expandText: "Leyenda", + showLegend: "Mostrar leyenda", + font: "Fuente", + fontPlaceholder: "(fuente heredada)", + size: "Tamaño", + sizePlaceholder: "px", + color: "Color", + position: { + top: "Arriba", + bottom: "Abajo", + left: "Izquierda", + right: "Derecha", + }, + }, + categoryAxis: { + expandText: "Eje de categorías", + title: { + expandText: "Título", + placeholder: "Título del eje", + font: "Fuente", + fontPlaceholder: "(fuente heredada)", + size: "Tamaño", + sizePlaceholder: "px", + color: "Color", + }, + labels: { + text: "Etiquetas", + font: "Fuente", + fontPlaceholder: "(fuente heredada)", + size: "Tamaño", + sizePlaceholder: "px", + color: "Color", + rotation: { + text: "Rotación", + auto: "Auto", + }, + reverseOrder: "Orden inverso", + }, + }, + valueAxis: { + expandText: "Eje de valores", + title: { + text: "Título", + placeholder: "Título del eje", + font: "Fuente", + fontPlaceholder: "(fuente heredada)", + size: "Tamaño", + sizePlaceholder: "px", + color: "Color", + }, + labels: { + text: "Etiquetas", + font: "Fuente", + fontPlaceholder: "(fuente heredada)", + size: "Tamaño", + sizePlaceholder: "px", + color: "Color", + rotation: { + text: "Rotación", + auto: "Auto", + }, + }, + }, + }, + } +} + +export default es \ No newline at end of file diff --git a/examples/kendo-react-e-commerce-astro-app/src/data/messages/fr.ts b/examples/kendo-react-e-commerce-astro-app/src/data/messages/fr.ts new file mode 100644 index 00000000..7f31495a --- /dev/null +++ b/examples/kendo-react-e-commerce-astro-app/src/data/messages/fr.ts @@ -0,0 +1,447 @@ +export const fr = { + title: "Bijoux Vilora", + subtitle: + "Nous proposons des bijoux exquis, chacun illustrant une élégance intemporelle", + buttonText: "Voir les Collections", + searchPlaceholder: "Rechercher", + addToCartButtonText: "Ajouter au Panier", + adminLabel: "Admin", + clientLabel: "Client", + languageMenuTitle: "Langue", + languageEnglish: "Anglais", + languageFrench: "Français", + languageSpanish: "Espagnol", + "radioButtons": { + "new": "Nouveau", + "existing": "Existant", + "justCurious": "Juste curieux" + }, + cookiesText: + "Nous utilisons des cookies pour améliorer votre expérience.", + rightsReservedText: "Tous droits réservés.", + subscribeText: "Abonnez-vous à notre newsletter :", + emailPlaceholder: "Email", + subscribeButtonText: "S'abonner", + filterLabel: "Filtrer :", + sortByLabel: "Trier par :", + clearFiltersButton: "Effacer les filtres", + categoryPlaceholder: "Catégorie", + materialPlaceholder: "Matériau", + categoriesData: ["Bracelets", "Bagues", "Boucles d'oreilles", "Montres", "Colliers"], + statusesData: ["Vente", "Recommandé", "Indispensable"], + materialsData: ["Or", "Argent"], + followUsText: "Suivez-nous :", + shoppingCartTitle: "Panier", + backButtonText: "Retour", + whyChooseUs: "Pourquoi nous choisir ?", + returnPolicyTitle: "Politique de Retour", + returnPolicyContent: "Vous pouvez retourner vos articles sous 30 jours pour un remboursement ou un échange complet.", + includedGiftWrappingTitle: "Emballage Cadeau Inclus", + includedGiftWrappingContent: "Ajoutez un emballage cadeau pour une touche spéciale, accompagné d'un message personnalisé pour vos proches.", + discountCodeTitle: "Code Promo Disponible", + discountCodeContent: "Appliquez votre code promo lors du paiement pour profiter d'économies exclusives sur votre commande.", + removeButtonText: "Supprimer", + emptyCartMessage: "Votre panier est vide.", + proceedToCheckoutButtonText: "Passer à la caisse", + customerCareTitle: "Service Client", + thankYou: { + title: "Merci !", + subtitle: "Votre commande a été passée avec succès.", + thankYouMessage: "Merci pour votre commande !", + orderSubmittedMessage: "Vous avez soumis votre commande", + backToShopping: "Retour au shopping" + }, + customerCareLinks: [ + "Nous Contacter", + "Achats en Ligne", + "Suivre Votre Commande", + "Livraison", + "Commandes & Paiement", + "Aide", + ], + ourCompanyTitle: "Notre Entreprise", + ourCompanyLinks: [ + "Emplacements Importants", + "Carrières", + "Responsabilité d'Entreprise", + "Durabilité", + "Soins de la Société", + ], + legalPrivacyTitle: "Légal & Confidentialité", + legalPrivacyLinks: [ + "Conditions d'Utilisation", + "Conditions de Vente", + "Politique de Retour", + "Politique de Confidentialité", + "Politique de Cookies", + ], + // Menu Translations + menuHome: "Accueil", + menuJewelry: "Bijoux", + menuContacts: "Contacts", + menuBracelets: "Bracelets", + menuRings: "Bagues", + menuEarrings: "Boucles d'oreilles", + menuWatches: "Montres", + menuAll: "Tout", + // Other Translations + bestsellersTitle: "Nos Meilleures Ventes", + bestsellersSubtitle: + "Profitez d'une excellente sélection de bijoux fins", + buyNowButtonText: "Acheter Maintenant", + timelessTitle: "Classiques Intemporels", + timelessSubtitle: "Découvrez nos collections artisanales uniques", + timelessContent: + "Les bijoux subliment le style et ajoutent de l'élégance, chaque pièce raconte une histoire unique.", + fineJewelryTitle: "Bijoux Fins", + fineJewelrySubtitle: "Découvrez nos collections artisanales uniques", + fineJewelryContent: + "Les bijoux rehaussent le style et apportent de la sophistication, chaque pièce raconte une histoire distincte.", + ringsTitle: "Nos Bagues", + ringsSubtitle: "Profitez d'une excellente sélection de bagues fines", + watchesTitle: "Nos Montres", + watchesSubtitle: "Profitez d'une excellente sélection de montres", + watchesContent: + "Les montres en or haut de gamme pour hommes sont le summum du luxe, alliant précision et savoir-faire sophistiqué.", + servicesTitle: "Services", + servicesSubtitle: + "Explorez des réparations expertes pour enrichir votre expérience", + servicesContent: + "Vilora propose des services tels que des designs personnalisés, des réparations et des expertises pour enrichir l'expérience client.", + testimonialsTitle: "Mots des Clients", + testimonialsSubtitle: "Que disent-ils de nous ?", + testimonialsData: [ + { + image: "/testemonials1.jpg", + name: "Erica Moore", + rating: 5, + description: + "Vilora a dépassé toutes mes attentes ! Le savoir-faire de mon collier en diamant est absolument époustouflant, et l'attention aux détails est sans égale. Du moment où j'ai passé ma commande jusqu'au jour où elle est arrivée, toute l'expérience a été parfaite.", + }, + { + image: "/testemonials2.jpg", + name: "Kelvin Hettinger", + rating: 4.5, + description: + "Je ne pourrais pas être plus heureux avec ma bague de fiançailles personnalisée de chez Vilora. L'équipe m'a aidé à concevoir la pièce parfaite, et le résultat final était encore plus beau que ce que j'avais imaginé. Leur service, qualité et dévouement à l'excellence font de Vilora mon choix pour tous les bijoux de luxe.", + }, + { + image: "/testemonials3.jpg", + name: "Karen Brooks", + rating: 5, + description: + "La collection de Vilora est tout simplement à couper le souffle. J'ai récemment acheté une bague en saphir blanc, et c'est devenu ma pièce préférée. L'élégance et la brillance des bijoux reflètent leur goût impeccable et leurs normes élevées. Je recommande vivement !", + }, + ], + // Contacts Page Translations + getInTouchTitle: "Contactez-nous", + getInTouchSubtitle: "Si vous avez des questions, contactez-nous", + fullNameLabel: "Nom complet", + fullNamePlaceholder: "Entrez votre nom complet", + emailLabel: "Email", + phoneNumberLabel: "Numéro de téléphone", + typeOfCustomerLabel: "Type de client", + dateLabel: "Date", + bookSlotButton: "Réserver un créneau", + contactsImageAlt: "Contacts", + // Thank You Page Translations + thankYouTitle: "Merci pour votre commande!", + thankYouSubtitle: "Vous avez soumis votre commande", + backToShoppingButton: "Retour aux achats", + allProductsTitle: "Sélection Fine", + allProductsSubtitle: "Appréciez le véritable artisanat", + chartSelectedDataButton: "Graphique des données sélectionnées", + top3SalesButton: "Top 3 des ventes par catégorie", + allProductsContentText: + "Les bijoux sont une forme significative d'expression de soi qui améliore le style personnel et ajoute de la beauté à toute occasion.", + collectionSerene: 'Collection "SERENE"', + collectionAurelia: 'Collection "AURELIA"', + collectionRavina: 'Collection "RAVINA"', + ourCollectionsTitle: "Nos Collections", + ourCollectionsSubtitle: "Profitez d'une excellente sélection de bijoux fins", + breadcrumbHome: "Accueil", + breadcrumbJewelry: "Bijoux", + buyButtonText: "Acheter", + handmadePinkDiamondRing: "Bague en diamant rose faite à la main", + diamondRingWithPinkRuby: "Bague en diamant avec rubis rose", + whiteSandDiamondRing: "Bague en diamant sable blanc", + productSubtitle: "En platine avec diamant naturel", + productDescription: "Alliances élégantes avec des perles lustrées.", + reviewsText: "{0} avis", + youMayAlsoLikeTitle: "Vous aimerez aussi", + youMayAlsoLikeSubtitle: "Profitez d'une excellente sélection de bijoux fins", + categories: { + Bracelets: "Bracelets", + Rings: "Bagues", + Earrings: "Boucles d'oreilles", + Watches: "Montres", + Necklaces: "Colliers", + }, + diamondWeddingRing: "Bague de mariage en diamant", + silverBraceletWithCross: "Bracelet en argent avec croix", + pinkSilverBracelet: "Bracelet en argent rose", + yellowGoldEarrings: "Boucles d'oreilles en or jaune", + silverHeartNecklace: "Collier cœur en argent", + handmadeSilverEarrings: "Boucles d'oreilles en argent faites à la main", + diamondWeddingBands: "Alliances en diamant", + casualSilverWatch: "Montre décontractée en argent", + silverBraceletWithOnyx: "Bracelet en argent avec onyx", + weddingBandsWithPearls: "Alliances avec perles", + silverWeddingBands: "Alliances en argent", + handmadeYellowGoldRing: "Bague en or jaune faite à la main", + diamondRingWithSapphire: "Bague en diamant avec saphir", + silverHeartBracelet: "Bracelet cœur en argent", + roseGoldEarringsWithOpal: "Boucles d'oreilles en or rose avec opale", + silverBraceletWithTopaz: "Bracelet en argent avec topaze", + handmadeDiamondRing: "Bague en diamant faite à la main", + diamondRingWithRuby: "Bague en diamant avec rubis", + silverWatch: "Montre en argent", + goldEarringsWithGarnet: "Boucles d'oreilles en or avec grenat", + statuses: { + statusSale: "Vente", + statusRecommended: "Recommandé", + statusMustHave: "Indispensable", + }, + materials: { + materialGold: "Or", + materialSilver: "Argent", + }, + paymentDetailsTitle: "Détails du paiement", + paymentDetailsSubtitle: "Veuillez soumettre vos détails de paiement", + paymentMethodCreditCard: "Carte de Crédit", + paymentMethodBankTransfer: "Virement Bancaire", + paymentMethodApplePay: "Apple Pay", + cardNumberLabel: "Numéro de carte", + expiryDateLabel: "Date d'expiration", + cvvLabel: "CVV*", + cardHolderLabel: "Titulaire de la carte", + submitOrderButton: "Valider la commande", + subTotalLabel: "Sous-total", + usDollarsLabel: "Dollars US", + vatLabel: "TVA", + shippingMethodLabel: "Mode de livraison", + standardFreeDeliveryLabel: "Livraison standard gratuite", + giftWrappingLabel: "Emballage cadeau", + includedGiftWrappingLabel: "Emballage cadeau inclus", + totalLabel: "Total", + grid: { + groupPanelEmpty: "Faites glisser un en-tête de colonne et déposez-le ici pour regrouper par cette colonne", + noRecords: "Aucun enregistrement disponible.", + pagerFirstPage: "Aller à la première page", + pagerPreviousPage: "Aller à la page précédente", + pagerNextPage: "Aller à la page suivante", + pagerLastPage: "Aller à la dernière page", + pagerPage: "Page", + pagerOf: "de", + pagerTotalPages: "{0}", + pagerItems: "articles", + pagerInfo: "{0} - {1} sur {2} articles", + pagerItemsPerPage: "articles par page", + filterEqOperator: "Est égal à", + filterNotEqOperator: "N'est pas égal à", + filterIsNullOperator: "Est nul", + filterIsNotNullOperator: "N'est pas nul", + filterIsEmptyOperator: "Est vide", + filterIsNotEmptyOperator: "N'est pas vide", + filterStartsWithOperator: "Commence par", + productTitle: "Produit", + nameTitle: "Nom", + skuTitle: "SKU", + categoryTitle: "Catégorie", + priceTitle: "Prix", + quantityTitle: "Quantité", + totalSalesTitle: "Ventes Totales", + filterContainsOperator: "Contient", + filterNotContainsOperator: "Ne contient pas", + filterEndsWithOperator: "Se termine par", + filterGteOperator: "Est supérieur ou égal à", + filterGtOperator: "Est supérieur à", + filterLteOperator: "Est inférieur ou égal à", + filterLtOperator: "Est inférieur à", + filterIsTrue: "Oui", + filterIsFalse: "Non", + filterBooleanAll: "(Tous)", + filterAfterOrEqualOperator: "Est après ou égal à", + filterAfterOperator: "Est après", + filterBeforeOperator: "Est avant", + filterBeforeOrEqualOperator: "Est avant ou égal à", + filterSubmitButton: "Filtrer", + filterClearButton: "Effacer les filtres", + filterAndLogic: "Et", + filterOrLogic: "Ou", + filterTitle: "Filtrer", + sortAscending: "Tri croissant", + sortDescending: "Tri décroissant", + searchPlaceholder: "Chercher", + filterCheckAll: "Tout vérifier", + pagerItemPerPage: "Articles par page", + filterChooseOperator: "Choisir un opérateur", + filterSelectedItems: "articles sélectionnés", + filterAriaLabel: "Filtrer", + sortAriaLabel: "Triable", + groupColumn: "Colonne de groupe", + groupExpand: "Développer le groupe", + groupCollapse: "Réduire le groupe", + groupPanelAriaLabel: "panneau de groupe", + ungroupColumn: "Dissocier la colonne", + detailExpand: "Développer la ligne de détail", + detailCollapse: "Réduire la ligne de détail", + + }, + chartWizard: { + window: { + title: "Aperçu du graphique", + }, + export: { + button: "Exporter", + PDF: "Fichier PDF", + SVG: "Fichier SVG", + PNG: "Fichier PNG", + }, + tab: { + chart: "Graphique", + data: "Données", + format: "Format", + }, + chart: { + barChart: { + expandText: "Graphique à barres", + bar: "Barre", + stackedBar: "Barres empilées", + "100%stackedBar": "Barres empilées à 100%", + }, + pieChart: { + expandText: "Graphique en secteur", + pie: "Secteur", + }, + columnChart: { + expandText: "Graphique en colonnes", + column: "Colonne", + stackedColumn: "Colonnes empilées", + "100%stackedColumn": "Colonnes empilées à 100%", + }, + lineChart: { + expandText: "Graphique en lignes", + line: "Ligne", + stackedLine: "Lignes empilées", + "100%stackedLine": "Lignes empilées à 100%", + }, + scatterChart: { + expandText: "Graphique de dispersion", + scatter: "Dispersion", + }, + }, + data: { + configuration: { + expandText: "Configuration", + categoryAxis: "Axe des catégories", + xAxis: "Axe X", + valueAxis: "Axe des valeurs", + series: { + title: "Séries", + add: "Ajouter", + }, + }, + }, + format: { + chartArea: { + expandText: "Zone du graphique", + margins: { + auto: "Auto", + left: "Gauche", + right: "Droite", + top: "Haut", + bottom: "Bas", + }, + background: { + color: "Couleur", + }, + }, + title: { + expandText: "Titre", + applyTo: "Appliquer à", + chartTitle: "Titre du graphique", + chartSubtitle: "Sous-titre du graphique", + label: "Titre", + font: "Police", + fontPlaceholder: "(police héritée)", + size: "Taille", + sizePlaceholder: "px", + color: "Couleur", + }, + series: { + expandText: "Séries", + applyTo: "Appliquer à", + allSeries: "Toutes les séries", + color: "Couleur", + showLabels: "Afficher les étiquettes", + }, + legend: { + expandText: "Légende", + showLegend: "Afficher la légende", + font: "Police", + fontPlaceholder: "(police héritée)", + size: "Taille", + sizePlaceholder: "px", + color: "Couleur", + position: { + top: "Haut", + bottom: "Bas", + left: "Gauche", + right: "Droite", + }, + }, + categoryAxis: { + expandText: "Axe des catégories", + title: { + expandText: "Titre", + placeholder: "Titre de l'axe", + font: "Police", + fontPlaceholder: "(police héritée)", + size: "Taille", + sizePlaceholder: "px", + color: "Couleur", + }, + labels: { + text: "Étiquettes", + font: "Police", + fontPlaceholder: "(police héritée)", + size: "Taille", + sizePlaceholder: "px", + color: "Couleur", + rotation: { + text: "Rotation", + auto: "Auto", + }, + reverseOrder: "Ordre inversé", + }, + }, + valueAxis: { + expandText: "Axe des valeurs", + title: { + text: "Titre", + placeholder: "Titre de l'axe", + font: "Police", + fontPlaceholder: "(police héritée)", + size: "Taille", + sizePlaceholder: "px", + color: "Couleur", + }, + labels: { + text: "Étiquettes", + font: "Police", + fontPlaceholder: "(police héritée)", + size: "Taille", + sizePlaceholder: "px", + color: "Couleur", + rotation: { + text: "Rotation", + auto: "Auto", + }, + }, + }, + }, + }, +} + +export default fr \ No newline at end of file diff --git a/examples/kendo-react-e-commerce-astro-app/src/data/types.ts b/examples/kendo-react-e-commerce-astro-app/src/data/types.ts index 6de34d0b..2b581ab1 100644 --- a/examples/kendo-react-e-commerce-astro-app/src/data/types.ts +++ b/examples/kendo-react-e-commerce-astro-app/src/data/types.ts @@ -1,23 +1,31 @@ export type CardDescriptor = { img: string; - collectionText: string; + collectionText?: string; + collectionTextKey?: string; + }; export type DataModel = { text: string | undefined; } -export type ListDataDescriptor = { - id?: number; - img: string | undefined; - status: string | null; - title: string; - rating?: number; +export interface ListDataDescriptor { + id: number; + img: string; + title: string; + description?: string; + reviews?: number; + rating: number; + titleKey?: string; category: string; + categoryKey?: string; + descriptionKey?: string; + status?: string; material: string; oldPrice: number | null; newPrice: number; -}; + } + export type BackgroundImageProps = { title: string; @@ -28,6 +36,7 @@ export type BackgroundImageProps = { export type CardListProps = { data: any[]; + layout: "grid" | "list"; } export type SectionProps = { diff --git a/examples/kendo-react-e-commerce-astro-app/src/helpers/languageStore.ts b/examples/kendo-react-e-commerce-astro-app/src/helpers/languageStore.ts new file mode 100644 index 00000000..e8488f3c --- /dev/null +++ b/examples/kendo-react-e-commerce-astro-app/src/helpers/languageStore.ts @@ -0,0 +1,14 @@ +import { atom } from 'nanostores'; + +export const selectedLanguage = atom('en'); + +if (typeof window !== 'undefined' && window.localStorage) { + const savedLanguage = localStorage.getItem('selectedLanguage'); + if (savedLanguage) { + selectedLanguage.set(savedLanguage); + } + + selectedLanguage.listen((newLanguage) => { + localStorage.setItem('selectedLanguage', newLanguage); + }); +} diff --git a/examples/kendo-react-e-commerce-astro-app/src/layouts/Layout.astro b/examples/kendo-react-e-commerce-astro-app/src/layouts/Layout.astro index 79294d8d..69a834e2 100644 --- a/examples/kendo-react-e-commerce-astro-app/src/layouts/Layout.astro +++ b/examples/kendo-react-e-commerce-astro-app/src/layouts/Layout.astro @@ -64,4 +64,4 @@ - + \ No newline at end of file diff --git a/examples/kendo-react-e-commerce-astro-app/src/pages/product/[id].astro b/examples/kendo-react-e-commerce-astro-app/src/pages/product/[id].astro index 4d9d9020..d86c140d 100644 --- a/examples/kendo-react-e-commerce-astro-app/src/pages/product/[id].astro +++ b/examples/kendo-react-e-commerce-astro-app/src/pages/product/[id].astro @@ -1,20 +1,27 @@ --- import Layout from '../../layouts/Layout.astro'; import ProductDetails from '../../components/ProductDetails'; -import listData from '../../data/listData'; +import Header from '../../components/Header'; +import Footer from '../../components/Footer'; +import getTranslatedListData from '../../data/listData'; import { ListDataDescriptor } from '../../data/types'; export async function getStaticPaths() { + const listData = getTranslatedListData(); return listData.map((product: ListDataDescriptor) => ({ params: { id: String(product.id) }, })); } const { id } = Astro.params; -const product = listData.find((item: ListDataDescriptor) => String(item.id) === id); + +const product = getTranslatedListData().find( + (item: ListDataDescriptor) => String(item.id) === id +); --- +
{product ? ( @@ -22,4 +29,5 @@ const product = listData.find((item: ListDataDescriptor) => String(item.id) ===
Product not found
)}
+