feat: add Russian localization and independent STT languages
CI / Typecheck, tests, lint (push) Canceled after 0s
CI / Standalone (mac-arm64) (push) Canceled after 0s
CI / Standalone (linux-x64) (push) Canceled after 0s
CI / Standalone (windows-x64) (push) Canceled after 0s

This commit is contained in:
2026-10-25 17:18:44 +03:00
parent b277ee3e0f
commit a50ca4b867
93 changed files with 3261 additions and 904 deletions
+16 -14
View File
@@ -1,4 +1,6 @@
"use client";
import { useI18n } from "@/components/i18n";
import { createContext, useContext, useEffect, useMemo, useRef, useState } from "react";
import { MaximizeIcon, MinusIcon, PlusIcon, XIcon } from "lucide-react";
@@ -83,6 +85,7 @@ export function MermaidOverlay({
inverted?: boolean;
onClose: () => void;
}) {
const { t } = useI18n();
// ── chart render (own instance, own ids); figure mode uses the raw svg ──
const [svg, setSvg] = useState<string | null>(rawSvg ?? null);
const [error, setError] = useState<string | null>(null);
@@ -218,16 +221,16 @@ export function MermaidOverlay({
className="absolute inset-0 z-40 flex flex-col bg-background/80 p-4 backdrop-blur-sm"
role="dialog"
aria-modal="true"
aria-label="Diagram focus"
aria-label={t("Diagram focus")}
>
<div className="mb-2 flex items-center gap-2">
<span className="text-sm font-medium">Diagram</span>
<span className="text-xs text-muted-foreground">from this lesson</span>
<Hint label="Close" binding="escape" side="left">
<span className="text-sm font-medium">{t("Diagram")}</span>
<span className="text-xs text-muted-foreground">{t("from this lesson")}</span>
<Hint label={t("Close")} binding="escape" side="left">
<button
type="button"
onClick={onClose}
aria-label="Close"
aria-label={t("Close")}
data-testid="mermaid-overlay-close"
className="ml-auto rounded-lg p-1.5 text-muted-foreground transition-colors hover:bg-accent hover:text-foreground"
>
@@ -287,32 +290,32 @@ export function MermaidOverlay({
/>
</div>
<div className="pointer-events-none absolute inset-x-0 bottom-0 flex items-end justify-between p-2">
<span className="text-xs text-muted-foreground/60">Drag to pan · scroll to zoom</span>
<span className="text-xs text-muted-foreground/60">{t("Drag to pan · scroll to zoom")}</span>
<div className="flex gap-1">
<Hint label="Zoom out" side="bottom">
<Hint label={t("Zoom out")} side="bottom">
<button
type="button"
aria-label="Zoom out"
aria-label={t("Zoom out")}
onClick={() => stepZoom(1 / 1.25)}
className="pointer-events-auto flex size-7 items-center justify-center rounded-md border border-border/70 bg-card/80 text-muted-foreground backdrop-blur transition-colors hover:bg-accent hover:text-foreground"
>
<MinusIcon className="size-3.5" />
</button>
</Hint>
<Hint label="Fit diagram to view" side="bottom">
<Hint label={t("Fit diagram to view")} side="bottom">
<button
type="button"
aria-label="Fit diagram to view"
aria-label={t("Fit diagram to view")}
onClick={fitView}
className="pointer-events-auto flex size-7 items-center justify-center rounded-md border border-border/70 bg-card/80 text-muted-foreground backdrop-blur transition-colors hover:bg-accent hover:text-foreground"
>
<MaximizeIcon className="size-3.5" />
</button>
</Hint>
<Hint label="Zoom in" side="bottom">
<Hint label={t("Zoom in")} side="bottom">
<button
type="button"
aria-label="Zoom in"
aria-label={t("Zoom in")}
onClick={() => stepZoom(1.25)}
className="pointer-events-auto flex size-7 items-center justify-center rounded-md border border-border/70 bg-card/80 text-muted-foreground backdrop-blur transition-colors hover:bg-accent hover:text-foreground"
>
@@ -325,8 +328,7 @@ export function MermaidOverlay({
) : (
<div className="flex h-full items-center justify-center gap-2 text-sm text-muted-foreground">
<span className="inline-block size-4 animate-spin rounded-full border border-current border-b-2" />
Rendering diagram…
</div>
{t("Rendering diagram…")}</div>
)}
</div>
</div>