This repository has been archived on 2026-02-15. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
BreakPilot Dev 19855efacc
Some checks failed
Tests / Go Tests (push) Has been cancelled
Tests / Python Tests (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / Go Lint (push) Has been cancelled
Tests / Python Lint (push) Has been cancelled
Tests / Security Scan (push) Has been cancelled
Tests / All Checks Passed (push) Has been cancelled
Security Scanning / Secret Scanning (push) Has been cancelled
Security Scanning / Dependency Vulnerability Scan (push) Has been cancelled
Security Scanning / Go Security Scan (push) Has been cancelled
Security Scanning / Python Security Scan (push) Has been cancelled
Security Scanning / Node.js Security Scan (push) Has been cancelled
Security Scanning / Docker Image Security (push) Has been cancelled
Security Scanning / Security Summary (push) Has been cancelled
CI/CD Pipeline / Go Tests (push) Has been cancelled
CI/CD Pipeline / Python Tests (push) Has been cancelled
CI/CD Pipeline / Website Tests (push) Has been cancelled
CI/CD Pipeline / Linting (push) Has been cancelled
CI/CD Pipeline / Security Scan (push) Has been cancelled
CI/CD Pipeline / Docker Build & Push (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Deploy to Staging (push) Has been cancelled
CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / CI Summary (push) Has been cancelled
ci/woodpecker/manual/build-ci-image Pipeline was successful
ci/woodpecker/manual/main Pipeline failed
feat: BreakPilot PWA - Full codebase (clean push without large binaries)
All services: admin-v2, studio-v2, website, ai-compliance-sdk,
consent-service, klausur-service, voice-service, and infrastructure.
Large PDFs and compiled binaries excluded via .gitignore.
2026-02-11 13:25:58 +01:00

110 lines
2.9 KiB
TypeScript

'use client'
/**
* LanguageSwitch Component
*
* Toggle button for switching between German and English terminology.
* Stores preference in localStorage.
*/
import { useState, useEffect } from 'react'
import { Language, DEFAULT_LANGUAGE } from '@/lib/compliance-i18n'
interface LanguageSwitchProps {
onChange?: (lang: Language) => void
className?: string
}
const STORAGE_KEY = 'breakpilot-compliance-lang'
export default function LanguageSwitch({ onChange, className = '' }: LanguageSwitchProps) {
const [language, setLanguage] = useState<Language>(DEFAULT_LANGUAGE)
const [mounted, setMounted] = useState(false)
// Load language from localStorage on mount
useEffect(() => {
setMounted(true)
const stored = localStorage.getItem(STORAGE_KEY) as Language | null
if (stored && (stored === 'de' || stored === 'en')) {
setLanguage(stored)
onChange?.(stored)
}
}, [onChange])
const toggleLanguage = () => {
const newLang: Language = language === 'de' ? 'en' : 'de'
setLanguage(newLang)
localStorage.setItem(STORAGE_KEY, newLang)
onChange?.(newLang)
}
// Avoid hydration mismatch
if (!mounted) {
return (
<div className={`h-8 w-16 bg-slate-100 rounded-full animate-pulse ${className}`} />
)
}
return (
<button
onClick={toggleLanguage}
className={`
relative inline-flex items-center h-8 px-1
bg-slate-100 hover:bg-slate-200
rounded-full transition-colors
focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2
${className}
`}
title={language === 'de' ? 'Switch to English' : 'Zu Deutsch wechseln'}
aria-label={language === 'de' ? 'Switch to English' : 'Zu Deutsch wechseln'}
>
{/* DE Button */}
<span
className={`
px-2 py-1 text-xs font-semibold rounded-full transition-all
${language === 'de'
? 'bg-white text-slate-900 shadow-sm'
: 'text-slate-500 hover:text-slate-700'
}
`}
>
DE
</span>
{/* EN Button */}
<span
className={`
px-2 py-1 text-xs font-semibold rounded-full transition-all
${language === 'en'
? 'bg-white text-slate-900 shadow-sm'
: 'text-slate-500 hover:text-slate-700'
}
`}
>
EN
</span>
</button>
)
}
/**
* Hook to get and set compliance language
*/
export function useComplianceLanguage(): [Language, (lang: Language) => void] {
const [language, setLanguage] = useState<Language>(DEFAULT_LANGUAGE)
useEffect(() => {
const stored = localStorage.getItem(STORAGE_KEY) as Language | null
if (stored && (stored === 'de' || stored === 'en')) {
setLanguage(stored)
}
}, [])
const setAndStore = (lang: Language) => {
setLanguage(lang)
localStorage.setItem(STORAGE_KEY, lang)
}
return [language, setAndStore]
}