Merge pull request #36 from cjpais/segudev-translate-to-english-setting
Add Translate to English Setting
This commit is contained in:
commit
7b3746e142
10 changed files with 77 additions and 7 deletions
|
|
@ -175,6 +175,7 @@ pub fn run() {
|
||||||
shortcut::reset_binding,
|
shortcut::reset_binding,
|
||||||
shortcut::change_ptt_setting,
|
shortcut::change_ptt_setting,
|
||||||
shortcut::change_audio_feedback_setting,
|
shortcut::change_audio_feedback_setting,
|
||||||
|
shortcut::change_translate_to_english_setting,
|
||||||
trigger_update_check,
|
trigger_update_check,
|
||||||
commands::models::get_available_models,
|
commands::models::get_available_models,
|
||||||
commands::models::get_model_info,
|
commands::models::get_model_info,
|
||||||
|
|
|
||||||
|
|
@ -173,6 +173,9 @@ impl TranscriptionManager {
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
// Get current settings to check translation preference
|
||||||
|
let settings = get_settings(&self.app_handle);
|
||||||
|
|
||||||
// Initialize parameters
|
// Initialize parameters
|
||||||
let mut params = FullParams::new(SamplingStrategy::default());
|
let mut params = FullParams::new(SamplingStrategy::default());
|
||||||
params.set_language(Some("auto"));
|
params.set_language(Some("auto"));
|
||||||
|
|
@ -183,6 +186,11 @@ impl TranscriptionManager {
|
||||||
params.set_suppress_blank(true);
|
params.set_suppress_blank(true);
|
||||||
params.set_suppress_non_speech_tokens(true);
|
params.set_suppress_non_speech_tokens(true);
|
||||||
|
|
||||||
|
// Enable translation to English if requested
|
||||||
|
if settings.translate_to_english {
|
||||||
|
params.set_translate(true);
|
||||||
|
}
|
||||||
|
|
||||||
state
|
state
|
||||||
.full(params, &audio)
|
.full(params, &audio)
|
||||||
.expect("failed to convert samples");
|
.expect("failed to convert samples");
|
||||||
|
|
@ -199,7 +207,12 @@ impl TranscriptionManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
let et = std::time::Instant::now();
|
let et = std::time::Instant::now();
|
||||||
println!("\ntook {}ms", (et - st).as_millis());
|
let translation_note = if settings.translate_to_english {
|
||||||
|
" (translated)"
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
};
|
||||||
|
println!("\ntook {}ms{}", (et - st).as_millis(), translation_note);
|
||||||
|
|
||||||
Ok(result.trim().to_string())
|
Ok(result.trim().to_string())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@ pub struct AppSettings {
|
||||||
pub selected_microphone: Option<String>,
|
pub selected_microphone: Option<String>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub selected_output_device: Option<String>,
|
pub selected_output_device: Option<String>,
|
||||||
|
#[serde(default = "default_translate_to_english")]
|
||||||
|
pub translate_to_english: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_model() -> String {
|
fn default_model() -> String {
|
||||||
|
|
@ -40,6 +42,11 @@ fn default_always_on_microphone() -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn default_translate_to_english() -> bool {
|
||||||
|
// Default to false - users need to opt-in to translation
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
pub const SETTINGS_STORE_PATH: &str = "settings_store.json";
|
pub const SETTINGS_STORE_PATH: &str = "settings_store.json";
|
||||||
|
|
||||||
pub fn get_default_settings() -> AppSettings {
|
pub fn get_default_settings() -> AppSettings {
|
||||||
|
|
@ -47,12 +54,12 @@ pub fn get_default_settings() -> AppSettings {
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
let default_shortcut = "ctrl+space";
|
let default_shortcut = "ctrl+space";
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
let default_shortcut = "alt+space"; // Alt key on macOS (Option key)
|
let default_shortcut = "alt+space"; // Alt key on macOS (Option key)
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
let default_shortcut = "ctrl+space";
|
let default_shortcut = "ctrl+space";
|
||||||
#[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "linux")))]
|
#[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "linux")))]
|
||||||
let default_shortcut = "alt+space"; // Fallback for other platforms
|
let default_shortcut = "alt+space"; // Fallback for other platforms
|
||||||
|
|
||||||
let mut bindings = HashMap::new();
|
let mut bindings = HashMap::new();
|
||||||
bindings.insert(
|
bindings.insert(
|
||||||
"transcribe".to_string(),
|
"transcribe".to_string(),
|
||||||
|
|
@ -83,6 +90,7 @@ pub fn get_default_settings() -> AppSettings {
|
||||||
always_on_microphone: false,
|
always_on_microphone: false,
|
||||||
selected_microphone: None,
|
selected_microphone: None,
|
||||||
selected_output_device: None,
|
selected_output_device: None,
|
||||||
|
translate_to_english: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -130,7 +138,8 @@ pub fn get_settings(app: &AppHandle) -> AppSettings {
|
||||||
.expect("Failed to initialize store");
|
.expect("Failed to initialize store");
|
||||||
|
|
||||||
if let Some(settings_value) = store.get("settings") {
|
if let Some(settings_value) = store.get("settings") {
|
||||||
serde_json::from_value::<AppSettings>(settings_value).unwrap_or_else(|_| get_default_settings())
|
serde_json::from_value::<AppSettings>(settings_value)
|
||||||
|
.unwrap_or_else(|_| get_default_settings())
|
||||||
} else {
|
} else {
|
||||||
get_default_settings()
|
get_default_settings()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,14 @@ pub fn change_audio_feedback_setting(app: AppHandle, enabled: bool) -> Result<()
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn change_translate_to_english_setting(app: AppHandle, enabled: bool) -> Result<(), String> {
|
||||||
|
let mut settings = settings::get_settings(&app);
|
||||||
|
settings.translate_to_english = enabled;
|
||||||
|
settings::write_settings(&app, settings);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn _register_shortcut(app: &AppHandle, binding: ShortcutBinding) -> Result<(), String> {
|
fn _register_shortcut(app: &AppHandle, binding: ShortcutBinding) -> Result<(), String> {
|
||||||
// Parse shortcut and return error if it fails
|
// Parse shortcut and return error if it fails
|
||||||
let shortcut = match binding.current_binding.parse::<Shortcut>() {
|
let shortcut = match binding.current_binding.parse::<Shortcut>() {
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,9 @@
|
||||||
{
|
{
|
||||||
"title": "Handy",
|
"title": "Handy",
|
||||||
"width": 540,
|
"width": 540,
|
||||||
"height": 590,
|
"height": 630,
|
||||||
"minWidth": 540,
|
"minWidth": 540,
|
||||||
"minHeight": 590,
|
"minHeight": 630,
|
||||||
"resizable": true,
|
"resizable": true,
|
||||||
"maximizable": false
|
"maximizable": false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import { PushToTalk } from "./PushToTalk";
|
||||||
import { AudioFeedback } from "./AudioFeedback";
|
import { AudioFeedback } from "./AudioFeedback";
|
||||||
import { OutputDeviceSelector } from "./OutputDeviceSelector";
|
import { OutputDeviceSelector } from "./OutputDeviceSelector";
|
||||||
import { HandyShortcut } from "./HandyShortcut";
|
import { HandyShortcut } from "./HandyShortcut";
|
||||||
|
import { TranslateToEnglish } from "./TranslateToEnglish";
|
||||||
import { SettingsGroup } from "../ui/SettingsGroup";
|
import { SettingsGroup } from "../ui/SettingsGroup";
|
||||||
|
|
||||||
export const Settings: React.FC = () => {
|
export const Settings: React.FC = () => {
|
||||||
|
|
@ -19,6 +20,7 @@ export const Settings: React.FC = () => {
|
||||||
<PushToTalk descriptionMode="tooltip" grouped={true} />
|
<PushToTalk descriptionMode="tooltip" grouped={true} />
|
||||||
<AudioFeedback descriptionMode="tooltip" grouped={true} />
|
<AudioFeedback descriptionMode="tooltip" grouped={true} />
|
||||||
<OutputDeviceSelector descriptionMode="tooltip" grouped={true} />
|
<OutputDeviceSelector descriptionMode="tooltip" grouped={true} />
|
||||||
|
<TranslateToEnglish descriptionMode="tooltip" grouped={true} />
|
||||||
<AlwaysOnMicrophone descriptionMode="tooltip" grouped={true} />
|
<AlwaysOnMicrophone descriptionMode="tooltip" grouped={true} />
|
||||||
</SettingsGroup>
|
</SettingsGroup>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
29
src/components/settings/TranslateToEnglish.tsx
Normal file
29
src/components/settings/TranslateToEnglish.tsx
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
import React from "react";
|
||||||
|
import { ToggleSwitch } from "../ui/ToggleSwitch";
|
||||||
|
import { useSettings } from "../../hooks/useSettings";
|
||||||
|
|
||||||
|
interface TranslateToEnglishProps {
|
||||||
|
descriptionMode?: "inline" | "tooltip";
|
||||||
|
grouped?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TranslateToEnglish: React.FC<TranslateToEnglishProps> = ({
|
||||||
|
descriptionMode = "tooltip",
|
||||||
|
grouped = false,
|
||||||
|
}) => {
|
||||||
|
const { getSetting, updateSetting, isUpdating } = useSettings();
|
||||||
|
|
||||||
|
const translateToEnglish = getSetting("translate_to_english") || false;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ToggleSwitch
|
||||||
|
checked={translateToEnglish}
|
||||||
|
onChange={(enabled) => updateSetting("translate_to_english", enabled)}
|
||||||
|
isUpdating={isUpdating("translate_to_english")}
|
||||||
|
label="Translate to English"
|
||||||
|
description="Automatically translate speech from other languages to English during transcription."
|
||||||
|
descriptionMode={descriptionMode}
|
||||||
|
grouped={grouped}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -5,3 +5,4 @@ export { AlwaysOnMicrophone } from "./AlwaysOnMicrophone";
|
||||||
export { PushToTalk } from "./PushToTalk";
|
export { PushToTalk } from "./PushToTalk";
|
||||||
export { AudioFeedback } from "./AudioFeedback";
|
export { AudioFeedback } from "./AudioFeedback";
|
||||||
export { HandyShortcut } from "./HandyShortcut";
|
export { HandyShortcut } from "./HandyShortcut";
|
||||||
|
export { TranslateToEnglish } from "./TranslateToEnglish";
|
||||||
|
|
|
||||||
|
|
@ -189,6 +189,11 @@ export const useSettings = (): UseSettingsReturn => {
|
||||||
deviceName: outputDeviceName,
|
deviceName: outputDeviceName,
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
case "translate_to_english":
|
||||||
|
await invoke("change_translate_to_english_setting", {
|
||||||
|
enabled: value,
|
||||||
|
});
|
||||||
|
break;
|
||||||
case "bindings":
|
case "bindings":
|
||||||
// Handle bindings separately - they use their own invoke methods
|
// Handle bindings separately - they use their own invoke methods
|
||||||
break;
|
break;
|
||||||
|
|
@ -231,6 +236,7 @@ export const useSettings = (): UseSettingsReturn => {
|
||||||
push_to_talk: false,
|
push_to_talk: false,
|
||||||
selected_microphone: "Default",
|
selected_microphone: "Default",
|
||||||
selected_output_device: "Default",
|
selected_output_device: "Default",
|
||||||
|
translate_to_english: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultValue = defaults[key];
|
const defaultValue = defaults[key];
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ export const SettingsSchema = z.object({
|
||||||
always_on_microphone: z.boolean(),
|
always_on_microphone: z.boolean(),
|
||||||
selected_microphone: z.string().nullable().optional(),
|
selected_microphone: z.string().nullable().optional(),
|
||||||
selected_output_device: z.string().nullable().optional(),
|
selected_output_device: z.string().nullable().optional(),
|
||||||
|
translate_to_english: z.boolean(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const BindingResponseSchema = z.object({
|
export const BindingResponseSchema = z.object({
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue