diff --git a/package-lock.json b/package-lock.json
index 51b0dbc..ae63a25 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,8 +10,12 @@
"dependencies": {
"@mdi/font": "~7.4.47",
"@tailwindcss/vite": "~4.2.2",
+ "i18next": "~26.0.0",
+ "i18next-http-backend": "~3.0.2",
"react": "^19.2.4",
- "react-dom": "^19.2.4"
+ "react-dom": "^19.2.4",
+ "react-i18next": "~17.0.0",
+ "react-router-dom": "~7.13.2"
},
"devDependencies": {
"@vitejs/plugin-react": "^6.0.1",
@@ -21,6 +25,15 @@
"vite": "^8.0.1"
}
},
+ "node_modules/@babel/runtime": {
+ "version": "7.29.2",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz",
+ "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/@emnapi/core": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.1.tgz",
@@ -773,6 +786,28 @@
],
"license": "CC-BY-4.0"
},
+ "node_modules/cookie": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz",
+ "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/cross-fetch": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz",
+ "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==",
+ "license": "MIT",
+ "dependencies": {
+ "node-fetch": "^2.6.12"
+ }
+ },
"node_modules/detect-libc": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
@@ -863,6 +898,55 @@
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
"license": "ISC"
},
+ "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.0",
+ "resolved": "https://registry.npmjs.org/i18next/-/i18next-26.0.0.tgz",
+ "integrity": "sha512-+Dg27j7VH40WRy+Q010hj3jxlxDb3qFkA7EwuK4kx0+glLxEqZsxdB8MqliPBkTrXEuNlEfeosM3lucAHK+0tQ==",
+ "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",
+ "dependencies": {
+ "@babel/runtime": "^7.29.2"
+ },
+ "peerDependencies": {
+ "typescript": "^5 || ^6"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/i18next-http-backend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-3.0.2.tgz",
+ "integrity": "sha512-PdlvPnvIp4E1sYi46Ik4tBYh/v/NbYfFFgTjkwFl0is8A18s7/bx9aXqsrOax9WUbeNS6mD2oix7Z0yGGf6m5g==",
+ "license": "MIT",
+ "dependencies": {
+ "cross-fetch": "4.0.0"
+ }
+ },
"node_modules/jiti": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
@@ -1148,6 +1232,26 @@
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
+ "node_modules/node-fetch": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
+ "license": "MIT",
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
"node_modules/node-releases": {
"version": "2.0.36",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz",
@@ -1162,9 +1266,9 @@
"license": "ISC"
},
"node_modules/picomatch": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
- "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
+ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
"license": "MIT",
"engines": {
"node": ">=12"
@@ -1229,6 +1333,71 @@
"react": "^19.2.4"
}
},
+ "node_modules/react-i18next": {
+ "version": "17.0.0",
+ "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-17.0.0.tgz",
+ "integrity": "sha512-L7aqwOePCExt6nlF7000lN2YKWnR7IpSpQId9sj01798Xn3LAncBdTHKl9lA/nr+YrG78BTqWPJxq9mlrrmH7Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.29.2",
+ "html-parse-stringify": "^3.0.1",
+ "use-sync-external-store": "^1.6.0"
+ },
+ "peerDependencies": {
+ "i18next": ">= 25.10.10",
+ "react": ">= 16.8.0",
+ "typescript": "^5 || ^6"
+ },
+ "peerDependenciesMeta": {
+ "react-dom": {
+ "optional": true
+ },
+ "react-native": {
+ "optional": true
+ },
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-router": {
+ "version": "7.13.2",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.13.2.tgz",
+ "integrity": "sha512-tX1Aee+ArlKQP+NIUd7SE6Li+CiGKwQtbS+FfRxPX6Pe4vHOo6nr9d++u5cwg+Z8K/x8tP+7qLmujDtfrAoUJA==",
+ "license": "MIT",
+ "dependencies": {
+ "cookie": "^1.0.1",
+ "set-cookie-parser": "^2.6.0"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=18",
+ "react-dom": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "7.13.2",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.13.2.tgz",
+ "integrity": "sha512-aR7SUORwTqAW0JDeiWF07e9SBE9qGpByR9I8kJT5h/FrBKxPMS6TiC7rmVO+gC0q52Bx7JnjWe8Z1sR9faN4YA==",
+ "license": "MIT",
+ "dependencies": {
+ "react-router": "7.13.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=18",
+ "react-dom": ">=18"
+ }
+ },
"node_modules/rolldown": {
"version": "1.0.0-rc.10",
"resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.10.tgz",
@@ -1274,6 +1443,12 @@
"integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
"license": "MIT"
},
+ "node_modules/set-cookie-parser": {
+ "version": "2.7.2",
+ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz",
+ "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==",
+ "license": "MIT"
+ },
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
@@ -1318,6 +1493,12 @@
"url": "https://github.com/sponsors/SuperchupuDev"
}
},
+ "node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
+ "license": "MIT"
+ },
"node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
@@ -1356,6 +1537,15 @@
"browserslist": ">= 4.21.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/vite": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/vite/-/vite-8.0.1.tgz",
@@ -1432,6 +1622,31 @@
"optional": true
}
}
+ },
+ "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/webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "license": "MIT",
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
}
}
}
diff --git a/package.json b/package.json
index 100608d..ea45ce3 100644
--- a/package.json
+++ b/package.json
@@ -11,8 +11,12 @@
"dependencies": {
"@mdi/font": "~7.4.47",
"@tailwindcss/vite": "~4.2.2",
+ "i18next": "~26.0.0",
+ "i18next-http-backend": "~3.0.2",
"react": "^19.2.4",
- "react-dom": "^19.2.4"
+ "react-dom": "^19.2.4",
+ "react-i18next": "~17.0.0",
+ "react-router-dom": "~7.13.2"
},
"devDependencies": {
"@vitejs/plugin-react": "^6.0.1",
diff --git a/public/i18n/de.json b/public/i18n/de.json
new file mode 100644
index 0000000..7e36f15
--- /dev/null
+++ b/public/i18n/de.json
@@ -0,0 +1,5 @@
+{
+ "welcome": "Dein Game-Backlog unter Kontrolle",
+ "login": "Anmelden",
+ "imprint": "Impressum"
+}
\ No newline at end of file
diff --git a/public/i18n/en.json b/public/i18n/en.json
new file mode 100644
index 0000000..208f748
--- /dev/null
+++ b/public/i18n/en.json
@@ -0,0 +1,5 @@
+{
+ "welcome": "Control your game backlog",
+ "login": "Login",
+ "imprint": "Imprint"
+}
\ No newline at end of file
diff --git a/src/App.jsx b/src/App.jsx
index e10478a..16ef0ff 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -1,67 +1,95 @@
-import React from 'react';
+import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';
+import { useTranslation } from 'react-i18next';
+import { useState, useEffect } from 'react';
+
+// Placeholder components to keep the routing structure simple
+function LandingPage() {
+ const { t } = useTranslation();
+ return (
+
+
+ {t('welcome')}
+
+
+ );
+}
+
+function LoginPage() {
+ const { t } = useTranslation();
+ return (
+
+
{t('login')}
+
+ );
+}
+
+function ImprintPage() {
+ const { t } = useTranslation();
+ return (
+
+
{t('imprint')}
+
+ );
+}
function App() {
- // Array to generate the placeholder game cards
- const mockGames = [1, 2, 3];
+ const { t, i18n } = useTranslation();
+ const [isDarkMode, setIsDarkMode] = useState(true);
- return (
-
-
-
-
- To Be Played
-
-
- Dashboard
- Login
-
-
+ // Apply dark mode class to the root HTML element for Tailwind
+ useEffect(() => {
+ if (isDarkMode) {
+ document.documentElement.classList.add('dark');
+ } else {
+ document.documentElement.classList.remove('dark');
+ }
+ }, [isDarkMode]);
-
-
-
- Dein Game-Backlog unter Kontrolle.
-
-
- Willkommen bei deiner neuen Applikation. Hier werden bald deine Spiele aus dem
- game-service gelistet.
-
-
+ const toggleLanguage = () => {
+ if (i18n.language === 'de') {
+ i18n.changeLanguage('en').then(r => console.log("Changed language to en"));
+ } else {
+ i18n.changeLanguage('de').then(r => console.log("Changed language to en"));
+ }
+ };
-
- {mockGames.map((n) => {
- return (
-
-
-
+ return (
+
+
- );
- })}
-
-
+
-
- © 2026 To Be Played — Entwickelt mit React & Tailwind v4
-
-
- );
+
+
+ } />
+ } />
+ } />
+
+
+
+
+
+
+ );
}
export default App;
\ No newline at end of file
diff --git a/src/i18n.js b/src/i18n.js
new file mode 100644
index 0000000..b899a46
--- /dev/null
+++ b/src/i18n.js
@@ -0,0 +1,19 @@
+import i18n from 'i18next';
+import {initReactI18next} from 'react-i18next';
+import HttpBackend from 'i18next-http-backend';
+
+
+i18n.use(HttpBackend)
+ .use(initReactI18next)
+ .init({
+ lng: 'de',
+ fallbackLng: 'en',
+ backend: {
+ loadPath: '/i18n/{{lng}}.json',
+ },
+ interpolation: {
+ escapeValue: false
+ }
+ });
+
+export default i18n;
\ No newline at end of file
diff --git a/src/main.jsx b/src/main.jsx
index 7003646..85bc3cc 100644
--- a/src/main.jsx
+++ b/src/main.jsx
@@ -1,6 +1,7 @@
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './App.jsx';
+import './i18n';
import './style.css';
import '@mdi/font/css/materialdesignicons.css';
diff --git a/src/style.css b/src/style.css
index a461c50..ffc5adb 100644
--- a/src/style.css
+++ b/src/style.css
@@ -1 +1,3 @@
-@import "tailwindcss";
\ No newline at end of file
+@import "tailwindcss";
+
+@custom-variant dark (&:is(.dark *));
\ No newline at end of file