diff --git a/client/src/components/InvitationAcceptance.tsx b/client/src/components/InvitationAcceptance.tsx index 39f130c..d1b7c6f 100644 --- a/client/src/components/InvitationAcceptance.tsx +++ b/client/src/components/InvitationAcceptance.tsx @@ -57,8 +57,6 @@ export default function InvitationAcceptance({ onAccepted, onCancel }: Invitatio const autoAcceptStarted = useRef(false) - const isDe = i18n.language.startsWith('de') - const sessionReady = (): boolean => { return !!(getActiveMasterKey() && localStorage.getItem('active_userid')) } @@ -83,19 +81,16 @@ export default function InvitationAcceptance({ onAccepted, onCancel }: Invitatio setLogbookKey(hexToBuffer(hexKey)) } catch (err) { console.error('Invalid key in URL fragment:', err) - setError(isDe - ? 'Der Einladungslink ist kryptografisch ungültig (Schlüssel fehlerhaft).' - : 'The invitation link is cryptographically invalid (corrupted key).') + setError(t('invitation.error_invalid_key')) } } else { - setError(isDe - ? 'Der Einladungslink enthält keinen Entschlüsselungsschlüssel (#key=...). Bitte den vollständigen Link vom Eigner verwenden.' - : 'The invitation link is missing the decryption key (#key=...). Please use the complete link from the owner.') + setError(t('invitation.error_missing_key')) } const rand = Math.floor(1000 + Math.random() * 9000) setRegUsername(`CrewSkipper_${rand}`) - }, [isDe]) + // eslint-disable-next-line react-hooks/exhaustive-deps -- mount-only: URL parsing and default username + }, []) useEffect(() => { if (token && logbookKey) { @@ -110,14 +105,12 @@ export default function InvitationAcceptance({ onAccepted, onCancel }: Invitatio const res = await fetch(`/api/collaboration/invite-details?token=${token}`) if (res.status === 410) { - setError(isDe - ? 'Diese Einladung ist abgelaufen (48 Stunden gültig).' - : 'This invitation link has expired (valid for 48 hours only).') + setError(t('invitation.error_expired')) return } if (!res.ok) { - throw new Error(isDe ? 'Einladungstoken ungültig.' : 'Failed to verify invitation token.') + throw new Error(t('invitation.error_invalid_token')) } const details = await res.json() @@ -130,7 +123,7 @@ export default function InvitationAcceptance({ onAccepted, onCancel }: Invitatio setDecryptedTitle(title) } catch (err: any) { console.error('Failed to load invitation details:', err) - setError(err.message || (isDe ? 'Einladungsdetails konnten nicht geladen werden.' : 'Invitation details could not be retrieved.')) + setError(err.message || t('invitation.error_load_failed')) } finally { setLoading(false) } @@ -141,9 +134,7 @@ export default function InvitationAcceptance({ onAccepted, onCancel }: Invitatio const activeUserId = localStorage.getItem('active_userid') if (!masterKey || !activeUserId) { autoAcceptStarted.current = false - setError(isDe - ? 'Sitzung unvollständig — bitte erneut anmelden (Benutzer-ID fehlt).' - : 'Incomplete session — please log in again (user ID missing).') + setError(t('invitation.error_incomplete_session')) setIsLoggedIn(false) return } @@ -194,12 +185,12 @@ export default function InvitationAcceptance({ onAccepted, onCancel }: Invitatio onAccepted(logbookId, decryptedTitle) } catch (err: any) { console.error('Accepting invitation failed:', err) - setError(err.message || (isDe ? 'Beitritt fehlgeschlagen.' : 'Acceptance failed.')) + setError(err.message || t('invitation.error_accept_failed')) autoAcceptStarted.current = false } finally { setAccepting(false) } - }, [logbookId, logbookKey, token, rawEncryptedTitle, decryptedTitle, onAccepted, isDe]) + }, [logbookId, logbookKey, token, rawEncryptedTitle, decryptedTitle, onAccepted, t]) useEffect(() => { if (loading || accepting || autoAcceptStarted.current) return @@ -235,7 +226,7 @@ export default function InvitationAcceptance({ onAccepted, onCancel }: Invitatio if (resolvedUser) setUsername(resolvedUser) setShowRecoveryFallback(true) } catch (err: any) { - setAuthError(err.message || (isDe ? 'Passkey-Anmeldung fehlgeschlagen.' : 'Passkey authentication failed.')) + setAuthError(err.message || t('invitation.error_login_failed')) } finally { setLoading(false) } @@ -247,9 +238,7 @@ export default function InvitationAcceptance({ onAccepted, onCancel }: Invitatio const resolvedUser = (username.trim() || encryptedPayloads.username || '').trim() if (!resolvedUser) { - setAuthError(isDe - ? 'Benutzername konnte nicht ermittelt werden — bitte erneut anmelden.' - : 'Could not determine username — please try logging in again.') + setAuthError(t('invitation.error_username_missing')) return } @@ -285,7 +274,7 @@ export default function InvitationAcceptance({ onAccepted, onCancel }: Invitatio setRecoveryPhrase(result.recoveryPhrase) } } catch (err: any) { - setAuthError(err.message || (isDe ? 'Registrierung fehlgeschlagen.' : 'Registration failed.')) + setAuthError(err.message || t('invitation.error_register_failed')) } finally { setLoading(false) } @@ -344,7 +333,7 @@ export default function InvitationAcceptance({ onAccepted, onCancel }: Invitatio />