Englisch als zweite Sprache fuer die oeffentlichen Seiten
Deploy / check (push) Has been cancelled
Deploy / deploy (push) Has been cancelled

Hub und Bot-Produktseite lassen sich jetzt auf Englisch umstellen. Die Wahl
haengt am Browser (Deutsch nur, wenn der Browser es will) und bleibt im
localStorage stehen.

- src/i18n.jsx: Context mit t(), tOr(), Datums- und Zahlenformat der Sprache.
  Keine Bibliothek, die Woerterbuecher werden mitgebaut — kein Nachlade-Blitzer.
- Platzhalter im %s-Stil, dieselbe Schreibweise wie in den Bot-Texten.
- Umschalter in der Navigation, zusaetzlich im Schubladen-Menue: .auth ist auf
  schmalen Schirmen ausgeblendet, sonst waere der Wechsel dort unerreichbar.
- Datums- und Zahlenformat folgen mit (31.07.2026 / 31/07/2026, 45.231 / 45,231).
- Die Funktionsliste kommt weiter deutsch vom Server; englische Modulnamen
  liegen unter feat.<id> im Woerterbuch. Fehlt einer, bleibt der Servertext
  stehen — ein neues Modul verschwindet nie von der Seite.

Das Config-Panel und die Discord-Texte bleiben deutsch.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-31 22:41:32 +02:00
co-authored by Claude Fable 5
parent 570e45fe60
commit 5360c8229f
19 changed files with 1084 additions and 329 deletions
+24 -16
View File
@@ -10,6 +10,7 @@ import Settings from './pages/Settings.jsx';
import Impressum from './pages/Impressum.jsx';
import Datenschutz from './pages/Datenschutz.jsx';
import { IconMenu, IconX } from './icons.jsx';
import { useT, LangSwitch } from './i18n.jsx';
export default function BotApp() {
const [me, setMe] = useState({ user: null, admin: false, scopes: [], loading: true });
@@ -17,6 +18,7 @@ export default function BotApp() {
const [drawer, setDrawer] = useState(false);
const [hub, setHub] = useState(null);
const location = useLocation();
const { t } = useT();
useEffect(() => { setDrawer(false); }, [location.pathname]);
@@ -43,40 +45,46 @@ export default function BotApp() {
</NavLink>
<nav className="nav-links">
<NavLink to="/features">Funktionen</NavLink>
<NavLink to="/commands">Befehle</NavLink>
{canDashboard && <NavLink to="/dashboard">Dashboard</NavLink>}
{hub && <a href={hub}>Community</a>}
<NavLink to="/features">{t('nav.features')}</NavLink>
<NavLink to="/commands">{t('nav.commands')}</NavLink>
{canDashboard && <NavLink to="/dashboard">{t('nav.dashboard')}</NavLink>}
{hub && <a href={hub}>{t('nav.community')}</a>}
</nav>
<div className="auth">
<LangSwitch />
{me.loading ? null : me.user ? (
<span className="user-chip">
{me.user.avatar && <img className="avatar" src={me.user.avatar} alt="" />}
<span className="username">{me.user.username}</span>
<a className="logout" href="/auth/logout" title="Abmelden">
<a className="logout" href="/auth/logout" title={t('nav.signOut')}>
<IconX size={13} />
</a>
</span>
) : (
<a className="btn-login" href="/auth/login">Anmelden</a>
<a className="btn-login" href="/auth/login">{t('nav.signIn')}</a>
)}
</div>
<button className="burger" onClick={() => setDrawer((d) => !d)} aria-label="Menü">
<button className="burger" onClick={() => setDrawer((d) => !d)} aria-label={t('nav.menu')}>
{drawer ? <IconX size={20} /> : <IconMenu size={20} />}
</button>
</header>
{drawer && (
<nav className="drawer" onClick={() => setDrawer(false)}>
<NavLink to="/features">Funktionen</NavLink>
<NavLink to="/commands">Befehle</NavLink>
{canDashboard && <NavLink to="/dashboard">Dashboard</NavLink>}
{hub && <a href={hub}>Community</a>}
<NavLink to="/features">{t('nav.features')}</NavLink>
<NavLink to="/commands">{t('nav.commands')}</NavLink>
{canDashboard && <NavLink to="/dashboard">{t('nav.dashboard')}</NavLink>}
{hub && <a href={hub}>{t('nav.community')}</a>}
{me.user
? <a href="/auth/logout">Abmelden</a>
: <a href="/auth/login">Anmelden</a>}
? <a href="/auth/logout">{t('nav.signOut')}</a>
: <a href="/auth/login">{t('nav.signIn')}</a>}
{/* Auf schmalen Schirmen ist .auth ausgeblendet — der
Sprachwechsel muss trotzdem erreichbar bleiben. */}
<div className="drawer-lang" onClick={(e) => e.stopPropagation()}>
<LangSwitch />
</div>
</nav>
)}
@@ -96,11 +104,11 @@ export default function BotApp() {
<span className="footer-logo">D4RKBOT<span>.</span></span>
<span className="footer-sep">//</span>
<a href="https://git.d4rkst3r.de/D4rkst3r/d4rkbot" target="_blank" rel="noreferrer">
Quellcode
{t('footer.source')}
</a>
<span className="footer-sep">//</span>
<NavLink to="/impressum">Impressum</NavLink>
<NavLink to="/datenschutz">Datenschutz</NavLink>
<NavLink to="/impressum">{t('footer.imprint')}</NavLink>
<NavLink to="/datenschutz">{t('footer.privacy')}</NavLink>
</footer>
</div>
);