diff --git a/package.json b/package.json index 559a84f..a1b983e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "redlight", "private": true, - "version": "1.0.0", + "version": "1.0.1", "type": "module", "scripts": { "dev": "concurrently -n client,server -c blue,green \"vite\" \"node --watch server/index.js\"", diff --git a/src/App.jsx b/src/App.jsx index e26924e..29674ab 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,5 +1,7 @@ +import { useEffect } from 'react'; import { Routes, Route, Navigate } from 'react-router-dom'; import { useAuth } from './contexts/AuthContext'; +import { useLanguage } from './contexts/LanguageContext'; import Layout from './components/Layout'; import ProtectedRoute from './components/ProtectedRoute'; import Home from './pages/Home'; @@ -13,6 +15,14 @@ import GuestJoin from './pages/GuestJoin'; export default function App() { const { user, loading } = useAuth(); + const { setLanguage } = useLanguage(); + + // Sync language from server when user loads + useEffect(() => { + if (user?.language) { + setLanguage(user.language); + } + }, [user?.language, setLanguage]); if (loading) { return ( diff --git a/src/i18n/de.json b/src/i18n/de.json index 21aacb6..9f8e411 100644 --- a/src/i18n/de.json +++ b/src/i18n/de.json @@ -157,7 +157,34 @@ "joinFailed": "Beitritt fehlgeschlagen", "endConfirm": "Meeting wirklich beenden?", "enterAccessCode": "Zugangscode eingeben:", - "notFound": "Raum nicht gefunden" + "notFound": "Raum nicht gefunden", + "guestAccessTitle": "Gastzugang", + "guestAccess": "Gastzugang aktivieren", + "guestAccessHint": "Ermöglicht nicht angemeldeten Benutzern, dem Meeting beizutreten.", + "moderatorCode": "Moderator-Code", + "moderatorCodeHint": "Optionaler Code für Moderator-Rechte", + "moderatorCodeDesc": "Gäste, die diesen Code eingeben, erhalten Moderator-Rechte.", + "guestLink": "Gast-Einladungslink", + "guestLinkCopied": "Gast-Link kopiert!", + "guestJoinTitle": "Meeting beitreten", + "guestCreatedBy": "Erstellt von", + "guestMeetingRunning": "Meeting läuft", + "guestMeetingNotStarted": "Noch nicht gestartet", + "guestYourName": "Ihr Name", + "guestNamePlaceholder": "Max Mustermann", + "guestAccessCode": "Zugangscode", + "guestAccessCodePlaceholder": "Code eingeben", + "guestModeratorCode": "Moderator-Code", + "guestModeratorOptional": "(optional)", + "guestModeratorPlaceholder": "Nur wenn Sie Moderator sind", + "guestJoinButton": "Meeting beitreten", + "guestWaitingMessage": "Das Meeting wurde noch nicht gestartet. Bitte warten Sie, bis der Moderator es startet.", + "guestAccessDenied": "Zugang nicht möglich", + "guestNameRequired": "Name ist erforderlich", + "guestJoinFailed": "Beitritt fehlgeschlagen", + "guestHasAccount": "Haben Sie ein Konto?", + "guestSignIn": "Anmelden", + "guestRoomNotFound": "Raum nicht gefunden" }, "recordings": { "title": "Aufnahmen", diff --git a/src/i18n/en.json b/src/i18n/en.json index 0dd55d3..6bc541b 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -157,7 +157,34 @@ "joinFailed": "Join failed", "endConfirm": "Really end meeting?", "enterAccessCode": "Enter access code:", - "notFound": "Room not found" + "notFound": "Room not found", + "guestAccessTitle": "Guest Access", + "guestAccess": "Enable guest access", + "guestAccessHint": "Allows unauthenticated users to join the meeting.", + "moderatorCode": "Moderator Code", + "moderatorCodeHint": "Optional code for moderator rights", + "moderatorCodeDesc": "Guests who enter this code will receive moderator rights.", + "guestLink": "Guest Invite Link", + "guestLinkCopied": "Guest link copied!", + "guestJoinTitle": "Join Meeting", + "guestCreatedBy": "Created by", + "guestMeetingRunning": "Meeting in progress", + "guestMeetingNotStarted": "Not started yet", + "guestYourName": "Your Name", + "guestNamePlaceholder": "John Doe", + "guestAccessCode": "Access Code", + "guestAccessCodePlaceholder": "Enter code", + "guestModeratorCode": "Moderator Code", + "guestModeratorOptional": "(optional)", + "guestModeratorPlaceholder": "Only if you are a moderator", + "guestJoinButton": "Join meeting", + "guestWaitingMessage": "The meeting has not started yet. Please wait for the moderator to start it.", + "guestAccessDenied": "Access denied", + "guestNameRequired": "Name is required", + "guestJoinFailed": "Join failed", + "guestHasAccount": "Have an account?", + "guestSignIn": "Sign in", + "guestRoomNotFound": "Room not found" }, "recordings": { "title": "Recordings", diff --git a/src/pages/GuestJoin.jsx b/src/pages/GuestJoin.jsx index fd1b1bc..694ed7f 100644 --- a/src/pages/GuestJoin.jsx +++ b/src/pages/GuestJoin.jsx @@ -3,9 +3,11 @@ import { useParams, Link } from 'react-router-dom'; import { Video, User, Lock, Shield, ArrowRight, Loader2, Users, Radio } from 'lucide-react'; import api from '../services/api'; import toast from 'react-hot-toast'; +import { useLanguage } from '../contexts/LanguageContext'; export default function GuestJoin() { const { uid } = useParams(); + const { t } = useLanguage(); const [roomInfo, setRoomInfo] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); @@ -22,7 +24,7 @@ export default function GuestJoin() { setRoomInfo(res.data.room); setStatus({ running: res.data.running }); } catch (err) { - setError(err.response?.data?.error || 'Raum nicht gefunden'); + setError(err.response?.data?.error || t('room.guestRoomNotFound')); } finally { setLoading(false); } @@ -44,7 +46,7 @@ export default function GuestJoin() { const handleJoin = async (e) => { e.preventDefault(); if (!name.trim()) { - toast.error('Name ist erforderlich'); + toast.error(t('room.guestNameRequired')); return; } @@ -59,7 +61,7 @@ export default function GuestJoin() { window.location.href = res.data.joinUrl; } } catch (err) { - toast.error(err.response?.data?.error || 'Beitritt fehlgeschlagen'); + toast.error(err.response?.data?.error || t('room.guestJoinFailed')); } finally { setJoining(false); } @@ -87,10 +89,10 @@ export default function GuestJoin() {
{error}
- Zum Login + {t('auth.login')} @@ -124,7 +126,7 @@ export default function GuestJoin() {- Erstellt von {roomInfo.owner_name} + {t('room.guestCreatedBy')} {roomInfo.owner_name}