diff --git a/package-lock.json b/package-lock.json index 5916ec4..c64d0bf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,11 +15,14 @@ "@types/node": "^22.13.0", "dotenv": "^16.4.7", "fs": "^0.0.1-security", + "i18next": "^24.2.2", + "i18next-browser-languagedetector": "^8.0.4", "lucide-react": "^0.474.0", "path": "^0.12.7", "pnpm": "^9.15.4", "react": "^18.3.1", "react-dom": "^18.3.1", + "react-i18next": "^15.4.1", "react-router-dom": "^7.1.5", "react-typed": "^2.0.12", "styled-components": "^6.1.14" @@ -260,6 +263,17 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/runtime": { + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.9.tgz", + "integrity": "sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/template": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", @@ -2262,6 +2276,52 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, + "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/i18next": { + "version": "24.2.2", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-24.2.2.tgz", + "integrity": "sha512-NE6i86lBCKRYZa5TaUDkU5S4HFgLIEJRLr3Whf2psgaxBleQ2LC1YW1Vc+SCgkAW7VEzndT6al6+CzegSUHcTQ==", + "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" + }, + "peerDependencies": { + "typescript": "^5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/i18next-browser-languagedetector": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.0.4.tgz", + "integrity": "sha512-f3frU3pIxD50/Tz20zx9TD9HobKYg47fmAETb117GKGPrhwcSSPJDoCposXlVycVebQ9GQohC3Efbpq7/nnJ5w==", + "dependencies": { + "@babel/runtime": "^7.23.2" + } + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -2775,6 +2835,27 @@ "react": "^18.3.1" } }, + "node_modules/react-i18next": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-15.4.1.tgz", + "integrity": "sha512-ahGab+IaSgZmNPYXdV1n+OYky95TGpFwnKRflX/16dY04DsYYKHtVLjeny7sBSCREEcoMbAgSkFiGLF5g5Oofw==", + "dependencies": { + "@babel/runtime": "^7.25.0", + "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-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -2838,6 +2919,11 @@ "react": ">16.8.0" } }, + "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==" + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -3102,7 +3188,7 @@ "version": "5.7.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", - "dev": true, + "devOptional": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -3244,6 +3330,14 @@ } } }, + "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/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 31c8d7f..a318732 100644 --- a/package.json +++ b/package.json @@ -17,11 +17,14 @@ "@types/node": "^22.13.0", "dotenv": "^16.4.7", "fs": "^0.0.1-security", + "i18next": "^24.2.2", + "i18next-browser-languagedetector": "^8.0.4", "lucide-react": "^0.474.0", "path": "^0.12.7", "pnpm": "^9.15.4", "react": "^18.3.1", "react-dom": "^18.3.1", + "react-i18next": "^15.4.1", "react-router-dom": "^7.1.5", "react-typed": "^2.0.12", "styled-components": "^6.1.14" diff --git a/src/locales/en-us.json b/src/locales/en-us.json new file mode 100644 index 0000000..c970cad --- /dev/null +++ b/src/locales/en-us.json @@ -0,0 +1,3 @@ +{ + "about": "I'm Giovani, a software engineering student, interning and studying in Minas Gerais, Brazil!" +} \ No newline at end of file diff --git a/src/locales/pt-br.json b/src/locales/pt-br.json new file mode 100644 index 0000000..62a6fa1 --- /dev/null +++ b/src/locales/pt-br.json @@ -0,0 +1,3 @@ +{ + "about": "Meu nome é Giovani, estudante de engenharia de software, estagiando e estudando em Minas Gerais, Brasil!" +} \ No newline at end of file diff --git a/src/pages/about/index.tsx b/src/pages/about/index.tsx index df6b18d..965ae06 100644 --- a/src/pages/about/index.tsx +++ b/src/pages/about/index.tsx @@ -1,12 +1,15 @@ +import '../../utils/i18n' import { MainContainer } from '../../components/MainContent/styles'; import { Paragraph } from '../../components/Paragraph/styles'; +import { useTranslation } from 'react-i18next'; export default function About() { + const { t } = useTranslation(); return (

About Me

- I'm Giovani, a software engineering student, interning and studying in Minas Gerais, Brazil! + {t("about")}
); diff --git a/src/utils/i18n.ts b/src/utils/i18n.ts new file mode 100644 index 0000000..0aba4b0 --- /dev/null +++ b/src/utils/i18n.ts @@ -0,0 +1,20 @@ +import i18n from "i18next"; +import { initReactI18next } from "react-i18next"; +import LanguageDetector from "i18next-browser-languagedetector"; + +import en from "../locales/en-us.json"; +import pt from "../locales/pt-br.json"; + +i18n + .use(initReactI18next) + .use(LanguageDetector) + .init({ + resources: { + en: { translation: en }, + pt: { translation: pt }, + }, + fallbackLng: "en", + interpolation: { escapeValue: false }, + }); + +export default i18n;