feat: add language context and translation support

- Introduced LanguageProvider to manage language state and translations.
- Updated components (Header, Hero, About, Skills, Projects, Education, Contact) to utilize translations.
- Added language toggle button in the header for switching between French and English.
- Enhanced styling for language toggle button in the header.
This commit is contained in:
Dayron
2025-11-12 18:36:51 +01:00
parent a4b4423ff4
commit e8722cf25d
10 changed files with 468 additions and 130 deletions

View File

@@ -3,8 +3,10 @@ import { motion } from 'framer-motion';
import { Mail, Phone, MapPin, Send, Github, Linkedin, MessageCircle, CheckCircle, AlertCircle } from 'lucide-react';
import { sendContactEmail } from '../services/emailService';
import type { ContactFormData } from '../services/emailService';
import { useLanguage } from '../contexts/LanguageContext';
const Contact = () => {
const { t } = useLanguage();
const [formData, setFormData] = useState({
name: '',
email: '',
@@ -93,7 +95,7 @@ const Contact = () => {
{
icon: <Linkedin size={24} />,
name: "LinkedIn",
url: "https://linkedin.com/in/dayronvanleemput", // Remplacez par votre profil
url: "https://www.linkedin.com/in/dayron-van-leemput-992a94398", // Remplacez par votre profil
color: "#0077B5"
}
];
@@ -131,9 +133,9 @@ const Contact = () => {
transition={{ duration: 0.8 }}
viewport={{ once: true }}
>
<h2 className="section-title">Contactez-moi</h2>
<h2 className="section-title">{t('contact.title')}</h2>
<p className="section-subtitle">
Une question, un projet ou simplement envie d'échanger ? N'hésitez pas à me contacter !
{t('contact.subtitle')}
</p>
</motion.div>
@@ -149,12 +151,10 @@ const Contact = () => {
<div className="contact-intro">
<h3>
<MessageCircle size={24} />
Restons en contact
{t('contact.stayInTouch')}
</h3>
<p>
Je suis toujours intéressé par de nouveaux projets, des collaborations
ou simplement des discussions autour de la technologie. N'hésitez pas
à me contacter !
{t('contact.intro')}
</p>
</div>
@@ -189,7 +189,7 @@ const Contact = () => {
</div>
<div className="social-links">
<h4>Retrouvez-moi aussi sur :</h4>
<h4>{t('contact.findMeOn')}</h4>
<div className="social-grid">
{socialLinks.map((social, index) => (
<motion.a
@@ -223,7 +223,7 @@ const Contact = () => {
{/* Formulaire de contact */}
<motion.div className="contact-form-container" variants={itemVariants}>
<h3>Envoyez-moi un message</h3>
<h3>{t('contact.sendMessage')}</h3>
{isSubmitted && (
<motion.div
@@ -233,7 +233,7 @@ const Contact = () => {
exit={{ opacity: 0, scale: 0.8 }}
>
<CheckCircle size={20} />
Message envoyé avec succès ! Je vous répondrai bientôt.
{t('contact.success')}
</motion.div>
)}
@@ -258,7 +258,7 @@ const Contact = () => {
transition={{ duration: 0.5, delay: 0.1 }}
viewport={{ once: true }}
>
<label htmlFor="name">Nom complet</label>
<label htmlFor="name">{t('contact.form.name')}</label>
<input
type="text"
id="name"
@@ -266,7 +266,7 @@ const Contact = () => {
value={formData.name}
onChange={handleChange}
required
placeholder="Votre nom"
placeholder={t('contact.form.name')}
/>
</motion.div>
@@ -277,7 +277,7 @@ const Contact = () => {
transition={{ duration: 0.5, delay: 0.2 }}
viewport={{ once: true }}
>
<label htmlFor="email">Email</label>
<label htmlFor="email">{t('contact.form.email')}</label>
<input
type="email"
id="email"
@@ -297,7 +297,7 @@ const Contact = () => {
transition={{ duration: 0.5, delay: 0.3 }}
viewport={{ once: true }}
>
<label htmlFor="subject">Sujet</label>
<label htmlFor="subject">{t('contact.form.subject')}</label>
<input
type="text"
id="subject"
@@ -305,7 +305,7 @@ const Contact = () => {
value={formData.subject}
onChange={handleChange}
required
placeholder="Objet de votre message"
placeholder={t('contact.form.subject')}
/>
</motion.div>
@@ -316,7 +316,7 @@ const Contact = () => {
transition={{ duration: 0.5, delay: 0.4 }}
viewport={{ once: true }}
>
<label htmlFor="message">Message</label>
<label htmlFor="message">{t('contact.form.message')}</label>
<textarea
id="message"
name="message"
@@ -324,7 +324,7 @@ const Contact = () => {
onChange={handleChange}
required
rows={6}
placeholder="Votre message..."
placeholder={t('contact.form.message')}
/>
</motion.div>
@@ -342,12 +342,12 @@ const Contact = () => {
{isSubmitting ? (
<>
<div className="loading-spinner" />
Envoi en cours...
{t('contact.form.sending')}
</>
) : (
<>
<Send size={20} />
Envoyer le message
{t('contact.form.send')}
</>
)}
</motion.button>