diff options
| author | Malte Voos <git@mal.tc> | 2025-12-05 15:35:38 +0100 |
|---|---|---|
| committer | Malte Voos <git@mal.tc> | 2025-12-05 15:43:58 +0100 |
| commit | c347b6133365dcf1b7da4e77890b20d04d6cfba4 (patch) | |
| tree | c83aac6f7d1e6edc57e607f01e5d3eeee8da4a0e /src/translation/deepl.rs | |
| parent | 652b1c2a0ce7db4885ebc51f7f09133a43401442 (diff) | |
| download | lleap-c347b6133365dcf1b7da4e77890b20d04d6cfba4.tar.gz lleap-c347b6133365dcf1b7da4e77890b20d04d6cfba4.zip | |
Diffstat (limited to 'src/translation/deepl.rs')
| -rw-r--r-- | src/translation/deepl.rs | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/src/translation/deepl.rs b/src/translation/deepl.rs new file mode 100644 index 0000000..f2e84d7 --- /dev/null +++ b/src/translation/deepl.rs @@ -0,0 +1,106 @@ +use std::{collections::BTreeMap, time::Duration}; + +use deepl::DeepLApi; +use relm4::prelude::*; + +use crate::{ + settings::Settings, + subtitles::{SUBTITLE_TRACKS, StreamIndex}, + translation::TRANSLATIONS, +}; + +pub struct DeeplTranslator { + stream_ix: Option<StreamIndex>, + next_cues_to_translate: BTreeMap<StreamIndex, usize>, +} + +#[derive(Debug)] +pub enum DeeplTranslatorMsg { + SelectTrack(Option<StreamIndex>), + // this is only used to drive the async translation + DoTranslate, +} + +impl AsyncComponent for DeeplTranslator { + type Init = (); + type Input = DeeplTranslatorMsg; + type Output = (); + type CommandOutput = (); + type Root = (); + type Widgets = (); + + async fn init( + _init: Self::Init, + _root: Self::Root, + sender: relm4::AsyncComponentSender<Self>, + ) -> AsyncComponentParts<Self> { + let model = Self { + stream_ix: None, + next_cues_to_translate: BTreeMap::new(), + }; + + sender.input(DeeplTranslatorMsg::DoTranslate); + + AsyncComponentParts { model, widgets: () } + } + + async fn update( + &mut self, + message: Self::Input, + sender: AsyncComponentSender<Self>, + _root: &Self::Root, + ) { + match message { + DeeplTranslatorMsg::SelectTrack(stream_ix) => { + self.stream_ix = stream_ix; + } + DeeplTranslatorMsg::DoTranslate => self.do_translate(sender).await, + } + } + + fn init_root() -> Self::Root { + () + } +} + +impl DeeplTranslator { + async fn do_translate(&mut self, sender: AsyncComponentSender<Self>) { + if let Some(stream_ix) = self.stream_ix { + let deepl = DeepLApi::with(&Settings::default().deepl_api_key()).new(); + + let next_cue_to_translate = self.next_cues_to_translate.entry(stream_ix).or_insert(0); + + if let Some(cue) = { + SUBTITLE_TRACKS + .read() + .get(&stream_ix) + .unwrap() + .texts + .get(*next_cue_to_translate) + .cloned() + } { + match deepl + .translate_text(cue, deepl::Lang::EN) + .model_type(deepl::ModelType::PreferQualityOptimized) + .await + { + Ok(mut resp) => { + TRANSLATIONS + .write() + .entry(stream_ix) + .or_insert(Vec::new()) + .push(resp.translations.pop().unwrap().text); + + *next_cue_to_translate = *next_cue_to_translate + 1; + } + Err(e) => { + log::error!("error fetching translation: {}", e) + } + }; + } + } + + relm4::tokio::time::sleep(Duration::from_secs(1)).await; + sender.input(DeeplTranslatorMsg::DoTranslate); + } +} |