diff --git a/README.md b/README.md index ee68993..af99590 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,12 @@ Google Translate TUI (Originally) Supported Translator: [`Apertium`](https://www.apertium.org/), -[`Argos`](https://translate.argosopentech.com/), [`Bing`](https://www.bing.com/translator), [`ChatGPT`](https://chat.openai.com/), [`DeepL`](https://deepl.com/translator)(only free API), [`DeepLX`](https://github.com/OwO-Network/DeepLX), [`Google`](https://translate.google.com/)(default), +[`Libre`](https://libretranslate.com/), [`Reverso`](https://www.reverso.net/text-translation) ## ScreenShot @@ -52,6 +52,22 @@ host: 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 ### Dependencies @@ -214,12 +230,12 @@ gtt -src "English" -dst "Chinese (Traditional)" See available languages on: - [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` - `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` - `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` +- [LibreTranslate Languages](https://libretranslate.com/languages) for `Libre` - [Reverso Translation](https://www.reverso.net/text-translation) for `Reverso` ## Credit diff --git a/config.go b/config.go index b5882c2..9caec68 100644 --- a/config.go +++ b/config.go @@ -45,8 +45,6 @@ func configInit() { "destination.border_color": "blue", "source.language.apertium": "English", "destination.language.apertium": "English", - "source.language.argos": "English", - "destination.language.argos": "English", "source.language.bing": "English", "destination.language.bing": "English", "source.language.chatgpt": "English", @@ -57,6 +55,8 @@ func configInit() { "destination.language.deeplx": "English", "source.language.google": "English", "destination.language.google": "English", + "source.language.libre": "English", + "destination.language.libre": "English", "source.language.reverso": "English", "destination.language.reverso": "English", "translator": "Google", @@ -162,7 +162,7 @@ func configInit() { // Import api key and host if file exists if err := serverConfig.ReadInConfig(); err == nil { // 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 if serverConfig.Get(fmt.Sprintf("api_key.%s.value", name)) != nil { translators[name].SetAPIKey(serverConfig.GetString(fmt.Sprintf("api_key.%s.value", name))) @@ -174,8 +174,10 @@ func configInit() { } } // host - if serverConfig.Get("host.deeplx") != nil { - translators["DeepLX"].SetHost(serverConfig.GetString("host.deeplx")) + for _, name := range []string{"DeepLX", "Libre"} { + if serverConfig.Get(fmt.Sprintf("host.%s", name)) != nil { + translators[name].SetHost(serverConfig.GetString(fmt.Sprintf("host.%s", name))) + } } } // Set argument language diff --git a/example/server.yaml b/example/server.yaml index 54d54a6..0a07678 100644 --- a/example/server.yaml +++ b/example/server.yaml @@ -9,5 +9,9 @@ api_key: deeplx: value: DEEPLX_API_KEY # file: $HOME/secrets/deeplx.txt + libre: + value: LIBRE_API_KEY + # file: $HOME/secrets/libre.txt host: deeplx: 127.0.0.1:1188 + libre: 127.0.0.1:5000 diff --git a/internal/translate/argos/language.go b/internal/translate/argos/language.go deleted file mode 100644 index 8cfdd5c..0000000 --- a/internal/translate/argos/language.go +++ /dev/null @@ -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", - } -) diff --git a/internal/translate/bing/translator.go b/internal/translate/bing/translator.go index a7417f7..4b992a7 100644 --- a/internal/translate/bing/translator.go +++ b/internal/translate/bing/translator.go @@ -141,21 +141,27 @@ func (t *Translator) Translate(message string) (translation *core.Translation, e } // Bing will return the request with list when success. // Otherwises, it would return map. Then the following err would not be nil. - if err = json.Unmarshal(body, &data); err == nil { - 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) + if err = json.Unmarshal(body, &data); err != nil { + return nil, err + } + + 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)) } - translation.POS = poses.format() + poses.add(pos["posTag"].(string), words) } + translation.POS = poses.format() return translation, nil } diff --git a/internal/translate/deeplx/translator.go b/internal/translate/deeplx/translator.go index b1022dc..307bb4c 100644 --- a/internal/translate/deeplx/translator.go +++ b/internal/translate/deeplx/translator.go @@ -62,7 +62,7 @@ func (t *Translator) Translate(message string) (translation *core.Translation, e } 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["message"].(string)) diff --git a/internal/translate/libre/language.go b/internal/translate/libre/language.go new file mode 100644 index 0000000..1417b2e --- /dev/null +++ b/internal/translate/libre/language.go @@ -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", + } +) diff --git a/internal/translate/argos/translator.go b/internal/translate/libre/translator.go similarity index 71% rename from internal/translate/argos/translator.go rename to internal/translate/libre/translator.go index b458a92..0a53a6b 100644 --- a/internal/translate/argos/translator.go +++ b/internal/translate/libre/translator.go @@ -1,4 +1,4 @@ -package argos +package libre import ( "encoding/json" @@ -11,7 +11,7 @@ import ( ) const ( - textURL = "https://translate.argosopentech.com/translate" + defaultURL = "https://libretranslate.com/translate" ) type Translator struct { @@ -26,7 +26,7 @@ func NewTranslator() *Translator { Server: new(core.Server), Language: new(core.Language), 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) 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, url.Values{ - "q": {message}, - "source": {langCode[t.GetSrcLang()]}, - "target": {langCode[t.GetDstLang()]}, + "q": {message}, + "source": {langCode[t.GetSrcLang()]}, + "target": {langCode[t.GetDstLang()]}, + "api_key": {t.GetAPIKey()}, }) if err != nil { return nil, err @@ -58,6 +66,9 @@ func (t *Translator) Translate(message string) (translation *core.Translation, e if len(data) <= 0 { return nil, errors.New("Translation not found") } + if res.StatusCode != 200 { + return nil, errors.New(data["error"].(string)) + } translation.TEXT = data["translatedText"].(string) diff --git a/internal/translate/translator.go b/internal/translate/translator.go index ee95633..a86fa44 100644 --- a/internal/translate/translator.go +++ b/internal/translate/translator.go @@ -2,25 +2,25 @@ package translate import ( "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/chatgpt" "github.com/eeeXun/gtt/internal/translate/core" "github.com/eeeXun/gtt/internal/translate/deepl" "github.com/eeeXun/gtt/internal/translate/deeplx" "github.com/eeeXun/gtt/internal/translate/google" + "github.com/eeeXun/gtt/internal/translate/libre" "github.com/eeeXun/gtt/internal/translate/reverso" ) var ( AllTranslator = []string{ "Apertium", - "Argos", "Bing", "ChatGPT", "DeepL", "DeepLX", "Google", + "Libre", "Reverso", } ) @@ -75,8 +75,6 @@ func NewTranslator(name string) Translator { switch name { case "Apertium": translator = apertium.NewTranslator() - case "Argos": - translator = argos.NewTranslator() case "Bing": translator = bing.NewTranslator() case "ChatGPT": @@ -87,6 +85,8 @@ func NewTranslator(name string) Translator { translator = deeplx.NewTranslator() case "Google": translator = google.NewTranslator() + case "Libre": + translator = libre.NewTranslator() case "Reverso": translator = reverso.NewTranslator() }