feat: bilingual website (DE/EN) with language switcher
CI / TypeScript — type-check (push) Successful in 8s
CI / Publish — build & push image (push) Successful in 8s
CI / Deploy — pull & restart on host (push) Successful in 2s

Add LangContext with localStorage persistence (default: DE).
DE/EN toggle in Nav (top-right, before CTA button).

All pages translated:
- Home: all 8 sections incl. NIS2 block
- Features: all 13 sections with full German bullet points
- Drivers: headings and descriptions
- Getting Started (coming soon)
- Roadmap: bilingual data arrays inline (Planned + Under consideration)
- NIS2: full Art. 21 mapping, evidence blocks, coming-soon list

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Christian Manivong
2026-06-28 17:00:22 +02:00
co-authored by Claude Sonnet 4.6
parent f194c379e4
commit d48c7143aa
11 changed files with 1011 additions and 618 deletions
+37
View File
@@ -0,0 +1,37 @@
import { createContext, useContext, useState, useEffect, type ReactNode } from 'react'
import { translations, type Lang } from '../i18n/translations'
interface LangContextValue {
lang: Lang
setLang: (l: Lang) => void
t: typeof translations.en
}
const LangContext = createContext<LangContextValue | null>(null)
export function LangProvider({ children }: { children: ReactNode }) {
const [lang, setLangState] = useState<Lang>(() => {
const stored = localStorage.getItem('lang')
return stored === 'de' || stored === 'en' ? stored : 'de'
})
useEffect(() => {
localStorage.setItem('lang', lang)
}, [lang])
function setLang(l: Lang) {
setLangState(l)
}
return (
<LangContext.Provider value={{ lang, setLang, t: translations[lang] }}>
{children}
</LangContext.Provider>
)
}
export function useLang() {
const ctx = useContext(LangContext)
if (!ctx) throw new Error('useLang must be used inside LangProvider')
return ctx
}