deeptrans/translator/
engine.rs

1use super::qcri::Qcri;
2use std::{fmt, str::FromStr};
3
4#[macro_export]
5macro_rules! codes_to_languages {
6    ( $($key:expr => $value:expr),* ) => {{
7        let mut map = std::collections::HashMap::new();
8        $( map.insert($key.to_string(), $value.to_string()); )*
9        map
10    }}
11}
12
13pub type LanguagesToCodes = std::collections::HashMap<String, String>;
14
15#[derive(
16    Debug,
17    Default,
18    Copy,
19    Clone,
20    Eq,
21    PartialEq,
22    Ord,
23    PartialOrd,
24    serde::Deserialize,
25    serde::Serialize,
26)]
27/// Represent a version of translator API, currently is oly used with Deepl
28pub enum Version {
29    V1,
30    #[default]
31    V2,
32}
33
34impl FromStr for Version {
35    type Err = ();
36
37    fn from_str(s: &str) -> Result<Self, Self::Err> {
38        match s {
39            "v1" => Ok(Version::V1),
40            "v2" => Ok(Version::V2),
41            _ => Err(()),
42        }
43    }
44}
45
46impl fmt::Display for Version {
47    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48        match self {
49            Version::V1 => "v1",
50            Version::V2 => "v2",
51        }
52        .fmt(f)
53    }
54}
55
56/// Enum that wraps engines, which use the translator under the hood to translate word(s)
57#[derive(Debug, Default, Eq, PartialEq, Clone, serde::Deserialize, serde::Serialize)]
58pub enum Engine {
59    #[default]
60    Google,
61    /// Get one api key here: https://www.deepl.com/docs-api/accessing-the-api/
62    Deepl {
63        api_key: String,
64        version: Version,
65        use_free_api: bool,
66    },
67    /// List of LibreTranslate endpoint can be found at:
68    /// https://github.com/LibreTranslate/LibreTranslate#mirrors
69    /// Some require an API key
70    Libre {
71        api_key: String,
72        url: String,
73    },
74    Linguee {
75        return_all: bool,
76    },
77    Microsoft {
78        api_key: String,
79        region: String,
80    },
81    MyMemory {
82        email: String,
83        /// set to True to return all synonym/similars of the translated text
84        return_all: bool,
85    },
86    Papago {
87        client_id: String,
88        secret_key: String,
89    },
90    Pons {
91        return_all: bool,
92    },
93    Qcri(Qcri),
94    Yandex {
95        api_key: String,
96        //api_version: String,
97    },
98}
99
100impl Engine {
101    #[inline(always)]
102    pub fn base_url(&self) -> String {
103        match &self {
104            Self::Google => "https://translate.google.com/m".into(),
105            Self::Deepl {
106                use_free_api,
107                version,
108                ..
109            } => {
110                let free = if *use_free_api { "-free" } else { "" };
111                format!("https://api{free}/{version}/translate")
112            }
113            Self::Libre { url, .. } => format!("{url}/translate"),
114            Self::Linguee { .. } => "https://www.linguee.com/".into(),
115            Self::Microsoft { .. } => {
116                "https://api.cognitive.microsofttranslator.com/translate?api-version=3.0".into()
117            }
118            Self::MyMemory { .. } => "http://api.mymemory.translated.net/get".into(),
119            // "https://papago.naver.com/"
120            Self::Papago { .. } => "https://openapi.naver.com/v1/papago/n2mt".into(),
121            Self::Pons { .. } => "https://en.pons.com/translate/".into(),
122            Self::Qcri(..) => Qcri::base_url("translate"),
123            Self::Yandex { .. } => "https://translate.yandex.net/api/v1.5/tr.json/translate".into(),
124        }
125    }
126
127    #[inline(always)]
128    pub const fn name(&self) -> &str {
129        match &self {
130            Self::Google => "Google",
131            Self::Deepl { .. } => "Deepl",
132            Self::Libre { .. } => "Libre",
133            Self::Linguee { .. } => "Linguee",
134            Self::Microsoft { .. } => "Microsoft",
135            Self::MyMemory { .. } => "MyMemory",
136            Self::Papago { .. } => "Papago",
137            Self::Pons { .. } => "Pons",
138            Self::Qcri(..) => "Qcri",
139            Self::Yandex { .. } => "Yandex",
140        }
141    }
142
143    #[inline(always)]
144    pub fn supported_languages(&self) -> LanguagesToCodes {
145        match &self {
146            Self::Google | Self::MyMemory { .. } | Self::Yandex { .. } => {
147                crate::codes_to_languages! {
148                    "Afrikaans" => "af",
149                    "Albanian" => "sq",
150                    "Amharic" => "am",
151                    "Arabic" => "ar",
152                    "Armenian" => "hy",
153                    "Azerbaijani" => "az",
154                    "Basque" => "eu",
155                    "Belarusian" => "be",
156                    "Bengali" => "bn",
157                    "Bosnian" => "bs",
158                    "Bulgarian" => "bg",
159                    "Catalan" => "ca",
160                    "Cebuano" => "ceb",
161                    "Chichewa" => "ny",
162                    "Chinese (simplified)" => "zh-CN",
163                    "Chinese (traditional)" => "zh-TW",
164                    "Corsican" => "co",
165                    "Croatian" => "hr",
166                    "Czech" => "cs",
167                    "Danish" => "da",
168                    "Dutch" => "nl",
169                    "English" => "en",
170                    "Esperanto" => "eo",
171                    "Estonian" => "et",
172                    "Filipino" => "tl",
173                    "Finnish" => "fi",
174                    "French" => "fr",
175                    "Frisian" => "fy",
176                    "Galician" => "gl",
177                    "Georgian" => "ka",
178                    "German" => "de",
179                    "Greek" => "el",
180                    "Gujarati" => "gu",
181                    "Haitian creole" => "ht",
182                    "Hausa" => "ha",
183                    "Hawaiian" => "haw",
184                    "Hebrew" => "iw",
185                    "Hindi" => "hi",
186                    "Hmong" => "hmn",
187                    "Hungarian" => "hu",
188                    "Icelandic" => "is",
189                    "Igbo" => "ig",
190                    "Indonesian" => "id",
191                    "Irish" => "ga",
192                    "Italian" => "it",
193                    "Japanese" => "ja",
194                    "Javanese" => "jw",
195                    "Kannada" => "kn",
196                    "Kazakh" => "kk",
197                    "Khmer" => "km",
198                    "Kinyarwanda" => "rw",
199                    "Korean" => "ko",
200                    "Kurdish" => "ku",
201                    "Kyrgyz" => "ky",
202                    "Lao" => "lo",
203                    "Latin" => "la",
204                    "Latvian" => "lv",
205                    "Lithuanian" => "lt",
206                    "Luxembourgish" => "lb",
207                    "Macedonian" => "mk",
208                    "Malagasy" => "mg",
209                    "Malay" => "ms",
210                    "Malayalam" => "ml",
211                    "Maltese" => "mt",
212                    "Maori" => "mi",
213                    "Marathi" => "mr",
214                    "Mongolian" => "mn",
215                    "Myanmar" => "my",
216                    "Nepali" => "ne",
217                    "Norwegian" => "no",
218                    "Odia" => "or",
219                    "Pashto" => "ps",
220                    "Persian" => "fa",
221                    "Polish" => "pl",
222                    "Portuguese" => "pt",
223                    "Punjabi" => "pa",
224                    "Romanian" => "ro",
225                    "Russian" => "ru",
226                    "Samoan" => "sm",
227                    "Scots gaelic" => "gd",
228                    "Serbian" => "sr",
229                    "Sesotho" => "st",
230                    "Shona" => "sn",
231                    "Sindhi" => "sd",
232                    "Sinhala" => "si",
233                    "Slovak" => "sk",
234                    "Slovenian" => "sl",
235                    "Somali" => "so",
236                    "Spanish" => "es",
237                    "Sundanese" => "su",
238                    "Swahili" => "sw",
239                    "Swedish" => "sv",
240                    "Tajik" => "tg",
241                    "Tamil" => "ta",
242                    "Tatar" => "tt",
243                    "Telugu" => "te",
244                    "Thai" => "th",
245                    "Turkish" => "tr",
246                    "Turkmen" => "tk",
247                    "Ukrainian" => "uk",
248                    "Urdu" => "ur",
249                    "Uyghur" => "ug",
250                    "Uzbek" => "uz",
251                    "Vietnamese" => "vi",
252                    "Welsh" => "cy",
253                    "Xhosa" => "xh",
254                    "Yiddish" => "yi",
255                    "Yoruba" => "yo",
256                    "Zulu" => "zu"
257                }
258            }
259            Self::Libre { .. } => crate::codes_to_languages! {
260                "English" => "en",
261                "Arabic" => "ar",
262                "Chinese" => "zh",
263                "French" => "fr",
264                "German" => "de",
265                "Hindi" => "hi",
266                "Indonesian" => "id",
267                "Irish" => "ga",
268                "Italian" => "it",
269                "Japanese" => "ja",
270                "Korean" => "ko",
271                "Polish" => "pl",
272                "Portuguese" => "pt",
273                "Russian" => "ru",
274                "Spanish" => "es",
275                "Turkish" => "tr",
276                "Vietnamese" => "vi"
277            },
278            Self::Linguee { .. } => crate::codes_to_languages! {
279                "Maltese" => "mt",
280                "English" => "en",
281                "German" => "de",
282                "Bulgarian" => "bg",
283                "Polish" => "pl",
284                "Portuguese" => "pt",
285                "Hungarian" => "hu",
286                "Romanian" => "ro",
287                "Russian" => "ru",
288                // "serbian" => "sr",
289                "Dutch" => "nl",
290                "Slovakian" => "sk",
291                "Greek" => "el",
292                "Slovenian" => "sl",
293                "Danish" => "da",
294                "Italian" => "it",
295                "Spanish" => "es",
296                "Finnish" => "fi",
297                "Chinese" => "zh",
298                "French" => "fr",
299                // "croatian" => "hr",
300                "Czech" => "cs",
301                "Laotian" => "lo",
302                "Swedish" => "sv",
303                "Latvian" => "lv",
304                "Estonian" => "et",
305                "Japanese" => "ja"
306            },
307            Self::Microsoft { .. } => crate::codes_to_languages! {
308                "Afrikaans" => "af",
309                "Amharic" => "am",
310                "Arabic" => "ar",
311                "Assamese" => "as",
312                "Azerbaijani" => "az",
313                "Bashkir" => "ba",
314                "Bulgarian" => "bg",
315                "Bangla" => "bn",
316                "Tibetan" => "bo",
317                "Bosnian" => "bs",
318                "Catalan" => "ca",
319                "Czech" => "cs",
320                "Welsh" => "cy",
321                "Danish" => "da",
322                "German" => "de",
323                "Divehi" => "dv",
324                "Greek" => "el",
325                "English" => "en",
326                "Spanish" => "es",
327                "Estonian" => "et",
328                "Basque" => "eu",
329                "Persian" => "fa",
330                "Finnish" => "fi",
331                "Filipino" => "fil",
332                "Fijian" => "fj",
333                "Faroese" => "fo",
334                "French" => "fr",
335                "French (Canada)" => "fr-CA",
336                "Irish" => "ga",
337                "Galician" => "gl",
338                "Gujarati" => "gu",
339                "Hebrew" => "he",
340                "Hindi" => "hi",
341                "Croatian" => "hr",
342                "Upper Sorbian" => "hsb",
343                "Haitian Creole" => "ht",
344                "Hungarian" => "hu",
345                "Armenian" => "hy",
346                "Indonesian" => "id",
347                "Inuinnaqtun" => "ikt",
348                "Icelandic" => "is",
349                "Italian" => "it",
350                "Inuktitut" => "iu",
351                "Inuktitut (Latin)" => "iu-Latn",
352                "Japanese" => "ja",
353                "Georgian" => "ka",
354                "Kazakh" => "kk",
355                "Khmer" => "km",
356                "Kurdish (Northern)" => "kmr",
357                "Kannada" => "kn",
358                "Korean" => "ko",
359                "Kurdish (Central)" => "ku",
360                "Kyrgyz" => "ky",
361                "Lao" => "lo",
362                "Lithuanian" => "lt",
363                "Latvian" => "lv",
364                "Chinese (Literary)" => "lzh",
365                "Malagasy" => "mg",
366                "Māori" => "mi",
367                "Macedonian" => "mk",
368                "Malayalam" => "ml",
369                "Mongolian (Cyrillic)" => "mn-Cyrl",
370                "Mongolian (Traditional)" => "mn-Mong",
371                "Marathi" => "mr",
372                "Malay" => "ms",
373                "Maltese" => "mt",
374                "Hmong Daw" => "mww",
375                "Myanmar (Burmese)" => "my",
376                "Norwegian" => "nb",
377                "Nepali" => "ne",
378                "Dutch" => "nl",
379                "Odia" => "or",
380                "Querétaro Otomi" => "otq",
381                "Punjabi" => "pa",
382                "Polish" => "pl",
383                "Dari" => "prs",
384                "Pashto" => "ps",
385                "Portuguese (Brazil)" => "pt",
386                "Portuguese (Portugal)" => "pt-PT",
387                "Romanian" => "ro",
388                "Russian" => "ru",
389                "Slovak" => "sk",
390                "Slovenian" => "sl",
391                "Samoan" => "sm",
392                "Somali" => "so",
393                "Albanian" => "sq",
394                "Serbian (Cyrillic)" => "sr-Cyrl",
395                "Serbian (Latin)" => "sr-Latn",
396                "Swedish" => "sv",
397                "Swahili" => "sw",
398                "Tamil" => "ta",
399                "Telugu" => "te",
400                "Thai" => "th",
401                "Tigrinya" => "ti",
402                "Turkmen" => "tk",
403                "Klingon (Latin)" => "tlh-Latn",
404                "Klingon (pIqaD)" => "tlh-Piqd",
405                "Tongan" => "to",
406                "Turkish" => "tr",
407                "Tatar" => "tt",
408                "Tahitian" => "ty",
409                "Uyghur" => "ug",
410                "Ukrainian" => "uk",
411                "Urdu" => "ur",
412                "Uzbek (Latin)" => "uz",
413                "Vietnamese" => "vi",
414                "Yucatec Maya" => "yua",
415                "Cantonese (Traditional)" => "yue",
416                "Chinese Simplified" => "zh-Hans",
417                "Chinese Traditional" => "zh-Hant",
418                "Zulu" => "zu"
419            },
420            Self::Deepl { .. } => crate::codes_to_languages! {
421                "Bulgarian" => "bg",
422                "Czech" => "cs",
423                "Danish" => "da",
424                "German" => "de",
425                "Greek" => "el",
426                "English" => "en",
427                "Spanish" => "es",
428                "Estonian" => "et",
429                "Finnish" => "fi",
430                "French" => "fr",
431                "Hungarian" => "hu",
432                "Italian" => "it",
433                "Japanese" => "ja",
434                "Lithuanian" => "lt",
435                "Latvian" => "lv",
436                "Dutch" => "nl",
437                "Polish" => "pl",
438                "Portuguese" => "pt",
439                "Romanian" => "ro",
440                "Russian" => "ru",
441                "Slovak" => "sk",
442                "Slovenian" => "sl",
443                "Swedish" => "sv",
444                "Chinese" => "zh"
445            },
446
447            Self::Papago { .. } => crate::codes_to_languages! {
448                 "Korean" => "ko",
449                 "English" => "en",
450                 "Japanese" => "ja",
451                 "Chinese" => "zh-CN",
452                 "Chinese Traditional" => "zh-TW",
453                 "Spanish" => "es",
454                 "French" => "fr",
455                 "Vietnamese" => "vi",
456                 "Thai" => "th",
457                 "Indonesia" =>   "id"
458            },
459
460            Self::Pons { .. } => crate::codes_to_languages! {
461                 "Arabic" => "ar",
462                 "Bulgarian" => "bg",
463                 "Chinese" => "zh-cn",
464                 "Czech" => "cs",
465                 "Danish" => "da",
466                 "Dutch" => "nl",
467                 "English" => "en",
468                 "French" => "fr",
469                 "German" => "de",
470                 "Greek" => "el",
471                 "Hungarian" => "hu",
472                 "Italian" => "it",
473                 "Latin" => "la",
474                 "Norwegian" => "no",
475                 "Polish" => "pl",
476                 "Portuguese" => "pt",
477                 "Russian" => "ru",
478                 "Slovenian" => "sl",
479                 "Spanish" => "es",
480                 "Swedish" => "sv",
481                 "Turkish" => "tr",
482                 "Elvish" => "elv"
483            },
484
485            Self::Qcri(..) => crate::codes_to_languages! {
486                "Arabic" => "ar",
487                "English" => "en",
488                "Spanish" => "es"
489            },
490        }
491    }
492}