Translate Sidebar nav labels into 26 languages
Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 28s
CI / test-go-edu-search (push) Successful in 30s
CI / test-python-klausur (push) Failing after 2m22s
CI / test-python-agent-core (push) Successful in 19s
CI / test-nodejs-website (push) Successful in 20s

- Lernmodule, Eltern, Woerterbuch, Meet, KI-Assistent now translated
- Uses NAV_LABELS dict with fallback chain (lang → en → de)
- Fixed "nav_eltern" → shows "Eltern"/"Parents"/"Ebeveyn" etc.
- Fixed "Lernmodule" hardcoded → uses nav_lernmodule key
- Woerterbuch link now points to /vocabulary (not /vocab-worksheet)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-04-29 18:33:11 +02:00
parent 399ab88f5f
commit 8d53b1f6b9

View File

@@ -10,6 +10,20 @@ import { useAlertsB2B } from '@/lib/AlertsB2BContext'
import { useMessages } from '@/lib/MessagesContext'
import { UserMenu } from '@/components/UserMenu'
/** Sidebar navigation labels in 26 languages */
const NAV_LABELS: Record<string, Record<string, string>> = {
nav_dashboard: { de: 'Dashboard', en: 'Dashboard', tr: 'Kontrol Paneli', ar: '\u0644\u0648\u062d\u0629 \u0627\u0644\u062a\u062d\u0643\u0645', uk: '\u041f\u0430\u043d\u0435\u043b\u044c', ru: '\u041f\u0430\u043d\u0435\u043b\u044c', pl: 'Panel', fr: 'Tableau de bord', es: 'Panel', it: 'Pannello', pt: 'Painel', nl: 'Dashboard', ro: 'Panou', el: '\u03a0\u03af\u03bd\u03b1\u03ba\u03b1\u03c2', bg: '\u0422\u0430\u0431\u043b\u043e', hr: 'Pocetna', cs: 'Prehled', hu: 'Iranyitopult', sv: 'Oversikt', da: 'Oversigt', fi: 'Yleisnakuma', sk: 'Prehad', sl: 'Pregled', lt: 'Skydelis', lv: 'Panelis', et: 'Ulevaade' },
nav_lernmodule: { de: 'Lernmodule', en: 'Learning', tr: 'Ogrenme', ar: '\u0627\u0644\u062a\u0639\u0644\u0645', uk: '\u041d\u0430\u0432\u0447\u0430\u043d\u043d\u044f', ru: '\u041e\u0431\u0443\u0447\u0435\u043d\u0438\u0435', pl: 'Nauka', fr: 'Apprentissage', es: 'Aprendizaje', it: 'Apprendimento', pt: 'Aprendizagem', nl: 'Leren', ro: 'Invatare', el: '\u039c\u03ac\u03b8\u03b7\u03c3\u03b7', bg: '\u0423\u0447\u0435\u043d\u0435', hr: 'Ucenje', cs: 'Uceni', hu: 'Tanulas', sv: 'Larande', da: 'Laering', fi: 'Oppiminen', sk: 'Ucenie', sl: 'Ucenje', lt: 'Mokymasis', lv: 'Macisanas', et: 'Oppimine' },
nav_eltern: { de: 'Eltern', en: 'Parents', tr: 'Ebeveyn', ar: '\u0627\u0644\u0648\u0627\u0644\u062f\u064a\u0646', uk: '\u0411\u0430\u0442\u044c\u043a\u0438', ru: '\u0420\u043e\u0434\u0438\u0442\u0435\u043b\u0438', pl: 'Rodzice', fr: 'Parents', es: 'Padres', it: 'Genitori', pt: 'Pais', nl: 'Ouders', ro: 'Parinti', el: '\u0393\u03bf\u03bd\u03b5\u03af\u03c2', bg: '\u0420\u043e\u0434\u0438\u0442\u0435\u043b\u0438', hr: 'Roditelji', cs: 'Rodice', hu: 'Szulok', sv: 'Foraldrar', da: 'Foraeldre', fi: 'Vanhemmat', sk: 'Rodicia', sl: 'Starsi', lt: 'Tevai', lv: 'Vecaki', et: 'Vanemad' },
nav_woerterbuch: { de: 'Woerterbuch', en: 'Dictionary', tr: 'Sozluk', ar: '\u0627\u0644\u0642\u0627\u0645\u0648\u0633', uk: '\u0421\u043b\u043e\u0432\u043d\u0438\u043a', ru: '\u0421\u043b\u043e\u0432\u0430\u0440\u044c', pl: 'Slownik', fr: 'Dictionnaire', es: 'Diccionario', it: 'Dizionario', pt: 'Dicionario', nl: 'Woordenboek', ro: 'Dictionar', el: '\u039b\u03b5\u03be\u03b9\u03ba\u03cc', bg: '\u0420\u0435\u0447\u043d\u0438\u043a', hr: 'Rjecnik', cs: 'Slovnik', hu: 'Szotar', sv: 'Ordbok', da: 'Ordbog', fi: 'Sanakirja', sk: 'Slovnik', sl: 'Slovar', lt: 'Zodynas', lv: 'Vardnica', et: 'Sonaraamat' },
nav_meet: { de: 'Videokonferenz', en: 'Video Call', tr: 'Gorusme', ar: '\u0645\u0643\u0627\u0644\u0645\u0629', uk: '\u0412\u0456\u0434\u0435\u043e\u0434\u0437\u0432\u0456\u043d\u043e\u043a', ru: '\u0412\u0438\u0434\u0435\u043e\u0437\u0432\u043e\u043d\u043e\u043a', pl: 'Wideorozmowa', fr: 'Visioconference', es: 'Videollamada', it: 'Videochiamata', pt: 'Videochamada', nl: 'Videogesprek', ro: 'Videoconferinta', el: '\u0392\u03b9\u03bd\u03c4\u03b5\u03bf\u03ba\u03bb\u03ae\u03c3\u03b7', bg: '\u0412\u0438\u0434\u0435\u043e\u0440\u0430\u0437\u0433\u043e\u0432\u043e\u0440', hr: 'Videopoziv', cs: 'Videohovor', hu: 'Videohivas', sv: 'Videosamtal', da: 'Videoopkald', fi: 'Videopuhelu', sk: 'Videohovor', sl: 'Videoklic', lt: 'Vaizdo skambutis', lv: 'Videozvans', et: 'Videokoone' },
nav_companion: { de: 'KI-Assistent', en: 'AI Assistant', tr: 'Yapay Zeka', ar: '\u0645\u0633\u0627\u0639\u062f \u0630\u0643\u064a', uk: '\u0428\u0406-\u0430\u0441\u0438\u0441\u0442\u0435\u043d\u0442', ru: '\u0418\u0418-\u0430\u0441\u0441\u0438\u0441\u0442\u0435\u043d\u0442', pl: 'Asystent AI', fr: 'Assistant IA', es: 'Asistente IA', it: 'Assistente IA', pt: 'Assistente IA', nl: 'AI-assistent', ro: 'Asistent AI', el: 'AI \u0392\u03bf\u03b7\u03b8\u03cc\u03c2', bg: 'AI \u0430\u0441\u0438\u0441\u0442\u0435\u043d\u0442', hr: 'AI pomoenik', cs: 'AI asistent', hu: 'AI asszisztens', sv: 'AI-assistent', da: 'AI-assistent', fi: 'Tekoalyavustaja', sk: 'AI asistent', sl: 'AI pomoenik', lt: 'DI asistentas', lv: 'MI paligs', et: 'Tehisabiabi' },
}
function navLabel(key: string, lang: string): string {
return NAV_LABELS[key]?.[lang] || NAV_LABELS[key]?.['en'] || NAV_LABELS[key]?.['de'] || key
}
interface SidebarProps {
selectedTab?: string
onTabChange?: (tab: string) => void
@@ -17,7 +31,7 @@ interface SidebarProps {
export function Sidebar({ selectedTab = 'dashboard', onTabChange }: SidebarProps) {
const [sidebarHovered, setSidebarHovered] = useState(false)
const { t } = useLanguage()
const { t, language } = useLanguage()
const { isDark } = useTheme()
const { unreadCount } = useAlerts()
const { unreadCount: b2bUnreadCount } = useAlertsB2B()
@@ -61,7 +75,7 @@ export function Sidebar({ selectedTab = 'dashboard', onTabChange }: SidebarProps
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" />
</svg>
), showMessagesBadge: true },
{ id: 'lernmodule', labelKey: 'Lernmodule', href: '/learn', icon: (
{ id: 'lernmodule', labelKey: 'nav_lernmodule', href: '/learn', icon: (
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253" />
</svg>
@@ -71,7 +85,7 @@ export function Sidebar({ selectedTab = 'dashboard', onTabChange }: SidebarProps
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z" />
</svg>
)},
{ id: 'vokabeln', labelKey: 'nav_vokabeln', href: '/vocab-worksheet', icon: (
{ id: 'vokabeln', labelKey: 'nav_woerterbuch', href: '/vocabulary', icon: (
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" />
</svg>
@@ -109,7 +123,7 @@ export function Sidebar({ selectedTab = 'dashboard', onTabChange }: SidebarProps
if (item.href !== '/') {
router.push(item.href)
} else if (item.id === 'vokabeln') {
router.push('/vocab-worksheet')
router.push('/vocabulary')
} else if (item.id === 'meet') {
router.push('/meet')
} else if (item.id === 'alerts') {
@@ -129,7 +143,7 @@ export function Sidebar({ selectedTab = 'dashboard', onTabChange }: SidebarProps
const getActiveItem = () => {
if (pathname === '/companion') return 'companion'
if (pathname === '/meet') return 'meet'
if (pathname === '/vocab-worksheet') return 'vokabeln'
if (pathname === '/vocab-worksheet' || pathname === '/vocabulary') return 'vokabeln'
if (pathname === '/worksheet-editor') return 'worksheet-editor'
if (pathname === '/worksheet-cleanup') return 'worksheet-cleanup'
if (pathname === '/magic-help') return 'magic-help'
@@ -211,7 +225,7 @@ export function Sidebar({ selectedTab = 'dashboard', onTabChange }: SidebarProps
)}
</span>
<span className="font-medium opacity-0 group-hover:opacity-100 transition-opacity duration-300 whitespace-nowrap flex items-center gap-2">
{t(item.labelKey)}
{NAV_LABELS[item.labelKey] ? navLabel(item.labelKey, language) : t(item.labelKey)}
{item.id === 'alerts' && unreadCount > 0 && (
<span className="px-1.5 py-0.5 text-[10px] rounded-full bg-amber-500/20 text-amber-500">
{unreadCount}