add choose language

This commit is contained in:
kinou-p 2024-05-05 05:55:19 +02:00
parent 151c9d9dc5
commit f7c992bcdf
10 changed files with 188 additions and 83 deletions

View File

@ -23,10 +23,13 @@
"bootstrap": "^4.6.0", "bootstrap": "^4.6.0",
"country-flag-icons": "^1.5.11", "country-flag-icons": "^1.5.11",
"framer-motion": "^11.1.7", "framer-motion": "^11.1.7",
"i18next": "^23.11.3",
"i18next-xhr-backend": "^3.2.2",
"react": "^18.3.1", "react": "^18.3.1",
"react-bootstrap": "^2.10.2", "react-bootstrap": "^2.10.2",
"react-country-flag": "^3.1.0", "react-country-flag": "^3.1.0",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-i18next": "^14.1.1",
"react-icons": "^5.2.0", "react-icons": "^5.2.0",
"react-router-dom": "^6.23.0", "react-router-dom": "^6.23.0",
"react-scripts": "^5.0.1", "react-scripts": "^5.0.1",
@ -9675,6 +9678,14 @@
"node": ">=12" "node": ">=12"
} }
}, },
"node_modules/html-parse-stringify": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz",
"integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==",
"dependencies": {
"void-elements": "3.1.0"
}
},
"node_modules/html-webpack-plugin": { "node_modules/html-webpack-plugin": {
"version": "5.6.0", "version": "5.6.0",
"resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz", "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz",
@ -9818,6 +9829,37 @@
"node": ">=10.17.0" "node": ">=10.17.0"
} }
}, },
"node_modules/i18next": {
"version": "23.11.3",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-23.11.3.tgz",
"integrity": "sha512-Pq/aSKowir7JM0rj+Wa23Kb6KKDUGno/HjG+wRQu0PxoTbpQ4N89MAT0rFGvXmLkRLNMb1BbBOKGozl01dabzg==",
"funding": [
{
"type": "individual",
"url": "https://locize.com"
},
{
"type": "individual",
"url": "https://locize.com/i18next.html"
},
{
"type": "individual",
"url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
}
],
"dependencies": {
"@babel/runtime": "^7.23.2"
}
},
"node_modules/i18next-xhr-backend": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/i18next-xhr-backend/-/i18next-xhr-backend-3.2.2.tgz",
"integrity": "sha512-OtRf2Vo3IqAxsttQbpjYnmMML12IMB5e0fc5B7qKJFLScitYaXa1OhMX0n0X/3vrfFlpHL9Ro/H+ps4Ej2j7QQ==",
"deprecated": "replaced by i18next-http-backend",
"dependencies": {
"@babel/runtime": "^7.5.5"
}
},
"node_modules/iconv-lite": { "node_modules/iconv-lite": {
"version": "0.6.3", "version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
@ -15542,6 +15584,27 @@
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz",
"integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg=="
}, },
"node_modules/react-i18next": {
"version": "14.1.1",
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-14.1.1.tgz",
"integrity": "sha512-QSiKw+ihzJ/CIeIYWrarCmXJUySHDwQr5y8uaNIkbxoGRm/5DukkxZs+RPla79IKyyDPzC/DRlgQCABHtrQuQQ==",
"dependencies": {
"@babel/runtime": "^7.23.9",
"html-parse-stringify": "^3.0.1"
},
"peerDependencies": {
"i18next": ">= 23.2.3",
"react": ">= 16.8.0"
},
"peerDependenciesMeta": {
"react-dom": {
"optional": true
},
"react-native": {
"optional": true
}
}
},
"node_modules/react-icons": { "node_modules/react-icons": {
"version": "5.2.0", "version": "5.2.0",
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.2.0.tgz", "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.2.0.tgz",
@ -17923,6 +17986,14 @@
"node": ">= 0.8" "node": ">= 0.8"
} }
}, },
"node_modules/void-elements": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz",
"integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/w3c-hr-time": { "node_modules/w3c-hr-time": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz",

View File

@ -18,10 +18,13 @@
"bootstrap": "^4.6.0", "bootstrap": "^4.6.0",
"country-flag-icons": "^1.5.11", "country-flag-icons": "^1.5.11",
"framer-motion": "^11.1.7", "framer-motion": "^11.1.7",
"i18next": "^23.11.3",
"i18next-xhr-backend": "^3.2.2",
"react": "^18.3.1", "react": "^18.3.1",
"react-bootstrap": "^2.10.2", "react-bootstrap": "^2.10.2",
"react-country-flag": "^3.1.0", "react-country-flag": "^3.1.0",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-i18next": "^14.1.1",
"react-icons": "^5.2.0", "react-icons": "^5.2.0",
"react-router-dom": "^6.23.0", "react-router-dom": "^6.23.0",
"react-scripts": "^5.0.1", "react-scripts": "^5.0.1",

View File

@ -11,8 +11,9 @@ import React, { useState } from "react";
import CssBaseline from '@mui/material/CssBaseline'; import CssBaseline from '@mui/material/CssBaseline';
import Header from './components/header'; import Header from './components/header';
import { ColorModeContext } from './utils/color-toggle'; import { ColorModeContext } from './utils/color-toggle';
import { useTranslation } from 'react-i18next';
import "./utils/i18n";
function App() function App()
{ {
@ -37,6 +38,8 @@ function App()
}, },
}); });
const { i18n, t } = useTranslation();
return ( return (
<BrowserRouter> <BrowserRouter>
<CssBaseline /> <CssBaseline />

View File

@ -2,11 +2,13 @@ import * as React from 'react';
import { Button as BaseButton } from '@mui/base/Button'; import { Button as BaseButton } from '@mui/base/Button';
import { styled } from '@mui/system'; import { styled } from '@mui/system';
import Stack from '@mui/material/Stack'; import Stack from '@mui/material/Stack';
import { useTranslation } from 'react-i18next';
export default function ButtonSimple() { export default function ButtonSimple() {
const { i18n, t } = useTranslation();
return ( return (
// <Stack spacing={2} direction="row"> // <Stack spacing={2} direction="row">
<Button>Mon CV</Button> <Button>{t("resume")}</Button>
); );
} }

View File

@ -1,63 +1,70 @@
import MenuSimple from './language'; import MenuSimple from './language';
import MaterialUISwitch from './switch' import MaterialUISwitch from './switch'
import { useTheme, ThemeProvider, createTheme } from '@mui/material/styles'; import { useTheme, ThemeProvider, createTheme } from '@mui/material/styles';
// import { ThemeProvider, createTheme } from '@mui/material/styles';
import React, { useState, useContext } from "react"; import React, { useState, useContext } from "react";
import logo from '../img/first.jpg'; import logo from '../img/first.jpg';
// import { ColorModeContext } from '../utils/color-toggle'
// const theme = useTheme()
// const colorMode = React.useContext(ColorModeContext);
import { ColorModeContext } from '../utils/color-toggle'; import { ColorModeContext } from '../utils/color-toggle';
import { useTranslation } from 'react-i18next';
// const { ColorMode, setColorMode } = useColorMode(); import ReactCountryFlag from "react-country-flag"
import { FormControl } from 'react-bootstrap';
import { Box, InputLabel, MenuItem} from '@mui/material';
import Select, { SelectChangeEvent } from '@mui/material/Select';
function Header() function Header()
{ {
const { i18n, t } = useTranslation();
const { changeMode } = useContext(ColorModeContext); const { changeMode } = useContext(ColorModeContext);
// const { colorMode, setColorMode } = changeMode(); const [language, setLanguage] = useState(1);
function handleChange() {
// i18n.language
i18n.changeLanguage(language ? 'en' : 'fr')
setLanguage(language ? 0 : 1)
}
// const toggleColorMode = () => {
// // Call setColorMode and pass the new color mode value
// setColorMode(colorMode === 'light' ? 'dark' : 'light');
// };
return ( return (
// <ThemeProvider theme={darkTheme}>
<header> <header>
<div className="header-content"> <div className="header-content">
{/* <h1 className="title">A.P</h1> */} <a className="logo" href="/">
<div className="logo">
<img src={logo} alt="Logo" /> <img src={logo} alt="Logo" />
</div> </a>
<div className="pages"> <div className="pages">
Contact {t("page1")}
</div> </div>
<div className="pages"> <div className="pages">
Projets {t("page2")}
</div> </div>
<div className="pages"> <div className="pages">
CV {t("page3")}
</div> </div>
<div className="pages"> <div className="pages">
Competences {t("page4")}
</div> </div>
<div className="language"> <div className="language">
<MenuSimple/> {/* <MenuSimple/> */}
<Box sx={{ minWidth: 120 }}>
{/* <FormControl > */}
{/* <InputLabel id="demo-simple-select-label">Age</InputLabel> */}
<Select
labelId="demo-simple-select-label"
id="demo-simple-select"
value={language}
// label="Age"
onChange={handleChange}
>
<MenuItem value={0}><ReactCountryFlag countryCode="GB" svg/></MenuItem>
<MenuItem value={1}><ReactCountryFlag countryCode="FR" svg/></MenuItem>
</Select>
{/* </FormControl> */}
</Box>
<MaterialUISwitch onChange={changeMode}/> <MaterialUISwitch onChange={changeMode}/>
{/* <Switch className="dark_mode" checked={toggleDarkMode} onChange={toggleDarkTheme} defaultChecked /> */}
</div> </div>
</div> </div>
</header> </header>
// </ThemeProvider>
) )
} }

View File

@ -8,28 +8,19 @@
} }
body { body {
/* overflow: hidden; */ overflow: hidden;
/* color:black; */
max-width: 100vw; max-width: 100vw;
font-family: "Fira Sans", Arial, sans-serif; font-family: "Fira Sans", Arial, sans-serif;
/* height: 100vh; */
width: 100vw; width: 100vw;
margin: 0; margin: 0;
padding: 0; padding: 0;
font-family: Arial, sans-serif; font-family: Arial, sans-serif;
/* border: 1vh solide white; */
} }
header { header {
width: 100%; width: 100%;
/* background-color: #a4a4a4; */
/* padding: 20px 0; */
text-align: center; text-align: center;
height: 15vh; height: 15vh;
/* border-bottom-width: 5px; */
/* border-bottom: 1cm; */
/* border-color: rgb(207, 0, 0); */
} }
.header-content { .header-content {
@ -37,39 +28,29 @@ body {
width: 100vw; width: 100vw;
height: 100%; height: 100%;
display: flex; display: flex;
/* align-items: center; */
justify-content: space-between; justify-content: space-between;
/* padding-left: 0px; */
} }
.logo img{ .logo img{
height: 100%; /* Adjust the size as needed */ height: 100%; /* Adjust the size as needed */
/* margin-right: 32.5vw; */
margin-left: 3vw; margin-left: 3vw;
margin-right: 20vw; margin-right: 20vw;
margin-bottom: 1vh; margin-bottom: 1vh;
/* margin-left: 20px; */
} }
.pages { .pages {
margin-left: 5vw; margin-left: 5vw;
font-weight: 800; font-weight: 800;
/* width: 5vw; */
/* margin-top: 5vh; */
align-self: center; align-self: center;
/* height: 5vh; */
transition-property: transform; transition-property: transform;
/* transition-duration: 200ms; */
transition: all 200ms ease; transition: all 200ms ease;
&:hover { &:hover {
transform: scale(1.1); transform: scale(1.1);
border-bottom: 4px solid; border-bottom: 2px solid;
} }
} }
.title { .title {
color:black; color:black;
font-weight: 800; font-weight: 800;
@ -93,15 +74,11 @@ body {
margin-right: 0vw; margin-right: 0vw;
} }
/* .css-15bhy65 {
/* margin-right: 20px; */
Button{ Button{
font-weight: 800; font-weight: 800;
} }
.dark_mode { .dark_mode {
/* font-weight: 800; */
margin-right: 2vw; margin-right: 2vw;
width: 8vw; width: 8vw;
} }
@ -128,10 +105,6 @@ body {
width: 50vh; width: 50vh;
height: 50%; height: 50%;
align-self: start; align-self: start;
/* margin-left: 30%; */
/* margin-left: 10%; */
/* margin-top: 15%; */
/* max-width: 60%; */
} }
.presentation { .presentation {
@ -142,9 +115,7 @@ body {
.home { .home {
position: absolute; position: absolute;
/* top: 50%; */
right: -100vw; right: -100vw;
/* height: 50%; */
animation: slideRight 2s ease forwards; animation: slideRight 2s ease forwards;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
@ -173,25 +144,17 @@ body {
margin-left: 70%; margin-left: 70%;
} }
/* .css-cg7pzv {
width: 20vw;
} */
.project_group { .project_group {
font-size: 1vw; font-size: 1vw;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
/* width: 100vw; */
/* justify-content: center; */
/* align-self: left; */
align-items: center; align-items: center;
} }
.project_list { .project_list {
vertical-align: baseline; vertical-align: baseline;
margin-right: 2vw; margin-right: 2vw;
/* justify-content: space-between; */
transition-property: transform; transition-property: transform;
transition-duration: 500ms; transition-duration: 500ms;
&:hover { &:hover {
@ -210,15 +173,9 @@ body {
transition: all 700ms ease; transition: all 700ms ease;
transform: scale(1.15); transform: scale(1.15);
color: rgb(0, 127, 255); color: rgb(0, 127, 255);
/* transition-property: transform; */
/* transition-duration: 700ms; */
/* padding-right: 10vh; */
opacity: 0; opacity: 0;
} }
.project_list:hover + .arrow { .project_list:hover + .arrow {
/* color: rgb(0, 127, 255); */
/* transition-property: transform; */
/* transition-duration: 700ms; */
opacity: 1; opacity: 1;
} }

View File

@ -5,7 +5,7 @@ import App from './App';
// import ColorModeProvider from './utils/color-toggle'; // import ColorModeProvider from './utils/color-toggle';
import reportWebVitals from './reportWebVitals'; import reportWebVitals from './reportWebVitals';
import "./utils/i18n";
import { ColorModeProvider } from "./utils/color-toggle" import { ColorModeProvider } from "./utils/color-toggle"
const root = ReactDOM.createRoot( const root = ReactDOM.createRoot(

View File

@ -2,26 +2,31 @@ import Header from '../components/header'
import ButtonSimple from '../components/button' import ButtonSimple from '../components/button'
import { FaArrowRightLong } from "react-icons/fa6"; import { FaArrowRightLong } from "react-icons/fa6";
import { useTranslation } from 'react-i18next';
function Home() function Home()
{ {
const { i18n, t } = useTranslation();
return( return(
<div> <div>
<body> <body>
{/* <Header/> */} {/* <Header/> */}
<div className='home'> <div className='home'>
<div className="presentation"> <div className="presentation">
<div className='hello'>Bienvenue.</div> <div className='hello'>{t("welcome")}</div>
<div className="description">Étudiant a 42 en informatique, je cherche un emploi afin de compléter {/* <div className="description">Étudiant a 42 en informatique, je cherche un emploi afin de compléter
ma formation académique par une expérience professionnelle qui a du sens. ma formation académique par une expérience professionnelle qui a du sens.
Je suis ouvert à de nombreuses propositions en rapport avec mes études Je suis ouvert à de nombreuses propositions en rapport avec mes études
et suis prêt à discuter de mon parcours plus amplement lors dun entretien.</div> et suis prêt à discuter de mon parcours plus amplement lors dun entretien.</div> */}
<div>{t("description")}</div>
<div className="cv_button"> <div className="cv_button">
<ButtonSimple/> <ButtonSimple/>
</div> </div>
</div> </div>
<div className="project"> <div className="project">
<div className='project_txt'>Projects</div> <div className='project_txt'>{t("project")}</div>
<div className = "project_group"> <div className = "project_group">
<p className="project_list">- Ft_Transcendence</p> <p className="project_list">- Ft_Transcendence</p>
<FaArrowRightLong className="arrow"/> <FaArrowRightLong className="arrow"/>

52
my-app/src/utils/i18n.tsx Normal file
View File

@ -0,0 +1,52 @@
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
// import i18n from "i18next";
// import LanguageDetector from "i18next-browser-languagedetector";
import Backend from "i18next-xhr-backend";
// import { initReactI18next } from "react-i18next";
// const fallbackLng = ["en"];
i18n
.use(Backend) // used to load data from othe directory
// .use(LanguageDetector) // detects the current language
.use(initReactI18next) // passes i18n down to react-i18next
.init({
fallbackLng: "fr",
// lng: getCurrentLang(),
interpolation: {
escapeValue: false,
},
resources: {
en: {
translation: {
page1: "Contact",
page2: "Projects",
page3: "Resume",
page4: "Skills",
page5: "",
description:"Student majoring in computer science at 42, I am seeking employment to complement my academic training with meaningful professional experience. I am open to various job opportunities related to my studies and am ready to discuss my background further during an interview.",
project:"Projects",
welcome:"Welcome.",
resume:"My Resume",
},
},
fr: {
translation: {
page1: "Contact",
page2: "Projets",
page3: "CV",
page4: "Competences",
page5: "",
description:"Étudiant a 42 en informatique, je cherche un emploi afin de compléter ma formation académique par une expérience professionnelle qui a du sens. Je suis ouvert à de nombreuses propositions en rapport avec mes études et suis prêt à discuter de mon parcours plus amplement lors dun entretien.",
project:"Projets",
welcome:"Bienvenue.",
resume:"Mon CV",
},
},
},
});
export default i18n;

View File

@ -0,0 +1,5 @@
export const LANGUAGES = [
{ label: "Spanish", code: "es" },
{ label: "English", code: "en" },
{ label: "French", code: "fr" },
];