feat: Wabenhain Honig-Shop Anwendung
Vollstaendige Next.js/Prisma-E-Commerce-Anwendung fuer eine Imkerei: Shop, Warenkorb, Stripe-Checkout, Kundenkonto mit 2FA, Admin-Bereich (Produkte, Ernten, Chargen, Bestellungen, Gutscheine, admin-editierbare Website-Inhalte), i18n (DE/EN), Rate-Limiting/CSP/Audit-Log-Haertung, PostgreSQL- und MySQL-Unterstuetzung ueber austauschbare Prisma- Treiber-Adapter, Unit-/Komponenten-/E2E-Tests.
This commit is contained in:
1 parent
5c76fcc266
commit
c7927f2883
240 files changed
+26096
-137
No files matched your search
@@ -0,0 +1,50 @@
|
||||
"use client";
|
||||
|
||||
import { useTransition } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { locales, localeLabels, type Locale } from "@/i18n/config";
|
||||
import { setLocaleAction } from "@/i18n/actions";
|
||||
import { useI18n } from "@/i18n/i18n-provider";
|
||||
|
||||
/**
|
||||
* Iteriert ueber locales aus i18n/config.ts statt DE/EN fest zu verdrahten —
|
||||
* eine dritte Sprache erscheint hier automatisch, sobald sie dort ergaenzt
|
||||
* wird, ohne diese Komponente anzufassen.
|
||||
*/
|
||||
export function LanguageSwitcher({ className = "" }: { className?: string }) {
|
||||
const { locale } = useI18n();
|
||||
const router = useRouter();
|
||||
const [isPending, startTransition] = useTransition();
|
||||
|
||||
function handleChange(next: Locale) {
|
||||
if (next === locale || isPending) return;
|
||||
startTransition(async () => {
|
||||
const formData = new FormData();
|
||||
formData.set("locale", next);
|
||||
await setLocaleAction(formData);
|
||||
router.refresh();
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`flex items-center gap-1 text-xs ${className}`} role="group" aria-label="Sprache wählen / Choose language">
|
||||
{locales.map((code, i) => (
|
||||
<span key={code} className="flex items-center">
|
||||
{i > 0 ? <span className="text-ink/30 mx-1" aria-hidden="true">/</span> : null}
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleChange(code)}
|
||||
disabled={isPending}
|
||||
aria-current={code === locale}
|
||||
title={localeLabels[code]}
|
||||
className={`uppercase tracking-wide transition-colors disabled:opacity-50 ${
|
||||
code === locale ? "text-forest font-medium" : "text-ink/50 hover:text-forest"
|
||||
}`}
|
||||
>
|
||||
{code}
|
||||
</button>
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user