source: code/trunk/engines/reverso.go@ 13

Last change on this file since 13 was 13, checked in by fattalion, 2 years ago

Add Reverso engine

File size: 3.9 KB
RevLine 
[13]1package engines
2
3import (
4 "bytes"
5 "encoding/json"
6 "fmt"
7 "net/http"
8)
9
10// Reverso is an engine that fetches data from https://reverso.net.
11type Reverso struct{}
12
13func (_ *Reverso) InternalName() string { return "reverso" }
14
15func (_ *Reverso) DisplayName() string { return "Reverso" }
16
17var reversoLangs = []Language{
18 {Name: "Arabic", Code: "ara"},
19 {Name: "Chinese (Simplified)", Code: "chi"}, // marketed as just "Chinese"
20 {Name: "Czech", Code: "cze"},
21 {Name: "Danish", Code: "dan"},
22 {Name: "Dutch", Code: "dut"},
23 {Name: "English", Code: "eng"},
24 {Name: "French", Code: "fra"},
25 {Name: "German", Code: "ger"},
26 {Name: "Hebrew", Code: "heb"},
27 {Name: "Hindi", Code: "hin"},
28 {Name: "Hungarian", Code: "hun"},
29 {Name: "Italian", Code: "ita"},
30 {Name: "Japanese", Code: "jpn"},
31 {Name: "Korean", Code: "kor"},
32 {Name: "Persian", Code: "per"},
33 {Name: "Polish", Code: "pol"},
34 {Name: "Portuguese", Code: "por"},
35 {Name: "Romanian", Code: "rum"},
36 {Name: "Russian", Code: "rus"},
37 {Name: "Slovak", Code: "slo"},
38 {Name: "Spanish", Code: "spa"},
39 {Name: "Swedish", Code: "swe"},
40 {Name: "Thai", Code: "tha"},
41 {Name: "Turkish", Code: "tur"},
42 {Name: "Ukrainian", Code: "ukr"},
43}
44
45func (_ *Reverso) SourceLanguages() ([]Language, error) { return reversoLangs, nil }
46
47func (_ *Reverso) TargetLanguages() ([]Language, error) { return reversoLangs, nil }
48
49func (_ *Reverso) SupportsAutodetect() bool { return true }
50
51type reversoAPIResponse struct {
52 LanguageDetection struct {
53 DetectedLanguage string `json:"detectedLanguage"`
54 } `json:"languageDetection"`
55 Translation []string `json:"translation"`
56}
57
58func (e *Reverso) callAPI(text string, from, to Language) (reversoAPIResponse, error) {
59 // `contextResults` must be false for language detection
60 formData := map[string]interface{}{
61 "format": "text",
62 "from": from.Code,
63 "to": to.Code,
64 "input": text,
65 "options": map[string]interface{}{
66 "sentenceSplitter": false,
67 "origin": "translation.web",
68 "contextResults": false,
69 "languageDetection": true,
70 },
71 }
72
73 formDataJSON, err := json.Marshal(formData)
74
75 if err != nil {
76 return reversoAPIResponse{}, err
77 }
78
79 request, err := http.NewRequest("POST", "https://api.reverso.net/translate/v1/translation", bytes.NewBuffer(formDataJSON))
80
81 if err != nil {
82 return reversoAPIResponse{}, err
83 }
84
85 request.Header.Set("Content-Type", "application/json")
86 // Returns 403 with empty or no user agent.
87 request.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; rv:110.0) Gecko/20100101 Firefox/110.0")
88
89 client := &http.Client{}
90
91 response, err := client.Do(request)
92
93 if err != nil {
94 return reversoAPIResponse{}, err
95 }
96
97 defer response.Body.Close()
98
99 if response.StatusCode != 200 {
100 return reversoAPIResponse{}, fmt.Errorf("got status code %d from Reverso API", response.StatusCode)
101 }
102
103 var result reversoAPIResponse
104
105 if err := json.NewDecoder(response.Body).Decode(&result); err != nil {
106 return reversoAPIResponse{}, err
107 }
108
109 return result, nil
110}
111
112func (e *Reverso) DetectLanguage(text string) (Language, error) {
113 // Any language pair works here, does not affect result
114 r, err := e.callAPI(text, reversoLangs[0], reversoLangs[1])
115
116 if err != nil {
117 return Language{}, err
118 }
119
120 langCode := r.LanguageDetection.DetectedLanguage
121
122 for _, lang := range reversoLangs {
123 if lang.Code == langCode {
124 return lang, nil
125 }
126 }
127
128 return Language{}, fmt.Errorf("language code \"%s\" is not in Reverso's language list", langCode)
129}
130
131func (e *Reverso) Translate(text string, from, to Language) (TranslationResult, error) {
132 if from.Code == "auto" {
133 from_, err := e.DetectLanguage(text)
134
135 if err != nil {
136 return TranslationResult{}, err
137 }
138
139 from = from_
140 }
141
142 var translation string
143
144 if from == to {
145 translation = text
146 } else {
147 r, err := e.callAPI(text, from, to)
148
149 if err != nil {
150 return TranslationResult{}, err
151 }
152
153 translation = r.Translation[0]
154 }
155
156 return TranslationResult{
157 SourceLanguage: from,
158 TranslatedText: translation,
159 }, nil
160}
Note: See TracBrowser for help on using the repository browser.