feat(linux): Add option to select typing tool (#760)
* feat(linux): Add option to select typing tool - Added a Linux-only typing tool setting shown for direct paste, with a new dropdown in advanced settings. - Wired new typing tool setting through settings store, bindings, and Tauri commands. - Added typing tool enum/defaults and selection handling in Linux clipboard direct typing. - Added translations for the new typing tool setting across locales. * fix compilation on macos * format * only list available tools * format --------- Co-authored-by: Thinh Vu <phuocthinhvu@gmail.com> Co-authored-by: CJ Pais <cj@cjpais.com>
This commit is contained in:
parent
d70d076bdc
commit
b02873dab5
24 changed files with 346 additions and 7 deletions
|
|
@ -1,4 +1,6 @@
|
|||
use crate::input::{self, EnigoState};
|
||||
#[cfg(target_os = "linux")]
|
||||
use crate::settings::TypingTool;
|
||||
use crate::settings::{get_settings, AutoSubmitKey, ClipboardHandling, PasteMethod};
|
||||
use enigo::{Direction, Enigo, Key, Keyboard};
|
||||
use log::info;
|
||||
|
|
@ -119,7 +121,43 @@ fn try_send_key_combo_linux(paste_method: &PasteMethod) -> Result<bool, String>
|
|||
/// Attempts to type text directly using Linux-native tools.
|
||||
/// Returns `Ok(true)` if a native tool handled it, `Ok(false)` to fall back to enigo.
|
||||
#[cfg(target_os = "linux")]
|
||||
fn try_direct_typing_linux(text: &str) -> Result<bool, String> {
|
||||
fn try_direct_typing_linux(text: &str, preferred_tool: TypingTool) -> Result<bool, String> {
|
||||
// If user specified a tool, try only that one
|
||||
if preferred_tool != TypingTool::Auto {
|
||||
return match preferred_tool {
|
||||
TypingTool::Wtype if is_wtype_available() => {
|
||||
info!("Using user-specified wtype");
|
||||
type_text_via_wtype(text)?;
|
||||
Ok(true)
|
||||
}
|
||||
TypingTool::Kwtype if is_kwtype_available() => {
|
||||
info!("Using user-specified kwtype");
|
||||
type_text_via_kwtype(text)?;
|
||||
Ok(true)
|
||||
}
|
||||
TypingTool::Dotool if is_dotool_available() => {
|
||||
info!("Using user-specified dotool");
|
||||
type_text_via_dotool(text)?;
|
||||
Ok(true)
|
||||
}
|
||||
TypingTool::Ydotool if is_ydotool_available() => {
|
||||
info!("Using user-specified ydotool");
|
||||
type_text_via_ydotool(text)?;
|
||||
Ok(true)
|
||||
}
|
||||
TypingTool::Xdotool if is_xdotool_available() => {
|
||||
info!("Using user-specified xdotool");
|
||||
type_text_via_xdotool(text)?;
|
||||
Ok(true)
|
||||
}
|
||||
_ => Err(format!(
|
||||
"Typing tool {:?} is not available on this system",
|
||||
preferred_tool
|
||||
)),
|
||||
};
|
||||
}
|
||||
|
||||
// Auto mode - existing fallback chain
|
||||
if is_wayland() {
|
||||
// KDE Wayland: prefer kwtype (uses KDE Fake Input protocol, supports umlauts)
|
||||
if is_kde_wayland() && is_kwtype_available() {
|
||||
|
|
@ -161,6 +199,29 @@ fn try_direct_typing_linux(text: &str) -> Result<bool, String> {
|
|||
Ok(false)
|
||||
}
|
||||
|
||||
/// Returns the list of available typing tools on this system.
|
||||
/// Always includes "auto" as the first entry.
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn get_available_typing_tools() -> Vec<String> {
|
||||
let mut tools = vec!["auto".to_string()];
|
||||
if is_wtype_available() {
|
||||
tools.push("wtype".to_string());
|
||||
}
|
||||
if is_kwtype_available() {
|
||||
tools.push("kwtype".to_string());
|
||||
}
|
||||
if is_dotool_available() {
|
||||
tools.push("dotool".to_string());
|
||||
}
|
||||
if is_ydotool_available() {
|
||||
tools.push("ydotool".to_string());
|
||||
}
|
||||
if is_xdotool_available() {
|
||||
tools.push("xdotool".to_string());
|
||||
}
|
||||
tools
|
||||
}
|
||||
|
||||
/// Check if wtype is available (Wayland text input tool)
|
||||
#[cfg(target_os = "linux")]
|
||||
fn is_wtype_available() -> bool {
|
||||
|
|
@ -434,10 +495,14 @@ fn send_key_combo_via_xdotool(paste_method: &PasteMethod) -> Result<(), String>
|
|||
}
|
||||
|
||||
/// Types text directly by simulating individual key presses.
|
||||
fn paste_direct(enigo: &mut Enigo, text: &str) -> Result<(), String> {
|
||||
fn paste_direct(
|
||||
enigo: &mut Enigo,
|
||||
text: &str,
|
||||
#[cfg(target_os = "linux")] typing_tool: TypingTool,
|
||||
) -> Result<(), String> {
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
if try_direct_typing_linux(text)? {
|
||||
if try_direct_typing_linux(text, typing_tool)? {
|
||||
return Ok(());
|
||||
}
|
||||
info!("Falling back to enigo for direct text input");
|
||||
|
|
@ -525,7 +590,12 @@ pub fn paste(text: String, app_handle: AppHandle) -> Result<(), String> {
|
|||
info!("PasteMethod::None selected - skipping paste action");
|
||||
}
|
||||
PasteMethod::Direct => {
|
||||
paste_direct(&mut enigo, &text)?;
|
||||
paste_direct(
|
||||
&mut enigo,
|
||||
&text,
|
||||
#[cfg(target_os = "linux")]
|
||||
settings.typing_tool,
|
||||
)?;
|
||||
}
|
||||
PasteMethod::CtrlV | PasteMethod::CtrlShiftV | PasteMethod::ShiftInsert => {
|
||||
paste_via_clipboard(
|
||||
|
|
|
|||
|
|
@ -274,6 +274,8 @@ pub fn run() {
|
|||
shortcut::change_debug_mode_setting,
|
||||
shortcut::change_word_correction_threshold_setting,
|
||||
shortcut::change_paste_method_setting,
|
||||
shortcut::get_available_typing_tools,
|
||||
shortcut::change_typing_tool_setting,
|
||||
shortcut::change_clipboard_handling_setting,
|
||||
shortcut::change_auto_submit_setting,
|
||||
shortcut::change_auto_submit_key_setting,
|
||||
|
|
|
|||
|
|
@ -255,6 +255,23 @@ impl SoundTheme {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Type)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum TypingTool {
|
||||
Auto,
|
||||
Wtype,
|
||||
Kwtype,
|
||||
Dotool,
|
||||
Ydotool,
|
||||
Xdotool,
|
||||
}
|
||||
|
||||
impl Default for TypingTool {
|
||||
fn default() -> Self {
|
||||
TypingTool::Auto
|
||||
}
|
||||
}
|
||||
|
||||
/* still handy for composing the initial JSON in the store ------------- */
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Type)]
|
||||
pub struct AppSettings {
|
||||
|
|
@ -337,6 +354,8 @@ pub struct AppSettings {
|
|||
pub show_tray_icon: bool,
|
||||
#[serde(default = "default_paste_delay_ms")]
|
||||
pub paste_delay_ms: u64,
|
||||
#[serde(default = "default_typing_tool")]
|
||||
pub typing_tool: TypingTool,
|
||||
}
|
||||
|
||||
fn default_model() -> String {
|
||||
|
|
@ -528,6 +547,10 @@ fn default_post_process_prompts() -> Vec<LLMPrompt> {
|
|||
}]
|
||||
}
|
||||
|
||||
fn default_typing_tool() -> TypingTool {
|
||||
TypingTool::Auto
|
||||
}
|
||||
|
||||
fn ensure_post_process_defaults(settings: &mut AppSettings) -> bool {
|
||||
let mut changed = false;
|
||||
for provider in default_post_process_providers() {
|
||||
|
|
@ -663,6 +686,7 @@ pub fn get_default_settings() -> AppSettings {
|
|||
keyboard_implementation: KeyboardImplementation::default(),
|
||||
show_tray_icon: default_show_tray_icon(),
|
||||
paste_delay_ms: default_paste_delay_ms(),
|
||||
typing_tool: default_typing_tool(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ use tauri_plugin_autostart::ManagerExt;
|
|||
|
||||
use crate::settings::{
|
||||
self, get_settings, AutoSubmitKey, ClipboardHandling, KeyboardImplementation, LLMPrompt,
|
||||
OverlayPosition, PasteMethod, ShortcutBinding, SoundTheme, APPLE_INTELLIGENCE_DEFAULT_MODEL_ID,
|
||||
APPLE_INTELLIGENCE_PROVIDER_ID,
|
||||
OverlayPosition, PasteMethod, ShortcutBinding, SoundTheme, TypingTool,
|
||||
APPLE_INTELLIGENCE_DEFAULT_MODEL_ID, APPLE_INTELLIGENCE_PROVIDER_ID,
|
||||
};
|
||||
use crate::tray;
|
||||
|
||||
|
|
@ -678,6 +678,40 @@ pub fn change_paste_method_setting(app: AppHandle, method: String) -> Result<(),
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
#[specta::specta]
|
||||
pub fn get_available_typing_tools() -> Vec<String> {
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
crate::clipboard::get_available_typing_tools()
|
||||
}
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
{
|
||||
vec!["auto".to_string()]
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
#[specta::specta]
|
||||
pub fn change_typing_tool_setting(app: AppHandle, tool: String) -> Result<(), String> {
|
||||
let mut settings = settings::get_settings(&app);
|
||||
let parsed = match tool.as_str() {
|
||||
"auto" => TypingTool::Auto,
|
||||
"wtype" => TypingTool::Wtype,
|
||||
"kwtype" => TypingTool::Kwtype,
|
||||
"dotool" => TypingTool::Dotool,
|
||||
"ydotool" => TypingTool::Ydotool,
|
||||
"xdotool" => TypingTool::Xdotool,
|
||||
other => {
|
||||
warn!("Invalid typing tool '{}', defaulting to auto", other);
|
||||
TypingTool::Auto
|
||||
}
|
||||
};
|
||||
settings.typing_tool = parsed;
|
||||
settings::write_settings(&app, settings);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
#[specta::specta]
|
||||
pub fn change_clipboard_handling_setting(app: AppHandle, handling: String) -> Result<(), String> {
|
||||
|
|
|
|||
|
|
@ -117,6 +117,17 @@ async changePasteMethodSetting(method: string) : Promise<Result<null, string>> {
|
|||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async getAvailableTypingTools() : Promise<string[]> {
|
||||
return await TAURI_INVOKE("get_available_typing_tools");
|
||||
},
|
||||
async changeTypingToolSetting(tool: string) : Promise<Result<null, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("change_typing_tool_setting", { tool }) };
|
||||
} catch (e) {
|
||||
if(e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async changeClipboardHandlingSetting(handling: string) : Promise<Result<null, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("change_clipboard_handling_setting", { handling }) };
|
||||
|
|
@ -719,7 +730,7 @@ async isLaptop() : Promise<Result<boolean, string>> {
|
|||
|
||||
/** user-defined types **/
|
||||
|
||||
export type AppSettings = { bindings: Partial<{ [key in string]: ShortcutBinding }>; push_to_talk: boolean; audio_feedback: boolean; audio_feedback_volume?: number; sound_theme?: SoundTheme; start_hidden?: boolean; autostart_enabled?: boolean; update_checks_enabled?: boolean; selected_model?: string; always_on_microphone?: boolean; selected_microphone?: string | null; clamshell_microphone?: string | null; selected_output_device?: string | null; translate_to_english?: boolean; selected_language?: string; overlay_position?: OverlayPosition; debug_mode?: boolean; log_level?: LogLevel; custom_words?: string[]; model_unload_timeout?: ModelUnloadTimeout; word_correction_threshold?: number; history_limit?: number; recording_retention_period?: RecordingRetentionPeriod; paste_method?: PasteMethod; clipboard_handling?: ClipboardHandling; auto_submit?: boolean; auto_submit_key?: AutoSubmitKey; post_process_enabled?: boolean; post_process_provider_id?: string; post_process_providers?: PostProcessProvider[]; post_process_api_keys?: Partial<{ [key in string]: string }>; post_process_models?: Partial<{ [key in string]: string }>; post_process_prompts?: LLMPrompt[]; post_process_selected_prompt_id?: string | null; mute_while_recording?: boolean; append_trailing_space?: boolean; app_language?: string; experimental_enabled?: boolean; keyboard_implementation?: KeyboardImplementation; show_tray_icon?: boolean; paste_delay_ms?: number }
|
||||
export type AppSettings = { bindings: Partial<{ [key in string]: ShortcutBinding }>; push_to_talk: boolean; audio_feedback: boolean; audio_feedback_volume?: number; sound_theme?: SoundTheme; start_hidden?: boolean; autostart_enabled?: boolean; update_checks_enabled?: boolean; selected_model?: string; always_on_microphone?: boolean; selected_microphone?: string | null; clamshell_microphone?: string | null; selected_output_device?: string | null; translate_to_english?: boolean; selected_language?: string; overlay_position?: OverlayPosition; debug_mode?: boolean; log_level?: LogLevel; custom_words?: string[]; model_unload_timeout?: ModelUnloadTimeout; word_correction_threshold?: number; history_limit?: number; recording_retention_period?: RecordingRetentionPeriod; paste_method?: PasteMethod; clipboard_handling?: ClipboardHandling; auto_submit?: boolean; auto_submit_key?: AutoSubmitKey; post_process_enabled?: boolean; post_process_provider_id?: string; post_process_providers?: PostProcessProvider[]; post_process_api_keys?: Partial<{ [key in string]: string }>; post_process_models?: Partial<{ [key in string]: string }>; post_process_prompts?: LLMPrompt[]; post_process_selected_prompt_id?: string | null; mute_while_recording?: boolean; append_trailing_space?: boolean; app_language?: string; experimental_enabled?: boolean; keyboard_implementation?: KeyboardImplementation; show_tray_icon?: boolean; paste_delay_ms?: number; typing_tool?: TypingTool }
|
||||
export type AudioDevice = { index: string; name: string; is_default: boolean }
|
||||
export type AutoSubmitKey = "enter" | "ctrl_enter" | "cmd_enter"
|
||||
export type BindingResponse = { success: boolean; binding: ShortcutBinding | null; error: string | null }
|
||||
|
|
@ -747,6 +758,7 @@ export type PostProcessProvider = { id: string; label: string; base_url: string;
|
|||
export type RecordingRetentionPeriod = "never" | "preserve_limit" | "days_3" | "weeks_2" | "months_3"
|
||||
export type ShortcutBinding = { id: string; name: string; description: string; default_binding: string; current_binding: string }
|
||||
export type SoundTheme = "marimba" | "pop" | "custom"
|
||||
export type TypingTool = "auto" | "wtype" | "kwtype" | "dotool" | "ydotool" | "xdotool"
|
||||
|
||||
/** tauri-specta globals **/
|
||||
|
||||
|
|
|
|||
82
src/components/settings/TypingTool.tsx
Normal file
82
src/components/settings/TypingTool.tsx
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
import React, { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Dropdown } from "../ui/Dropdown";
|
||||
import { SettingContainer } from "../ui/SettingContainer";
|
||||
import { useSettings } from "../../hooks/useSettings";
|
||||
import { useOsType } from "../../hooks/useOsType";
|
||||
import { commands } from "@/bindings";
|
||||
import type { TypingTool } from "@/bindings";
|
||||
|
||||
interface TypingToolProps {
|
||||
descriptionMode?: "inline" | "tooltip";
|
||||
grouped?: boolean;
|
||||
}
|
||||
|
||||
const allToolLabels: Record<string, string> = {
|
||||
wtype: "wtype",
|
||||
kwtype: "kwtype",
|
||||
dotool: "dotool",
|
||||
ydotool: "ydotool",
|
||||
xdotool: "xdotool",
|
||||
};
|
||||
|
||||
export const TypingToolSetting: React.FC<TypingToolProps> = React.memo(
|
||||
({ descriptionMode = "tooltip", grouped = false }) => {
|
||||
const { t } = useTranslation();
|
||||
const { getSetting, updateSetting, isUpdating } = useSettings();
|
||||
const osType = useOsType();
|
||||
const [availableTools, setAvailableTools] = useState<string[] | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (osType !== "linux") return;
|
||||
commands
|
||||
.getAvailableTypingTools()
|
||||
.then(setAvailableTools)
|
||||
.catch(() => {
|
||||
setAvailableTools(["auto"]);
|
||||
});
|
||||
}, [osType]);
|
||||
|
||||
// Only show this setting on Linux
|
||||
if (osType !== "linux") {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Only show if paste method is "direct"
|
||||
const pasteMethod = getSetting("paste_method");
|
||||
if (pasteMethod !== "direct") {
|
||||
return null;
|
||||
}
|
||||
|
||||
const tools = availableTools ?? ["auto"];
|
||||
const typingToolOptions = tools.map((tool) =>
|
||||
tool === "auto"
|
||||
? {
|
||||
value: "auto",
|
||||
label: t("settings.advanced.typingTool.options.auto"),
|
||||
}
|
||||
: { value: tool, label: allToolLabels[tool] ?? tool },
|
||||
);
|
||||
|
||||
const selectedTool = (getSetting("typing_tool") || "auto") as TypingTool;
|
||||
|
||||
return (
|
||||
<SettingContainer
|
||||
title={t("settings.advanced.typingTool.title")}
|
||||
description={t("settings.advanced.typingTool.description")}
|
||||
descriptionMode={descriptionMode}
|
||||
grouped={grouped}
|
||||
tooltipPosition="bottom"
|
||||
>
|
||||
<Dropdown
|
||||
options={typingToolOptions}
|
||||
selectedValue={selectedTool}
|
||||
onSelect={(value) =>
|
||||
updateSetting("typing_tool", value as TypingTool)
|
||||
}
|
||||
disabled={isUpdating("typing_tool")}
|
||||
/>
|
||||
</SettingContainer>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
|
@ -8,6 +8,7 @@ import { StartHidden } from "../StartHidden";
|
|||
import { AutostartToggle } from "../AutostartToggle";
|
||||
import { ShowTrayIcon } from "../ShowTrayIcon";
|
||||
import { PasteMethodSetting } from "../PasteMethod";
|
||||
import { TypingToolSetting } from "../TypingTool";
|
||||
import { ClipboardHandlingSetting } from "../ClipboardHandling";
|
||||
import { AutoSubmit } from "../AutoSubmit";
|
||||
import { PostProcessingToggle } from "../PostProcessingToggle";
|
||||
|
|
@ -36,6 +37,7 @@ export const AdvancedSettings: React.FC = () => {
|
|||
|
||||
<SettingsGroup title={t("settings.advanced.groups.output")}>
|
||||
<PasteMethodSetting descriptionMode="tooltip" grouped={true} />
|
||||
<TypingToolSetting descriptionMode="tooltip" grouped={true} />
|
||||
<ClipboardHandlingSetting descriptionMode="tooltip" grouped={true} />
|
||||
<AutoSubmit descriptionMode="tooltip" grouped={true} />
|
||||
</SettingsGroup>
|
||||
|
|
|
|||
|
|
@ -222,6 +222,13 @@
|
|||
"none": "بلا"
|
||||
}
|
||||
},
|
||||
"typingTool": {
|
||||
"title": "أداة الكتابة",
|
||||
"description": ".اختر أداة الكتابة في Linux لاستخدامها مع طريقة اللصق المباشر. سيكتشف \"تلقائي\" تلقائياً أفضل أداة متاحة لنظامك ويستخدمها",
|
||||
"options": {
|
||||
"auto": "تلقائي (موصى به)"
|
||||
}
|
||||
},
|
||||
"clipboardHandling": {
|
||||
"title": "التعامل مع الحافظة",
|
||||
"description": ".'عدم تعديل الحافظة' يحافظ على محتويات حافظتك الحالية بعد التفريغ. 'نسخ إلى الحافظة' يترك نتيجة التفريغ في حافظتك بعد اللصق",
|
||||
|
|
|
|||
|
|
@ -244,6 +244,13 @@
|
|||
"none": "Žádné"
|
||||
}
|
||||
},
|
||||
"typingTool": {
|
||||
"title": "Nástroj pro psaní",
|
||||
"description": "Vyberte, který linuxový nástroj pro psaní použít pro metodu přímého vložení. Auto automaticky zjistí a použije nejlepší dostupný nástroj pro váš systém.",
|
||||
"options": {
|
||||
"auto": "Auto (Doporučeno)"
|
||||
}
|
||||
},
|
||||
"clipboardHandling": {
|
||||
"title": "Práce se schránkou",
|
||||
"description": "'Neměnit schránku' zachová po přepisu aktuální obsah schránky. 'Kopírovat do schránky' ponechá po vložení výsledek přepisu ve schránce.",
|
||||
|
|
|
|||
|
|
@ -244,6 +244,13 @@
|
|||
"none": "Keine"
|
||||
}
|
||||
},
|
||||
"typingTool": {
|
||||
"title": "Eingabetool",
|
||||
"description": "Wählen Sie, welches Linux-Eingabetool für die Direkt-Einfügen-Methode verwendet werden soll. Auto erkennt und verwendet automatisch das beste verfügbare Tool für Ihr System.",
|
||||
"options": {
|
||||
"auto": "Auto (Empfohlen)"
|
||||
}
|
||||
},
|
||||
"clipboardHandling": {
|
||||
"title": "Zwischenablage-Verhalten",
|
||||
"description": "Zwischenablage nicht ändern bewahrt den aktuellen Inhalt nach der Transkription. In Zwischenablage kopieren hinterlässt das Transkriptionsergebnis in der Zwischenablage.",
|
||||
|
|
|
|||
|
|
@ -244,6 +244,13 @@
|
|||
"none": "None"
|
||||
}
|
||||
},
|
||||
"typingTool": {
|
||||
"title": "Typing Tool",
|
||||
"description": "Choose which Linux typing tool to use for Direct paste method. Auto will automatically detect and use the best available tool for your system.",
|
||||
"options": {
|
||||
"auto": "Auto (Recommended)"
|
||||
}
|
||||
},
|
||||
"clipboardHandling": {
|
||||
"title": "Clipboard Handling",
|
||||
"description": "Don't Modify Clipboard preserves your current clipboard contents after transcription. Copy to Clipboard leaves the transcription result in your clipboard after pasting.",
|
||||
|
|
|
|||
|
|
@ -244,6 +244,13 @@
|
|||
"none": "Ninguno"
|
||||
}
|
||||
},
|
||||
"typingTool": {
|
||||
"title": "Herramienta de Escritura",
|
||||
"description": "Elige qué herramienta de escritura de Linux usar para el método de pegado directo. Auto detectará y usará automáticamente la mejor herramienta disponible para tu sistema.",
|
||||
"options": {
|
||||
"auto": "Auto (Recomendado)"
|
||||
}
|
||||
},
|
||||
"clipboardHandling": {
|
||||
"title": "Manejo del Portapapeles",
|
||||
"description": "No Modificar Portapapeles conserva el contenido actual de tu portapapeles después de la transcripción. Copiar al Portapapeles deja el resultado de la transcripción en tu portapapeles después de pegar.",
|
||||
|
|
|
|||
|
|
@ -244,6 +244,13 @@
|
|||
"none": "Aucun"
|
||||
}
|
||||
},
|
||||
"typingTool": {
|
||||
"title": "Outil de frappe",
|
||||
"description": "Choisissez quel outil de frappe Linux utiliser pour la méthode de collage direct. Auto détectera et utilisera automatiquement le meilleur outil disponible pour votre système.",
|
||||
"options": {
|
||||
"auto": "Auto (Recommandé)"
|
||||
}
|
||||
},
|
||||
"clipboardHandling": {
|
||||
"title": "Gestion du presse-papiers",
|
||||
"description": "Ne pas modifier le presse-papiers préserve le contenu actuel de votre presse-papiers après la transcription. Copier dans le presse-papiers laisse le résultat de la transcription dans votre presse-papiers après le collage.",
|
||||
|
|
|
|||
|
|
@ -244,6 +244,13 @@
|
|||
"none": "Nessuno"
|
||||
}
|
||||
},
|
||||
"typingTool": {
|
||||
"title": "Strumento di digitazione",
|
||||
"description": "Scegli quale strumento di digitazione Linux usare per il metodo di incolla diretto. Auto rileverà e userà automaticamente lo strumento migliore disponibile per il tuo sistema.",
|
||||
"options": {
|
||||
"auto": "Auto (Consigliato)"
|
||||
}
|
||||
},
|
||||
"clipboardHandling": {
|
||||
"title": "Gestione Appunti",
|
||||
"description": "Non Modificare gli Appunti mantiene il contenuto dei tuoi appunti dopo la trascrizione. Copia negli Appunti lascia il risultato della trascrizione negli appunti dopo aver incollato.",
|
||||
|
|
|
|||
|
|
@ -244,6 +244,13 @@
|
|||
"none": "なし"
|
||||
}
|
||||
},
|
||||
"typingTool": {
|
||||
"title": "タイピングツール",
|
||||
"description": "直接貼り付け方式で使用する Linux のタイピングツールを選択します。Auto は自動的に最適なツールを検出して使用します。",
|
||||
"options": {
|
||||
"auto": "Auto(推奨)"
|
||||
}
|
||||
},
|
||||
"clipboardHandling": {
|
||||
"title": "クリップボードの処理",
|
||||
"description": "クリップボードを変更しないを選択すると、文字起こし後も現在のクリップボード内容が保持されます。クリップボードにコピーを選択すると、貼り付け後も文字起こし結果がクリップボードに残ります。",
|
||||
|
|
|
|||
|
|
@ -244,6 +244,13 @@
|
|||
"none": "없음"
|
||||
}
|
||||
},
|
||||
"typingTool": {
|
||||
"title": "타이핑 도구",
|
||||
"description": "직접 붙여넣기 방식에 사용할 Linux 타이핑 도구를 선택하세요. Auto는 시스템에서 사용 가능한 최적의 도구를 자동으로 감지해 사용합니다.",
|
||||
"options": {
|
||||
"auto": "Auto (권장)"
|
||||
}
|
||||
},
|
||||
"clipboardHandling": {
|
||||
"title": "클립보드 처리",
|
||||
"description": "클립보드 수정 안 함은 전사 후 현재 클립보드 내용을 보존합니다. 클립보드에 복사는 붙여넣기 후 전사 결과를 클립보드에 남겨둡니다.",
|
||||
|
|
|
|||
|
|
@ -244,6 +244,13 @@
|
|||
"none": "Brak"
|
||||
}
|
||||
},
|
||||
"typingTool": {
|
||||
"title": "Narzędzie do wpisywania",
|
||||
"description": "Wybierz, którego narzędzia do wpisywania w Linuxie użyć dla metody bezpośredniego wklejania. Auto automatycznie wykryje i użyje najlepszego dostępnego narzędzia dla Twojego systemu.",
|
||||
"options": {
|
||||
"auto": "Auto (Zalecane)"
|
||||
}
|
||||
},
|
||||
"clipboardHandling": {
|
||||
"title": "Obsługa schowka",
|
||||
"description": "Nie modyfikuj schowka zachowuje jego zawartość. Kopiuj do schowka pozostawia wynik transkrypcji w schowku.",
|
||||
|
|
|
|||
|
|
@ -244,6 +244,13 @@
|
|||
"none": "Nenhum"
|
||||
}
|
||||
},
|
||||
"typingTool": {
|
||||
"title": "Ferramenta de digitação",
|
||||
"description": "Escolha qual ferramenta de digitação do Linux usar para o método de colagem direta. Auto detectará e usará automaticamente a melhor ferramenta disponível para o seu sistema.",
|
||||
"options": {
|
||||
"auto": "Auto (Recomendado)"
|
||||
}
|
||||
},
|
||||
"clipboardHandling": {
|
||||
"title": "Manipulação da Área de Transferência",
|
||||
"description": "Não Modificar Área de Transferência preserva o conteúdo atual da área de transferência após a transcrição. Copiar para Área de Transferência deixa o resultado da transcrição na área de transferência após colar.",
|
||||
|
|
|
|||
|
|
@ -244,6 +244,13 @@
|
|||
"none": "Нет"
|
||||
}
|
||||
},
|
||||
"typingTool": {
|
||||
"title": "Инструмент ввода",
|
||||
"description": "Выберите, какой инструмент ввода в Linux использовать для метода прямой вставки. Auto автоматически определит и использует лучший доступный инструмент для вашей системы.",
|
||||
"options": {
|
||||
"auto": "Auto (Рекомендуется)"
|
||||
}
|
||||
},
|
||||
"clipboardHandling": {
|
||||
"title": "Обработка буфера обмена",
|
||||
"description": "Функция «Не изменять буфер обмена» сохраняет текущее содержимое буфера обмена после транскрипции. Копировать в буфер обмена оставляет результат транскрипции в буфере обмена после вставки.",
|
||||
|
|
|
|||
|
|
@ -244,6 +244,13 @@
|
|||
"none": "Yok"
|
||||
}
|
||||
},
|
||||
"typingTool": {
|
||||
"title": "Yazma Aracı",
|
||||
"description": "Doğrudan yapıştırma yöntemi için hangi Linux yazma aracının kullanılacağını seçin. Auto, sisteminiz için mevcut en iyi aracı otomatik olarak algılar ve kullanır.",
|
||||
"options": {
|
||||
"auto": "Auto (Önerilen)"
|
||||
}
|
||||
},
|
||||
"clipboardHandling": {
|
||||
"title": "Pano Yönetimi",
|
||||
"description": "Panoyu Değiştirme, transkripsiyon sonrası mevcut pano içeriğini korur. Panoya Kopyala ise yapıştırma işleminden sonra transkripsiyon sonucunu panoda bırakır.",
|
||||
|
|
|
|||
|
|
@ -244,6 +244,13 @@
|
|||
"none": "Немає"
|
||||
}
|
||||
},
|
||||
"typingTool": {
|
||||
"title": "Інструмент введення",
|
||||
"description": "Виберіть, який інструмент введення в Linux використовувати для методу прямого вставлення. Auto автоматично визначить і використає найкращий доступний інструмент для вашої системи.",
|
||||
"options": {
|
||||
"auto": "Auto (Рекомендовано)"
|
||||
}
|
||||
},
|
||||
"clipboardHandling": {
|
||||
"title": "Робота з буфером обміну",
|
||||
"description": "Не змінювати буфер обміну зберігає поточний вміст буфера після транскрипції. Копіювати в буфер обміну залишає результат транскрипції в буфері після вставки.",
|
||||
|
|
|
|||
|
|
@ -244,6 +244,13 @@
|
|||
"none": "Không có"
|
||||
}
|
||||
},
|
||||
"typingTool": {
|
||||
"title": "Công cụ gõ",
|
||||
"description": "Chọn công cụ gõ trên Linux cho phương thức dán trực tiếp. Auto sẽ tự động phát hiện và dùng công cụ tốt nhất có sẵn cho hệ thống của bạn.",
|
||||
"options": {
|
||||
"auto": "Auto (Khuyến nghị)"
|
||||
}
|
||||
},
|
||||
"clipboardHandling": {
|
||||
"title": "Xử lý Clipboard",
|
||||
"description": "Không sửa đổi Clipboard giữ nguyên nội dung clipboard hiện tại sau khi chuyển đổi. Sao chép vào Clipboard để lại kết quả chuyển đổi trong clipboard sau khi dán.",
|
||||
|
|
|
|||
|
|
@ -244,6 +244,13 @@
|
|||
"none": "无"
|
||||
}
|
||||
},
|
||||
"typingTool": {
|
||||
"title": "输入工具",
|
||||
"description": "选择在直接粘贴方式下使用的 Linux 输入工具。Auto 会自动检测并使用系统中可用的最佳工具。",
|
||||
"options": {
|
||||
"auto": "Auto(推荐)"
|
||||
}
|
||||
},
|
||||
"clipboardHandling": {
|
||||
"title": "剪贴板处理",
|
||||
"description": "不修改剪贴板将在转录后保留当前剪贴板内容。复制到剪贴板将在粘贴后将转录结果留在剪贴板中。",
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ const settingUpdaters: {
|
|||
word_correction_threshold: (value) =>
|
||||
commands.changeWordCorrectionThresholdSetting(value as number),
|
||||
paste_method: (value) => commands.changePasteMethodSetting(value as string),
|
||||
typing_tool: (value) => commands.changeTypingToolSetting(value as string),
|
||||
clipboard_handling: (value) =>
|
||||
commands.changeClipboardHandlingSetting(value as string),
|
||||
auto_submit: (value) => commands.changeAutoSubmitSetting(value as boolean),
|
||||
|
|
|
|||
Loading…
Reference in a new issue