diff --git a/next-i18next.config.js b/next-i18next.config.js index ba2afd3..16c02bc 100644 --- a/next-i18next.config.js +++ b/next-i18next.config.js @@ -2,7 +2,7 @@ const path = require("path"); module.exports = { i18n: { - locales: ['en', 'vi', 'fr' , 'ar'], // List all supported locales + locales: ['en', 'ru', 'id' , 'ar'], // List all supported locales defaultLocale: 'en', // Set the default locale }, }; diff --git a/public/locales/ar/FAQ.json b/public/locales/ar/FAQ.json new file mode 100644 index 0000000..b9fe231 --- /dev/null +++ b/public/locales/ar/FAQ.json @@ -0,0 +1,24 @@ +{ + "faqTitle": "الأسئلة الشائعة", + "faqSubtitle": "هل لديك أسئلة؟ نحن هنا للمساعدة!", + "faqQuestion1": "كيف يمكنني حجز جولة على موقعكم؟", + "faqAnswer1": "لحجز جولة، ببساطة اختر الوجهة التي ترغب فيها من 'قائمة الجولات'، اختر التواريخ الخاصة بك، واتبع الخطوات لإكمال عملية الحجز.", + "faqQuestion2": "هل يمكنني تخصيص جولتي؟", + "faqAnswer2": "نعم، تتيح لك ميزة 'الجولة المخصصة' تخصيص رحلتك بناءً على تفضيلاتك. انقر على 'الجولة المخصصة' في أعلى الصفحة لبدء تخصيص تجربتك.", + "faqQuestion3": "ما طرق الدفع التي تقبلها؟", + "faqAnswer3": "نقبل جميع بطاقات الائتمان الرئيسية، باي بال، والتحويلات البنكية. يمكنك اختيار الطريقة المفضلة لديك أثناء عملية الدفع.", + "faqQuestion4": "كيف يمكنني معرفة ما إذا تم تأكيد حجزي؟", + "faqAnswer4": "بمجرد إتمام عملية الدفع، ستتلقى رسالة تأكيد عبر البريد الإلكتروني تحتوي على جميع تفاصيل حجزك. يمكنك أيضًا عرض تفاصيل الحجز في لوحة التحكم الخاصة بحسابك.", + "faqQuestion5": "هل يمكنني إلغاء أو تعديل حجزتي؟", + "faqAnswer5": "نعم، يمكنك إلغاء أو تعديل حجزك من حسابك. يرجى ملاحظة أنه يجب إجراء الإلغاء قبل 24 ساعة على الأقل من بداية الجولة لكي تكون مؤهلاً لاسترداد المبلغ.", + "faqQuestion6": "هل هناك أي رسوم مخفية؟", + "faqAnswer6": "لا، جميع الرسوم شفافة وتُعرض مسبقًا قبل إتمام الحجز. نحن نضمن أنه لا توجد أي رسوم مخفية.", + "faqQuestion7": "هل تقدمون خصومات للمجموعات؟", + "faqAnswer7": "نعم، نقدم خصومات للمجموعات التي تحجز أعدادًا كبيرة. يرجى الاتصال بفريق الدعم الخاص بنا للحصول على مزيد من المعلومات حول أسعار المجموعات.", + "faqQuestion8": "هل يشمل الحجز تأمين السفر؟", + "faqAnswer8": "نعم، جميع باقات الجولات لدينا تشمل تأمين السفر الأساسي. يمكنك اختيار ترقية باقة التأمين الخاصة بك أثناء عملية الدفع.", + "faqQuestion9": "ماذا يحدث إذا تم إلغاء الجولة من قبل الموفر؟", + "faqAnswer9": "إذا تم إلغاء الجولة من قبل الموفر بسبب ظروف غير متوقعة، ستتلقى استردادًا كاملًا أو خيار إعادة جدولة الجولة.", + "faqQuestion10": "كيف يمكنني الاتصال بدعم العملاء؟", + "faqAnswer10": "يمكنك الاتصال بدعم العملاء عن طريق النقر على زر 'اتصل بنا' في أسفل الصفحة أو بزيارة قسم الدعم." +} diff --git a/public/locales/ar/common.json b/public/locales/ar/common.json index 8552cf7..b138874 100644 --- a/public/locales/ar/common.json +++ b/public/locales/ar/common.json @@ -1,116 +1,222 @@ { - "home": "Accueil", - "allTours": "Tous les Tours", - "blogs": "Blogs", - "faq": "FAQ", - "aboutUs": "À Propos de Nous", - "customTour": "Tour Personnalisé", - "searchPlaceholder": "Où aller ?", - "searchDescription": "Partout • N'importe quelle semaine • Ajouter des invités", - "beginAdventure": "Commencez votre aventure spirituelle", - "planPilgrimage": "Planifiez votre pèlerinage facilement. Trouvez les meilleures accommodations, transports et expériences guidées vers les sanctuaires chiites à travers le monde", - "startJourney": "Commencez votre voyage", - "listOfTours": "Liste des Tours", - "exploreTours": "Explorez les tours et accommodations adaptées pour un voyage spirituel et mémorable", - "tourPeriod": "Période du Tour", - "tourPeriodDescription": "Début - Fin", - "guests": "Invités", - "addGuests": "Ajouter des invités", - "available": "Disponible", - "soldOut": "Épuisé", - "showMore": "Montrez-moi plus", - "happeningCities": "Villes Animées", - "costEffectiveAdvertising": "Publicité Rentable", - "costEffectiveDescription": "Avec une annonce gratuite, vous pouvez faire la publicité de votre location sans frais initiaux", - "reachMillions": "Atteignez des millions avec Chisfis", - "reachMillionsDescription": "Des millions de personnes recherchent des lieux uniques où séjourner à travers le monde", - "secureAndSimple": "Securisé et Simple", - "secureDescription": "Une annonce sur Holiday Lettings vous offre un moyen sécurisé et facile de prendre des réservations et des paiements en ligne", - "mobileApps": "Applications Mobiles", - "mobileAppsDescription": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed dapibus porttitor nisl, sit amet finibus libero.", - "installation": "Installation", - "releaseNotes": "Notes de Version", - "upgradeGuide": "Guide de Mise à Niveau", - "browserSupport": "Support des Navigateurs", - "editorSupport": "Support de l'Éditeur", - "designFeatures": "Caractéristiques de Design", - "prototyping": "Prototypage", - "designSystems": "Systèmes de Design", - "pricing": "Tarification", - "security": "Sécurité", - "bestPractices": "Meilleures Pratiques", - "support": "Support", - "developers": "Développeurs", - "learnDesign": "Apprendre le Design", - "releases": "Versions", - "discussionForums": "Forums de Discussion", - "codeOfConduct": "Code de Conduite", - "communityResources": "Ressources Communautaires", - "contributing": "Contribuer", - "concurrentMode": "Mode Concurrent", - "goodNews": "Bonnes Nouvelles d'Ailleurs", - "whatPeopleThink": "Voyons ce que les gens pensent de Chisfis", - "testimonial": "Cet endroit est exactement comme sur la photo publiée sur Chisfis. Excellent service, nous avons passé un très bon séjour !", - "clientName": "Tiana Abie", - "clientLocation": "Malaisie", - "myTrips": "Mes Voyages", - "account": "Compte", - "menu": "Menu", - "gettingStarted": "Premiers Pas", - "explore": "Explorer", - "resources": "Ressources", - "community": "Communauté", - "placeType": "Type de Lieu", - "noTours": "Aucun tour disponible", - "itinerary": "Itinéraire", - "itineraryTitle": "Itinéraire", - "total": "Total", - "reserve": "Réserver", - "tourFeatures": "Caractéristiques du Tour", - "tourFeaturesTitle": "Caractéristiques du Tour", - "startRating": "Évaluation de Début", - "listingDetails": "Détails", - "imageAlt": "Image du tour", - "loading": "Chargement...", - "adults": "Adultes", - "adultsDesc": "Âges 13 ou plus", - "children": "Enfants", - "childrenDesc": "Âges 2–12", - "infants": "Bébés", - "infantsDesc": "Âges 0–2", - "traveler": "Voyageur", - "responses": "Réponses ({{count}})", - "submit": "Soumettre", - "cancel": "Annuler", - "relatedPosts": "Articles Connexes", - "aboutUsHeading": "👋 À Propos de Nous.", - "aboutUsSubheading": "Nous sommes une équipe passionnée dédiée à la création d'expériences de voyage inoubliables pour les explorateurs et les rêveurs. Des escapades sereines sur des plages tropicales aux aventures à sensations fortes dans des lieux exotiques, nous concevons des voyages aussi uniques que vous. Rejoignez-nous et explorons le monde, une aventure à la fois !", - "statisticTitle": "🚀 Faits Rapides", - "statisticDescription": "Nous sommes impartiaux et indépendants, et chaque jour nous créons des programmes et du contenu distinctifs de classe mondiale.", - "statisticHeading1": "10 millions", - "statisticSubHeading1": "D'articles ont été publiés à travers le monde (au 30 septembre 2021)", - "statisticHeading2": "100 000", - "statisticSubHeading2": "Utilisateurs enregistrés (au 30 septembre 2021)", + "home": "الرئيسية", + "allTours": "جميع الجولات", + "blogs": "المدونات", + "faq": "الأسئلة الشائعة", + "aboutUs": "من نحن", + "customTour": "جولة مخصصة", + "searchPlaceholder": "إلى أين؟", + "searchDescription": "أي مكان • أي أسبوع • إضافة ضيوف", + "beginAdventure": "ابدأ رحلتك", + "beginAdventure1": "الروحية", + "beginAdventure2": "المغامرة", + "planPilgrimage": "خطط لرحلة الحج بسهولة. اعثر على أفضل أماكن الإقامة، وسائل النقل، والتجارب الموجهة إلى الأضرحة الشيعية في جميع أنحاء العالم.", + "startJourney": "ابدأ رحلتك", + "listOfTours": "قائمة الجولات", + "exploreTours": "استكشف الجولات والإقامات التي تم تصميمها لرحلة روحية لا تُنسى", + "tourPeriod": "مدة الجولة", + "tourPeriodDescription": "البداية - النهاية", + "guests": "الضيوف", + "addGuests": "إضافة ضيوف", + "available": "متاح", + "soldOut": "نفذ من المخزون", + "showMore": "عرض المزيد", + "happeningCities": "المدن النشطة", + "costEffectiveAdvertising": "إعلانات فعالة من حيث التكلفة", + "costEffectiveDescription": "من خلال إدراج مجاني، يمكنك الإعلان عن إيجارك دون تكاليف مسبقة", + "reachMillions": "وصل إلى الملايين مع Chisfis", + "reachMillionsDescription": "ملايين الأشخاص يبحثون عن أماكن فريدة للإقامة حول العالم", + "secureAndSimple": "آمن وبسيط", + "secureDescription": "يوفر إدراج Holiday Lettings طريقة آمنة وسهلة لاستلام الحجوزات والمدفوعات عبر الإنترنت", + "mobileApps": "تطبيقات الهاتف المحمول", + "mobileAppsDescription": "لوريم إيبسوم دولار سيت أميت، كونسيكتيتور أديبيسكينغ أليت. سيد دابيبوس بورتتيتور نيسل، سيت أميت فينيبوس ليبرو.", + "installation": "التثبيت", + "releaseNotes": "ملاحظات الإصدار", + "upgradeGuide": "دليل الترقية", + "browserSupport": "دعم المتصفح", + "editorSupport": "دعم المحرر", + "designFeatures": "ميزات التصميم", + "prototyping": "النمذجة الأولية", + "designSystems": "أنظمة التصميم", + "pricing": "التسعير", + "security": "الأمان", + "bestPractices": "أفضل الممارسات", + "support": "الدعم", + "developers": "المطورون", + "learnDesign": "تعلم التصميم", + "releases": "الإصدارات", + "discussionForums": "منتديات المناقشة", + "codeOfConduct": "مدونة السلوك", + "communityResources": "موارد المجتمع", + "contributing": "المساهمة", + "concurrentMode": "وضع التوازي", + "goodNews": "أخبار جيدة من بعيد", + "whatPeopleThink": "لنرَ ماذا يفكر الناس في Chisfis", + "testimonial": "هذا المكان هو تمامًا كما في الصورة المنشورة على Chisfis. خدمة رائعة، قضينا إقامة رائعة!", + "clientName": "تيانا أبي", + "clientLocation": "ماليزيا", + "myTrips": "رحلاتي", + "account": "الحساب", + "menu": "القائمة", + "gettingStarted": "البدء", + "explore": "استكشاف", + "resources": "الموارد", + "community": "المجتمع", + "placeType": "نوع المكان", + "noTours": "لا توجد جولات متاحة", + "itinerary": "خطة الرحلة", + "itineraryTitle": "خطة الرحلة", + "total": "الإجمالي", + "reserve": "احجز", + "tourFeatures": "ميزات الجولة", + "tourFeaturesTitle": "ميزات الجولة", + "startRating": "تقييم البدء", + "listingDetails": "التفاصيل", + "imageAlt": "صورة للجولة", + "loading": "جاري التحميل...", + "adults": "البالغين", + "adultsDesc": "الأعمار 13 فما فوق", + "children": "الأطفال", + "childrenDesc": "الأعمار من 2 إلى 12", + "infants": "الرضع", + "infantsDesc": "الأعمار من 0 إلى 2", + "traveler": "المسافر", + "responses": "الردود ({{count}})", + "submit": "إرسال", + "cancel": "إلغاء", + "relatedPosts": "المنشورات ذات الصلة", + "aboutUsHeading": "👋 عنّا", + "aboutUsSubheading": "نحن فريق متحمس مكرس لصناعة تجارب سفر لا تُنسى للمستكشفين والحالمين على حد سواء. من الهروب الهادئ إلى الشواطئ الاستوائية إلى المغامرات المليئة بالأدرينالين في الأماكن الغريبة، نصمم رحلات فريدة كما أنت. انضم إلينا ولنكشف العالم، مغامرة واحدة في كل مرة!", + "statisticTitle": "🚀 حقائق سريعة", + "statisticDescription": "نحن محايدون ومستقلون، وكل يوم نصنع برامج ومحتوى متميز على مستوى عالمي.", + "statisticHeading1": "10 مليون", + "statisticSubHeading1": "تم نشر المقالات حول العالم (حتى 30 سبتمبر 2021)", + "statisticHeading2": "100,000", + "statisticSubHeading2": "حسابات المستخدمين المسجلة (حتى 30 سبتمبر 2021)", "statisticHeading3": "220+", - "statisticSubHeading3": "Pays et régions où nous sommes présents (au 30 septembre 2021)", - "customTrip": "Voyage Personnalisé", - "guide": "Guide", - "guideDescription": "Tout d'abord, écrivez l'origine de votre départ, puis choisissez la première destination de votre voyage, le nombre de nuits de séjour et le moyen de transport, puis choisissez vos destinations de voyage si vous le souhaitez.", - "beginYourTrip": "Commencez Votre Voyage", - "startDate": "Date de Début", - "numberOfPassengers": "Nombre de Passagers", - "destination": "Destination", - "selectCity": "Sélectionner une Ville", - "transportation": "Transport", - "selectTransport": "Sélectionner le Transport", - "hotel": "Hôtel", - "selectHotel": "Sélectionner l'Hôtel", - "duration": "Durée", - "finishDate": "Date de Fin", - "addDestination": "Ajouter une Destination", - "continue": "Continuer", - "successMessage": "Enregistré avec succès", - "to": "à", - "login": "Se Connecter", - "signup": "S'inscrire" + "statisticSubHeading3": "الدول والمناطق التي تتواجد فيها خدماتنا (حتى 30 سبتمبر 2021)", + "customTrip": "رحلة مخصصة", + "guide": "الدليل", + "guideDescription": "أولاً، اكتب مصدر مغادرتك، ثم اختر أول وجهة في رحلتك، عدد ليالي الإقامة، ووسائل السفر، ثم اختر وجهاتك إذا رغبت.", + "beginYourTrip": "ابدأ رحلتك", + "startDate": "تاريخ البدء", + "numberOfPassengers": "عدد الركاب", + "destination": "الوجهة", + "selectCity": "اختر المدينة", + "transportation": "النقل", + "selectTransport": "اختر وسيلة النقل", + "hotel": "الفندق", + "selectHotel": "اختر الفندق", + "duration": "المدة", + "finishDate": "تاريخ الانتهاء", + "addDestination": "أضف وجهة", + "continue": "استمرار", + "successMessage": "تم التسجيل بنجاح", + "to": "إلى", + "login": "تسجيل الدخول", + "signup": "إنشاء حساب", + "All": "الكل", + "create": "إنشاء", + "createPersonalizedTourLine1": "أنشئ جولتك المخصصة وصمم", + "createPersonalizedTourLine2": "تجربة السفر المثالية المخصصة لتفضيلاتك.", + "imageAltCustomTourBackground": "خلفية الجولة المخصصة", + "howItWorks": { + "title": "كيف يعمل", + "desc": "ابق هادئًا وسافر بثقة", + "vectorAlt": "صورة توضيحية توضح كيفية العمل", + "bookAndRelax": { + "title": "احجز واسترخي", + "desc": "دَعْ كل رحلة تكون تجربة ملهمة، وكل غرفة مساحة هادئة" + }, + "smartChecklist": { + "title": "قائمة التحقق الذكية", + "desc": "دَعْ كل رحلة تكون تجربة ملهمة، وكل غرفة مساحة هادئة" + }, + "saveMore": { + "title": "وفر أكثر", + "desc": "دَعْ كل رحلة تكون تجربة ملهمة، وكل غرفة مساحة هادئة" + }, + "item1": { + "imageAlt": "توضيح ميزة احجز واسترخي", + "imageAltDark": "توضيح ميزة احجز واسترخي في الوضع المظلم" + }, + "item2": { + "imageAlt": "توضيح ميزة قائمة التحقق الذكية", + "imageAltDark": "توضيح ميزة قائمة التحقق الذكية في الوضع المظلم" + }, + "item3": { + "imageAlt": "توضيح ميزة وفر أكثر", + "imageAltDark": "توضيح ميزة وفر أكثر في الوضع المظلم" + } + }, + "imageAltMapBackground": "خلفية الخريطة", + "imageAltAppRightImg": "صورة التطبيق اليمنى", + "buttonDownloadOnAppStore": "تنزيل من متجر التطبيقات", + "buttonGetItOnGooglePlay": "احصل عليها من Google Play", + "tourSuggestion": { + "heading": "الدول", + "subHeading": "أماكن شهيرة نوصي بها لك", + "vectorAlt": "صورة توضيحية توضح اقتراحات الجولات", + "categories": { + "Nature House": "منزل طبيعي", + "Wooden house": "منزل خشبي", + "Houseboat": "قارب منزل", + "Farm House": "منزل مزرعة", + "Dome House": "منزل قبة", + "Wooden Dome": "قبة خشبية" + } + }, + "tourSuggestion.heading": "الدول", + "tourSuggestion.subHeading": "أماكن شهيرة نوصي بها لك", + "cardCategory3.imageAltPlaces": "أماكن", + "cardCategory3.tours": "الجولات", + "sectionClientSay": { + "heading": "ماذا يقول عملاؤنا عنا؟", + "imageAltMain": "صورة رئيسية لآراء العملاء", + "imageAltClient1": "العميل 1", + "imageAltClient2": "العميل 2", + "imageAltClient3": "العميل 3", + "imageAltClient4": "العميل 4", + "imageAltClient5": "العميل 5", + "imageAltClient6": "العميل 6", + "imageAltQuotation1": "علامة اقتباس يسار", + "imageAltQuotation2": "علامة اقتباس يمين", + "testimonials": { + "0": { + "content": "كانت الرحلة مع عقيلة تجربة روحية غنية. المرشدين المطلعين والطاقم الدافئ جعلوا كل لحظة لا تُنسى.", + "clientName": "تيانا أبي", + "clientAddress": "ماليزيا" + }, + "1": { + "content": "تم ترتيب كل شيء بشكل مثالي، من الإقامة إلى الزيارات إلى الأماكن المقدسة. شعرت بالاهتمام طوال الجولة.", + "clientName": "ليني سويفان", + "clientAddress": "لندن" + }, + "2": { + "content": "الانضمام إلى هذه الجولة سمح لي بالتواصل بشكل عميق مع المسافرين الآخرين وتراثي. أوصي بشدة بـ عقيلة لرحلة ذات مغزى!", + "clientName": "بيرتا إميلي", + "clientAddress": "طوكيو" + } + } + }, + "sectionGridFilterCard": { + "allTours": "جميع الجولات", + "noToursAvailable": "لا توجد جولات متاحة", + "toursInfo": "{{count}} إقامة · {{dateRange}} · {{guests}} ضيوف" + }, + "accountHeading": "معلومات الحساب", + "nameLabel": "الاسم", + "emailLabel": "البريد الإلكتروني", + "phoneLabel": "رقم الهاتف", + "changeImage": "تغيير الصورة", + "updateButton": "تحديث المعلومات", + "signOutButton": "تسجيل الخروج", + "deleteButton": "حذف الحساب", + "deleteSuccess": "تم حذف حسابك بنجاح.", + "signOutSuccess": "تم تسجيل الخروج بنجاح.", + "updateSuccess": "تم تحديث معلوماتك بنجاح.", + "noChanges": "لم يتم اكتشاف أي تغييرات.", + "errorGeneric": "حدث خطأ ما. يرجى المحاولة مرة أخرى.", + "errorUnknown": "حدث خطأ غير معروف.", + "benefits": "الفوائد" } diff --git a/public/locales/ar/footer.json b/public/locales/ar/footer.json new file mode 100644 index 0000000..a8fa8b6 --- /dev/null +++ b/public/locales/ar/footer.json @@ -0,0 +1,23 @@ +{ + "widgetMenus": { + "Quick Links": { + "title": "روابط سريعة", + "menus": [ + { "label": "جميع الجولات" }, + { "label": "المدونات" }, + { "label": "الأسئلة الشائعة" }, + { "label": "من نحن" } + ] + } + }, + "aboutUs": { + "title": "من نحن", + "description": "نحن فريق متحمس مكرس لصناعة تجارب سفر لا تُنسى للمستكشفين والحالمين على حد سواء. من الهروب الهادئ إلى الشواطئ الاستوائية إلى المغامرات المليئة بالأدرينالين في الأماكن الغريبة، نصمم رحلات فريدة كما أنت. انضم إلينا ولنكشف العالم، مغامرة واحدة في كل مرة!" + }, + "footerNav": { + "description": "نحن فريق متحمس مكرس لصناعة تجارب سفر لا تُنسى للمستكشفين والحالمين على حد سواء." + }, + "socials": { + "title": "تابعنا" + } +} \ No newline at end of file diff --git a/public/locales/ar/form.json b/public/locales/ar/form.json new file mode 100644 index 0000000..918769e --- /dev/null +++ b/public/locales/ar/form.json @@ -0,0 +1,91 @@ +{ + "selectTour": "اختر جولتك", + "tourPeriod": "مدة الجولة", + "startEndDate": "البداية - النهاية", + "guests": "الضيوف", + "addGuests": "إضافة ضيوف", + "adults": "البالغين", + "adultsDesc": "الأعمار 13 فما فوق", + "children": "الأطفال", + "childrenDesc": "الأعمار من 2 إلى 12", + "infants": "الرضع", + "infantsDesc": "الأعمار من 0 إلى 2", + "clear": "مسح", + "submit": "إرسال", + "login": "تسجيل الدخول", + "phoneNumber": "رقم الهاتف", + "enterPhoneNumber": "أدخل رقم هاتفك", + "password": "كلمة المرور", + "forgotPassword": "نسيت كلمة المرور؟", + "enterPassword": "أدخل كلمة المرور", + "continue": "استمرار", + "createAccount": "إنشاء حساب", + "invalidPhoneNumber": "رقم الهاتف غير صالح.", + "invalidPhoneNumberFormat": "تنسيق رقم الهاتف غير صالح.", + "passwordRequired": "كلمة المرور مطلوبة.", + "loginSuccessful": "تم تسجيل الدخول بنجاح!", + "loginFailed": "فشل تسجيل الدخول، يرجى التحقق من بياناتك.", + "unknownError": "حدث خطأ غير معروف.", + "hidePassword": "إخفاء كلمة المرور", + "showPassword": "عرض كلمة المرور", + "signup": "إنشاء حساب", + "changePassword": "تغيير كلمة المرور", + "fullName": "الاسم الكامل", + "enterFullName": "أدخل اسمك الكامل", + "confirmPassword": "تأكيد كلمة المرور", + "enterConfirmPassword": "أعد إدخال كلمة المرور", + "alreadyHaveAccount": "هل لديك حساب بالفعل؟", + "signIn": "تسجيل الدخول", + "errorOccurred": "حدث خطأ.", + "hideConfirmPassword": "إخفاء تأكيد كلمة المرور", + "showConfirmPassword": "عرض تأكيد كلمة المرور", + "verificationMethod": "طريقة التحقق", + "sendViaWhatsApp": "إرسال عبر واتساب", + "sendViaSMS": "إرسال عبر الرسائل النصية", + "verificationCode": "رمز التحقق", + "enterOtpDescription": "أدخل الرمز المكون من 5 أرقام الذي أرسلناه لإكمال تسجيل حسابك", + "haventGotCode": "لم تحصل على رمز التأكيد بعد؟", + "resend": "إعادة إرسال", + "seconds": "ثواني", + "confirm": "تأكيد", + "signInSuccessful": "تم تسجيل دخولك بنجاح", + "somethingWentWrong": "حدث خطأ ما. يرجى المحاولة مرة أخرى.", + "otpInput": "إدخال OTP {{index}}", + "otpNotComplete": "رمز التحقق غير صالح", + "addNewPassenger": "إضافة راكب جديد", + "passengerInfo": "معلومات الراكب", + "passportNo": "رقم الجواز", + "fullNameRequired": "الاسم الكامل مطلوب.", + "passportRequired": "رقم الجواز مطلوب.", + "passportNumeric": "يجب أن يكون رقم الجواز رقميًا.", + "dobRequired": "تاريخ الميلاد مطلوب.", + "phoneRequired": "رقم الهاتف مطلوب.", + "phoneNumeric": "يجب أن يكون رقم الهاتف رقميًا.", + "passportImageRequired": "صورة الجواز مطلوبة.", + "editPassengerInfo": "تعديل معلومات الراكب", + "backToBills": "العودة إلى الفواتير", + "noBillsAvailable": "لا توجد فواتير متاحة", + "awaitingPayment": "بانتظار الدفع", + "approved": "معتمد", + "rejected": "مرفوض", + "pending": "قيد الانتظار", + "issuedDate": "تاريخ الإصدار", + "expirationDate": "تاريخ الانتهاء", + "tourInvoiceAmount": "قيمة فاتورة الجولة", + "viewBill": "عرض الفاتورة", + "transactionReceiptUpdated": "تم تحديث إيصال العملية بنجاح", + "updateFailed": "فشل في تحديث الإيصال", + "billDetails": "تفاصيل الفاتورة", + "whyRejected": "لماذا تم رفضها؟", + "numberOfPassengers": "عدد الركاب", + "adult": "بالغ", + "infant": "رضيع", + "tourPrice": "سعر الجولة", + "accountNumber": "رقم الحساب", + "uploadPassportImage": "تحميل صورة الجواز", + "noFileSelected": "لم يتم اختيار ملف", + "uploadedImage": "الصورة المرفوعة", + "delete": "حذف", + "currentReceipt": "الإيصال الحالي", + "copy": "نسخ" +} diff --git a/public/locales/ar/navigation.json b/public/locales/ar/navigation.json new file mode 100644 index 0000000..abd5950 --- /dev/null +++ b/public/locales/ar/navigation.json @@ -0,0 +1,15 @@ +{ + "text-home": "الرئيسية", + "text-all-tours": "جميع الجولات", + "text-blog": "المدونة", + "text-faq": "الأسئلة الشائعة", + "text-about": "عن الموقع", + "text-language": "اللغة", + "text-no-match": "لا توجد نتائج", + "search-placeholder": "اكتب وابحث...", + "customTrip": "رحلة مخصصة", + "navAccount": "الحساب", + "navMyTrips": "رحلاتي", + "navPassengersList": "قائمة الركاب", + "navBills": "الفواتير" +} diff --git a/public/locales/en/FAQ.json b/public/locales/en/FAQ.json index e70cd29..c2961db 100644 --- a/public/locales/en/FAQ.json +++ b/public/locales/en/FAQ.json @@ -1,25 +1,24 @@ { - "faqTitle": "Frequently Asked Questions", - "faqSubtitle": "Have Questions? We are here to help you!", - "faqQuestion1": "How can I book a tour on your site?", - "faqAnswer1": "To book a tour, simply select your desired destination from the 'List of Tours', choose your dates, and follow the steps to complete the booking process.", - "faqQuestion2": "Can I customize my tour?", - "faqAnswer2": "Yes, our 'Customize Tour' feature allows you to tailor your journey based on your preferences. Click on 'Customize Tour' at the top of the page to start personalizing your experience.", - "faqQuestion3": "What payment methods do you accept?", - "faqAnswer3": "We accept all major credit cards, PayPal, and bank transfers. You can choose your preferred method during the checkout process.", - "faqQuestion4": "How do I know my booking is confirmed?", - "faqAnswer4": "Once you complete the payment process, you will receive a confirmation email with all the details of your booking. You can also view your booking details in your account dashboard.", - "faqQuestion5": "Can I cancel or modify my booking?", - "faqAnswer5": "Yes, you can cancel or modify your booking from your account. Please note that cancellations must be made at least 24 hours before the tour starts to be eligible for a refund.", - "faqQuestion6": "Are there any hidden fees?", - "faqAnswer6": "No, all fees are transparent and shown upfront before you complete your booking. We ensure there are no hidden fees.", - "faqQuestion7": "Do you offer group discounts?", - "faqAnswer7": "Yes, we offer group discounts for larger bookings. Please contact our support team for more information on group rates.", - "faqQuestion8": "Is travel insurance included in the booking?", - "faqAnswer8": "Yes, all our tour packages include basic travel insurance. You can choose to upgrade your insurance package during the checkout process.", - "faqQuestion9": "What happens if the tour is canceled by the provider?", - "faqAnswer9": "If the tour is canceled by the provider due to unforeseen circumstances, you will receive a full refund or the option to reschedule your tour.", - "faqQuestion10": "How can I contact customer support?", - "faqAnswer10": "You can contact customer support by clicking the 'Contact Us' button at the bottom of the page or by visiting our support section." - } - \ No newline at end of file + "faqTitle": "Frequently Asked Questions", + "faqSubtitle": "Have questions? We are here to help!", + "faqQuestion1": "How can I book a tour on your site?", + "faqAnswer1": "To book a tour, simply select your desired destination from the 'List of Tours', choose your dates, and follow the steps to complete the booking process.", + "faqQuestion2": "Can I customize my tour?", + "faqAnswer2": "Yes, our 'Customize Tour' feature allows you to tailor your journey based on your preferences. Click on 'Customize Tour' at the top of the page to start personalizing your experience.", + "faqQuestion3": "What payment methods do you accept?", + "faqAnswer3": "We accept all major credit cards, PayPal, and bank transfers. You can choose your preferred method during the checkout process.", + "faqQuestion4": "How do I know my booking is confirmed?", + "faqAnswer4": "Once you complete the payment process, you will receive a confirmation email with all the details of your booking. You can also view your booking details in your account dashboard.", + "faqQuestion5": "Can I cancel or modify my booking?", + "faqAnswer5": "Yes, you can cancel or modify your booking from your account. Please note that cancellations must be made at least 24 hours before the tour starts to be eligible for a refund.", + "faqQuestion6": "Are there any hidden fees?", + "faqAnswer6": "No, all fees are transparent and shown upfront before you complete your booking. We ensure there are no hidden fees.", + "faqQuestion7": "Do you offer group discounts?", + "faqAnswer7": "Yes, we offer group discounts for larger bookings. Please contact our support team for more information on group rates.", + "faqQuestion8": "Is travel insurance included in the booking?", + "faqAnswer8": "Yes, all our tour packages include basic travel insurance. You can choose to upgrade your insurance package during the checkout process.", + "faqQuestion9": "What happens if the tour is canceled by the provider?", + "faqAnswer9": "If the tour is canceled by the provider due to unforeseen circumstances, you will receive a full refund or the option to reschedule your tour.", + "faqQuestion10": "How can I contact customer support?", + "faqAnswer10": "You can contact customer support by clicking the 'Contact Us' button at the bottom of the page or by visiting our support section." +} diff --git a/public/locales/en/common.json b/public/locales/en/common.json index aa9507b..c871980 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -10,23 +10,23 @@ "beginAdventure": "Begin your", "beginAdventure1": "spiritual", "beginAdventure2": "adventure", - "planPilgrimage": "Plan your pilgrimage with ease. Find the best accommodations, transportation, and guided experiences to Shia shrines around the world", + "planPilgrimage": "Plan your pilgrimage with ease. Find the best accommodations, transportation, and guided experiences to Shia shrines around the world.", "startJourney": "Start your journey", "listOfTours": "List of Tours", "exploreTours": "Explore tours and accommodations tailored for a spiritual and memorable journey", - "tourPeriod": "Tour period", + "tourPeriod": "Tour Period", "tourPeriodDescription": "Start - End", "guests": "Guests", "addGuests": "Add guests", "available": "Available", - "soldOut": "Sold Out", + "soldOut": "Sold out", "showMore": "Show me more", - "happeningCities": "Happening cities", - "costEffectiveAdvertising": "Cost-effective advertising", + "happeningCities": "Happening Cities", + "costEffectiveAdvertising": "Cost-effective Advertising", "costEffectiveDescription": "With a free listing, you can advertise your rental with no upfront costs", "reachMillions": "Reach millions with Chisfis", "reachMillionsDescription": "Millions of people are searching for unique places to stay around the world", - "secureAndSimple": "Secure and simple", + "secureAndSimple": "Secure and Simple", "secureDescription": "A Holiday Lettings listing gives you a secure and easy way to take bookings and payments online", "mobileApps": "Mobile Apps", "mobileAppsDescription": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed dapibus porttitor nisl, sit amet finibus libero.", @@ -35,22 +35,22 @@ "upgradeGuide": "Upgrade Guide", "browserSupport": "Browser Support", "editorSupport": "Editor Support", - "designFeatures": "Design features", + "designFeatures": "Design Features", "prototyping": "Prototyping", - "designSystems": "Design systems", + "designSystems": "Design Systems", "pricing": "Pricing", "security": "Security", - "bestPractices": "Best practices", + "bestPractices": "Best Practices", "support": "Support", "developers": "Developers", - "learnDesign": "Learn design", + "learnDesign": "Learn Design", "releases": "Releases", "discussionForums": "Discussion Forums", "codeOfConduct": "Code of Conduct", "communityResources": "Community Resources", "contributing": "Contributing", "concurrentMode": "Concurrent Mode", - "goodNews": "Good news from far away", + "goodNews": "Good News from Far Away", "whatPeopleThink": "Let's see what people think of Chisfis", "testimonial": "This place is exactly like the picture posted on Chisfis. Great service, we had a great stay!", "clientName": "Tiana Abie", @@ -58,11 +58,11 @@ "myTrips": "My Trips", "account": "Account", "menu": "Menu", - "gettingStarted": "Getting started", + "gettingStarted": "Getting Started", "explore": "Explore", "resources": "Resources", "community": "Community", - "placeType": "Type of place", + "placeType": "Type of Place", "noTours": "No tours available", "itinerary": "Itinerary", "itineraryTitle": "Itinerary", @@ -85,34 +85,139 @@ "submit": "Submit", "cancel": "Cancel", "relatedPosts": "Related Posts", - "aboutUsHeading": "👋 About Us.", + "aboutUsHeading": "👋 About Us", "aboutUsSubheading": "We are a passionate team dedicated to crafting unforgettable travel experiences for explorers and dreamers alike. From serene escapes on tropical beaches to adrenaline-fueled adventures in exotic locales, we curate journeys that are as unique as you are. Join us and let’s explore the world, one adventure at a time!", "statisticTitle": "🚀 Fast Facts", "statisticDescription": "We’re impartial and independent, and every day we create distinctive, world-class programmes and content.", "statisticHeading1": "10 million", - "statisticSubHeading1": "Articles have been public around the world (as of Sept. 30, 2021)", + "statisticSubHeading1": "Articles have been published around the world (as of Sept. 30, 2021)", "statisticHeading2": "100,000", - "statisticSubHeading2": "Registered users account (as of Sept. 30, 2021)", + "statisticSubHeading2": "Registered user accounts (as of Sept. 30, 2021)", "statisticHeading3": "220+", "statisticSubHeading3": "Countries and regions have our presence (as of Sept. 30, 2021)", "customTrip": "Custom Trip", "guide": "Guide", "guideDescription": "First, write the origin of your departure, then choose the first destination of your trip, the number of nights of stay, and the means of travel, then choose your travel destinations if you wish.", "beginYourTrip": "Begin your trip", - "startDate": "Start Date", - "numberOfPassengers": "Number Of Passengers", + "startDate": "Start date", + "numberOfPassengers": "Number of passengers", "destination": "Destination", - "selectCity": "Select City", + "selectCity": "Select city", "transportation": "Transportation", - "selectTransport": "Select Transport", + "selectTransport": "Select transport", "hotel": "Hotel", - "selectHotel": "Select Hotel", + "selectHotel": "Select hotel", "duration": "Duration", "finishDate": "Finish date", - "addDestination": "Add Destination", + "addDestination": "Add destination", "continue": "Continue", - "successMessage": "Successfully Registered", + "successMessage": "Successfully registered", "to": "to", - "login": "LogIn", - "signup": "Sign Up" + "login": "Login", + "signup": "Sign up", + "All": "All", + "create": "Create", + "createPersonalizedTourLine1": "Create your personalized tour and design the", + "createPersonalizedTourLine2": "perfect travel experience tailored to your preferences.", + "imageAltCustomTourBackground": "Custom tour background", + + "howItWorks": { + "title": "How it works", + "desc": "Keep calm & travel on", + "vectorAlt": "Decorative vector image illustrating how it works", + "bookAndRelax": { + "title": "Book & Relax", + "desc": "Let each trip be an inspirational journey, each room a peaceful space" + }, + "smartChecklist": { + "title": "Smart Checklist", + "desc": "Let each trip be an inspirational journey, each room a peaceful space" + }, + "saveMore": { + "title": "Save More", + "desc": "Let each trip be an inspirational journey, each room a peaceful space" + }, + "item1": { + "imageAlt": "Book & Relax feature illustration", + "imageAltDark": "Book & Relax feature illustration in dark mode" + }, + "item2": { + "imageAlt": "Smart Checklist feature illustration", + "imageAltDark": "Smart Checklist feature illustration in dark mode" + }, + "item3": { + "imageAlt": "Save More feature illustration", + "imageAltDark": "Save More feature illustration in dark mode" + } + }, + "imageAltMapBackground": "Map background", + "imageAltAppRightImg": "App right image", + "buttonDownloadOnAppStore": "Download on the App Store", + "buttonGetItOnGooglePlay": "Get it on Google Play", + "tourSuggestion": { + "heading": "Countries", + "subHeading": "Popular places to recommend for you", + "vectorAlt": "Decorative vector image illustrating tour suggestions", + "categories": { + "Nature House": "Nature House", + "Wooden house": "Wooden House", + "Houseboat": "Houseboat", + "Farm House": "Farm House", + "Dome House": "Dome House", + "Wooden Dome": "Wooden Dome" + } + }, + "tourSuggestion.heading": "Countries", + "tourSuggestion.subHeading": "Popular places to recommend for you", + "cardCategory3.imageAltPlaces": "Places", + "cardCategory3.tours": "Tours", + "sectionClientSay": { + "heading": "What do our customers say about us?", + "imageAltMain": "Client Say Main Image", + "imageAltClient1": "Client 1", + "imageAltClient2": "Client 2", + "imageAltClient3": "Client 3", + "imageAltClient4": "Client 4", + "imageAltClient5": "Client 5", + "imageAltClient6": "Client 6", + "imageAltQuotation1": "Quotation Mark Left", + "imageAltQuotation2": "Quotation Mark Right", + "testimonials": { + "0": { + "content": "Traveling with Aqila was a spiritually enriching experience. The knowledgeable guides and warm staff made every moment memorable.", + "clientName": "Tiana Abie", + "clientAddress": "Malaysia" + }, + "1": { + "content": "Everything was perfectly arranged, from accommodations to visits to sacred sites. I felt well taken care of throughout the entire tour.", + "clientName": "Lennie Swiffan", + "clientAddress": "London" + }, + "2": { + "content": "Joining this tour allowed me to connect deeply with fellow travelers and my heritage. Highly recommend Aqila for a meaningful trip!", + "clientName": "Berta Emili", + "clientAddress": "Tokyo" + } + } + }, + "sectionGridFilterCard": { + "allTours": "All Tours", + "noToursAvailable": "No tours available", + "toursInfo": "{{count}} stays · {{dateRange}} · {{guests}} Guests" + }, + "accountHeading": "Account Information", + "nameLabel": "Name", + "emailLabel": "Email", + "phoneLabel": "Phone", + "changeImage": "Change Image", + "updateButton": "Update Info", + "signOutButton": "Sign Out", + "deleteButton": "Delete Account", + "deleteSuccess": "Your account has been deleted successfully.", + "signOutSuccess": "You have signed out successfully.", + "updateSuccess": "Your information has been updated successfully.", + "noChanges": "No changes detected.", + "errorGeneric": "Something went wrong. Please try again.", + "errorUnknown": "An unknown error occurred.", + "benefits" : "BENEFITS" } diff --git a/public/locales/en/footer.json b/public/locales/en/footer.json new file mode 100644 index 0000000..b0d2067 --- /dev/null +++ b/public/locales/en/footer.json @@ -0,0 +1,23 @@ +{ + "widgetMenus": { + "Quick Links": { + "title": "Quick Links", + "menus": [ + { "label": "All Tours" }, + { "label": "Blogs" }, + { "label": "FAQ" }, + { "label": "About Us" } + ] + } + }, + "aboutUs": { + "title": "About Us", + "description": "We are a passionate team dedicated to crafting unforgettable travel experiences for explorers and dreamers alike. From serene escapes on tropical beaches to adrenaline-fueled adventures in exotic locales, we curate journeys that are as unique as you are. Join us and let’s explore the world, one adventure at a time!" + }, + "footerNav": { + "description": "We are a passionate team dedicated to crafting unforgettable travel experiences for explorers and dreamers alike." + }, + "socials": { + "title": "Follow us" + } +} diff --git a/public/locales/en/form.json b/public/locales/en/form.json new file mode 100644 index 0000000..dfe425a --- /dev/null +++ b/public/locales/en/form.json @@ -0,0 +1,91 @@ +{ + "selectTour": "Select your tour", + "tourPeriod": "Tour period", + "startEndDate": "Start - End", + "guests": "Guests", + "addGuests": "Add Guests", + "adults": "Adults", + "adultsDesc": "Ages 13 or above", + "children": "Children", + "childrenDesc": "Ages 2–12", + "infants": "Infants", + "infantsDesc": "Ages 0–2", + "clear": "Clear", + "submit": "Submit", + "login": "Login", + "phoneNumber": "Phone Number", + "enterPhoneNumber": "Enter your phone number", + "password": "Password", + "forgotPassword": "Forgot password?", + "enterPassword": "Enter your password", + "continue": "Continue", + "createAccount": "Create an account", + "invalidPhoneNumber": "Invalid phone number.", + "invalidPhoneNumberFormat": "Invalid phone number format.", + "passwordRequired": "Password is required.", + "loginSuccessful": "Login successful!", + "loginFailed": "Login failed, please check your credentials.", + "unknownError": "An unknown error occurred.", + "hidePassword": "Hide password", + "showPassword": "Show password", + "signup": "Signup", + "changePassword": "Change password", + "fullName": "Full Name", + "enterFullName": "Enter your full name", + "confirmPassword": "Confirm Password", + "enterConfirmPassword": "Re-enter your password", + "alreadyHaveAccount": "Already have an account?", + "signIn": "Sign in", + "errorOccurred": "An error occurred.", + "hideConfirmPassword": "Hide confirm password", + "showConfirmPassword": "Show confirm password", + "verificationMethod": "Verification method", + "sendViaWhatsApp": "Send via WhatsApp", + "sendViaSMS": "Send via SMS", + "verificationCode": "Verification Code", + "enterOtpDescription": "Enter the 5-digit code that we sent to complete your account registration", + "haventGotCode": "Haven't got the confirmation code yet?", + "resend": "Resend", + "seconds": "Seconds", + "confirm": "Confirm", + "signInSuccessful": "Your sign in was successful", + "somethingWentWrong": "Something went wrong. Please try again.", + "otpInput": "OTP input {{index}}", + "otpNotComplete": "Verification code is not valid", + "addNewPassenger": "Add new passenger", + "passengerInfo": "Passenger information", + "passportNo": "Passport No", + "fullNameRequired": "Full Name is required.", + "passportRequired": "Passport Number is required.", + "passportNumeric": "Passport Number must be numeric.", + "dobRequired": "Date of Birth is required.", + "phoneRequired": "Phone Number is required.", + "phoneNumeric": "Phone Number must be numeric.", + "passportImageRequired": "Passport image is required.", + "editPassengerInfo": "Edit Passenger Information", + "backToBills": "Back to Bills", + "noBillsAvailable": "No bills available", + "awaitingPayment": "Awaiting Payment", + "approved": "Approved", + "rejected": "Rejected", + "pending": "Pending", + "issuedDate": "Issued Date", + "expirationDate": "Expiration Date", + "tourInvoiceAmount": "Tour Invoice Amount", + "viewBill": "View Bill", + "transactionReceiptUpdated": "Transaction receipt updated successfully", + "updateFailed": "Failed to update receipt", + "billDetails": "Bill Details", + "whyRejected": "Why was it rejected?", + "numberOfPassengers": "Number of Passengers", + "adult": "Adult", + "infant": "Infant", + "tourPrice": "Tour Price", + "accountNumber": "Account Number", + "uploadPassportImage": "Upload Passport Image", + "noFileSelected": "No File Selected", + "uploadedImage": "Uploaded Image", + "delete": "Delete", + "currentReceipt": "Current Receipt", + "copy": "Copy" +} diff --git a/public/locales/en/navigation.json b/public/locales/en/navigation.json new file mode 100644 index 0000000..e02ff8d --- /dev/null +++ b/public/locales/en/navigation.json @@ -0,0 +1,15 @@ +{ + "text-home": "Home", + "text-all-tours": "All Tours", + "text-blog": "Blog", + "text-faq": "FAQ", + "text-about": "About", + "text-language": "Language", + "text-no-match": "No Matches Found", + "search-placeholder": "Type and search...", + "customTrip": "Custom Trip", + "navAccount": "Account", + "navMyTrips": "My Trips", + "navPassengersList": "Passengers List", + "navBills": "Bills" +} diff --git a/public/locales/fr/common.json b/public/locales/fr/common.json deleted file mode 100644 index 8552cf7..0000000 --- a/public/locales/fr/common.json +++ /dev/null @@ -1,116 +0,0 @@ -{ - "home": "Accueil", - "allTours": "Tous les Tours", - "blogs": "Blogs", - "faq": "FAQ", - "aboutUs": "À Propos de Nous", - "customTour": "Tour Personnalisé", - "searchPlaceholder": "Où aller ?", - "searchDescription": "Partout • N'importe quelle semaine • Ajouter des invités", - "beginAdventure": "Commencez votre aventure spirituelle", - "planPilgrimage": "Planifiez votre pèlerinage facilement. Trouvez les meilleures accommodations, transports et expériences guidées vers les sanctuaires chiites à travers le monde", - "startJourney": "Commencez votre voyage", - "listOfTours": "Liste des Tours", - "exploreTours": "Explorez les tours et accommodations adaptées pour un voyage spirituel et mémorable", - "tourPeriod": "Période du Tour", - "tourPeriodDescription": "Début - Fin", - "guests": "Invités", - "addGuests": "Ajouter des invités", - "available": "Disponible", - "soldOut": "Épuisé", - "showMore": "Montrez-moi plus", - "happeningCities": "Villes Animées", - "costEffectiveAdvertising": "Publicité Rentable", - "costEffectiveDescription": "Avec une annonce gratuite, vous pouvez faire la publicité de votre location sans frais initiaux", - "reachMillions": "Atteignez des millions avec Chisfis", - "reachMillionsDescription": "Des millions de personnes recherchent des lieux uniques où séjourner à travers le monde", - "secureAndSimple": "Securisé et Simple", - "secureDescription": "Une annonce sur Holiday Lettings vous offre un moyen sécurisé et facile de prendre des réservations et des paiements en ligne", - "mobileApps": "Applications Mobiles", - "mobileAppsDescription": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed dapibus porttitor nisl, sit amet finibus libero.", - "installation": "Installation", - "releaseNotes": "Notes de Version", - "upgradeGuide": "Guide de Mise à Niveau", - "browserSupport": "Support des Navigateurs", - "editorSupport": "Support de l'Éditeur", - "designFeatures": "Caractéristiques de Design", - "prototyping": "Prototypage", - "designSystems": "Systèmes de Design", - "pricing": "Tarification", - "security": "Sécurité", - "bestPractices": "Meilleures Pratiques", - "support": "Support", - "developers": "Développeurs", - "learnDesign": "Apprendre le Design", - "releases": "Versions", - "discussionForums": "Forums de Discussion", - "codeOfConduct": "Code de Conduite", - "communityResources": "Ressources Communautaires", - "contributing": "Contribuer", - "concurrentMode": "Mode Concurrent", - "goodNews": "Bonnes Nouvelles d'Ailleurs", - "whatPeopleThink": "Voyons ce que les gens pensent de Chisfis", - "testimonial": "Cet endroit est exactement comme sur la photo publiée sur Chisfis. Excellent service, nous avons passé un très bon séjour !", - "clientName": "Tiana Abie", - "clientLocation": "Malaisie", - "myTrips": "Mes Voyages", - "account": "Compte", - "menu": "Menu", - "gettingStarted": "Premiers Pas", - "explore": "Explorer", - "resources": "Ressources", - "community": "Communauté", - "placeType": "Type de Lieu", - "noTours": "Aucun tour disponible", - "itinerary": "Itinéraire", - "itineraryTitle": "Itinéraire", - "total": "Total", - "reserve": "Réserver", - "tourFeatures": "Caractéristiques du Tour", - "tourFeaturesTitle": "Caractéristiques du Tour", - "startRating": "Évaluation de Début", - "listingDetails": "Détails", - "imageAlt": "Image du tour", - "loading": "Chargement...", - "adults": "Adultes", - "adultsDesc": "Âges 13 ou plus", - "children": "Enfants", - "childrenDesc": "Âges 2–12", - "infants": "Bébés", - "infantsDesc": "Âges 0–2", - "traveler": "Voyageur", - "responses": "Réponses ({{count}})", - "submit": "Soumettre", - "cancel": "Annuler", - "relatedPosts": "Articles Connexes", - "aboutUsHeading": "👋 À Propos de Nous.", - "aboutUsSubheading": "Nous sommes une équipe passionnée dédiée à la création d'expériences de voyage inoubliables pour les explorateurs et les rêveurs. Des escapades sereines sur des plages tropicales aux aventures à sensations fortes dans des lieux exotiques, nous concevons des voyages aussi uniques que vous. Rejoignez-nous et explorons le monde, une aventure à la fois !", - "statisticTitle": "🚀 Faits Rapides", - "statisticDescription": "Nous sommes impartiaux et indépendants, et chaque jour nous créons des programmes et du contenu distinctifs de classe mondiale.", - "statisticHeading1": "10 millions", - "statisticSubHeading1": "D'articles ont été publiés à travers le monde (au 30 septembre 2021)", - "statisticHeading2": "100 000", - "statisticSubHeading2": "Utilisateurs enregistrés (au 30 septembre 2021)", - "statisticHeading3": "220+", - "statisticSubHeading3": "Pays et régions où nous sommes présents (au 30 septembre 2021)", - "customTrip": "Voyage Personnalisé", - "guide": "Guide", - "guideDescription": "Tout d'abord, écrivez l'origine de votre départ, puis choisissez la première destination de votre voyage, le nombre de nuits de séjour et le moyen de transport, puis choisissez vos destinations de voyage si vous le souhaitez.", - "beginYourTrip": "Commencez Votre Voyage", - "startDate": "Date de Début", - "numberOfPassengers": "Nombre de Passagers", - "destination": "Destination", - "selectCity": "Sélectionner une Ville", - "transportation": "Transport", - "selectTransport": "Sélectionner le Transport", - "hotel": "Hôtel", - "selectHotel": "Sélectionner l'Hôtel", - "duration": "Durée", - "finishDate": "Date de Fin", - "addDestination": "Ajouter une Destination", - "continue": "Continuer", - "successMessage": "Enregistré avec succès", - "to": "à", - "login": "Se Connecter", - "signup": "S'inscrire" -} diff --git a/public/locales/id/FAQ.json b/public/locales/id/FAQ.json new file mode 100644 index 0000000..1efff62 --- /dev/null +++ b/public/locales/id/FAQ.json @@ -0,0 +1,24 @@ +{ + "faqTitle": "Pertanyaan yang Sering Diajukan", + "faqSubtitle": "Punya pertanyaan? Kami di sini untuk membantu!", + "faqQuestion1": "Bagaimana cara saya memesan tur di situs Anda?", + "faqAnswer1": "Untuk memesan tur, cukup pilih tujuan yang Anda inginkan dari 'Daftar Tur', pilih tanggal Anda, dan ikuti langkah-langkah untuk menyelesaikan proses pemesanan.", + "faqQuestion2": "Apakah saya bisa menyesuaikan tur saya?", + "faqAnswer2": "Ya, fitur 'Tur Kustom' kami memungkinkan Anda untuk menyesuaikan perjalanan berdasarkan preferensi Anda. Klik 'Tur Kustom' di bagian atas halaman untuk memulai personalisasi pengalaman Anda.", + "faqQuestion3": "Metode pembayaran apa yang Anda terima?", + "faqAnswer3": "Kami menerima semua kartu kredit utama, PayPal, dan transfer bank. Anda dapat memilih metode pembayaran yang diinginkan selama proses checkout.", + "faqQuestion4": "Bagaimana cara saya tahu jika pemesanan saya sudah dikonfirmasi?", + "faqAnswer4": "Setelah Anda menyelesaikan proses pembayaran, Anda akan menerima email konfirmasi dengan semua detail pemesanan Anda. Anda juga dapat melihat detail pemesanan Anda di dasbor akun Anda.", + "faqQuestion5": "Bisakah saya membatalkan atau mengubah pemesanan saya?", + "faqAnswer5": "Ya, Anda dapat membatalkan atau mengubah pemesanan Anda dari akun Anda. Harap dicatat bahwa pembatalan harus dilakukan setidaknya 24 jam sebelum tur dimulai agar memenuhi syarat untuk mendapatkan pengembalian dana.", + "faqQuestion6": "Apakah ada biaya tersembunyi?", + "faqAnswer6": "Tidak, semua biaya transparan dan ditampilkan sebelumnya sebelum Anda menyelesaikan pemesanan. Kami memastikan tidak ada biaya tersembunyi.", + "faqQuestion7": "Apakah Anda menawarkan diskon untuk grup?", + "faqAnswer7": "Ya, kami menawarkan diskon grup untuk pemesanan besar. Silakan hubungi tim dukungan kami untuk informasi lebih lanjut mengenai tarif grup.", + "faqQuestion8": "Apakah asuransi perjalanan termasuk dalam pemesanan?", + "faqAnswer8": "Ya, semua paket tur kami termasuk asuransi perjalanan dasar. Anda dapat memilih untuk meningkatkan paket asuransi Anda selama proses checkout.", + "faqQuestion9": "Apa yang terjadi jika tur dibatalkan oleh penyedia?", + "faqAnswer9": "Jika tur dibatalkan oleh penyedia karena keadaan yang tidak terduga, Anda akan menerima pengembalian dana penuh atau pilihan untuk menjadwal ulang tur Anda.", + "faqQuestion10": "Bagaimana cara saya menghubungi dukungan pelanggan?", + "faqAnswer10": "Anda dapat menghubungi dukungan pelanggan dengan mengklik tombol 'Hubungi Kami' di bagian bawah halaman atau dengan mengunjungi bagian dukungan kami." +} diff --git a/public/locales/id/common.json b/public/locales/id/common.json new file mode 100644 index 0000000..464bfa2 --- /dev/null +++ b/public/locales/id/common.json @@ -0,0 +1,222 @@ +{ + "home": "Beranda", + "allTours": "Semua Tur", + "blogs": "Blog", + "faq": "FAQ", + "aboutUs": "Tentang Kami", + "customTour": "Tur Kustom", + "searchPlaceholder": "Ke mana?", + "searchDescription": "Ke mana saja • Minggu mana saja • Tambahkan tamu", + "beginAdventure": "Mulai perjalanan", + "beginAdventure1": "spiritual", + "beginAdventure2": "petualangan", + "planPilgrimage": "Rencanakan perjalanan ziarah Anda dengan mudah. Temukan akomodasi terbaik, transportasi, dan pengalaman terpanduan ke makam-makam Syiah di seluruh dunia.", + "startJourney": "Mulai perjalanan Anda", + "listOfTours": "Daftar Tur", + "exploreTours": "Jelajahi tur dan akomodasi yang disesuaikan untuk perjalanan spiritual yang tak terlupakan", + "tourPeriod": "Periode Tur", + "tourPeriodDescription": "Mulai - Selesai", + "guests": "Tamu", + "addGuests": "Tambahkan tamu", + "available": "Tersedia", + "soldOut": "Habis terjual", + "showMore": "Tampilkan lebih banyak", + "happeningCities": "Kota yang sedang berlangsung", + "costEffectiveAdvertising": "Iklan Hemat Biaya", + "costEffectiveDescription": "Dengan daftar gratis, Anda dapat mengiklankan penyewaan Anda tanpa biaya di muka", + "reachMillions": "Jangkau jutaan dengan Chisfis", + "reachMillionsDescription": "Jutaan orang mencari tempat unik untuk menginap di seluruh dunia", + "secureAndSimple": "Aman dan Sederhana", + "secureDescription": "Daftar Holiday Lettings memberi Anda cara aman dan mudah untuk menerima pemesanan dan pembayaran secara online", + "mobileApps": "Aplikasi Seluler", + "mobileAppsDescription": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed dapibus porttitor nisl, sit amet finibus libero.", + "installation": "Instalasi", + "releaseNotes": "Catatan Rilis", + "upgradeGuide": "Panduan Pembaruan", + "browserSupport": "Dukungan Browser", + "editorSupport": "Dukungan Editor", + "designFeatures": "Fitur Desain", + "prototyping": "Pembuatan Prototipe", + "designSystems": "Sistem Desain", + "pricing": "Harga", + "security": "Keamanan", + "bestPractices": "Praktik Terbaik", + "support": "Dukungan", + "developers": "Pengembang", + "learnDesign": "Belajar Desain", + "releases": "Rilis", + "discussionForums": "Forum Diskusi", + "codeOfConduct": "Kode Etik", + "communityResources": "Sumber Daya Komunitas", + "contributing": "Berkontribusi", + "concurrentMode": "Mode Bersamaan", + "goodNews": "Berita Baik dari Jauh", + "whatPeopleThink": "Mari kita lihat apa yang dipikirkan orang tentang Chisfis", + "testimonial": "Tempat ini persis seperti gambar yang diposting di Chisfis. Layanan yang luar biasa, kami memiliki waktu yang luar biasa!", + "clientName": "Tiana Abie", + "clientLocation": "Malaysia", + "myTrips": "Perjalanan Saya", + "account": "Akun", + "menu": "Menu", + "gettingStarted": "Memulai", + "explore": "Jelajahi", + "resources": "Sumber Daya", + "community": "Komunitas", + "placeType": "Jenis Tempat", + "noTours": "Tidak ada tur yang tersedia", + "itinerary": "Rencana Perjalanan", + "itineraryTitle": "Rencana Perjalanan", + "total": "Total", + "reserve": "Pesan", + "tourFeatures": "Fitur Tur", + "tourFeaturesTitle": "Fitur Tur", + "startRating": "Mulai Peringkat", + "listingDetails": "Detail", + "imageAlt": "Gambar tur", + "loading": "Memuat...", + "adults": "Dewasa", + "adultsDesc": "Usia 13 atau lebih", + "children": "Anak-anak", + "childrenDesc": "Usia 2–12", + "infants": "Bayi", + "infantsDesc": "Usia 0–2", + "traveler": "Pelancong", + "responses": "Tanggapan ({{count}})", + "submit": "Kirim", + "cancel": "Batal", + "relatedPosts": "Postingan Terkait", + "aboutUsHeading": "👋 Tentang Kami", + "aboutUsSubheading": "Kami adalah tim yang penuh semangat yang berdedikasi untuk menciptakan pengalaman perjalanan yang tak terlupakan bagi para penjelajah dan pemimpi. Dari pelarian damai di pantai tropis hingga petualangan yang memacu adrenalin di tempat-tempat eksotis, kami merancang perjalanan yang sama uniknya dengan Anda. Bergabunglah dengan kami dan mari jelajahi dunia, satu petualangan pada satu waktu!", + "statisticTitle": "🚀 Fakta Cepat", + "statisticDescription": "Kami tidak memihak dan independen, dan setiap hari kami menciptakan program dan konten yang unik dan berkualitas dunia.", + "statisticHeading1": "10 juta", + "statisticSubHeading1": "Artikel telah diterbitkan di seluruh dunia (hingga 30 September 2021)", + "statisticHeading2": "100.000", + "statisticSubHeading2": "Akun pengguna terdaftar (hingga 30 September 2021)", + "statisticHeading3": "220+", + "statisticSubHeading3": "Negara dan wilayah yang memiliki kehadiran kami (hingga 30 September 2021)", + "customTrip": "Tur Kustom", + "guide": "Pemandu", + "guideDescription": "Pertama, tulis asal keberangkatan Anda, kemudian pilih tujuan pertama perjalanan Anda, jumlah malam menginap, dan sarana transportasi, lalu pilih tujuan perjalanan Anda jika Anda mau.", + "beginYourTrip": "Mulai perjalanan Anda", + "startDate": "Tanggal mulai", + "numberOfPassengers": "Jumlah penumpang", + "destination": "Tujuan", + "selectCity": "Pilih kota", + "transportation": "Transportasi", + "selectTransport": "Pilih transportasi", + "hotel": "Hotel", + "selectHotel": "Pilih hotel", + "duration": "Durasi", + "finishDate": "Tanggal selesai", + "addDestination": "Tambahkan tujuan", + "continue": "Lanjutkan", + "successMessage": "Berhasil terdaftar", + "to": "ke", + "login": "Masuk", + "signup": "Daftar", + "All": "Semua", + "create": "Buat", + "createPersonalizedTourLine1": "Buat tur kustom Anda dan desain", + "createPersonalizedTourLine2": "pengalaman perjalanan yang sempurna sesuai dengan preferensi Anda.", + "imageAltCustomTourBackground": "Latar belakang tur kustom", + "howItWorks": { + "title": "Cara kerja", + "desc": "Tetap tenang & teruskan perjalanan", + "vectorAlt": "Gambar vektor dekoratif yang menggambarkan cara kerjanya", + "bookAndRelax": { + "title": "Pesan & Santai", + "desc": "Biarkan setiap perjalanan menjadi perjalanan inspiratif, setiap kamar menjadi ruang yang damai" + }, + "smartChecklist": { + "title": "Daftar Periksa Pintar", + "desc": "Biarkan setiap perjalanan menjadi perjalanan inspiratif, setiap kamar menjadi ruang yang damai" + }, + "saveMore": { + "title": "Hemat Lebih Banyak", + "desc": "Biarkan setiap perjalanan menjadi perjalanan inspiratif, setiap kamar menjadi ruang yang damai" + }, + "item1": { + "imageAlt": "Ilustrasi fitur Pesan & Santai", + "imageAltDark": "Ilustrasi fitur Pesan & Santai dalam mode gelap" + }, + "item2": { + "imageAlt": "Ilustrasi fitur Daftar Periksa Pintar", + "imageAltDark": "Ilustrasi fitur Daftar Periksa Pintar dalam mode gelap" + }, + "item3": { + "imageAlt": "Ilustrasi fitur Hemat Lebih Banyak", + "imageAltDark": "Ilustrasi fitur Hemat Lebih Banyak dalam mode gelap" + } + }, + "imageAltMapBackground": "Latar belakang peta", + "imageAltAppRightImg": "Gambar kanan aplikasi", + "buttonDownloadOnAppStore": "Unduh di App Store", + "buttonGetItOnGooglePlay": "Dapatkan di Google Play", + "tourSuggestion": { + "heading": "Negara", + "subHeading": "Tempat populer yang kami rekomendasikan untuk Anda", + "vectorAlt": "Gambar vektor dekoratif yang menggambarkan saran tur", + "categories": { + "Nature House": "Rumah Alam", + "Wooden house": "Rumah Kayu", + "Houseboat": "Rumah Perahu", + "Farm House": "Rumah Pertanian", + "Dome House": "Rumah Kubah", + "Wooden Dome": "Kubah Kayu" + } + }, + "tourSuggestion.heading": "Negara", + "tourSuggestion.subHeading": "Tempat populer yang kami rekomendasikan untuk Anda", + "cardCategory3.imageAltPlaces": "Tempat", + "cardCategory3.tours": "Tur", + "sectionClientSay": { + "heading": "Apa kata pelanggan kami tentang kami?", + "imageAltMain": "Gambar utama Ulasan Klien", + "imageAltClient1": "Klien 1", + "imageAltClient2": "Klien 2", + "imageAltClient3": "Klien 3", + "imageAltClient4": "Klien 4", + "imageAltClient5": "Klien 5", + "imageAltClient6": "Klien 6", + "imageAltQuotation1": "Tanda kutip kiri", + "imageAltQuotation2": "Tanda kutip kanan", + "testimonials": { + "0": { + "content": "Perjalanan dengan Aqila adalah pengalaman yang memperkaya secara spiritual. Pemandu yang berpengetahuan dan staf yang ramah membuat setiap momen tak terlupakan.", + "clientName": "Tiana Abie", + "clientAddress": "Malaysia" + }, + "1": { + "content": "Semua diatur dengan sempurna, dari akomodasi hingga kunjungan ke situs suci. Saya merasa sangat diperhatikan sepanjang perjalanan.", + "clientName": "Lennie Swiffan", + "clientAddress": "London" + }, + "2": { + "content": "Bergabung dengan tur ini memungkinkan saya untuk terhubung lebih dalam dengan sesama pelancong dan warisan saya. Sangat merekomendasikan Aqila untuk perjalanan yang bermakna!", + "clientName": "Berta Emili", + "clientAddress": "Tokyo" + } + } + }, + "sectionGridFilterCard": { + "allTours": "Semua Tur", + "noToursAvailable": "Tidak ada tur yang tersedia", + "toursInfo": "{{count}} malam · {{dateRange}} · {{guests}} Tamu" + }, + "accountHeading": "Informasi Akun", + "nameLabel": "Nama", + "emailLabel": "Email", + "phoneLabel": "Telepon", + "changeImage": "Ganti Gambar", + "updateButton": "Perbarui Info", + "signOutButton": "Keluar", + "deleteButton": "Hapus Akun", + "deleteSuccess": "Akun Anda telah berhasil dihapus.", + "signOutSuccess": "Anda telah berhasil keluar.", + "updateSuccess": "Informasi Anda telah berhasil diperbarui.", + "noChanges": "Tidak ada perubahan yang terdeteksi.", + "errorGeneric": "Terjadi kesalahan. Silakan coba lagi.", + "errorUnknown": "Terjadi kesalahan yang tidak diketahui.", + "benefits": "MANFAAT" +} diff --git a/public/locales/id/footer.json b/public/locales/id/footer.json new file mode 100644 index 0000000..3b7a244 --- /dev/null +++ b/public/locales/id/footer.json @@ -0,0 +1,23 @@ +{ + "widgetMenus": { + "Quick Links": { + "title": "Tautan Cepat", + "menus": [ + { "label": "Semua Tur" }, + { "label": "Blog" }, + { "label": "FAQ" }, + { "label": "Tentang Kami" } + ] + } + }, + "aboutUs": { + "title": "Tentang Kami", + "description": "Kami adalah tim yang berdedikasi untuk menciptakan pengalaman perjalanan yang tak terlupakan bagi para penjelajah dan pemimpi. Dari pelarian tenang ke pantai tropis hingga petualangan penuh adrenalin di tempat-tempat eksotis, kami merancang perjalanan yang unik seperti Anda. Bergabunglah dengan kami dan mari jelajahi dunia, satu petualangan pada satu waktu!" + }, + "footerNav": { + "description": "Kami adalah tim yang berdedikasi untuk menciptakan pengalaman perjalanan yang tak terlupakan bagi para penjelajah dan pemimpi." + }, + "socials": { + "title": "Ikuti Kami" + } +} diff --git a/public/locales/id/form.json b/public/locales/id/form.json new file mode 100644 index 0000000..78bef01 --- /dev/null +++ b/public/locales/id/form.json @@ -0,0 +1,91 @@ +{ + "selectTour": "Pilih tur Anda", + "tourPeriod": "Periode tur", + "startEndDate": "Mulai - Selesai", + "guests": "Tamu", + "addGuests": "Tambahkan tamu", + "adults": "Dewasa", + "adultsDesc": "Usia 13 tahun atau lebih", + "children": "Anak-anak", + "childrenDesc": "Usia 2–12 tahun", + "infants": "Bayi", + "infantsDesc": "Usia 0–2 tahun", + "clear": "Hapus", + "submit": "Kirim", + "login": "Masuk", + "phoneNumber": "Nomor Telepon", + "enterPhoneNumber": "Masukkan nomor telepon Anda", + "password": "Kata sandi", + "forgotPassword": "Lupa kata sandi?", + "enterPassword": "Masukkan kata sandi Anda", + "continue": "Lanjutkan", + "createAccount": "Buat akun", + "invalidPhoneNumber": "Nomor telepon tidak valid.", + "invalidPhoneNumberFormat": "Format nomor telepon tidak valid.", + "passwordRequired": "Kata sandi diperlukan.", + "loginSuccessful": "Masuk berhasil!", + "loginFailed": "Masuk gagal, periksa kredensial Anda.", + "unknownError": "Terjadi kesalahan yang tidak diketahui.", + "hidePassword": "Sembunyikan kata sandi", + "showPassword": "Tampilkan kata sandi", + "signup": "Daftar", + "changePassword": "Ubah kata sandi", + "fullName": "Nama lengkap", + "enterFullName": "Masukkan nama lengkap Anda", + "confirmPassword": "Konfirmasi kata sandi", + "enterConfirmPassword": "Masukkan kata sandi Anda kembali", + "alreadyHaveAccount": "Sudah punya akun?", + "signIn": "Masuk", + "errorOccurred": "Terjadi kesalahan.", + "hideConfirmPassword": "Sembunyikan konfirmasi kata sandi", + "showConfirmPassword": "Tampilkan konfirmasi kata sandi", + "verificationMethod": "Metode verifikasi", + "sendViaWhatsApp": "Kirim lewat WhatsApp", + "sendViaSMS": "Kirim lewat SMS", + "verificationCode": "Kode verifikasi", + "enterOtpDescription": "Masukkan kode 5 digit yang kami kirim untuk menyelesaikan pendaftaran akun Anda", + "haventGotCode": "Belum menerima kode konfirmasi?", + "resend": "Kirim ulang", + "seconds": "Detik", + "confirm": "Konfirmasi", + "signInSuccessful": "Masuk Anda berhasil", + "somethingWentWrong": "Ada yang salah. Silakan coba lagi.", + "otpInput": "Masukkan OTP {{index}}", + "otpNotComplete": "Kode verifikasi tidak valid", + "addNewPassenger": "Tambah penumpang baru", + "passengerInfo": "Informasi penumpang", + "passportNo": "Nomor Paspor", + "fullNameRequired": "Nama lengkap diperlukan.", + "passportRequired": "Nomor paspor diperlukan.", + "passportNumeric": "Nomor paspor harus berupa angka.", + "dobRequired": "Tanggal lahir diperlukan.", + "phoneRequired": "Nomor telepon diperlukan.", + "phoneNumeric": "Nomor telepon harus berupa angka.", + "passportImageRequired": "Gambar paspor diperlukan.", + "editPassengerInfo": "Ubah Informasi Penumpang", + "backToBills": "Kembali ke Tagihan", + "noBillsAvailable": "Tidak ada tagihan yang tersedia", + "awaitingPayment": "Menunggu Pembayaran", + "approved": "Disetujui", + "rejected": "Ditolak", + "pending": "Tertunda", + "issuedDate": "Tanggal Dikeluarkan", + "expirationDate": "Tanggal Kadaluarsa", + "tourInvoiceAmount": "Jumlah Faktur Tur", + "viewBill": "Lihat Tagihan", + "transactionReceiptUpdated": "Tanda terima transaksi berhasil diperbarui", + "updateFailed": "Gagal memperbarui tanda terima", + "billDetails": "Detail Tagihan", + "whyRejected": "Mengapa ditolak?", + "numberOfPassengers": "Jumlah Penumpang", + "adult": "Dewasa", + "infant": "Bayi", + "tourPrice": "Harga Tur", + "accountNumber": "Nomor Akun", + "uploadPassportImage": "Unggah Gambar Paspor", + "noFileSelected": "Tidak ada file yang dipilih", + "uploadedImage": "Gambar yang diunggah", + "delete": "Hapus", + "currentReceipt": "Tanda Terima Saat Ini", + "copy": "Salin" +} diff --git a/public/locales/id/navigation.json b/public/locales/id/navigation.json new file mode 100644 index 0000000..e6d0d1a --- /dev/null +++ b/public/locales/id/navigation.json @@ -0,0 +1,15 @@ +{ + "textHome": "Beranda", + "textAllTours": "Semua Tur", + "textBlog": "Blog", + "textFaq": "FAQ", + "textAbout": "Tentang", + "textLanguage": "Bahasa", + "textNoMatch": "Tidak Ditemukan Hasil", + "searchPlaceholder": "Ketik dan cari...", + "customTrip": "Tur Kustom", + "navAccount": "Akun", + "navMyTrips": "Perjalanan Saya", + "navPassengersList": "Daftar Penumpang", + "navBills": "Tagihan" +} diff --git a/public/locales/ru/FAQ.json b/public/locales/ru/FAQ.json new file mode 100644 index 0000000..c58288f --- /dev/null +++ b/public/locales/ru/FAQ.json @@ -0,0 +1,24 @@ +{ + "faqTitle": "Часто задаваемые вопросы", + "faqSubtitle": "Есть вопросы? Мы здесь, чтобы помочь!", + "faqQuestion1": "Как я могу забронировать тур на вашем сайте?", + "faqAnswer1": "Чтобы забронировать тур, просто выберите желаемое направление из 'Списка туров', выберите даты и следуйте шагам, чтобы завершить процесс бронирования.", + "faqQuestion2": "Могу ли я настроить свой тур?", + "faqAnswer2": "Да, наша функция 'Настроить тур' позволяет вам адаптировать путешествие в соответствии с вашими предпочтениями. Нажмите на 'Настроить тур' в верхней части страницы, чтобы начать персонализировать ваш опыт.", + "faqQuestion3": "Какие способы оплаты вы принимаете?", + "faqAnswer3": "Мы принимаем все основные кредитные карты, PayPal и банковские переводы. Вы можете выбрать предпочтительный способ оплаты во время оформления заказа.", + "faqQuestion4": "Как я могу узнать, что моя бронь подтверждена?", + "faqAnswer4": "После завершения процесса оплаты вы получите подтверждающее письмо с деталями бронирования. Вы также можете просматривать детали бронирования в своей панели управления аккаунтом.", + "faqQuestion5": "Могу ли я отменить или изменить свою бронь?", + "faqAnswer5": "Да, вы можете отменить или изменить свою бронь через ваш аккаунт. Обратите внимание, что отмена должна быть сделана не позднее чем за 24 часа до начала тура, чтобы иметь право на возврат средств.", + "faqQuestion6": "Есть ли скрытые сборы?", + "faqAnswer6": "Нет, все сборы прозрачны и показываются заранее перед завершением бронирования. Мы гарантируем, что скрытых сборов нет.", + "faqQuestion7": "Предлагаете ли вы скидки для групп?", + "faqAnswer7": "Да, мы предлагаем скидки для групповых бронирований. Пожалуйста, свяжитесь с нашей службой поддержки для получения дополнительной информации о групповых тарифах.", + "faqQuestion8": "Включает ли страховка путешествия в бронирование?", + "faqAnswer8": "Да, все наши турпакеты включают базовую страховку путешествий. Вы можете выбрать улучшенную страховку во время оформления заказа.", + "faqQuestion9": "Что происходит, если тур отменен поставщиком?", + "faqAnswer9": "Если тур отменяется поставщиком по независящим от нас причинам, вы получите полный возврат средств или возможность переноса тура на другую дату.", + "faqQuestion10": "Как я могу связаться со службой поддержки клиентов?", + "faqAnswer10": "Вы можете связаться со службой поддержки клиентов, нажав на кнопку 'Связаться с нами' внизу страницы или посетив наш раздел поддержки." +} diff --git a/public/locales/ru/common.json b/public/locales/ru/common.json new file mode 100644 index 0000000..932c1a9 --- /dev/null +++ b/public/locales/ru/common.json @@ -0,0 +1,222 @@ +{ + "home": "Главная", + "allTours": "Все туры", + "blogs": "Блоги", + "faq": "Часто задаваемые вопросы", + "aboutUs": "О нас", + "customTour": "Индивидуальный тур", + "searchPlaceholder": "Куда?", + "searchDescription": "Любое место • Любая неделя • Добавить гостей", + "beginAdventure": "Начните ваше", + "beginAdventure1": "духовное", + "beginAdventure2": "приключение", + "planPilgrimage": "Планируйте своё паломничество с легкостью. Найдите лучшие варианты проживания, транспорт и экскурсии по шиитским святыням по всему миру.", + "startJourney": "Начните своё путешествие", + "listOfTours": "Список туров", + "exploreTours": "Исследуйте туры и места проживания, адаптированные для духовного и незабываемого путешествия", + "tourPeriod": "Период тура", + "tourPeriodDescription": "Начало - Конец", + "guests": "Гости", + "addGuests": "Добавить гостей", + "available": "Доступно", + "soldOut": "Распродано", + "showMore": "Показать больше", + "happeningCities": "Города, где проходят события", + "costEffectiveAdvertising": "Рентабельная реклама", + "costEffectiveDescription": "С бесплатным размещением вы можете рекламировать свою аренду без предоплаты", + "reachMillions": "Достигайте миллионов с Chisfis", + "reachMillionsDescription": "Миллионы людей ищут уникальные места для проживания по всему миру", + "secureAndSimple": "Безопасно и просто", + "secureDescription": "Размещение на Holiday Lettings предоставляет вам безопасный и простой способ принимать бронирования и платежи онлайн", + "mobileApps": "Мобильные приложения", + "mobileAppsDescription": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed dapibus porttitor nisl, sit amet finibus libero.", + "installation": "Установка", + "releaseNotes": "Примечания к версии", + "upgradeGuide": "Руководство по обновлению", + "browserSupport": "Поддержка браузеров", + "editorSupport": "Поддержка редактора", + "designFeatures": "Особенности дизайна", + "prototyping": "Прототипирование", + "designSystems": "Системы дизайна", + "pricing": "Ценообразование", + "security": "Безопасность", + "bestPractices": "Лучшие практики", + "support": "Поддержка", + "developers": "Разработчики", + "learnDesign": "Изучение дизайна", + "releases": "Выпуски", + "discussionForums": "Форумы для обсуждений", + "codeOfConduct": "Кодекс поведения", + "communityResources": "Ресурсы сообщества", + "contributing": "Вклад", + "concurrentMode": "Режим параллельной работы", + "goodNews": "Хорошие новости издалека", + "whatPeopleThink": "Посмотрим, что люди думают о Chisfis", + "testimonial": "Это место точно такое же, как на фотографии, опубликованной на Chisfis. Отличное обслуживание, мы отлично провели время!", + "clientName": "Тиана Аби", + "clientLocation": "Малайзия", + "myTrips": "Мои поездки", + "account": "Аккаунт", + "menu": "Меню", + "gettingStarted": "Начало работы", + "explore": "Изучить", + "resources": "Ресурсы", + "community": "Сообщество", + "placeType": "Тип места", + "noTours": "Нет доступных туров", + "itinerary": "Маршрут", + "itineraryTitle": "Маршрут", + "total": "Итого", + "reserve": "Забронировать", + "tourFeatures": "Особенности тура", + "tourFeaturesTitle": "Особенности тура", + "startRating": "Оценка начала", + "listingDetails": "Детали", + "imageAlt": "Изображение тура", + "loading": "Загрузка...", + "adults": "Взрослые", + "adultsDesc": "Возраст 13 лет и старше", + "children": "Дети", + "childrenDesc": "Возраст 2–12 лет", + "infants": "Младенцы", + "infantsDesc": "Возраст 0–2 года", + "traveler": "Путешественник", + "responses": "Ответы ({{count}})", + "submit": "Отправить", + "cancel": "Отменить", + "relatedPosts": "Похожие записи", + "aboutUsHeading": "👋 О нас", + "aboutUsSubheading": "Мы страстная команда, стремящаяся создавать незабываемые путешествия для исследователей и мечтателей. От спокойных побегов на тропических пляжах до захватывающих приключений в экзотических местах — мы составляем путешествия, которые так же уникальны, как и вы. Присоединяйтесь к нам и давайте исследовать мир, одно приключение за раз!", + "statisticTitle": "🚀 Быстрые факты", + "statisticDescription": "Мы беспристрастны и независимы, и каждый день создаем уникальные, мировые программы и контент.", + "statisticHeading1": "10 миллионов", + "statisticSubHeading1": "Статьи были опубликованы по всему миру (на 30 сентября 2021 года)", + "statisticHeading2": "100,000", + "statisticSubHeading2": "Зарегистрированных пользователей (на 30 сентября 2021 года)", + "statisticHeading3": "220+", + "statisticSubHeading3": "Страны и регионы, где мы представлены (на 30 сентября 2021 года)", + "customTrip": "Индивидуальный тур", + "guide": "Гид", + "guideDescription": "Сначала напишите место вашего отправления, затем выберите первую точку назначения вашей поездки, количество ночей проживания и средство передвижения, затем выберите ваши дальнейшие точки назначения, если хотите.", + "beginYourTrip": "Начните ваше путешествие", + "startDate": "Дата начала", + "numberOfPassengers": "Количество пассажиров", + "destination": "Пункт назначения", + "selectCity": "Выберите город", + "transportation": "Транспорт", + "selectTransport": "Выберите транспорт", + "hotel": "Отель", + "selectHotel": "Выберите отель", + "duration": "Продолжительность", + "finishDate": "Дата окончания", + "addDestination": "Добавить пункт назначения", + "continue": "Продолжить", + "successMessage": "Успешно зарегистрировано", + "to": "к", + "login": "Войти", + "signup": "Зарегистрироваться", + "All": "Все", + "create": "Создать", + "createPersonalizedTourLine1": "Создайте свой персонализированный тур и разработайте", + "createPersonalizedTourLine2": "идеальный опыт путешествия, соответствующий вашим предпочтениям.", + "imageAltCustomTourBackground": "Фон индивидуального тура", + "howItWorks": { + "title": "Как это работает", + "desc": "Оставайтесь спокойными и продолжайте путешествовать", + "vectorAlt": "Декоративная векторная картинка, иллюстрирующая, как это работает", + "bookAndRelax": { + "title": "Забронируйте и расслабьтесь", + "desc": "Позвольте каждому путешествию быть вдохновляющим, каждой комнате — мирным пространством" + }, + "smartChecklist": { + "title": "Умный список", + "desc": "Позвольте каждому путешествию быть вдохновляющим, каждой комнате — мирным пространством" + }, + "saveMore": { + "title": "Сэкономьте больше", + "desc": "Позвольте каждому путешествию быть вдохновляющим, каждой комнате — мирным пространством" + }, + "item1": { + "imageAlt": "Иллюстрация функции Забронируйте и расслабьтесь", + "imageAltDark": "Иллюстрация функции Забронируйте и расслабьтесь в темном режиме" + }, + "item2": { + "imageAlt": "Иллюстрация функции Умный список", + "imageAltDark": "Иллюстрация функции Умный список в темном режиме" + }, + "item3": { + "imageAlt": "Иллюстрация функции Сэкономьте больше", + "imageAltDark": "Иллюстрация функции Сэкономьте больше в темном режиме" + } + }, + "imageAltMapBackground": "Фон карты", + "imageAltAppRightImg": "Правая картинка приложения", + "buttonDownloadOnAppStore": "Скачать в App Store", + "buttonGetItOnGooglePlay": "Получить в Google Play", + "tourSuggestion": { + "heading": "Страны", + "subHeading": "Популярные места, которые мы рекомендуем для вас", + "vectorAlt": "Декоративная векторная картинка, иллюстрирующая предложения по турам", + "categories": { + "Nature House": "Дом в природе", + "Wooden house": "Деревянный дом", + "Houseboat": "Дом на воде", + "Farm House": "Фермерский дом", + "Dome House": "Купольный дом", + "Wooden Dome": "Деревянный купол" + } + }, + "tourSuggestion.heading": "Страны", + "tourSuggestion.subHeading": "Популярные места, которые мы рекомендуем для вас", + "cardCategory3.imageAltPlaces": "Места", + "cardCategory3.tours": "Туры", + "sectionClientSay": { + "heading": "Что говорят наши клиенты о нас?", + "imageAltMain": "Основное изображение отзывов клиентов", + "imageAltClient1": "Клиент 1", + "imageAltClient2": "Клиент 2", + "imageAltClient3": "Клиент 3", + "imageAltClient4": "Клиент 4", + "imageAltClient5": "Клиент 5", + "imageAltClient6": "Клиент 6", + "imageAltQuotation1": "Левая кавычка", + "imageAltQuotation2": "Правая кавычка", + "testimonials": { + "0": { + "content": "Путешествие с Aqila было духовно обогащающе. Знание гидов и дружелюбный персонал сделали каждое мгновение незабываемым.", + "clientName": "Тиана Аби", + "clientAddress": "Малайзия" + }, + "1": { + "content": "Все было идеально организовано, от проживания до посещений святых мест. Я чувствовал заботу на протяжении всей поездки.", + "clientName": "Ленни Суффан", + "clientAddress": "Лондон" + }, + "2": { + "content": "Присоединившись к этому туру, я смог глубже понять себя и моё наследие. Рекомендую Aqila для значимого путешествия!", + "clientName": "Берта Эмили", + "clientAddress": "Токио" + } + } + }, + "sectionGridFilterCard": { + "allTours": "Все туры", + "noToursAvailable": "Нет доступных туров", + "toursInfo": "{{count}} ночей · {{dateRange}} · {{guests}} Гостей" + }, + "accountHeading": "Информация об аккаунте", + "nameLabel": "Имя", + "emailLabel": "Электронная почта", + "phoneLabel": "Телефон", + "changeImage": "Изменить изображение", + "updateButton": "Обновить информацию", + "signOutButton": "Выйти", + "deleteButton": "Удалить аккаунт", + "deleteSuccess": "Ваш аккаунт был успешно удален.", + "signOutSuccess": "Вы успешно вышли из аккаунта.", + "updateSuccess": "Ваша информация была успешно обновлена.", + "noChanges": "Изменения не обнаружены.", + "errorGeneric": "Произошла ошибка. Пожалуйста, попробуйте снова.", + "errorUnknown": "Произошла неизвестная ошибка.", + "benefits": "ПРЕИМУЩЕСТВА" +} diff --git a/public/locales/ru/footer.json b/public/locales/ru/footer.json new file mode 100644 index 0000000..6d70e03 --- /dev/null +++ b/public/locales/ru/footer.json @@ -0,0 +1,23 @@ +{ + "widgetMenus": { + "Quick Links": { + "title": "Быстрые ссылки", + "menus": [ + { "label": "Все туры" }, + { "label": "Блоги" }, + { "label": "FAQ" }, + { "label": "О нас" } + ] + } + }, + "aboutUs": { + "title": "О нас", + "description": "Мы — команда, увлеченная созданием незабываемых путешествий для исследователей и мечтателей. От спокойного отдыха на тропических пляжах до приключений, полных адреналина, в экзотических местах — мы разрабатываем уникальные путешествия, такие же уникальные, как и вы. Присоединяйтесь к нам, и давайте открывать мир, одно приключение за раз!" + }, + "footerNav": { + "description": "Мы — команда, увлеченная созданием незабываемых путешествий для исследователей и мечтателей." + }, + "socials": { + "title": "Следите за нами" + } +} diff --git a/public/locales/ru/form.json b/public/locales/ru/form.json new file mode 100644 index 0000000..f5a222b --- /dev/null +++ b/public/locales/ru/form.json @@ -0,0 +1,91 @@ +{ + "selectTour": "Выберите ваш тур", + "tourPeriod": "Период тура", + "startEndDate": "Начало - Конец", + "guests": "Гости", + "addGuests": "Добавить гостей", + "adults": "Взрослые", + "adultsDesc": "Возраст 13 лет и старше", + "children": "Дети", + "childrenDesc": "Возраст 2–12 лет", + "infants": "Младенцы", + "infantsDesc": "Возраст 0–2 года", + "clear": "Очистить", + "submit": "Отправить", + "login": "Войти", + "phoneNumber": "Номер телефона", + "enterPhoneNumber": "Введите ваш номер телефона", + "password": "Пароль", + "forgotPassword": "Забыли пароль?", + "enterPassword": "Введите ваш пароль", + "continue": "Продолжить", + "createAccount": "Создать аккаунт", + "invalidPhoneNumber": "Неверный номер телефона.", + "invalidPhoneNumberFormat": "Неверный формат номера телефона.", + "passwordRequired": "Пароль обязателен.", + "loginSuccessful": "Вход выполнен успешно!", + "loginFailed": "Не удалось войти, проверьте свои данные.", + "unknownError": "Произошла неизвестная ошибка.", + "hidePassword": "Скрыть пароль", + "showPassword": "Показать пароль", + "signup": "Зарегистрироваться", + "changePassword": "Изменить пароль", + "fullName": "Полное имя", + "enterFullName": "Введите ваше полное имя", + "confirmPassword": "Подтвердите пароль", + "enterConfirmPassword": "Введите пароль повторно", + "alreadyHaveAccount": "Уже есть аккаунт?", + "signIn": "Войти", + "errorOccurred": "Произошла ошибка.", + "hideConfirmPassword": "Скрыть подтверждение пароля", + "showConfirmPassword": "Показать подтверждение пароля", + "verificationMethod": "Метод подтверждения", + "sendViaWhatsApp": "Отправить через WhatsApp", + "sendViaSMS": "Отправить через SMS", + "verificationCode": "Код подтверждения", + "enterOtpDescription": "Введите 5-значный код, который мы отправили для завершения регистрации", + "haventGotCode": "Еще не получили код подтверждения?", + "resend": "Отправить снова", + "seconds": "Секунды", + "confirm": "Подтвердить", + "signInSuccessful": "Вы успешно вошли в систему", + "somethingWentWrong": "Что-то пошло не так. Пожалуйста, попробуйте снова.", + "otpInput": "Ввод OTP {{index}}", + "otpNotComplete": "Код подтверждения недействителен", + "addNewPassenger": "Добавить нового пассажира", + "passengerInfo": "Информация о пассажире", + "passportNo": "Номер паспорта", + "fullNameRequired": "Полное имя обязательно.", + "passportRequired": "Номер паспорта обязателен.", + "passportNumeric": "Номер паспорта должен быть числовым.", + "dobRequired": "Дата рождения обязательна.", + "phoneRequired": "Номер телефона обязателен.", + "phoneNumeric": "Номер телефона должен быть числовым.", + "passportImageRequired": "Изображение паспорта обязательно.", + "editPassengerInfo": "Редактировать информацию о пассажире", + "backToBills": "Вернуться к счетам", + "noBillsAvailable": "Нет доступных счетов", + "awaitingPayment": "Ожидание оплаты", + "approved": "Одобрено", + "rejected": "Отклонено", + "pending": "В ожидании", + "issuedDate": "Дата выдачи", + "expirationDate": "Дата истечения", + "tourInvoiceAmount": "Сумма счета за тур", + "viewBill": "Просмотреть счет", + "transactionReceiptUpdated": "Квитанция о транзакции успешно обновлена", + "updateFailed": "Не удалось обновить квитанцию", + "billDetails": "Детали счета", + "whyRejected": "Почему отклонено?", + "numberOfPassengers": "Количество пассажиров", + "adult": "Взрослый", + "infant": "Младенец", + "tourPrice": "Стоимость тура", + "accountNumber": "Номер счета", + "uploadPassportImage": "Загрузить изображение паспорта", + "noFileSelected": "Файл не выбран", + "uploadedImage": "Загруженное изображение", + "delete": "Удалить", + "currentReceipt": "Текущая квитанция", + "copy": "Копировать" +} diff --git a/public/locales/ru/navigation.json b/public/locales/ru/navigation.json new file mode 100644 index 0000000..ee0e828 --- /dev/null +++ b/public/locales/ru/navigation.json @@ -0,0 +1,15 @@ +{ + "text-home": "Главная", + "text-all-tours": "Все туры", + "text-blog": "Блог", + "text-faq": "Часто задаваемые вопросы", + "text-about": "О нас", + "text-language": "Язык", + "text-no-match": "Результатов не найдено", + "search-placeholder": "Введите для поиска...", + "customTrip": "Индивидуальный тур", + "navAccount": "Аккаунт", + "navMyTrips": "Мои поездки", + "navPassengersList": "Список пассажиров", + "navBills": "Счета" +} diff --git a/src/app/[locale]/(account-pages)/(components)/Nav.tsx b/src/app/[locale]/(account-pages)/(components)/Nav.tsx index d84f75b..197263c 100644 --- a/src/app/[locale]/(account-pages)/(components)/Nav.tsx +++ b/src/app/[locale]/(account-pages)/(components)/Nav.tsx @@ -4,33 +4,35 @@ import { Route } from "@/routers/types"; import Link from "next/link"; import { usePathname } from "next/navigation"; import React from "react"; +import { useTranslation } from "react-i18next"; export const Nav = () => { + const { t } = useTranslation("navigation"); const pathname = usePathname(); const listNav: Route[] = [ - "/account", - "/my-trips", - "/passengers-list", - "/bills", + { path: "/account", label: t("navAccount") }, + { path: "/my-trips", label: t("navMyTrips") }, + { path: "/passengers-list", label: t("navPassengersList") }, + { path: "/bills", label: t("navBills") }, ]; return (
-
- {listNav.map((item) => { - const isActive = pathname === item; +
+ {listNav.map(({ path, label }) => { + const isActive = pathname === path; return ( - {item.replace("-", " ").replace("/", " ")} + {label} ); })} diff --git a/src/app/[locale]/(account-pages)/account/page.tsx b/src/app/[locale]/(account-pages)/account/page.tsx index ab4e60e..9157fbf 100644 --- a/src/app/[locale]/(account-pages)/account/page.tsx +++ b/src/app/[locale]/(account-pages)/account/page.tsx @@ -1,6 +1,7 @@ "use client"; import React, { useState, ChangeEvent, FC, useEffect } from "react"; +import { useTranslation } from "react-i18next"; import Label from "@/components/Label"; import Avatar from "@/shared/Avatar"; import ButtonPrimary from "@/shared/ButtonPrimary"; @@ -14,55 +15,28 @@ import { toast } from "react-toastify"; export interface AccountPageProps {} -interface User { - fullname: string; - email: string; - phone_number: string; - avatar: string; - token: string; -} - -interface LoadingState { - delete?: boolean; - change?: boolean; -} - -interface APIResponse { - - avatar: string; - email: string; - fullname: string; - phone_number: string; - -} - const AccountPage: FC = () => { + const { t } = useTranslation("common"); const router = useRouter(); const { user, setUser, clerUser } = useUserContext(); - // Redirect to home if user object is empty useEffect(() => { if (!Object.keys(user).length) { router.replace("/"); } }, [user, router]); - // Return null to avoid rendering when redirecting - // if (!Object.keys(user).length) { - // return null; - // } - const [name, setName] = useState(user.fullname || ""); const [email, setEmail] = useState(user.email || ""); const [number, setNumber] = useState(user.phone_number || ""); const [image, setImage] = useState(null); const [imageURL, setImageURL] = useState(null); const [error, setError] = useState(""); - const [loading, setLoading] = useState({}); + const [loading, setLoading] = useState({ delete: false, change: false }); const deleteHandler = async (): Promise => { setError(""); - setLoading({ delete: true }); + setLoading({ ...loading, delete: true }); try { const response = await axiosInstance.delete(`/api/account/profile/delete/`, { headers: { @@ -71,47 +45,38 @@ const AccountPage: FC = () => { }); if (response.status === 204) { clerUser(); - toast.success("Your Delete account was successful") + toast.success(t("deleteSuccess")); } else { - setError("Something went wrong"); + setError(t("errorGeneric")); } } catch (error: unknown) { if (error instanceof Error) { toast.error(error.message); } else { - setError("An unknown error occurred"); + setError(t("errorUnknown")); } } finally { - setLoading({ delete: false }); + setLoading({ ...loading, delete: false }); } }; const signOutHandler = (): void => { clerUser(); - toast.success("Your sign out was successful") + toast.success(t("signOutSuccess")); }; const changeHandler = async (): Promise => { setError(""); - setLoading({ change: true }); - + setLoading({ ...loading, change: true }); + const formData = new FormData(); - - if (name !== user.fullname) { - formData.append("fullname", name); - } - - if (email !== user.email) { - formData.append("email", email); - } - - if (imageURL) { - formData.append("avatar", imageURL); - } - + if (name !== user.fullname) formData.append("fullname", name); + if (email !== user.email) formData.append("email", email); + if (imageURL) formData.append("avatar", imageURL); + if (formData.has("fullname") || formData.has("email") || formData.has("avatar")) { try { - const response = await axiosInstance.put( + const response = await axiosInstance.put( `/api/account/profile/update/`, formData, { @@ -122,37 +87,33 @@ const AccountPage: FC = () => { } ); if (response.status === 200) { - console.log(response); - - toast.success("Updated successfully"); + toast.success(t("updateSuccess")); setUser({ ...user, - avatar: response.data.avatar, - email: response.data.email, fullname: response.data.fullname, - phone_number: response.data.phone_number, + email: response.data.email, + avatar: response.data.avatar, }); } else { - setError("Something went wrong"); + setError(t("errorGeneric")); } } catch (error: unknown) { if (error instanceof Error) { setError(error.message); } else { - setError("An unknown error occurred"); + setError(t("errorUnknown")); } } finally { - setLoading({ change: false }); + setLoading({ ...loading, change: false }); } } else { - toast.info("No changes detected"); - setLoading({ change: false }); + toast.info(t("noChanges")); + setLoading({ ...loading, change: false }); } }; - const handleFileChange = async (e: ChangeEvent): Promise => { - const file : File | undefined = e.target.files?.[0]; + const file = e.target.files?.[0]; if (file) { const uploadedFile = await getImageURL(file); setImageURL(uploadedFile.url); @@ -162,7 +123,7 @@ const AccountPage: FC = () => { return (
-

Account information

+

{t("accountHeading")}

@@ -172,22 +133,7 @@ const AccountPage: FC = () => { sizeClass="w-32 h-32" />
- - - - Change Image + {t("changeImage")}
= () => { />
-
+
- + setName(e.target.value)} @@ -207,7 +153,7 @@ const AccountPage: FC = () => { />
- + setEmail(e.target.value)} @@ -215,7 +161,7 @@ const AccountPage: FC = () => { />
- + setNumber(e.target.value)} @@ -225,17 +171,17 @@ const AccountPage: FC = () => {
- Update info + {t("updateButton")} - Sign out + {t("signOutButton")} - Delete account + {t("deleteButton")}
diff --git a/src/app/[locale]/(account-pages)/bills/BillCard.tsx b/src/app/[locale]/(account-pages)/bills/BillCard.tsx index 44fbe2f..9c43758 100644 --- a/src/app/[locale]/(account-pages)/bills/BillCard.tsx +++ b/src/app/[locale]/(account-pages)/bills/BillCard.tsx @@ -1,17 +1,16 @@ -// BillCard.tsx +"use client"; + import React from "react"; import ButtonPrimary from "@/shared/ButtonPrimary"; -export type BillStatus = - | "awaiting_payment" - | "approved" - | "rejected" - | "pending"; import { BiSolidPlaneAlt } from "react-icons/bi"; import { FaSimCard } from "react-icons/fa"; import { BsCart3 } from "react-icons/bs"; import { MdCurrencyExchange } from "react-icons/md"; +import { useTranslation } from "react-i18next"; + +export type BillStatus = "awaiting_payment" | "approved" | "rejected" | "pending"; + export interface Bill { - service: string; id: number; title: string; created_at: string; @@ -31,63 +30,48 @@ export interface Bill { }; transaction_receipt: string; card_number: string | number; + service: string; } interface BillCardProps { bill: Bill; - onViewDetail: (bill: Bill) => void; // Add onViewDetail prop + onViewDetail: (bill: Bill) => void; } -const statusStyles: { [key in BillStatus]: JSX.Element } = { - awaiting_payment: ( - - Awaiting Payment - - ), - approved: ( - - Approved - - ), - rejected: ( - - Rejected - - ), - pending: ( - - Pending - - ), -}; +const BillCard: React.FC = ({ bill, onViewDetail }) => { + const { t } = useTranslation("form"); + const statusStyles: { [key in BillStatus]: JSX.Element } = { + awaiting_payment: ( + + {t("awaitingPayment")} + + ), + approved: ( + + {t("approved")} + + ), + rejected: ( + + {t("rejected")} + + ), + pending: ( + + {t("pending")} + + ), + }; -const BillCard: React.FC = ({ bill, onViewDetail }) => { - console.log(bill); return (

- {bill.service.includes("Tour") && ( - - - - )} - {bill.service.includes("SIM Card") && ( - - - - )} - {bill.service.includes("Shop") && ( - - - - )} - {bill.service.includes("Tasrif") && ( - - - - )} + {bill.service.includes("tour") && } + {bill.service.includes("SIM Card") && } + {bill.service.includes("shop") && } + {bill.service.includes("tasrif") && } {bill.service}

{statusStyles[bill.status]} @@ -95,21 +79,21 @@ const BillCard: React.FC = ({ bill, onViewDetail }) => {
- Issued Date: + {t("issuedDate")}: {bill.created_at}
- Expiration Date: + {t("expirationDate")}: {bill.expiration_date}
- Tour Invoice Amount: + {t("tourInvoiceAmount")}: ${bill.amount}
onViewDetail(bill)} className="mt-4"> - View Bill + {t("viewBill")}
); diff --git a/src/app/[locale]/(account-pages)/bills/[slug]/page.tsx b/src/app/[locale]/(account-pages)/bills/[slug]/page.tsx index 1a82bf2..c343c66 100644 --- a/src/app/[locale]/(account-pages)/bills/[slug]/page.tsx +++ b/src/app/[locale]/(account-pages)/bills/[slug]/page.tsx @@ -1,4 +1,4 @@ -"use client" +"use client"; import React, { useState } from "react"; import axiosInstance from "@/components/api/axios"; @@ -9,6 +9,7 @@ import { useUserContext } from "@/components/contexts/userContext"; import getImageURL from "@/components/api/getImageURL"; import { toast, ToastContainer } from "react-toastify"; import Image from "next/image"; +import { useTranslation } from "react-i18next"; export type BillStatus = | "awaiting_payment" @@ -16,50 +17,50 @@ export type BillStatus = | "rejected" | "pending"; - export interface Bill { - id: number; - title: string; - created_at: string; - expiration_date: string; - amount: number; - status: BillStatus; - passengers: { type: string; count: number }[]; - accountNumber: string; - message?: string; - uploadedImage?: { - name: string; - size: string; - src: string; - }; - detail_service: { - passenger_counts: { adults: string; children: string; infants: string }; - }; - transaction_receipt: string; - card_number: string | number; - } - - interface BillDetailCardProps { - bill: Bill; - } +export interface Bill { + id: number; + title: string; + created_at: string; + expiration_date: string; + amount: number; + status: BillStatus; + passengers: { type: string; count: number }[]; + accountNumber: string; + message?: string; + uploadedImage?: { + name: string; + size: string; + src: string; + }; + detail_service: { + passenger_counts: { adults: string; children: string; infants: string }; + }; + transaction_receipt: string; + card_number: string | number; +} + +interface BillDetailCardProps { + bill: Bill; +} const statusStyles: { [key in BillStatus]: JSX.Element } = { awaiting_payment: ( - Awaiting Payment + {"t('awaitingPayment')"} ), approved: ( - Approved + {"t('approved')"} ), rejected: ( - Rejected + {"t('rejected')"} ), pending: ( - Pending + {"t('pending')"} ), }; @@ -69,6 +70,7 @@ const BillDetailCard: React.FC = ({ bill }) => { const [loadingUpload, setLoadingUpload] = useState(false); const [loading, setLoading] = useState(false); const { user } = useUserContext(); + const { t } = useTranslation("form"); const handleFileChange = async (e: React.ChangeEvent) => { setLoadingUpload(true); const file = e.target.files?.[0]; @@ -82,24 +84,30 @@ const BillDetailCard: React.FC = ({ bill }) => { const handleSubmit = () => { setLoading(true); if (uploadedFile) { - const formData = new FormData(); - formData.append("transaction_receipt", uploadedFile); axiosInstance - .patch(`/api/factors/update/${bill.id}/`, formData, { - headers: { - Authorization: `token ${user.token}`, + .patch( + `/api/factors/update/${bill.id}/`, + { + transaction_receipt: uploadedFile, }, - }) + { + headers: { + Authorization: `token ${user.token}`, + }, + } + ) .then(() => { - toast.success("Transaction receipt updated successfully"); + toast.success(t("transactionReceiptUpdated")); setLoading(false); }) - .catch(() => { - toast.error("Error updating transaction receipt"); + .catch((error) => { + console.log(error); + + toast.error(t("updateFailed")); setLoading(false); }); } else { - console.log("No new file to upload"); + console.log(t("noFileSelected")); } }; @@ -112,58 +120,56 @@ const BillDetailCard: React.FC = ({ bill }) => { {bill.message && (
-

Why was it rejected?

+

{t("whyRejected")}

{bill.message}

)}
- Issued Date: + {t("issuedDate")}: {bill.created_at}
- Expiration Date: + {t("expirationDate")}: {bill.expiration_date}
-

Number of Passengers

+

{t("numberOfPassengers")}

- - # {bill.detail_service.passenger_counts.adults} (Adults) - + {bill.detail_service.passenger_counts.adults && ( + # {t("adult")}: {bill.detail_service.passenger_counts.adults} + )}
- - # {bill.detail_service.passenger_counts.children} (Children) - + {bill.detail_service.passenger_counts.children && ( + # {t("children")}: {bill.detail_service.passenger_counts.children} + )}
- - # {bill.detail_service.passenger_counts.infants} (Infants) - + {bill.detail_service.passenger_counts.infants && ( + # {t("infant")}: {bill.detail_service.passenger_counts.infants} + )}
- Tour Price: + {t("tourPrice")}: ${bill.amount}
-

Account Number

+

{t("accountNumber")}

- - {bill.card_number} - - + {bill.card_number} +
{bill.uploadedImage ? (
-

Uploaded Image

+

{t("uploadedImage")}

Uploaded = ({ bill }) => { />
{bill.uploadedImage.name} - - {bill.uploadedImage.size} - - + {bill.uploadedImage.size} +
) : (
= ({ bill }) => { type="file" onChange={handleFileChange} /> - {loadingUpload &&

Loading ...

} + {loadingUpload &&

{t("loading")}

} {bill.transaction_receipt ? ( - Current Receipt + {t("currentReceipt")} ) : ( - No File Selected + {t("noFileSelected")} )}
@@ -203,23 +212,27 @@ const BillDetailCard: React.FC = ({ bill }) => { )}
- - Submit + + {t("submit")} + position="top-right" + autoClose={5000} + hideProgressBar={false} + newestOnTop={false} + closeOnClick + rtl={false} + pauseOnFocusLoss + draggable + pauseOnHover + theme="light" + />
); }; -export default BillDetailCard; +export default BillDetailCard; \ No newline at end of file diff --git a/src/app/[locale]/(account-pages)/bills/page.tsx b/src/app/[locale]/(account-pages)/bills/page.tsx index 1453134..3d2571f 100644 --- a/src/app/[locale]/(account-pages)/bills/page.tsx +++ b/src/app/[locale]/(account-pages)/bills/page.tsx @@ -1,15 +1,15 @@ "use client"; + import React, { useEffect, useState } from "react"; import BillCard from "./BillCard"; import BillDetailCard from "./[slug]/page"; import axiosInstance from "@/components/api/axios"; import { useUserContext } from "@/components/contexts/userContext"; +import { useTranslation } from "react-i18next"; -// Define the BillStatus and Bill interfaces export type BillStatus = "awaiting_payment" | "approved" | "rejected" | "pending"; export interface Bill { - service: string; id: number; title: string; created_at: string; @@ -29,12 +29,14 @@ export interface Bill { }; transaction_receipt: string; card_number: string | number; + service: string; } const BillsPage: React.FC = () => { const [bills, setBills] = useState([]); const [selectedBill, setSelectedBill] = useState(null); const { user } = useUserContext(); + const { t } = useTranslation("form"); const handleViewDetail = (bill: Bill) => { setSelectedBill(bill); @@ -51,7 +53,6 @@ const BillsPage: React.FC = () => { }, }) .then((response) => { - // Transform API response to match the Bill interface const billsFromApi = response.data.results.map((bill: any) => ({ id: bill.id, title: bill.title, @@ -66,6 +67,7 @@ const BillsPage: React.FC = () => { detail_service: bill.detail_service, transaction_receipt: bill.transaction_receipt, card_number: bill.card_number, + service: bill.service, })); setBills(billsFromApi); }) @@ -79,14 +81,18 @@ const BillsPage: React.FC = () => { {selectedBill ? (
- ) : ( + ) : bills.length > 0 ? ( bills.map((bill, index) => ( )) + ) : ( +
+

{t("noBillsAvailable")}

+
)}
); diff --git a/src/app/[locale]/(account-pages)/my-trips/page.tsx b/src/app/[locale]/(account-pages)/my-trips/page.tsx index b57e41c..1eaf64c 100644 --- a/src/app/[locale]/(account-pages)/my-trips/page.tsx +++ b/src/app/[locale]/(account-pages)/my-trips/page.tsx @@ -1,37 +1,26 @@ "use client"; import { Tab } from "@headlessui/react"; -import CarCard from "@/components/CarCard"; -import ExperiencesCard from "@/components/ExperiencesCard"; -import StayCard from "@/components/StayCard"; -import { - DEMO_CAR_LISTINGS, - DEMO_EXPERIENCES_LISTINGS, - DEMO_STAY_LISTINGS, -} from "@/data/listings"; -import React, { Fragment, use, useEffect, useState } from "react"; -import ButtonSecondary from "@/shared/ButtonSecondary"; -import axiosInstance from "@/components/api/axios"; import StayCard2 from "@/components/StayCard2"; +import React, { useEffect, useState } from "react"; +import axiosInstance from "@/components/api/axios"; import { useRouter } from "next/navigation"; import { useUserContext } from "@/components/contexts/userContext"; +import { useTranslation } from "react-i18next"; import { StayDataType } from "@/data/types"; - -// interface stay { -// id : string -// } - const MyTrips = () => { - const router = useRouter() - let [tours , setTours] = useState([]); - const { user } =useUserContext() + const router = useRouter(); + const { t } = useTranslation("common"); + const [tours, setTours] = useState([]); + const { user } = useUserContext(); useEffect(() => { if (!Object.keys(user).length) { router.replace("/signup"); } }, [user, router]); + useEffect(() => { axiosInstance .get("/api/tours/orders/", { @@ -41,20 +30,17 @@ const MyTrips = () => { }) .then((response) => { setTours(response.data.results); - console.log(response); - }) .catch((error) => { console.error(error); }); - }, []); + }, [user.token]); - const renderSection1 = () => { return (
-

Save lists

+

{t("myTrips")}

@@ -63,11 +49,15 @@ const MyTrips = () => {
- {tours.length ? (tours?.filter((_, i) => i < 8).map((stay : StayDataType) => ( - - ))) : (

You have no trips

)} -
-
+ {tours.length ? ( + tours + .filter((_, i) => i < 8) + .map((stay: StayDataType) => ( + + )) + ) : ( +

{t("noTrips")}

+ )}
diff --git a/src/app/[locale]/(account-pages)/passengers-list/PassengerTable.tsx b/src/app/[locale]/(account-pages)/passengers-list/PassengerTable.tsx index 615d42f..0fd9e57 100644 --- a/src/app/[locale]/(account-pages)/passengers-list/PassengerTable.tsx +++ b/src/app/[locale]/(account-pages)/passengers-list/PassengerTable.tsx @@ -1,17 +1,19 @@ "use client"; + +import React, { FC, useState } from "react"; import axiosInstance from "@/components/api/axios"; import { useUserContext } from "@/components/contexts/userContext"; import { useRouter } from "next/navigation"; -import React, { FC, useState } from "react"; import { IoMdTrash } from "react-icons/io"; import { MdEdit } from "react-icons/md"; +import { useTranslation } from "react-i18next"; interface Passenger { birthdate: string; fullname: string; id: number; passport_image: string; - passport_number: string; + passport_number: string; phone_number: string; } @@ -23,6 +25,7 @@ const PassengerTable: FC = ({ data }) => { const { user } = useUserContext(); const router = useRouter(); const [show, setShow] = useState(true); + const { t } = useTranslation("form"); const deleteHandler = async () => { try { @@ -33,7 +36,7 @@ const PassengerTable: FC = ({ data }) => { }); setShow(false); } catch (error) { - console.log(error); + console.error(error); } }; @@ -43,22 +46,20 @@ const PassengerTable: FC = ({ data }) => { !show && "hidden" } sm:w-[500px] flex items-center justify-between p-4 bg-white rounded-xl shadow-sm border border-neutral-200 dark:bg-neutral-800`} > - {/* Passenger Information */}

- Passenger information + {t("passengerInfo")}

{data.fullname}

{data.passport_number && (

- Passport No: {data.passport_number} + {t("passportNo")}: {data.passport_number}

)}
- {/* Action Icons */}
{time > 0 && ( - ({time} Seconds) + + {`(${t("seconds")} ${time} )`} + )}

{error &&

{error}

} @@ -177,11 +221,13 @@ console.log(form); e.preventDefault(); submitHandler(); }} + disabled={loading} > - Confirm + {t("confirm")}
+
); }; diff --git a/src/app/[locale]/signup/page.tsx b/src/app/[locale]/signup/page.tsx index 6b42515..f8cfde1 100644 --- a/src/app/[locale]/signup/page.tsx +++ b/src/app/[locale]/signup/page.tsx @@ -11,10 +11,12 @@ import { useRouter } from "next/navigation"; import { ToastContainer, toast } from "react-toastify"; import "react-toastify/dist/ReactToastify.css"; import { BiShow, BiHide } from "react-icons/bi"; +import { useTranslation } from "react-i18next"; export interface PageSignUpProps {} const PageSignUp: FC = () => { + const { t } = useTranslation("form"); const router = useRouter(); const { user, setForm } = useUserContext(); const [name, setName] = useState(""); @@ -35,12 +37,14 @@ const PageSignUp: FC = () => { } }; + // Redirect to home if the user is already logged in useEffect(() => { if (Object.keys(user).length) { router.replace("/"); } }, [user, router]); + // Display validation errors as toast notifications useEffect(() => { Object.values(errors).forEach((error) => { toast.error(error, { @@ -58,12 +62,12 @@ const PageSignUp: FC = () => { const submitHandler = async () => { const form = { - name, - countryCode, - phoneNumber, - password, - confirmPassword, - verification_methodes: "", + fullname : name, + range_phone : countryCode, + phone_number : phoneNumber, + password : password, + password_confirmation : confirmPassword, + verification_method: "whatsapp", method: "register", }; @@ -71,14 +75,36 @@ const PageSignUp: FC = () => { setLoading(true); setForm(form); try { - const response = await axiosInstance.get( - `/api/account/verfication/?range_phone=${countryCode}&phone_number=${phoneNumber}` + const response = await axiosInstance.post( + `/api/account/register/` , { + fullname : name, + range_phone : countryCode, + phone_number : "+" + countryCode + phoneNumber, + password : password, + password_confirmation : confirmPassword, + verification_method: "whatsapp", + method: "register", + } ); - form.verification_methodes = response.data.verification_method; - router.replace("/signup/methodes"); + router.replace("/signup/otp-code"); } catch (error: any) { - console.error("Error fetching data:", error); - setFailed(error.message || "An error occurred."); + if (error.response?.data?.errors?.length) { + error.response?.data?.errors?.map((err)=>{ + if (err.field) { + toast.error( + `${err.field} : ${err.message}` + ); + + }else{ + toast.error( + err.message + ); + } + }) + } + else{ + toast.error(error.message || t("errorOccurred")) + } } finally { setLoading(false); } @@ -89,22 +115,25 @@ const PageSignUp: FC = () => {

- Signup + {t("signup")}

e.preventDefault()}> + {/* Full Name Field */} + + {/* Phone Number Field */} + + {/* Password Field */} + + {/* Confirm Password Field */} + + {/* Display Failed Message */} {failed &&

{failed}

} + + {/* Submit Button */} - Continue + {t("continue")}
+ + {/* Signup Link */} - Already have an account?{" "} + {t("alreadyHaveAccount")}{" "} - Sign in + {t("signIn")}
+
); }; diff --git a/src/app/[locale]/tours/SectionGridFilterCard.tsx b/src/app/[locale]/tours/SectionGridFilterCard.tsx index 2ac85f9..52a7c62 100644 --- a/src/app/[locale]/tours/SectionGridFilterCard.tsx +++ b/src/app/[locale]/tours/SectionGridFilterCard.tsx @@ -1,14 +1,17 @@ "use client"; -import React, { FC, useContext, useEffect, useState } from "react"; -import { DEMO_STAY_LISTINGS } from "@/data/listings"; +import React, { FC, useEffect, useState } from "react"; +import convertNumbThousand from "@/utils/convertNumbThousand"; +import Link from "next/link"; +import Image from "next/image"; +import { useToursContext } from "@/components/contexts/tourDetails"; +import { useSearchParams } from "next/navigation"; +import Heading2 from "@/shared/Heading2"; // Assuming Heading2 is used elsewhere +import StayCard2 from "./Card"; +import { useTranslation } from "react-i18next"; import { StayDataType } from "@/data/types"; +import { DEMO_STAY_LISTINGS } from "@/data/listings"; import TabFilters from "./TabFilters"; -import Heading2 from "@/shared/Heading2"; -import StayCard2 from "./Card"; -import { useToursContext } from "@/components/contexts/tourDetails"; -import { useParams, useSearchParams } from "next/navigation"; -import { useRouter } from "next/navigation"; export interface SectionGridFilterCardProps { className?: string; @@ -19,27 +22,29 @@ const SectionGridFilterCard: FC = ({ className = "", data = DEMO_STAY_LISTINGS, }) => { + const { t } = useTranslation("common"); const { countries, tours } = useToursContext(); const [countryTours, setCountryTours] = useState(tours.results || []); const [checked, setChecked] = useState<{ [key: string]: boolean }>({}); - const searchParams = useSearchParams() -console.log(searchParams); + const searchParams = useSearchParams(); + console.log(searchParams); // Get the list of selected countries - const filteredCountries = Object.keys(checked).filter((countryName) => checked[countryName]); + const filteredCountries = Object.keys(checked).filter( + (countryName) => checked[countryName] + ); - useEffect(()=>{ - const country = searchParams.get("country") - if (searchParams.has("country")){ + useEffect(() => { + const country = searchParams.get("country"); + if (searchParams.has("country") && country) { setChecked({ - [country] : true - }) + [country]: true, + }); } - } , [searchParams]) -console.log(checked); - - + }, [searchParams]); + + console.log(checked); useEffect(() => { if (!tours.results) return; @@ -60,20 +65,23 @@ console.log(checked); setCountryTours(filteredTours); } - }, [checked, countries, tours.results]); + }, [checked, countries, tours.results, filteredCountries]); return ( -
-
-

{"All Tours"}

- {/* - 233 stays - · - Aug 12 - 18 - ·2 Guests - */} - -
+
+
+

+ {t("sectionGridFilterCard.allTours")} +

+ {/* Uncomment and internationalize if needed + + {t("sectionGridFilterCard.toursInfo", { count: 233, dateRange: "Aug 12 - 18", guests: 2 })} + + */} +
@@ -82,11 +90,11 @@ console.log(checked); {countryTours.length > 0 ? ( countryTours.map((stay) => ) ) : ( -

No tours Available

+

{t("sectionGridFilterCard.noToursAvailable")}

)}
); }; -export default SectionGridFilterCard; \ No newline at end of file +export default SectionGridFilterCard; diff --git a/src/app/[locale]/tours/[slug]/page.tsx b/src/app/[locale]/tours/[slug]/page.tsx index 3e8a4b7..bfafc68 100644 --- a/src/app/[locale]/tours/[slug]/page.tsx +++ b/src/app/[locale]/tours/[slug]/page.tsx @@ -90,9 +90,9 @@ const ListingStayDetailPage: FC = () => { {itineraries.map((item, index) => (
-
+
{itineraries.length !== index + 1 && ( -
+
)}
@@ -131,13 +131,17 @@ const ListingStayDetailPage: FC = () => { const renderSidebar = () => { const total = details?.final_price && passengers - ? ((passengers.guestAdults * Number(details.price)) + (passengers.guestChildren * Number(details.price_child)) + (passengers.guestInfants * Number(details?.price_infant))).toLocaleString("en-US", { + ? ( + passengers.guestAdults * Number(details.price) + + passengers.guestChildren * Number(details.price_child) + + passengers.guestInfants * Number(details?.price_infant) + ).toLocaleString("en-US", { style: "currency", currency: "USD", }) : 0; - console.log(details); - + console.log(details); + return (
{/* Price display */} @@ -153,8 +157,13 @@ const ListingStayDetailPage: FC = () => {
)} {/* */} - {} - + { + + }
{/* Booking Form */} @@ -173,7 +182,7 @@ const ListingStayDetailPage: FC = () => { {/* Reserve Button */} {
{/* Main Image */} -
+
{details && ( { {/* Main content section */}
{/* Left Content */} -
+
{renderSectionDetails()} {renderTourFeatures()} {renderItinerarySection()} diff --git a/src/app/globals.css b/src/app/globals.css index 2ffacc2..b809779 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -13,9 +13,14 @@ } .hero-image{ - left: -450px; + left: -550px; } + @media(max-width : 1600px) { + .hero-image{ + left: -350px; + } + } @media(max-width : 1400px) { .hero-image{ left: -400px; @@ -26,4 +31,8 @@ left: -300px; top: 0px; } - } \ No newline at end of file + } + + .container{ + max-width: 1440px; + } diff --git a/src/components/BackgroundSection.tsx b/src/components/BackgroundSection.tsx index fbb36ef..6d91681 100644 --- a/src/components/BackgroundSection.tsx +++ b/src/components/BackgroundSection.tsx @@ -11,7 +11,7 @@ const BackgroundSection: FC = ({ }) => { return (
{children} diff --git a/src/components/CardCategory3.tsx b/src/components/CardCategory3.tsx index da774d1..fa9fdf4 100644 --- a/src/components/CardCategory3.tsx +++ b/src/components/CardCategory3.tsx @@ -1,19 +1,11 @@ "use client"; import React, { FC, useEffect, useState } from "react"; -import convertNumbThousand from "@/utils/convertNumbThousand"; +import { TaxonomyType } from "@/data/types"; import Link from "next/link"; import Image from "next/image"; - -// Define the TaxonomyType, CountryType, and TourType interfaces - -interface TaxonomyType { - count: number; - name: string; - href?: string; - thumbnail?: string; - city: { thumbnail: string }[]; // Assuming 'city' is an array of objects with 'thumbnail' -} +import { useTranslation } from "react-i18next"; +import convertNumbThousand from "@/utils/convertNumbThousand"; interface CountryType { name: string; @@ -37,6 +29,7 @@ const CardCategory3: FC = ({ countries, tours, }) => { + const { t } = useTranslation("common"); const { count, name, href = "/", thumbnail } = taxonomy; // Set the state with proper typing for country tours @@ -65,12 +58,12 @@ const CardCategory3: FC = ({ places ) : ( -
+ @@ -83,7 +76,7 @@ const CardCategory3: FC = ({ - {convertNumbThousand(countryTours.length || 0)} Tours + {convertNumbThousand(countryTours.length || 0)} {t("cardCategory3.tours")}
diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx index bc62f68..c016b88 100644 --- a/src/components/Footer.tsx +++ b/src/components/Footer.tsx @@ -1,10 +1,12 @@ "use client"; +import React, { FC } from "react"; +import { useTranslation } from "react-i18next"; import Logo from "@/shared/Logo"; import SocialsList1 from "@/shared/SocialsList1"; import { CustomLink } from "@/data/types"; -import React from "react"; import FooterNav from "./FooterNav"; +import Image from "next/image"; export interface WidgetFooterMenu { id: string; @@ -12,65 +14,32 @@ export interface WidgetFooterMenu { menus: CustomLink[]; } -const widgetMenus: WidgetFooterMenu[] = [ - { - id: "5", - title: "Getting started", - menus: [ - { href: "#", label: "Installation" }, - { href: "#", label: "Release Notes" }, - { href: "#", label: "Upgrade Guide" }, - { href: "#", label: "Browser Support" }, - { href: "#", label: "Editor Support" }, - ], - }, - { - id: "1", - title: "Explore", - menus: [ - { href: "#", label: "Design features" }, - { href: "#", label: "Prototyping" }, - { href: "#", label: "Design systems" }, - { href: "#", label: "Pricing" }, - { href: "#", label: "Security" }, - ], - }, - { - id: "2", - title: "Resources", - menus: [ - { href: "#", label: "Best practices" }, - { href: "#", label: "Support" }, - { href: "#", label: "Developers" }, - { href: "#", label: "Learn design" }, - { href: "#", label: "Releases" }, - ], - }, - { - id: "4", - title: "Community", - menus: [ - { href: "#", label: "Discussion Forums" }, - { href: "#", label: "Code of Conduct" }, - { href: "#", label: "Community Resources" }, - { href: "#", label: "Contributing" }, - { href: "#", label: "Concurrent Mode" }, - ], - }, -]; - const Footer: React.FC = () => { + const { t } = useTranslation("footer"); + + const widgetMenus: WidgetFooterMenu[] = [ + { + id: "5", + title: "Quick Links", + menus: [ + { href: "tours", label: t("widgetMenus.Quick Links.menus.0.label") }, + { href: "blog", label: t("widgetMenus.Quick Links.menus.1.label") }, + { href: "faq", label: t("widgetMenus.Quick Links.menus.2.label") }, + { href: "about", label: t("widgetMenus.Quick Links.menus.3.label") }, + ], + } + ]; + const renderWidgetMenuItem = (menu: WidgetFooterMenu, index: number) => { return ( -
+

- {menu.title} + {t(`widgetMenus.${menu.title}.title`)}