feat(34-06): wire useTranslation into 10 remaining components

- ThreadTabs: tab labels (gear, planning, setups) via collection namespace
- PlanningView: section title, tab labels, empty state steps, CTAs via threads namespace
- TotalsBar: 'Sign in' link via common.auth.signIn
- ThreadCard: resolved badge and candidate count (plural) via threads namespace
- PublicSetupCard: by/anonymous and item count (plural) via setups namespace
- SetupImpactSelector: compare dropdown placeholder via setups.impact.compareWith
- ClassificationBadge: base/worn/consumable labels via collection.classificationBadge
- ImpactDeltaBadge: add mode label via setups.impact.adding
- ImageUpload: click-to-add, error messages via common.imageUpload
- DashboardCard: skipped (renders props only, no hardcoded UI strings)
- Add card, planning keys to en/de threads.json
- Add classificationBadge, tabs, totals keys to en/de collection.json
- Add card.by, card.anonymous, impact.compareWith to en/de setups.json
- Add imageUpload keys to en/de common.json
- Build passes, all 19 i18n parity tests pass
This commit is contained in:
2026-04-17 20:26:50 +02:00
parent 755c0ab89f
commit 480abdd17f
17 changed files with 133 additions and 44 deletions

View File

@@ -1,3 +1,4 @@
import { useTranslation } from "react-i18next";
import type { CandidateDelta } from "../hooks/useImpactDeltas";
interface ImpactDeltaBadgeProps {
@@ -11,6 +12,8 @@ export function ImpactDeltaBadge({
type,
formatFn,
}: ImpactDeltaBadgeProps) {
const { t } = useTranslation("setups");
if (!delta || delta.mode === "none") return null;
const value = type === "weight" ? delta.weightDelta : delta.priceDelta;
@@ -28,7 +31,7 @@ export function ImpactDeltaBadge({
<span className="text-xs text-green-600">
+{formatFn(value)}
{delta.mode === "add" && (
<span className="ml-0.5 text-green-500">(add)</span>
<span className="ml-0.5 text-green-500">({t("impact.adding")})</span>
)}
</span>
);