feat(i18n): full app + docs localization (de/en)
Build & Push Docker Image / build (push) Successful in 2m33s

- translate remaining pages/components (admin, analytics, redundancy,
  trash, compare, browse, watchlist, admin tools tab, category combobox,
  theme toggle, tool preview card, tool-new/edit) to t() calls
- locales: 453 keys each, parity verified
- docs: bilingual handbook + release notes via *.en.md variants,
  language-aware docs.tsx (markdown paths, nav titles, search index),
  LanguageSwitcher in docs header
- generate-docs: emit per-locale handbook/release/search output,
  localized index.json fields (fileEn/titleEn), en-aware snapshots
This commit is contained in:
opencode
2026-08-04 08:35:05 +02:00
parent a65e2eb92c
commit 3de59ccaaf
77 changed files with 3786 additions and 440 deletions
@@ -1,4 +1,5 @@
import { Link } from "wouter";
import { useTranslation } from "react-i18next";
import type { ToolWithStats } from "@workspace/api-client-react";
import { Badge } from "@/components/ui/badge";
@@ -6,6 +7,7 @@ import { RatingStars } from "@/components/rating-stars";
import { MiniBars } from "@/components/mini-bars";
export function ToolPreviewCard({ tool }: { tool: ToolWithStats }) {
const { t } = useTranslation();
return (
<div className="space-y-3">
<div>
@@ -22,7 +24,7 @@ export function ToolPreviewCard({ tool }: { tool: ToolWithStats }) {
<div className="space-y-1.5">
<div className="flex items-center justify-between text-xs">
<span className="text-muted-foreground">{tool.ratingCount} review{tool.ratingCount === 1 ? "" : "s"}</span>
<span className="text-muted-foreground">{t("browse.reviewCount", { count: tool.ratingCount })}</span>
<span className="font-semibold tabular-nums">
{tool.avgCombined != null ? tool.avgCombined.toFixed(1) : ""}/5
</span>
@@ -47,8 +49,7 @@ export function ToolPreviewCard({ tool }: { tool: ToolWithStats }) {
href={`/tools/${tool.id}`}
className="block w-full rounded-md border border-primary/40 bg-primary/5 px-3 py-1.5 text-center text-xs font-medium text-primary hover:bg-primary/10"
>
View details
</Link>
</div>
{t("common.viewDetails")}
</Link> </div>
);
}