feat: add conversion between Simplified and Traditional Chinese. (#356)
* feat: add conversion between Simplified and Traditional Chinese. If the selected language is Simplified or Traditional Chinese, it will convert the text to the selected variant(Simplified or Traditional) after been recognized, depends on opencc, if it is not installed, the conversion will skip. * Adopting ferrous-opencc makes cross-platform packaging easier.
This commit is contained in:
parent
0c5989d824
commit
ec3b06d5b2
5 changed files with 306 additions and 7 deletions
238
src-tauri/Cargo.lock
generated
238
src-tauri/Cargo.lock
generated
|
|
@ -109,6 +109,56 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon",
|
||||
"colorchoice",
|
||||
"is_terminal_polyfill",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "3.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"once_cell_polyfill",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.100"
|
||||
|
|
@ -432,6 +482,26 @@ version = "1.8.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba"
|
||||
|
||||
[[package]]
|
||||
name = "bincode"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740"
|
||||
dependencies = [
|
||||
"bincode_derive",
|
||||
"serde",
|
||||
"unty",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bincode_derive"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09"
|
||||
dependencies = [
|
||||
"virtue",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bindgen"
|
||||
version = "0.69.5"
|
||||
|
|
@ -705,6 +775,25 @@ dependencies = [
|
|||
"toml 0.9.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cbindgen"
|
||||
version = "0.29.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "befbfd072a8e81c02f8c507aefce431fe5e7d051f83d48a23ffc9b9fe5a11799"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"heck 0.5.0",
|
||||
"indexmap 2.12.0",
|
||||
"log",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"syn 2.0.108",
|
||||
"tempfile",
|
||||
"toml 0.9.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.43"
|
||||
|
|
@ -788,6 +877,46 @@ dependencies = [
|
|||
"libloading 0.8.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.52"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa8120877db0e5c011242f96806ce3c94e0737ab8108532a76a3300a01db2ab8"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.52"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02576b399397b659c26064fbc92a75fede9d18ffd5f80ca1cd74ddab167016e1"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
"strsim",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.49"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671"
|
||||
dependencies = [
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d"
|
||||
|
||||
[[package]]
|
||||
name = "clipboard-win"
|
||||
version = "5.4.1"
|
||||
|
|
@ -836,6 +965,12 @@ dependencies = [
|
|||
"objc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
|
||||
|
||||
[[package]]
|
||||
name = "combine"
|
||||
version = "4.6.7"
|
||||
|
|
@ -1704,6 +1839,38 @@ dependencies = [
|
|||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ferrous-opencc"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7604efd2d4d8ee72dcbf7b24b604d7a4c764dfab40152bbe12ae241f784560b"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"cbindgen",
|
||||
"clap",
|
||||
"ferrous-opencc-compiler",
|
||||
"fst",
|
||||
"phf 0.11.3",
|
||||
"phf_codegen 0.11.3",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tempfile",
|
||||
"thiserror 2.0.17",
|
||||
"wasm-bindgen-test",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ferrous-opencc-compiler"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "161c89665fa27878bd14fa7adc2e392f4e17f6fe9d45d66d6e73585c70f3e4e0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"fst",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "field-offset"
|
||||
version = "0.3.6"
|
||||
|
|
@ -1828,6 +1995,12 @@ version = "1.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
|
||||
|
||||
[[package]]
|
||||
name = "fst"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ab85b9b05e3978cc9a9cf8fea7f01b494e1a09ed3037e16ba39edc7a29eb61a"
|
||||
|
||||
[[package]]
|
||||
name = "funty"
|
||||
version = "2.0.0"
|
||||
|
|
@ -2335,6 +2508,7 @@ dependencies = [
|
|||
"cpal",
|
||||
"enigo",
|
||||
"env_filter",
|
||||
"ferrous-opencc",
|
||||
"flate2",
|
||||
"futures-util",
|
||||
"hound",
|
||||
|
|
@ -2903,6 +3077,12 @@ dependencies = [
|
|||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
version = "1.70.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.12.1"
|
||||
|
|
@ -3278,6 +3458,16 @@ dependencies = [
|
|||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minicov"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f27fe9f1cc3c22e1687f9446c2083c4c5fc7f0bcf1c7a86bdbded14985895b4b"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
|
|
@ -3922,6 +4112,12 @@ version = "1.21.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell_polyfill"
|
||||
version = "1.70.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
|
||||
|
||||
[[package]]
|
||||
name = "open"
|
||||
version = "5.3.2"
|
||||
|
|
@ -7353,6 +7549,12 @@ version = "0.9.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
||||
|
||||
[[package]]
|
||||
name = "unty"
|
||||
version = "0.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae"
|
||||
|
||||
[[package]]
|
||||
name = "ureq"
|
||||
version = "3.1.2"
|
||||
|
|
@ -7426,6 +7628,12 @@ version = "1.0.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.18.1"
|
||||
|
|
@ -7473,6 +7681,12 @@ version = "0.9.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "virtue"
|
||||
version = "0.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1"
|
||||
|
||||
[[package]]
|
||||
name = "vswhom"
|
||||
version = "0.1.0"
|
||||
|
|
@ -7611,6 +7825,30 @@ dependencies = [
|
|||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-test"
|
||||
version = "0.3.54"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e381134e148c1062f965a42ed1f5ee933eef2927c3f70d1812158f711d39865"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"minicov",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"wasm-bindgen-test-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-test-macro"
|
||||
version = "0.3.54"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b673bca3298fe582aeef8352330ecbad91849f85090805582400850f8270a2e8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-streams"
|
||||
version = "0.4.2"
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ rusqlite = { version = "0.32.1", features = ["bundled"] }
|
|||
tar = "0.4.44"
|
||||
flate2 = "1.0"
|
||||
transcribe-rs = "0.1.4"
|
||||
ferrous-opencc = "0.2.3"
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
signal-hook = "0.3"
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ use async_openai::types::{
|
|||
};
|
||||
use log::{debug, error};
|
||||
use once_cell::sync::Lazy;
|
||||
use ferrous_opencc::{OpenCC, config::BuiltinConfig};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use std::time::Instant;
|
||||
|
|
@ -160,6 +161,47 @@ async fn maybe_post_process_transcription(
|
|||
}
|
||||
}
|
||||
|
||||
async fn maybe_convert_chinese_variant(
|
||||
settings: &AppSettings,
|
||||
transcription: &str,
|
||||
) -> Option<String> {
|
||||
// Check if language is set to Simplified or Traditional Chinese
|
||||
let is_simplified = settings.selected_language == "zh-Hans";
|
||||
let is_traditional = settings.selected_language == "zh-Hant";
|
||||
|
||||
if !is_simplified && !is_traditional {
|
||||
debug!("selected_language is not Simplified or Traditional Chinese; skipping translation");
|
||||
return None;
|
||||
}
|
||||
|
||||
debug!("Starting Chinese translation using OpenCC for language: {}", settings.selected_language);
|
||||
|
||||
// Use OpenCC to convert based on selected language
|
||||
let config = if is_simplified {
|
||||
// Convert Traditional Chinese to Simplified Chinese
|
||||
BuiltinConfig::Tw2sp
|
||||
} else {
|
||||
// Convert Simplified Chinese to Traditional Chinese
|
||||
BuiltinConfig::S2twp
|
||||
};
|
||||
|
||||
match OpenCC::from_config(config) {
|
||||
Ok(converter) => {
|
||||
let converted = converter.convert(transcription);
|
||||
debug!(
|
||||
"OpenCC translation completed. Input length: {}, Output length: {}",
|
||||
transcription.len(),
|
||||
converted.len()
|
||||
);
|
||||
Some(converted)
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Failed to initialize OpenCC converter: {}. Falling back to original transcription.", e);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ShortcutAction for TranscribeAction {
|
||||
fn start(&self, app: &AppHandle, binding_id: &str, _shortcut_str: &str) {
|
||||
let start_time = Instant::now();
|
||||
|
|
@ -273,7 +315,15 @@ impl ShortcutAction for TranscribeAction {
|
|||
let mut post_processed_text: Option<String> = None;
|
||||
let mut post_process_prompt: Option<String> = None;
|
||||
|
||||
if let Some(processed_text) =
|
||||
// First, check if Chinese variant conversion is needed
|
||||
if let Some(converted_text) =
|
||||
maybe_convert_chinese_variant(&settings, &transcription).await
|
||||
{
|
||||
final_text = converted_text.clone();
|
||||
post_processed_text = Some(converted_text);
|
||||
}
|
||||
// Then apply regular post-processing if enabled
|
||||
else if let Some(processed_text) =
|
||||
maybe_post_process_transcription(&settings, &transcription).await
|
||||
{
|
||||
final_text = processed_text.clone();
|
||||
|
|
|
|||
|
|
@ -349,12 +349,21 @@ impl TranscriptionManager {
|
|||
|
||||
match engine {
|
||||
LoadedEngine::Whisper(whisper_engine) => {
|
||||
let params = WhisperInferenceParams {
|
||||
language: if settings.selected_language == "auto" {
|
||||
None
|
||||
// Normalize language code for Whisper
|
||||
// Convert zh-Hans and zh-Hant to zh since Whisper uses ISO 639-1 codes
|
||||
let whisper_language = if settings.selected_language == "auto" {
|
||||
None
|
||||
} else {
|
||||
let normalized = if settings.selected_language == "zh-Hans" || settings.selected_language == "zh-Hant" {
|
||||
"zh".to_string()
|
||||
} else {
|
||||
Some(settings.selected_language.clone())
|
||||
},
|
||||
settings.selected_language.clone()
|
||||
};
|
||||
Some(normalized)
|
||||
};
|
||||
|
||||
let params = WhisperInferenceParams {
|
||||
language: whisper_language,
|
||||
translate: settings.translate_to_english,
|
||||
..Default::default()
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ export interface Language {
|
|||
export const LANGUAGES: Language[] = [
|
||||
{ value: "auto", label: "Auto Detect" },
|
||||
{ value: "en", label: "English" },
|
||||
{ value: "zh", label: "Chinese" },
|
||||
{ value: "zh-Hans", label: "Simplified Chinese" },
|
||||
{ value: "zh-Hant", label: "Traditional Chinese" },
|
||||
{ value: "de", label: "German" },
|
||||
{ value: "es", label: "Spanish" },
|
||||
{ value: "ru", label: "Russian" },
|
||||
|
|
|
|||
Loading…
Reference in a new issue