mai/engines/libretranslate.go
yakumo.izuru 21388e220d GET HTTP リクエストが機能しない問題を修正し、iCIBA および LibreTranslate エンジンを再追加し、マニュアル ページを作成し、Docker に関連するものを削除しました。
Signed-off-by: Izuru Yakumo <yakumo.izuru@chaotic.ninja>

git-svn-id: file:///srv/svn/repo/mai/trunk@60 e410bdd4-646f-c54f-a7ce-fffcc4f439ae
2024-01-20 23:01:02 +00:00

170 lines
3.9 KiB
Go

package engines
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
)
// LibreTranslate is an engine that interfaces with any
// [LibreTranslate](https://github.com/LibreTranslate/LibreTranslate) instance.
type LibreTranslate struct {
// InstanceURL is the URL to a LibreTranslate instance, for example
// "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 (_ *LibreTranslate) DisplayName() string { return "LibreTranslate" }
func (e *LibreTranslate) 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 []struct {
Name string `json:"name"`
Code string `json:"code"`
}
if err := json.NewDecoder(response.Body).Decode(&langsResponse); err != nil {
return nil, err
}
langs := Language{}
for _, lang := range langsResponse {
langs[lang.Code] = lang.Name
}
return langs, nil
}
func (e *LibreTranslate) SourceLanguages() (Language, error) { return e.getLangs() }
func (e *LibreTranslate) TargetLanguages() (Language, error) { return e.getLangs() }
func (e *LibreTranslate) Tts(text, lang string) (string, error) { return "", nil }
type libreDetectResponse []struct {
Confidence float64 `json:"confidence"`
LanguageCode string `json:"language"`
}
func (e *LibreTranslate) detectLanguage(text string) (string, error) {
formData := map[string]string{"q": text}
if e.APIKey != "" {
formData["api_key"] = e.APIKey
}
formDataJSON, err := json.Marshal(formData)
if err != nil {
return "", err
}
response, err := http.Post(e.InstanceURL+"/detect", "application/json", bytes.NewBuffer(formDataJSON))
if err != nil {
return "", err
}
defer response.Body.Close()
if response.StatusCode != 200 {
return "", 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 "", err
}
maxConfidenceLang := langs[0]
for _, lang := range langs[1:] {
if lang.Confidence > maxConfidenceLang.Confidence {
maxConfidenceLang = lang
}
}
engineLangs, err := e.getLangs()
if err != nil {
return "", err
}
for code := range engineLangs {
if code == maxConfidenceLang.LanguageCode {
return code, nil
}
}
return "", fmt.Errorf("language code \"%s\" is not in the instance's language list", maxConfidenceLang.LanguageCode)
}
func (e *LibreTranslate) Translate(text string, from, to string) (TranslationResult, error) {
formData := map[string]string{
"q": text,
"source": from,
"target": to,
}
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 struct {
TranslatedText string `json:"translatedText"`
}
if err := json.NewDecoder(response.Body).Decode(&responseJSON); err != nil {
return TranslationResult{}, err
}
if r, err := e.detectLanguage(text); err == nil {
from = r
}
return TranslationResult{
TranslatedText: responseJSON.TranslatedText,
SourceLanguage: from,
}, nil
}