fix(i18n): update consent banner on locale switch

Use next-intl translations instead of reading NEXT_LOCALE cookie once, so banner text updates immediately when switching languages.

fix(activity-feed): make loading UI match dark theme

Avoid the white loading card on hard reload by using the same dark styling as the normal feed.

Co-authored-by: dennis <dennis@konkol.net>
This commit is contained in:
Cursor Agent
2026-01-14 16:00:05 +00:00
parent e115a23485
commit 9082bd256a
2 changed files with 17 additions and 38 deletions

View File

@@ -1553,16 +1553,16 @@ export default function ActivityFeed() {
<motion.div
initial={false}
animate={{ scale: 1, opacity: 1 }}
className="pointer-events-auto bg-white/80 backdrop-blur-2xl border border-white/60 rounded-2xl shadow-xl overflow-hidden w-full"
className="pointer-events-auto bg-black/95 backdrop-blur-2xl border border-white/10 rounded-2xl shadow-2xl overflow-hidden w-full"
>
<div className="w-full px-4 py-3 flex items-center justify-between">
<div className="flex items-center gap-3">
<div className="relative">
<Activity size={18} className="text-stone-900" />
<Activity size={18} className="text-white" />
</div>
<div className="text-left">
<h3 className="text-sm font-bold text-stone-900">Live Activity</h3>
<p className="text-[10px] text-stone-500">Loading...</p>
<h3 className="text-sm font-bold text-white">Live Activity</h3>
<p className="text-[10px] text-white/50">Loading...</p>
</div>
</div>
<div className="flex items-center gap-2"></div>

View File

@@ -1,49 +1,28 @@
"use client";
import React, { useMemo, useState } from "react";
import React, { useState } from "react";
import { useConsent, type ConsentState } from "./ConsentProvider";
import { useTranslations } from "next-intl";
export default function ConsentBanner() {
const { consent, setConsent } = useConsent();
const [draft, setDraft] = useState<ConsentState>({ analytics: false, chat: false });
const [minimized, setMinimized] = useState(false);
const locale = useMemo(() => {
if (typeof document === "undefined") return "en";
const match = document.cookie
.split(";")
.map((c) => c.trim())
.find((c) => c.startsWith("NEXT_LOCALE="));
if (!match) return "en";
return decodeURIComponent(match.split("=").slice(1).join("=")) || "en";
}, []);
const t = useTranslations("consent");
const shouldShow = consent === null;
if (!shouldShow) return null;
const s = locale === "de"
? {
title: "Datenschutz-Einstellungen",
description:
"Wir nutzen optionale Dienste (Analytics und Chat), um die Seite zu verbessern. Du kannst deine Auswahl jederzeit ändern.",
essential: "Essentiell",
analytics: "Analytics",
chat: "Chatbot",
acceptAll: "Alles akzeptieren",
acceptSelected: "Auswahl akzeptieren",
rejectAll: "Alles ablehnen",
}
: {
title: "Privacy settings",
description:
"We use optional services (analytics and chat) to improve the site. You can change your choice anytime.",
essential: "Essential",
analytics: "Analytics",
chat: "Chatbot",
acceptAll: "Accept all",
acceptSelected: "Accept selected",
rejectAll: "Reject all",
};
const s = {
title: t("title"),
description: t("description"),
essential: t("essential"),
analytics: t("analytics"),
chat: t("chat"),
acceptAll: t("acceptAll"),
acceptSelected: t("acceptSelected"),
rejectAll: t("rejectAll"),
};
if (minimized) {
return (