diff --git a/Front-end/package-lock.json b/Front-end/package-lock.json
index 4ac76c5..102cc6d 100644
--- a/Front-end/package-lock.json
+++ b/Front-end/package-lock.json
@@ -13,12 +13,15 @@
"@emotion/styled": "^11.14.0",
"@mui/material": "^7.0.1",
"axios": "^1.8.4",
+ "i18next": "^26.0.1",
+ "i18next-browser-languagedetector": "^8.2.1",
"jwt-decode": "^4.0.0",
"lucide-react": "^0.427.0",
"react": "^18.3.1",
"react-charts": "^3.0.0-beta.57",
"react-circle-progress-bar": "^0.1.4",
"react-dom": "^18.3.1",
+ "react-i18next": "^17.0.1",
"react-router-dom": "^7.4.0",
"recharts": "^2.15.1"
},
@@ -266,13 +269,10 @@
}
},
"node_modules/@babel/runtime": {
- "version": "7.27.0",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz",
- "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==",
+ "version": "7.29.2",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz",
+ "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==",
"license": "MIT",
- "dependencies": {
- "regenerator-runtime": "^0.14.0"
- },
"engines": {
"node": ">=6.9.0"
}
@@ -3807,6 +3807,56 @@
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
"license": "MIT"
},
+ "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==",
+ "license": "MIT",
+ "dependencies": {
+ "void-elements": "3.1.0"
+ }
+ },
+ "node_modules/i18next": {
+ "version": "26.0.1",
+ "resolved": "https://registry.npmjs.org/i18next/-/i18next-26.0.1.tgz",
+ "integrity": "sha512-vtz5sXU4+nkCm8yEU+JJ6yYIx0mkg9e68W0G0PXpnOsmzLajNsW5o28DJMqbajxfsfq0gV3XdrBudsDQnwxfsQ==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://www.locize.com/i18next"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.locize.com"
+ }
+ ],
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/runtime": "^7.29.2"
+ },
+ "peerDependencies": {
+ "typescript": "^5 || ^6"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/i18next-browser-languagedetector": {
+ "version": "8.2.1",
+ "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.2.1.tgz",
+ "integrity": "sha512-bZg8+4bdmaOiApD7N7BPT9W8MLZG+nPTOFlLiJiT8uzKXFjhxw4v2ierCXOwB5sFDMtuA5G4kgYZ0AznZxQ/cw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.23.2"
+ }
+ },
"node_modules/ignore": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
@@ -5259,6 +5309,33 @@
"react": "^18.3.1"
}
},
+ "node_modules/react-i18next": {
+ "version": "17.0.1",
+ "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-17.0.1.tgz",
+ "integrity": "sha512-iG65FGnFHcYyHNuT01ukffYWCOBFTWSdVD8EZd/dCVWgtjFPObcSsvYYNwcsokO/rDcTb5d6D8Acv8MrOdm6Hw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.29.2",
+ "html-parse-stringify": "^3.0.1",
+ "use-sync-external-store": "^1.6.0"
+ },
+ "peerDependencies": {
+ "i18next": ">= 26.0.1",
+ "react": ">= 16.8.0",
+ "typescript": "^5 || ^6"
+ },
+ "peerDependenciesMeta": {
+ "react-dom": {
+ "optional": true
+ },
+ "react-native": {
+ "optional": true
+ },
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
"node_modules/react-is": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
@@ -5421,12 +5498,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/regenerator-runtime": {
- "version": "0.14.1",
- "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
- "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
- "license": "MIT"
- },
"node_modules/regexp.prototype.flags": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
@@ -6307,6 +6378,15 @@
"punycode": "^2.1.0"
}
},
+ "node_modules/use-sync-external-store": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz",
+ "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -6468,6 +6548,15 @@
}
}
},
+ "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==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
diff --git a/Front-end/package.json b/Front-end/package.json
index 36bfe68..6c314e3 100644
--- a/Front-end/package.json
+++ b/Front-end/package.json
@@ -14,12 +14,15 @@
"@emotion/styled": "^11.14.0",
"@mui/material": "^7.0.1",
"axios": "^1.8.4",
+ "i18next": "^26.0.1",
+ "i18next-browser-languagedetector": "^8.2.1",
"jwt-decode": "^4.0.0",
"lucide-react": "^0.427.0",
"react": "^18.3.1",
"react-charts": "^3.0.0-beta.57",
"react-circle-progress-bar": "^0.1.4",
"react-dom": "^18.3.1",
+ "react-i18next": "^17.0.1",
"react-router-dom": "^7.4.0",
"recharts": "^2.15.1"
},
diff --git a/Front-end/src/components/BatterieInfo.jsx b/Front-end/src/components/BatterieInfo.jsx
index 642fe31..4a0b2b9 100644
--- a/Front-end/src/components/BatterieInfo.jsx
+++ b/Front-end/src/components/BatterieInfo.jsx
@@ -1,8 +1,10 @@
import React from "react";
import { Battery } from "lucide-react";
import Progress from "react-circle-progress-bar";
+import { useTranslation } from "react-i18next";
function BatterieInfo({ object }) {
+ const { t } = useTranslation();
return (
@@ -10,13 +12,13 @@ function BatterieInfo({ object }) {
- Etat de la batterie
+ {t('components.batterieInfo.title')}
- Type de batterie :{" "}
+ {t('components.batterieInfo.batteryType')}{" "}
{object.type_batterie}
diff --git a/Front-end/src/components/FormNewObject.jsx b/Front-end/src/components/FormNewObject.jsx
index 10c93c8..fa62272 100644
--- a/Front-end/src/components/FormNewObject.jsx
+++ b/Front-end/src/components/FormNewObject.jsx
@@ -3,8 +3,10 @@ import { BadgePlus } from "lucide-react";
import axios from "axios";
import { API_BASE_URL } from "../config";
import { useAuth } from "../AuthContext";
+import { useTranslation } from "react-i18next";
function FormNewObject({ isAdmin }) {
+ const { t } = useTranslation();
const { user } = useAuth();
const [categorie, setCategorie] = useState();
const [description, setDescription] = useState("");
@@ -35,12 +37,12 @@ function FormNewObject({ isAdmin }) {
proprio_id,
})
.then((response) => {
- setMessRequete("Votre objet à bien été enregistré !");
+ setMessRequete(t('components.formNewObject.successRecord'));
setEnregistre(true);
console.log("Ajout de l'objet réussit :", response.data);
})
.catch((error) => {
- setMessRequete("Il y a eu une erreur dans l'ajout de votre objet !");
+ setMessRequete(t('components.formNewObject.errorRecord'));
console.error("Erreur lors de l'ajout de l'objet :", error);
});
setVerif(false);
@@ -54,7 +56,7 @@ function FormNewObject({ isAdmin }) {
.get(`${API_BASE_URL}/getCategories`)
.then((response) => {
if (response.data.length === 0) {
- console.warn("Aucune catégorie disponible.");
+ console.warn(t('components.formNewObject.noCategory'));
} else {
setCategorie(response.data);
}
@@ -93,7 +95,7 @@ function FormNewObject({ isAdmin }) {
{isAdmin ? (
- Ajouter un nouvel objet
+ {t('components.formNewObject.addTitle')}
) : (
<>
@@ -102,8 +104,8 @@ function FormNewObject({ isAdmin }) {
{!verif
- ? "Entrez les données de votre nouvel objet"
- : "Êtes-vous sûr de ces données ?"}
+ ? t('components.formNewObject.enterData')
+ : t('components.formNewObject.confirmData')}
>
)}
@@ -113,7 +115,7 @@ function FormNewObject({ isAdmin }) {
htmlFor="nom"
className="block mb-2 text-sm font-medium text-gray-900"
>
- Nom :
+ {t('components.formNewObject.name')}
- Description :
+ {t('components.formNewObject.description')}
- Type :
+ {t('components.formNewObject.type')}