source: code/trunk/engines/libretranslate.go@ 23

Last change on this file since 23 was 23, checked in by manerakai, 22 months ago

Improved code

File size: 3.9 KB
Line 
1package engines
2
3import (
4 "bytes"
5 "encoding/json"
6 "fmt"
7 "net/http"
8)
9
10// LibreTranslate is an engine that interfaces with any
11// [LibreTranslate](https://github.com/LibreTranslate/LibreTranslate) instance.
12type LibreTranslate struct {
13 // InstanceURL is the URL to a LibreTranslate instance, for example
14 // "https://libretranslate.com".
15 InstanceURL string
16 // APIKey is the API key for the given instance. If empty, then no API
17 // key will be sent along with requests to the instance.
18 //
19 // Some instances issue API keys to users so that they can have a
20 // higher rate limit. See
21 // https://github.com/LibreTranslate/LibreTranslate#manage-api-keys for
22 // more information.
23 APIKey string
24}
25
26func (_ *LibreTranslate) DisplayName() string { return "LibreTranslate" }
27
28func (e *LibreTranslate) getLangs() (Language, error) {
29 response, err := http.Get(e.InstanceURL + "/languages")
30
31 if err != nil {
32 return nil, err
33 }
34
35 defer response.Body.Close()
36
37 if response.StatusCode != 200 {
38 return nil, fmt.Errorf("got status code %d from LibreTranslate API", response.StatusCode)
39 }
40
41 var langsResponse []struct {
42 Name string `json:"name"`
43 Code string `json:"code"`
44 }
45
46 if err := json.NewDecoder(response.Body).Decode(&langsResponse); err != nil {
47 return nil, err
48 }
49
50 langs := Language{}
51
52 for _, lang := range langsResponse {
53 langs[lang.Code] = lang.Name
54 }
55
56 return langs, nil
57
58}
59
60func (e *LibreTranslate) SourceLanguages() (Language, error) { return e.getLangs() }
61
62func (e *LibreTranslate) TargetLanguages() (Language, error) { return e.getLangs() }
63
64func (e *LibreTranslate) Tts(text, lang string) (string, error) { return "", nil }
65
66type libreDetectResponse []struct {
67 Confidence float64 `json:"confidence"`
68 LanguageCode string `json:"language"`
69}
70
71func (e *LibreTranslate) detectLanguage(text string) (string, error) {
72 formData := map[string]string{"q": text}
73
74 if e.APIKey != "" {
75 formData["api_key"] = e.APIKey
76 }
77
78 formDataJSON, err := json.Marshal(formData)
79
80 if err != nil {
81 return "", err
82 }
83
84 response, err := http.Post(e.InstanceURL+"/detect", "application/json", bytes.NewBuffer(formDataJSON))
85
86 if err != nil {
87 return "", err
88 }
89
90 defer response.Body.Close()
91
92 if response.StatusCode != 200 {
93 return "", fmt.Errorf("got status code %d from LibreTranslate API", response.StatusCode)
94 }
95
96 var langs libreDetectResponse
97
98 if err := json.NewDecoder(response.Body).Decode(&langs); err != nil {
99 return "", err
100 }
101
102 maxConfidenceLang := langs[0]
103
104 for _, lang := range langs[1:] {
105 if lang.Confidence > maxConfidenceLang.Confidence {
106 maxConfidenceLang = lang
107 }
108 }
109
110 engineLangs, err := e.getLangs()
111
112 if err != nil {
113 return "", err
114 }
115
116 for code := range engineLangs {
117 if code == maxConfidenceLang.LanguageCode {
118 return code, nil
119 }
120 }
121
122 return "", fmt.Errorf("language code \"%s\" is not in the instance's language list", maxConfidenceLang.LanguageCode)
123}
124
125func (e *LibreTranslate) Translate(text string, from, to string) (TranslationResult, error) {
126 formData := map[string]string{
127 "q": text,
128 "source": from,
129 "target": to,
130 }
131
132 if e.APIKey != "" {
133 formData["api_key"] = e.APIKey
134 }
135
136 formDataJSON, err := json.Marshal(formData)
137
138 if err != nil {
139 return TranslationResult{}, err
140 }
141
142 response, err := http.Post(e.InstanceURL+"/translate", "application/json", bytes.NewBuffer(formDataJSON))
143
144 if err != nil {
145 return TranslationResult{}, err
146 }
147
148 defer response.Body.Close()
149
150 if response.StatusCode != 200 {
151 return TranslationResult{}, fmt.Errorf("got status code %d from LibreTranslate API", response.StatusCode)
152 }
153
154 var responseJSON struct {
155 TranslatedText string `json:"translatedText"`
156 }
157
158 if err := json.NewDecoder(response.Body).Decode(&responseJSON); err != nil {
159 return TranslationResult{}, err
160 }
161
162 if r, err := e.detectLanguage(text); err == nil {
163 from = r
164 }
165
166 return TranslationResult{
167 TranslatedText: responseJSON.TranslatedText,
168 SourceLanguage: from,
169 }, nil
170}
Note: See TracBrowser for help on using the repository browser.