feat: add multilingual dictation and simplify chat STT picker

This commit is contained in:
2026-10-26 00:58:25 +03:00
parent 1c6ae6b2e2
commit bdd7d5e866
10 changed files with 140 additions and 40 deletions
+6 -1
View File
@@ -2,9 +2,11 @@
import en from "./locales/en.json";
import ru from "./locales/ru.json";
export type Language = "en" | "ru";
export type SttLanguage = Language | "multi";
export type TranslationParams = Record<string, string | number | null | undefined>;
export type Translator = (message: string | null | undefined, params?: TranslationParams) => string;
export function isLanguage(value: unknown): value is Language { return value === "en" || value === "ru"; }
export function isSttLanguage(value: unknown): value is SttLanguage { return isLanguage(value) || value === "multi"; }
/** The preferred system language wins; unsupported preferences resolve to English. */
export function systemLanguage(languages: string | readonly string[] | null | undefined): Language {
@@ -20,6 +22,9 @@ export function systemLanguage(languages: string | readonly string[] | null | un
export function resolveLanguage(preference: unknown, system?: string | readonly string[] | null): Language {
return isLanguage(preference) ? preference : systemLanguage(system);
}
export function resolveSttLanguage(preference: unknown, system?: string | readonly string[] | null): SttLanguage {
return isSttLanguage(preference) ? preference : systemLanguage(system);
}
export function localeTag(language: Language): string { return language === "ru" ? "ru-RU" : "en-US"; }
type Entry = string | Partial<Record<Intl.LDMLPluralRule, string>>;
@@ -58,7 +63,7 @@ export function learningLanguageInstruction(language: Language): string {
: "LANGUAGE: Use English for all learner-facing content, including teaching, questions and choices, plans, titles, practice, research summaries, knowledge-graph propositions, and text in generated diagrams, figures and demos. Preserve code, notation, identifiers, proper names and quoted source text. Follow an explicit learner request for a different language or a language-learning exercise when necessary.";
}
/** Streaming configuration: the language is pinned once at recording start, including reconnects. */
export function dictationUrl(language: Language): string {
export function dictationUrl(language: SttLanguage): string {
const params = new URLSearchParams({ model: "nova-3", language, encoding: "linear16", sample_rate: "16000", channels: "1", smart_format: "true", punctuate: "true", endpointing: "300" });
return `wss://api.deepgram.com/v1/listen?${params}`;
}