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
+9 -8
View File
@@ -1,4 +1,6 @@
"use client";
import { useI18n } from "@/components/i18n";
import { useCallback, useRef, useState } from "react";
import { ChevronRightIcon } from "lucide-react";
@@ -50,6 +52,7 @@ export interface PracticeDockProps {
}
export function PracticeDock({ problemCallId, input, expanded, onExpand, onSubmit, onEscape, compactionRunning = false }: PracticeDockProps) {
const { t } = useI18n();
const [thinking, setThinking] = useState("");
// Ref MIRRORS the field ("nothing gets lost", the question-dock
// discipline): a submit resuming after `await finishDictation()` reads
@@ -93,7 +96,7 @@ export function PracticeDock({ problemCallId, input, expanded, onExpand, onSubmi
className="flex w-full cursor-pointer items-center gap-2 px-4 py-3 text-left text-sm text-muted-foreground transition-colors hover:text-foreground"
>
<ChevronRightIcon className="size-4 shrink-0 rotate-90" />
<span className="font-medium">Problem</span>
<span className="font-medium">{t("Problem")}</span>
<span className="min-w-0 flex-1 truncate">{input.statement}</span>
</button>
);
@@ -107,7 +110,7 @@ export function PracticeDock({ problemCallId, input, expanded, onExpand, onSubmi
markdown + LaTeX rendered, capped by the measured column
(--dock-max-h; the old fixed 40vh cut long problems short). */}
<div className="max-h-[var(--dock-max-h,40vh)] overflow-y-auto px-4 pt-3 pb-2">
<div className="mb-1 text-xs font-medium uppercase tracking-wide text-muted-foreground">Problem</div>
<div className="mb-1 text-xs font-medium uppercase tracking-wide text-muted-foreground">{t("Problem")}</div>
<div className="lh-prose text-[15px]">
<MessageResponse>{typeof input.statement === "string" ? repairMathForDisplay(input.statement) : input.statement}</MessageResponse>
</div>
@@ -120,8 +123,7 @@ export function PracticeDock({ problemCallId, input, expanded, onExpand, onSubmi
className="m-1.5 rounded-[10px] border border-border/70 bg-background/60 transition-colors focus-within:border-primary/50"
>
<div className="px-2.5 pt-2 text-xs font-medium uppercase tracking-wide text-muted-foreground">
YOUR THINKING
</div>
{t("YOUR THINKING")}</div>
<textarea
value={thinking}
onChange={(e) => {
@@ -144,7 +146,7 @@ export function PracticeDock({ problemCallId, input, expanded, onExpand, onSubmi
submit();
}
}}
placeholder="Work here, think out loud."
placeholder={t("Work here, think out loud.")}
rows={4}
className={cn(
"field-sizing-content lh-input max-h-64 min-h-16 w-full resize-none bg-transparent px-2.5 pb-2 outline-none placeholder:text-muted-foreground",
@@ -156,7 +158,7 @@ export function PracticeDock({ problemCallId, input, expanded, onExpand, onSubmi
field 10 − p-1 (4) = button 6. */}
<div className="flex items-center justify-between gap-2 p-1">
<span aria-hidden className="pl-1.5 text-xs text-muted-foreground">
{compactionRunning ? "compacting session…" : "↵ submits · ⇧↵ newline"}
{compactionRunning ? t("compacting session…") : t("↵ submits · ⇧↵ newline")}
</span>
<Button
type="button"
@@ -165,8 +167,7 @@ export function PracticeDock({ problemCallId, input, expanded, onExpand, onSubmi
onClick={() => submit()}
className="ml-auto h-9 rounded-[6px] px-3.5 text-sm font-medium"
>
Submit thinking
</Button>
{t("Submit thinking")}</Button>
</div>
</div>
</div>