v/GTT
1
0
mirror of https://github.com/eeeXun/GTT.git synced 2025-05-16 07:40:44 -07:00

feat: add LibreTranslate, remove ArgosTranslate

ArgosTranslate is offline. Change it to LibreTranslate
This commit is contained in:
eeeXun 2024-08-10 21:45:32 +08:00
parent b3f4135732
commit 8a9f267229
9 changed files with 169 additions and 76 deletions

View File

@ -4,12 +4,12 @@ Google Translate TUI (Originally)
Supported Translator: Supported Translator:
[`Apertium`](https://www.apertium.org/), [`Apertium`](https://www.apertium.org/),
[`Argos`](https://translate.argosopentech.com/),
[`Bing`](https://www.bing.com/translator), [`Bing`](https://www.bing.com/translator),
[`ChatGPT`](https://chat.openai.com/), [`ChatGPT`](https://chat.openai.com/),
[`DeepL`](https://deepl.com/translator)(only free API), [`DeepL`](https://deepl.com/translator)(only free API),
[`DeepLX`](https://github.com/OwO-Network/DeepLX), [`DeepLX`](https://github.com/OwO-Network/DeepLX),
[`Google`](https://translate.google.com/)(default), [`Google`](https://translate.google.com/)(default),
[`Libre`](https://libretranslate.com/),
[`Reverso`](https://www.reverso.net/text-translation) [`Reverso`](https://www.reverso.net/text-translation)
## ScreenShot ## ScreenShot
@ -52,6 +52,22 @@ host:
deeplx: 127.0.0.1:1188 # <- Replace with your server IP address and port deeplx: 127.0.0.1:1188 # <- Replace with your server IP address and port
``` ```
## Libre
If you want to use official [LibreTranslate](https://libretranslate.com/), you have to obtain an API Key on their [website](https://portal.libretranslate.com/).
Alternatively, if you want to host it by yourself, you must provide the IP address and port.
Make sure add them to `$XDG_CONFIG_HOME/gtt/server.yaml` or `$HOME/.config/gtt/server.yaml`.
See the example in [server.yaml](example/server.yaml) file.
```yaml
api_key:
libre:
value: LIBRE_API_KEY # <- Replace with your API Key
# file: $HOME/secrets/libre.txt # <- You can also specify the file where to read API Key
host:
libre: 127.0.0.1:5000 # <- Replace with your server IP address and port
```
## Install ## Install
### Dependencies ### Dependencies
@ -214,12 +230,12 @@ gtt -src "English" -dst "Chinese (Traditional)"
See available languages on: See available languages on:
- [Apertium Translate](https://www.apertium.org/) for `Apertium` - [Apertium Translate](https://www.apertium.org/) for `Apertium`
- [argosopentech/argos-translate](https://github.com/argosopentech/argos-translate#supported-languages) for `Argos`
- [Bing language-support](https://learn.microsoft.com/en-us/azure/cognitive-services/translator/language-support#translation) for `Bing` - [Bing language-support](https://learn.microsoft.com/en-us/azure/cognitive-services/translator/language-support#translation) for `Bing`
- `ChatGPT` is same as `Google`. See [Google Language support](https://cloud.google.com/translate/docs/languages) - `ChatGPT` is same as `Google`. See [Google Language support](https://cloud.google.com/translate/docs/languages)
- [DeepL API docs](https://www.deepl.com/docs-api/translate-text/) for `DeepL` - [DeepL API docs](https://www.deepl.com/docs-api/translate-text/) for `DeepL`
- `DeepLX` is same as `DeepL`. See [DeepL API docs](https://cloud.google.com/translate/docs/languages) - `DeepLX` is same as `DeepL`. See [DeepL API docs](https://cloud.google.com/translate/docs/languages)
- [Google Language support](https://cloud.google.com/translate/docs/languages) for `Google` - [Google Language support](https://cloud.google.com/translate/docs/languages) for `Google`
- [LibreTranslate Languages](https://libretranslate.com/languages) for `Libre`
- [Reverso Translation](https://www.reverso.net/text-translation) for `Reverso` - [Reverso Translation](https://www.reverso.net/text-translation) for `Reverso`
## Credit ## Credit

View File

@ -45,8 +45,6 @@ func configInit() {
"destination.border_color": "blue", "destination.border_color": "blue",
"source.language.apertium": "English", "source.language.apertium": "English",
"destination.language.apertium": "English", "destination.language.apertium": "English",
"source.language.argos": "English",
"destination.language.argos": "English",
"source.language.bing": "English", "source.language.bing": "English",
"destination.language.bing": "English", "destination.language.bing": "English",
"source.language.chatgpt": "English", "source.language.chatgpt": "English",
@ -57,6 +55,8 @@ func configInit() {
"destination.language.deeplx": "English", "destination.language.deeplx": "English",
"source.language.google": "English", "source.language.google": "English",
"destination.language.google": "English", "destination.language.google": "English",
"source.language.libre": "English",
"destination.language.libre": "English",
"source.language.reverso": "English", "source.language.reverso": "English",
"destination.language.reverso": "English", "destination.language.reverso": "English",
"translator": "Google", "translator": "Google",
@ -162,7 +162,7 @@ func configInit() {
// Import api key and host if file exists // Import api key and host if file exists
if err := serverConfig.ReadInConfig(); err == nil { if err := serverConfig.ReadInConfig(); err == nil {
// api key // api key
for _, name := range []string{"ChatGPT", "DeepL", "DeepLX"} { for _, name := range []string{"ChatGPT", "DeepL", "DeepLX", "Libre"} {
// Read from value first, then read from file // Read from value first, then read from file
if serverConfig.Get(fmt.Sprintf("api_key.%s.value", name)) != nil { if serverConfig.Get(fmt.Sprintf("api_key.%s.value", name)) != nil {
translators[name].SetAPIKey(serverConfig.GetString(fmt.Sprintf("api_key.%s.value", name))) translators[name].SetAPIKey(serverConfig.GetString(fmt.Sprintf("api_key.%s.value", name)))
@ -174,8 +174,10 @@ func configInit() {
} }
} }
// host // host
if serverConfig.Get("host.deeplx") != nil { for _, name := range []string{"DeepLX", "Libre"} {
translators["DeepLX"].SetHost(serverConfig.GetString("host.deeplx")) if serverConfig.Get(fmt.Sprintf("host.%s", name)) != nil {
translators[name].SetHost(serverConfig.GetString(fmt.Sprintf("host.%s", name)))
}
} }
} }
// Set argument language // Set argument language

View File

@ -9,5 +9,9 @@ api_key:
deeplx: deeplx:
value: DEEPLX_API_KEY value: DEEPLX_API_KEY
# file: $HOME/secrets/deeplx.txt # file: $HOME/secrets/deeplx.txt
libre:
value: LIBRE_API_KEY
# file: $HOME/secrets/libre.txt
host: host:
deeplx: 127.0.0.1:1188 deeplx: 127.0.0.1:1188
libre: 127.0.0.1:5000

View File

@ -1,44 +0,0 @@
package argos
var (
lang = []string{
"Arabic",
"Auto",
"Chinese",
"English",
"French",
"German",
"Hindi",
"Indonesian",
"Irish",
"Italian",
"Japanese",
"Korean",
"Polish",
"Portuguese",
"Russian",
"Spanish",
"Turkish",
"Vietnamese",
}
langCode = map[string]string{
"Arabic": "ar",
"Auto": "auto",
"Chinese": "zh",
"English": "en",
"French": "fr",
"German": "de",
"Hindi": "hi",
"Indonesian": "id",
"Irish": "ga",
"Italian": "it",
"Japanese": "ja",
"Korean": "ko",
"Polish": "pl",
"Portuguese": "pt",
"Russian": "ru",
"Spanish": "es",
"Turkish": "tr",
"Vietnamese": "vi",
}
)

View File

@ -141,22 +141,28 @@ func (t *Translator) Translate(message string) (translation *core.Translation, e
} }
// Bing will return the request with list when success. // Bing will return the request with list when success.
// Otherwises, it would return map. Then the following err would not be nil. // Otherwises, it would return map. Then the following err would not be nil.
if err = json.Unmarshal(body, &data); err == nil { if err = json.Unmarshal(body, &data); err != nil {
poses := make(posSet) return nil, err
for _, pos := range data[0].(map[string]interface{})["translations"].([]interface{}) {
pos := pos.(map[string]interface{})
var words posWords
words.target = pos["displayTarget"].(string)
for _, backTranslation := range pos["backTranslations"].([]interface{}) {
backTranslation := backTranslation.(map[string]interface{})
words.add(backTranslation["displayText"].(string))
}
poses.add(pos["posTag"].(string), words)
}
translation.POS = poses.format()
} }
if len(data) <= 0 {
return nil, errors.New("Translation not found")
}
poses := make(posSet)
for _, pos := range data[0].(map[string]interface{})["translations"].([]interface{}) {
pos := pos.(map[string]interface{})
var words posWords
words.target = pos["displayTarget"].(string)
for _, backTranslation := range pos["backTranslations"].([]interface{}) {
backTranslation := backTranslation.(map[string]interface{})
words.add(backTranslation["displayText"].(string))
}
poses.add(pos["posTag"].(string), words)
}
translation.POS = poses.format()
return translation, nil return translation, nil
} }

View File

@ -62,7 +62,7 @@ func (t *Translator) Translate(message string) (translation *core.Translation, e
} }
if len(data) <= 0 { if len(data) <= 0 {
return nil, errors.New("translation not found") return nil, errors.New("Translation not found")
} }
if res.StatusCode != 200 { if res.StatusCode != 200 {
return nil, errors.New(data["message"].(string)) return nil, errors.New(data["message"].(string))

View File

@ -0,0 +1,98 @@
package libre
var (
lang = []string{
"Albanian",
"Arabic",
"Auto",
"Azerbaijani",
"Bengali",
"Bulgarian",
"Catalan",
"Chinese",
"Chinese (traditional)",
"Czech",
"Danish",
"Dutch",
"English",
"Esperanto",
"Estonian",
"Finnish",
"French",
"German",
"Greek",
"Hebrew",
"Hindi",
"Hungarian",
"Indonesian",
"Irish",
"Italian",
"Japanese",
"Korean",
"Latvian",
"Lithuanian",
"Malay",
"Norwegian",
"Persian",
"Polish",
"Portuguese",
"Romanian",
"Russian",
"Slovak",
"Slovenian",
"Spanish",
"Swedish",
"Tagalog",
"Thai",
"Turkish",
"Ukranian",
"Urdu",
}
langCode = map[string]string{
"Albanian": "sq",
"Arabic": "ar",
"Auto": "auto",
"Azerbaijani": "az",
"Bengali": "bn",
"Bulgarian": "bg",
"Catalan": "ca",
"Chinese": "zh",
"Chinese (traditional)": "zt",
"Czech": "cs",
"Danish": "da",
"Dutch": "nl",
"English": "en",
"Esperanto": "eo",
"Estonian": "et",
"Finnish": "fi",
"French": "fr",
"German": "de",
"Greek": "el",
"Hebrew": "he",
"Hindi": "hi",
"Hungarian": "hu",
"Indonesian": "id",
"Irish": "ga",
"Italian": "it",
"Japanese": "ja",
"Korean": "ko",
"Latvian": "lv",
"Lithuanian": "lt",
"Malay": "ms",
"Norwegian": "nb",
"Persian": "fa",
"Polish": "pl",
"Portuguese": "pt",
"Romanian": "ro",
"Russian": "ru",
"Slovak": "sk",
"Slovenian": "sl",
"Spanish": "es",
"Swedish": "sv",
"Tagalog": "tl",
"Thai": "th",
"Turkish": "tr",
"Ukranian": "uk",
"Urdu": "ur",
}
)

View File

@ -1,4 +1,4 @@
package argos package libre
import ( import (
"encoding/json" "encoding/json"
@ -11,7 +11,7 @@ import (
) )
const ( const (
textURL = "https://translate.argosopentech.com/translate" defaultURL = "https://libretranslate.com/translate"
) )
type Translator struct { type Translator struct {
@ -26,7 +26,7 @@ func NewTranslator() *Translator {
Server: new(core.Server), Server: new(core.Server),
Language: new(core.Language), Language: new(core.Language),
TTS: core.NewTTS(), TTS: core.NewTTS(),
EngineName: core.NewEngineName("Argos"), EngineName: core.NewEngineName("Libre"),
} }
} }
@ -38,11 +38,19 @@ func (t *Translator) Translate(message string) (translation *core.Translation, e
translation = new(core.Translation) translation = new(core.Translation)
var data map[string]interface{} var data map[string]interface{}
var textURL string
if len(t.GetHost()) > 0 {
textURL = "http://"+t.GetHost()+"/translate"
} else {
textURL = defaultURL
}
res, err := http.PostForm(textURL, res, err := http.PostForm(textURL,
url.Values{ url.Values{
"q": {message}, "q": {message},
"source": {langCode[t.GetSrcLang()]}, "source": {langCode[t.GetSrcLang()]},
"target": {langCode[t.GetDstLang()]}, "target": {langCode[t.GetDstLang()]},
"api_key": {t.GetAPIKey()},
}) })
if err != nil { if err != nil {
return nil, err return nil, err
@ -58,6 +66,9 @@ func (t *Translator) Translate(message string) (translation *core.Translation, e
if len(data) <= 0 { if len(data) <= 0 {
return nil, errors.New("Translation not found") return nil, errors.New("Translation not found")
} }
if res.StatusCode != 200 {
return nil, errors.New(data["error"].(string))
}
translation.TEXT = data["translatedText"].(string) translation.TEXT = data["translatedText"].(string)

View File

@ -2,25 +2,25 @@ package translate
import ( import (
"github.com/eeeXun/gtt/internal/translate/apertium" "github.com/eeeXun/gtt/internal/translate/apertium"
"github.com/eeeXun/gtt/internal/translate/argos"
"github.com/eeeXun/gtt/internal/translate/bing" "github.com/eeeXun/gtt/internal/translate/bing"
"github.com/eeeXun/gtt/internal/translate/chatgpt" "github.com/eeeXun/gtt/internal/translate/chatgpt"
"github.com/eeeXun/gtt/internal/translate/core" "github.com/eeeXun/gtt/internal/translate/core"
"github.com/eeeXun/gtt/internal/translate/deepl" "github.com/eeeXun/gtt/internal/translate/deepl"
"github.com/eeeXun/gtt/internal/translate/deeplx" "github.com/eeeXun/gtt/internal/translate/deeplx"
"github.com/eeeXun/gtt/internal/translate/google" "github.com/eeeXun/gtt/internal/translate/google"
"github.com/eeeXun/gtt/internal/translate/libre"
"github.com/eeeXun/gtt/internal/translate/reverso" "github.com/eeeXun/gtt/internal/translate/reverso"
) )
var ( var (
AllTranslator = []string{ AllTranslator = []string{
"Apertium", "Apertium",
"Argos",
"Bing", "Bing",
"ChatGPT", "ChatGPT",
"DeepL", "DeepL",
"DeepLX", "DeepLX",
"Google", "Google",
"Libre",
"Reverso", "Reverso",
} }
) )
@ -75,8 +75,6 @@ func NewTranslator(name string) Translator {
switch name { switch name {
case "Apertium": case "Apertium":
translator = apertium.NewTranslator() translator = apertium.NewTranslator()
case "Argos":
translator = argos.NewTranslator()
case "Bing": case "Bing":
translator = bing.NewTranslator() translator = bing.NewTranslator()
case "ChatGPT": case "ChatGPT":
@ -87,6 +85,8 @@ func NewTranslator(name string) Translator {
translator = deeplx.NewTranslator() translator = deeplx.NewTranslator()
case "Google": case "Google":
translator = google.NewTranslator() translator = google.NewTranslator()
case "Libre":
translator = libre.NewTranslator()
case "Reverso": case "Reverso":
translator = reverso.NewTranslator() translator = reverso.NewTranslator()
} }