170 lines
4.2 KiB
Go
170 lines
4.2 KiB
Go
package simplytranslate_engines
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
)
|
|
|
|
// LibreTranslateEngine is an engine that interfaces with any
|
|
// [LibreTranslate](https://github.com/LibreTranslate/LibreTranslate) instance.
|
|
type LibreTranslateEngine struct {
|
|
// InstanceURL is the URL to a LibreTranslate instance, for instance
|
|
// "https://libretranslate.com".
|
|
InstanceURL string
|
|
// APIKey is the API key for the given instance. If empty, then no API
|
|
// key will be sent along with requests to the instance.
|
|
//
|
|
// Some instances issue API keys to users so that they can have a
|
|
// higher rate limit. See
|
|
// https://github.com/LibreTranslate/LibreTranslate#manage-api-keys for
|
|
// more information.
|
|
APIKey string
|
|
}
|
|
|
|
func (_ *LibreTranslateEngine) InternalName() string { return "libre" }
|
|
|
|
func (_ *LibreTranslateEngine) DisplayName() string { return "LibreTranslate" }
|
|
|
|
type libreLanguagesResponse []struct {
|
|
Name string `json:"name"`
|
|
Code string `json:"code"`
|
|
}
|
|
|
|
func (e *LibreTranslateEngine) getLangs() ([]Language, error) {
|
|
response, err := http.Get(e.InstanceURL + "/languages")
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
defer response.Body.Close()
|
|
|
|
if response.StatusCode != 200 {
|
|
return nil, fmt.Errorf("got status code %d from LibreTranslate API", response.StatusCode)
|
|
}
|
|
|
|
var langsResponse libreLanguagesResponse
|
|
|
|
if err := json.NewDecoder(response.Body).Decode(&langsResponse); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
langs := make([]Language, len(langsResponse))
|
|
|
|
for i, lang := range langsResponse {
|
|
langs[i] = Language{Name: lang.Name, Code: lang.Code}
|
|
}
|
|
|
|
return langs, nil
|
|
|
|
}
|
|
|
|
func (e *LibreTranslateEngine) SourceLanguages() ([]Language, error) { return e.getLangs() }
|
|
|
|
func (e *LibreTranslateEngine) TargetLanguages() ([]Language, error) { return e.getLangs() }
|
|
|
|
func (_ *LibreTranslateEngine) SupportsAutodetect() bool { return true }
|
|
|
|
type libreDetectResponse []struct {
|
|
Confidence float64 `json:"confidence"`
|
|
LanguageCode string `json:"language"`
|
|
}
|
|
|
|
func (e *LibreTranslateEngine) DetectLanguage(text string) (Language, error) {
|
|
formData := map[string]string{"q": text}
|
|
|
|
if e.APIKey != "" {
|
|
formData["api_key"] = e.APIKey
|
|
}
|
|
|
|
formDataJSON, err := json.Marshal(formData)
|
|
|
|
if err != nil {
|
|
return Language{}, err
|
|
}
|
|
|
|
response, err := http.Post(e.InstanceURL+"/detect", "application/json", bytes.NewBuffer(formDataJSON))
|
|
|
|
if err != nil {
|
|
return Language{}, err
|
|
}
|
|
|
|
defer response.Body.Close()
|
|
|
|
if response.StatusCode != 200 {
|
|
return Language{}, fmt.Errorf("got status code %d from LibreTranslate API", response.StatusCode)
|
|
}
|
|
|
|
var langs libreDetectResponse
|
|
|
|
if err := json.NewDecoder(response.Body).Decode(&langs); err != nil {
|
|
return Language{}, err
|
|
}
|
|
|
|
maxConfidenceLang := langs[0]
|
|
|
|
for _, lang := range langs[1:] {
|
|
if lang.Confidence > maxConfidenceLang.Confidence {
|
|
maxConfidenceLang = lang
|
|
}
|
|
}
|
|
|
|
engineLangs, err := e.getLangs()
|
|
|
|
if err != nil {
|
|
return Language{}, err
|
|
}
|
|
|
|
for _, lang := range engineLangs {
|
|
if lang.Code == maxConfidenceLang.LanguageCode {
|
|
return lang, nil
|
|
}
|
|
}
|
|
|
|
return Language{}, fmt.Errorf("language code \"%s\" is not in the instance's language list", maxConfidenceLang.LanguageCode)
|
|
}
|
|
|
|
type libreTranslateResponse struct {
|
|
TranslatedText string `json:"translatedText"`
|
|
}
|
|
|
|
func (e *LibreTranslateEngine) Translate(text string, from Language, to Language) (TranslationResult, error) {
|
|
formData := map[string]string{
|
|
"q": text,
|
|
"source": from.Code,
|
|
"target": to.Code,
|
|
}
|
|
|
|
if e.APIKey != "" {
|
|
formData["api_key"] = e.APIKey
|
|
}
|
|
|
|
formDataJSON, err := json.Marshal(formData)
|
|
|
|
if err != nil {
|
|
return TranslationResult{}, err
|
|
}
|
|
|
|
response, err := http.Post(e.InstanceURL+"/translate", "application/json", bytes.NewBuffer(formDataJSON))
|
|
|
|
if err != nil {
|
|
return TranslationResult{}, err
|
|
}
|
|
|
|
defer response.Body.Close()
|
|
|
|
if response.StatusCode != 200 {
|
|
return TranslationResult{}, fmt.Errorf("got status code %d from LibreTranslate API", response.StatusCode)
|
|
}
|
|
|
|
var responseJSON libreTranslateResponse
|
|
|
|
if err := json.NewDecoder(response.Body).Decode(&responseJSON); err != nil {
|
|
return TranslationResult{}, err
|
|
}
|
|
|
|
return TranslationResult{SourceLanguage: from, TranslatedText: responseJSON.TranslatedText}, nil
|
|
}
|