Compare commits

..

11 Commits

Author SHA1 Message Date
543198994b feat: add Plausible support
All checks were successful
Linux arm64 / Build-and-Deploy (push) Successful in 46s
2025-05-15 20:29:03 +02:00
Morph01
b9ce2ffdc2 Add multi-languages support with i18next
Some checks failed
Linux arm64 / Build-and-Deploy (push) Failing after 7s
2025-03-04 21:39:02 +01:00
Morph01
069be079eb the CI file changed its name unintentionally ^^
All checks were successful
Linux arm64 / Build-and-Deploy (push) Successful in 36s
2024-11-23 19:04:06 +01:00
aac41fd363 Update build.yml with test deploy with brain
All checks were successful
Linux arm64 / Build-and-Deploy (push) Successful in 39s
2024-11-23 16:47:59 +00:00
dff4093315 Update build.yml with test deploy
All checks were successful
Linux arm64 / Build-and-Deploy (push) Successful in 34s
2024-11-23 16:33:16 +00:00
1be90da3c3 Update build.yml with test deploy
Some checks failed
Linux arm64 / Build-and-Deploy (push) Failing after 34s
2024-11-23 16:31:14 +00:00
1588363d97 Update build.yml with test deploy with brain
Some checks failed
Linux arm64 / Build-and-Deploy (push) Failing after 38s
2024-11-23 16:27:55 +00:00
0c64ba030c Update build.yml with test deploy
Some checks failed
Linux arm64 / Build-and-Deploy (push) Failing after 38s
2024-11-23 16:26:00 +00:00
d630bb4812 Update build.yml
All checks were successful
Linux arm64 / Build (push) Successful in 37s
2024-11-23 15:50:07 +00:00
c067f0b437 test another ssh key
Some checks failed
Linux arm64 / Build (push) Failing after 35s
2024-11-06 15:54:13 +00:00
Morph01
21355ac913 feat: add pipeline
Some checks failed
Linux arm64 / Build (push) Failing after 36s
2024-11-06 12:35:34 +01:00
21 changed files with 2477 additions and 1780 deletions

View File

@@ -0,0 +1,48 @@
name: Linux arm64
run-name: Build and Deploy Portfolio
on: [push]
jobs:
Build-and-Deploy:
runs-on: ubuntu-latest
steps:
- name: Check out repository code
uses: actions/checkout@v3
- name: Install dependencies and build
run: |
npm ci
npm run build
- name: Set up SSH agent
uses: webfactory/ssh-agent@v0.9.0
with:
ssh-private-key: ${{ secrets.SSH_KEY_PORTFOLIO }}
- name: Add remote host to known_hosts
run: |
mkdir -p ~/.ssh
ssh-keyscan -H git.ale-pri.com >> ~/.ssh/known_hosts
- name: Upload build folder to temporary directory on remote server
run: |
scp -r build ubuntu@git.ale-pri.com:Poubelle/portfolio
- name: Deploy to final directory on remote server
run: |
ssh ubuntu@git.ale-pri.com << 'EOF'
BUILD_TMP=Poubelle/portfolio
DEPLOY_DIR=/var/www/portfolio
sudo mkdir -p $DEPLOY_DIR
sudo rsync -a --delete $BUILD_TMP/ $DEPLOY_DIR/
sudo chown -R www-data:www-data $DEPLOY_DIR
sudo chmod -R 755 $DEPLOY_DIR
sudo rm -rf $BUILD_TMP
sudo nginx -t && sudo systemctl reload nginx
EOF

3786
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -7,12 +7,19 @@
},
"dependencies": {
"@types/react-router-dom": "^5.3.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.22.0",
"i18next": "^22.5.1",
"i18next-browser-languagedetector": "^8.1.0",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-i18next": "^10.0.0",
"react-router-dom": "^7.6.0",
"react-scripts": "^5.0.1",
"react-scroll": "^1.8.9",
"web-vitals": "^2.1.4"
"react-scroll": "^1.9.3",
"typescript": "^4.9.5",
"web-vitals": "^5.0.1"
},
"devDependencies": {
"@babel/plugin-transform-private-property-in-object": "^7.27.1"
},
"scripts": {
"start": "react-scripts --openssl-legacy-provider start",
@@ -30,4 +37,4 @@
"last 1 safari version"
]
}
}
}

BIN
public/img/cinetour.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 365 KiB

BIN
public/img/docker.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
public/img/gauss.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

BIN
public/img/git.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
public/img/kubernetes.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -13,6 +13,10 @@
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<title>Portfolio</title>
<!-- Plausible -->
<script defer data-domain="thibaut.ale-pri.com"
src="https://plausible.ale-pri.com/js/script.file-downloads.hash.outbound-links.js"></script>
<script>window.plausible = window.plausible || function () { (window.plausible.q = window.plausible.q || []).push(arguments) }</script>
</head>
<body>

View File

@@ -3,6 +3,7 @@ import React from "react";
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import Home from "./Pages/Home/Homescreen";
import Navbar from "./Pages/Home/Navbar";
import "./i18n";
function App() {
return (

View File

@@ -1,4 +1,8 @@
import { useTranslation } from "react-i18next";
export default function AboutMe() {
const { t } = useTranslation();
return (
<section id="AboutMe" className="about--section">
<div className="about--section--img">
@@ -6,13 +10,13 @@ export default function AboutMe() {
</div>
<div className="hero--section--content-box about--section--box">
<div className="hero--section--content">
<p className="section--title">À propos</p>
<h1 className="skills-section--heading">À propos de moi</h1>
<p className="section--title">{t('about.title')}</p>
<h1 className="skills-section--heading">{t('about.heading')}</h1>
<p className="hero--section-description">
Alternant en troisième année d'école d'ingénieur à Polytech Lyon en Informatique en alternance à WORLDLINE, occupant le poste d'ingénieur SRE/OPS.
{t('about.description1')}
</p>
<p className="hero--section-description">
Passionné dinformatique, je suis à la recherche dune mobilité à l'étranger pour développer mes compétences et contribuer à un projet d'entreprise quil soit orienté Infrastructure, Développement, OPS, Bases de Données ...
{t('about.description2')}
</p>
</div>
</div>

View File

@@ -1,16 +1,19 @@
import { useTranslation } from "react-i18next";
export default function ContactMe() {
const { t } = useTranslation();
return (
<section id="Contact" className="contact--section">
<div>
<p className="sub--title">Rentrer en Contact</p>
<h2>Contactez Moi</h2>
<p className="sub--title">{t('contact.title')}</p>
<h2>{t('contact.heading')}</h2>
<p className="text-lg-with-margin">
Si vous voulez me contacter, vous pouvez m'envoyer un mail à l'adresse
email suivante :
{t('contact.description1')}
</p>
<a href="mailto:thibaut.alessi@free.fr">thibaut.alessi@free.fr</a>
<p className="text-lg">
Ou bien directement par LinkedIn en bas de page.
{t('contact.description2')}
</p>
</div>
</section>

View File

@@ -1,13 +1,25 @@
import { Link } from "react-scroll";
import React from "react";
import { useTranslation } from "react-i18next";
function Footer() {
const { t } = useTranslation();
return (
<footer className="footer--container">
<div className="footer--link--container">
<div>
<Link
activeClass="navbar--active-content"
spy={true}
smooth={true}
offset={-70}
duration={500}
to="heroSection"
className="footer--logo"
style={{ cursor: 'pointer' }}
>
<img src="./img/logo.png" alt="Logo" />
</div>
</Link>
<div className="footer--items">
<ul>
<li>
@@ -19,8 +31,10 @@ function Footer() {
duration={500}
to="heroSection"
className="text-md"
style={{ cursor: 'pointer' }}
>
Accueil
{t('footer.home')}
</Link>
</li>
<li>
@@ -32,8 +46,9 @@ function Footer() {
duration={500}
to="MyPortfolio"
className="text-md"
style={{ cursor: 'pointer' }}
>
Portfolio
{t('footer.portfolio')}
</Link>
</li>
<li>
@@ -45,8 +60,9 @@ function Footer() {
duration={500}
to="AboutMe"
className="text-md"
style={{ cursor: 'pointer' }}
>
À propos de moi
{t('footer.about')}
</Link>
</li>
</ul>

View File

@@ -1,26 +1,24 @@
import { Link } from "react-router-dom";
import { useTranslation } from "react-i18next";
export default function HeroSection() {
const openGitHub = (link) => {
window.open(link, "_blank");
};
const { t } = useTranslation();
return (
<section id="heroSection" className="hero--section">
<div className="hero--section--content-box">
<div className="hero--section--content">
<p className="section--title">Hello, je suis ALESSI Thibaut</p>
<p className="section--title">{t('hero.hello')}</p>
<h1 className="hero--section--title">
<span className="hero--section--title--color">
Etudiant à Polytech Lyon
{t('hero.student')}
</span>{" "}
<br />
Passionné d'informatique
{t('hero.passion')}
</h1>
<p className="hero--section--description">
J'aime le C++, le SQL, la guitare, le sport et voyager.
{t('hero.description')}
<br />
Mon objectif, m'améliorer chaque jour.
{t('hero.goal')}
</p>
</div>
</div>

View File

@@ -1,8 +1,11 @@
import { Link } from "react-router-dom";
import data from "../../data/index.json";
import { useTranslation } from "react-i18next";
export default function MyPortfolio() {
const openGitHub = (link) => {
const { t, i18n } = useTranslation();
const currentLang = (i18n.language || 'fr').split('-')[0];
const openLinkInNewTab = (link) => {
window.open(link, "_blank");
};
@@ -10,11 +13,11 @@ export default function MyPortfolio() {
<section className="portfolio--section" id="MyPortfolio">
<div className="portfolio--container-box">
<div className="portfolio--container">
<p className="sub--title">Projets récents</p>
<h2 className="section--heading">Mon Portfolio</h2>
<p className="sub--title">{t('portfolio.title')}</p>
<h2 className="section--heading">{t('portfolio.heading')}</h2>
</div>
<div>
<button className="btn btn-github" onClick={() => openGitHub("https://github.com/Morph01")}>
<button className="btn btn-github" onClick={() => openLinkInNewTab("https://github.com/Morph01")}>
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
@@ -29,23 +32,27 @@ export default function MyPortfolio() {
fill="currentColor"
/>
</svg>
Visiter mon GitHub
{t('portfolio.github')}
</button>
</div>
</div>
<div className="portfolio--section--container">
{data?.portfolio?.map((item, index) => (
<div key={index} className="portfolio--section--card">
<div key={index} className="portfolio--section--card"
onClick={() => openLinkInNewTab(item.link)}
style={{ cursor: 'pointer' }}>
<div className="portfolio--section--img">
<img src={item.src} alt="Placeholder" />
<img src={item.src} alt={item.title[currentLang]} />
</div>
<div className="portfolio--section--card--content">
<div>
<h3 className="portfolio--section--title">{item.title}</h3>
<p className="text-md">{item.description}</p>
<h3 className="portfolio--section--title">
{item.title[currentLang]}
</h3>
<p className="text-md">{item.description[currentLang]}</p>
</div>
<p className="text-sm portfolio--link" onClick={() => openGitHub(item.link)}>
{item.voir}
<p className="text-sm portfolio--link">
{item.voir[currentLang]}
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"

View File

@@ -1,21 +1,25 @@
import { useTranslation } from "react-i18next";
import data from "../../data/index.json";
export default function MySkills() {
const { t, i18n } = useTranslation();
const currentLang = (i18n.language || 'fr').split('-')[0];
return (
<section className="skills--section" id="mySkills">
<div className="portfolio--container">
<p className="section--title">Mes Compétences</p>
<h2 className="skills--section--heading">Mes Skills</h2>
<p className="section--title">{t('skills.title')}</p>
<h2 className="skills--section--heading">{t('skills.heading')}</h2>
</div>
<div className="skills--section--container">
{data?.skills?.map((item, index) => (
<div key={index} className="skills--section--card">
<div className="skills--section--img">
<img src={item.src} alt="Tools" />
<img src={item.src} alt="Product Chain" />
</div>
<div className="skills--section--card--content">
<h3 className="skills--section--title">{item.title}</h3>
<p className="skills--section--description">{item.description}</p>
<h3 className="skills--section--title">{item.title[currentLang]}</h3>
<p className="skills--section--description">{item.description[currentLang]}</p>
</div>
</div>
))}

View File

@@ -1,8 +1,10 @@
import { useState, useEffect } from "react";
import { Link } from "react-scroll";
import { useTranslation } from "react-i18next";
function Navbar() {
const [navActive, setNavActive] = useState(false);
const { t } = useTranslation();
const toggleNav = () => {
setNavActive(!navActive);
@@ -34,9 +36,19 @@ function Navbar() {
return (
<nav className={`navbar ${navActive ? "active" : ""}`}>
<div>
<Link
onClick={closeMenu}
activeClass="navbar--active-content"
spy={false}
smooth={true}
offset={-70}
duration={500}
to="heroSection"
className="navbar--logo"
style={{ cursor: 'pointer' }}
>
<img src="./img/logo.png" alt="Logo" />
</div>
</Link>
<a
className={`nav__hamburger ${navActive ? "active" : ""}`}
onClick={toggleNav}
@@ -58,7 +70,7 @@ function Navbar() {
to="heroSection"
className="navbar--content"
>
Accueil
{t('navbar.home')}
</Link>
</li>
<li>
@@ -72,7 +84,7 @@ function Navbar() {
to="MyPortfolio"
className="navbar--content"
>
Portfolio
{t('navbar.portfolio')}
</Link>
</li>
<li>
@@ -86,7 +98,7 @@ function Navbar() {
to="AboutMe"
className="navbar--content"
>
À propos de moi
{t('navbar.about')}
</Link>
</li>
</ul>
@@ -101,7 +113,7 @@ function Navbar() {
to="Contact"
className="btn btn-outline-primary"
>
Contactez Moi
{t('navbar.contact')}
</Link>
</nav>
);

View File

@@ -3,58 +3,151 @@
{
"id": "1",
"src": "./img/cpp.png",
"title": "POO (Programmation Orientée Objet)",
"description": "Développement en C++ du jeu Blitz."
"title": {
"fr": "POO (Programmation Orientée Objet)",
"en": "OOP (Object-Oriented Programming)"
},
"description": {
"fr": "Développement en C++ du jeu Blitz.",
"en": "Development of the Blitz game in C++."
}
},
{
"id": "2",
"src": "./img/sql.png",
"title": "Base de Données et SGBD MySQL",
"description": "Utilisation du SGBD MySQL pour le projet de mise en place d'une base de données pour le jeu Blitz."
"id": "2",
"src": "./img/sql.png",
"title": {
"fr": "Base de Données et SGBD MySQL",
"en": "Databases and MySQL DBMS"
},
"description": {
"fr": "Utilisation du SGBD MySQL pour le projet de mise en place d'une base de données pour le jeu Blitz.",
"en": "Using MySQL DBMS for implementing a database for the Blitz game."
}
},
{
"id": "3",
"src": "./img/html-css.png",
"title": "Front-End",
"description": "Développement de l'interface Front-End du site de notre participation à la Nuit de l'Info 2024 en HTML, SCSS, ReactJS + Vite."
"title": {
"fr": "Front-End",
"en": "Front-End"
},
"description": {
"fr": "Développement de l'interface Front-End du site de notre participation à la Nuit de l'Info 2024 en HTML, SCSS, ReactJS + Vite.",
"en": "Development of the Front-End interface for our 'Nuit de l'Info 2024' participation website using HTML, SCSS, ReactJS + Vite."
}
},
{
"id": "4",
"src": "./img/java.png",
"title": "POO (Programmation Orientée Objet)",
"description": "Développement et compréhension de code JAVA, accordé avec Maven et Hibernate par exemple."
"title": {
"fr": "POO (Programmation Orientée Objet)",
"en": "OOP (Object-Oriented Programming)"
},
"description": {
"fr": "Développement et compréhension de code JAVA, accordé avec Maven et Hibernate par exemple.",
"en": "Development and understanding of JAVA code, combined with tools like Maven and Hibernate."
}
},
{
"id": "5",
"src": "./img/jira.png",
"title": "Gestion de Projet / Méthodes agiles / ITIL",
"description": "Compréhension et application au quotidien de méthodes agiles, processus ITIL."
"title": {
"fr": "Gestion de Projet / Méthodes agiles / ITIL",
"en": "Project Management / Agile Methods / ITIL"
},
"description": {
"fr": "Compréhension et application au quotidien de méthodes agiles, processus ITIL.",
"en": "Understanding and daily application of agile methods and ITIL processes."
}
},
{
"id": "6",
"src": "./img/git.png",
"title": {
"fr": "Git",
"en": "Git"
},
"description": {
"fr": "Utilisation de Git pour la gestion de version de tout mes projets.",
"en": "Using Git for version control of all my projects."
}
},
{
"id": "7",
"src": "./img/docker.png",
"title": {
"fr": "Docker",
"en": "Docker"
},
"description": {
"fr": "Utilisation de Docker pour mettre en place des conteneurs pour mes projets et expérience de la conteneurisation de diverses applications chez Worldline.",
"en": "Use of Docker to set up containers for my projects and experienced containerization of various applications at Worldline."
}
},
{
"id": "8",
"src": "./img/kubernetes.png",
"title": {
"fr": "Kubernetes",
"en": "Kubernetes"
},
"description": {
"fr": "Utilisation de Kubernetes pour la gestion de conteneurs d'une plateforme de plusieurs applications sur GCP (Google Cloud Platform).",
"en": "Using Kubernetes to manage containers for a multi-application platform on GCP (Google Cloud Platform)."
}
}
],
"portfolio": [
{
"id": "1",
"src": "./img/cinetour.png",
"title": {
"fr": "Cinetour",
"en": "Cinetour"
},
"description": {
"fr": "Une application web pour les cinéphiles et les amateurs de voyage pour explorer les lieux réels où leurs films préférés ont été tournés. Développée avec Java (Spring Boot), React Frontend, MySQL, Dockerisée et hébergée sur un serveur cloud personnel.",
"en": "A web application for cinephiles and travel enthusiasts to explore the real-life locations where their favorite films were shot. Developed with Java (Spring Boot), React Frontend, MySQL, Dockerized and hosted on a personal cloud server."
},
"voir": {
"fr": "Découvrir",
"en": "Discover"
},
"link": "https://cinetour.ale-pri.com"
},
{
"id": "2",
"src": "./img/blitz.jpg",
"title": "Blitz",
"description": "Jeu 3D multijoueurs cross-platforme (Windows, Linux, MacOS, Android) développé en C++, interface 3D avec OpenGL, interface utilisateur avec ImGui.",
"voir": "Voir Sur Gitea",
"title": {
"fr": "Blitz",
"en": "Blitz"
},
"description": {
"fr": "Jeu 3D multijoueurs cross-platforme (Windows, Linux, MacOS, Android) développé en C++, interface 3D avec OpenGL, interface utilisateur avec ImGui.",
"en": "Cross-platform multiplayer 3D game (Windows, Linux, MacOS, Android) developed in C++, 3D interface with OpenGL, user interface with ImGui."
},
"voir": {
"fr": "Voir Sur Gitea",
"en": "View On Gitea"
},
"link": "https://git.ale-pri.com/Blitz/Blitz"
},
{
"id": "2",
"src": "./img/gauss.png",
"title": "Elimination de Gauss-Jordan",
"description": "Utilisation C++ pour effectuer plusieurs opérations sur des matrices afin de trouver le noyau et l'image d'applications linéaires par la méthode du pivot de Gauss",
"voir": "Voir Sur Gitea",
"link": "https://git.ale-pri.com/ProjetMAM/Pivot"
},
{
"id": "3",
"src": "./img/nuitinfo.png",
"title": "Front-End",
"description": "Participation à la nuit de l'info 2024, coté au front-end.",
"voir": "Voir Sur GitHub",
"link": "https://github.com/PolyCrusader/PolyCrusader"
"src": "./img/gauss.jpg",
"title": {
"fr": "Elimination de Gauss-Jordan",
"en": "Gauss-Jordan Elimination"
},
"description": {
"fr": "Utilisation C++ pour effectuer plusieurs opérations sur des matrices afin de trouver le noyau et l'image d'applications linéaires par la méthode du pivot de Gauss",
"en": "Using C++ to perform various operations on matrices to find the kernel and image of linear applications using the Gaussian pivot method"
},
"voir": {
"fr": "Voir Sur Gitea",
"en": "View On Gitea"
},
"link": "https://git.ale-pri.com/ProjetMAM/Pivot"
}
]
}

32
src/i18n/index.js Normal file
View File

@@ -0,0 +1,32 @@
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import translationEN from './locales/en.json';
import translationFR from './locales/fr.json';
const resources = {
en: {
translation: translationEN
},
fr: {
translation: translationFR
}
};
i18n
.use(LanguageDetector)
.use(initReactI18next)
.init({
resources,
fallbackLng: 'fr',
detection: {
order: ['navigator', 'htmlTag', 'path', 'subdomain'],
caches: ['localStorage']
},
interpolation: {
escapeValue: false
}
});
export default i18n;

41
src/i18n/locales/en.json Normal file
View File

@@ -0,0 +1,41 @@
{
"navbar": {
"home": "Home",
"portfolio": "Portfolio",
"about": "About Me",
"contact": "Contact Me"
},
"hero": {
"hello": "Hello, I'm ALESSI Thibaut",
"student": "Student at Polytech Lyon",
"passion": "SRE/OPS apprentice at WORLDLINE",
"description": "I love Java, Docker, guitar, chess, sports, and traveling.",
"goal": "My goal is to improve every day."
},
"skills": {
"title": "My Competencies",
"heading": "My Skills"
},
"about": {
"title": "About",
"heading": "About Me",
"description1": "Third-year engineering student at Polytech Lyon in Computer Science, working as an SRE/OPS engineer at WORLDLINE through an apprenticeship program.",
"description2": "Passionate about IT, I'm looking for an opportunity for a summer internship abroad to develop my skills and contribute to a company project, whether Cloud, Infrastructure, Development, OPS..."
},
"portfolio": {
"title": "Recent Projects",
"heading": "My Portfolio",
"github": "Visit my GitHub"
},
"contact": {
"title": "Get in Touch",
"heading": "Contact Me",
"description1": "If you want to contact me, you can send me an email at:",
"description2": "Or directly through LinkedIn at the bottom of the page."
},
"footer": {
"home": "Home",
"portfolio": "Portfolio",
"about": "About Me"
}
}

41
src/i18n/locales/fr.json Normal file
View File

@@ -0,0 +1,41 @@
{
"navbar": {
"home": "Accueil",
"portfolio": "Portfolio",
"about": "À propos de moi",
"contact": "Contactez Moi"
},
"hero": {
"hello": "Hello, je suis ALESSI Thibaut",
"student": "Etudiant à Polytech Lyon",
"passion": "Alternant SRE/OPS chez WORLDLINE",
"description": "J'aime Java, Docker, la guitare, les échecs, le sport et voyager.",
"goal": "Mon objectif, m'améliorer chaque jour."
},
"skills": {
"title": "Mes Compétences",
"heading": "Mes Skills"
},
"about": {
"title": "À propos",
"heading": "À propos de moi",
"description1": "Alternant en troisième année d'école d'ingénieur à Polytech Lyon en Informatique en alternance à WORLDLINE, occupant le poste d'ingénieur SRE/OPS.",
"description2": "Passionné d'informatique, je suis à la recherche d'une opportunité pour un stage d'été à l'étranger pour développer mes compétences et contribuer à un projet d'entreprise qu'il soit orienté Cloud, Infrastructure, Développement, OPS..."
},
"portfolio": {
"title": "Projets récents",
"heading": "Mon Portfolio",
"github": "Visiter mon GitHub"
},
"contact": {
"title": "Rentrer en Contact",
"heading": "Contactez Moi",
"description1": "Si vous voulez me contacter, vous pouvez m'envoyer un mail à l'adresse email suivante :",
"description2": "Ou bien directement par LinkedIn en bas de page."
},
"footer": {
"home": "Accueil",
"portfolio": "Portfolio",
"about": "À propos de moi"
}
}