From 72034636afde59a2f52cb1ca89f3264eed66b6bd Mon Sep 17 00:00:00 2001 From: eeeXun Date: Thu, 8 Feb 2024 22:41:29 +0800 Subject: [PATCH] feat: add DeepLX --- README.md | 20 ++++++- config.go | 4 +- example/server.yaml | 2 + internal/translate/deeplx/language.go | 67 +++++++++++++++++++++ internal/translate/deeplx/translator.go | 80 +++++++++++++++++++++++++ internal/translate/translator.go | 4 ++ 6 files changed, 174 insertions(+), 3 deletions(-) create mode 100644 internal/translate/deeplx/language.go create mode 100644 internal/translate/deeplx/translator.go diff --git a/README.md b/README.md index cd30c59..3b89454 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ Supported Translator: [`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), [`Reverso`](https://www.reverso.net/text-translation) @@ -17,8 +18,8 @@ ChatGPT and DeepL translations require API keys, which can be obtained from [OpenAI API keys](https://platform.openai.com/account/api-keys) and [DeepL API signup](https://www.deepl.com/pro-api) pages, respectively. Note that only the free API is supported for DeepL currently. Once you have your -API key add it to `$XDG_CONFIG_HOME/gtt/server.yaml` or -`$HOME/.config/gtt/server.yaml` +API key add it 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: @@ -26,6 +27,20 @@ api_key: deepl: DEEPL_API_KEY # <- Replace with your API Key ``` +## DeepLX + +The DeepLX is self-hosted server. You must provide IP address and port at +`$XDG_CONFIG_HOME/gtt/server.yaml` or `$HOME/.config/gtt/server.yaml`. +The api key for DeepLX is optional, depending on your setting. +See the example in [server.yaml](example/server.yaml) file. + +```yaml +api_key: + deeplx: DEEPLX_API_KEY # <- Replace with your API Key +host: + deeplx: 127.0.0.1:1188 # <- Replace with your DeepLX server IP address and port +``` + ## ScreenShot ![screenshot](https://github.com/eeeXun/gtt/assets/58657914/3841c2bf-62f7-434a-9e77-91c3748c5675) @@ -194,6 +209,7 @@ See available languages on: - [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` - [Reverso Translation](https://www.reverso.net/text-translation) for `Reverso` diff --git a/config.go b/config.go index b4af331..5180cb2 100644 --- a/config.go +++ b/config.go @@ -51,6 +51,8 @@ func configInit() { "destination.language.chatgpt": "English", "source.language.deepl": "English", "destination.language.deepl": "English", + "source.language.deeplx": "English", + "destination.language.deeplx": "English", "source.language.google": "English", "destination.language.google": "English", "source.language.reverso": "English", @@ -156,7 +158,7 @@ func configInit() { SetDstBorderColor(config.GetString("destination.border_color")) // Import api key if file exists if err := serverConfig.ReadInConfig(); err == nil { - for _, name := range []string{"ChatGPT", "DeepL"} { + for _, name := range []string{"ChatGPT", "DeepL", "DeepLX"} { if serverConfig.Get(fmt.Sprintf("api_key.%s", name)) != nil { translators[name].SetAPIKey(serverConfig.GetString(fmt.Sprintf("api_key.%s", name))) } diff --git a/example/server.yaml b/example/server.yaml index cee7957..575ca58 100644 --- a/example/server.yaml +++ b/example/server.yaml @@ -1,3 +1,5 @@ +# This file should be located at $XDG_CONFIG_HOME/gtt/server.yaml or $HOME/.config/gtt/server.yaml. api_key: chatgpt: CHATGPT_API_KEY deepl: DEEPL_API_KEY + deeplx: DEEPLX_API_KEY diff --git a/internal/translate/deeplx/language.go b/internal/translate/deeplx/language.go new file mode 100644 index 0000000..02480c4 --- /dev/null +++ b/internal/translate/deeplx/language.go @@ -0,0 +1,67 @@ +package deeplx + +// Generated from DeepL +var ( + lang = []string{ + "Bulgarian", + "Chinese", + "Czech", + "Danish", + "Dutch", + "English", + "Estonian", + "Finnish", + "French", + "German", + "Greek", + "Hungarian", + "Indonesian", + "Italian", + "Japanese", + "Korean", + "Latvian", + "Lithuanian", + "Norwegian", + "Polish", + "Portuguese", + "Romanian", + "Russian", + "Slovak", + "Slovenian", + "Spanish", + "Swedish", + "Turkish", + "Ukrainian", + } + langCode = map[string]string{ + "Bulgarian": "BG", + "Chinese": "ZH", + "Czech": "CS", + "Danish": "DA", + "Dutch": "NL", + "English": "EN", + "Estonian": "ET", + "Finnish": "FI", + "French": "FR", + "German": "DE", + "Greek": "EL", + "Hungarian": "HU", + "Indonesian": "ID", + "Italian": "IT", + "Japanese": "JA", + "Korean": "KO", + "Latvian": "LV", + "Lithuanian": "LT", + "Norwegian": "NB", + "Polish": "PL", + "Portuguese": "PT", + "Romanian": "RO", + "Russian": "RU", + "Slovak": "SK", + "Slovenian": "SL", + "Spanish": "ES", + "Swedish": "SV", + "Turkish": "TR", + "Ukrainian": "UK", + } +) diff --git a/internal/translate/deeplx/translator.go b/internal/translate/deeplx/translator.go new file mode 100644 index 0000000..b19513b --- /dev/null +++ b/internal/translate/deeplx/translator.go @@ -0,0 +1,80 @@ +package deeplx + +import ( + "bytes" + "encoding/json" + "errors" + "io" + "net/http" + + "github.com/eeeXun/gtt/internal/translate/core" +) + +const ( + textURL = "http://localhost:1188/translate" +) + +type Translator struct { + *core.APIKey + *core.Language + *core.TTSLock + core.EngineName +} + +func NewTranslator() *Translator { + return &Translator{ + APIKey: new(core.APIKey), + Language: new(core.Language), + TTSLock: core.NewTTSLock(), + EngineName: core.NewEngineName("DeepLX"), + } +} + +func (t *Translator) GetAllLang() []string { + return lang +} + +func (t *Translator) Translate(message string) (translation *core.Translation, err error) { + translation = new(core.Translation) + var data map[string]interface{} + + userData, _ := json.Marshal(map[string]interface{}{ + "text": message, + "source_lang": langCode[t.GetSrcLang()], + "target_lang": langCode[t.GetDstLang()], + }) + req, _ := http.NewRequest(http.MethodPost, + textURL, + bytes.NewBuffer(userData), + ) + req.Header.Add("Content-Type", "application/json") + req.Header.Add("Authorization", "Bearer "+t.GetAPIKey()) + res, err := http.DefaultClient.Do(req) + if err != nil { + return nil, err + } + body, err := io.ReadAll(res.Body) + if err != nil { + return nil, err + } + if err = json.Unmarshal(body, &data); err != nil { + return nil, err + } + + if len(data) <= 0 { + return nil, errors.New("translation not found") + } + if res.StatusCode != 200 { + return nil, errors.New(data["message"].(string)) + } + + translation.TEXT = data["data"].(string) + + return translation, nil +} + +func (t *Translator) PlayTTS(lang, message string) error { + defer t.ReleaseLock() + + return errors.New(t.GetEngineName() + " does not support text to speech") +} diff --git a/internal/translate/translator.go b/internal/translate/translator.go index 8e44928..a301aa4 100644 --- a/internal/translate/translator.go +++ b/internal/translate/translator.go @@ -7,6 +7,7 @@ import ( "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/reverso" ) @@ -18,6 +19,7 @@ var ( "Bing", "ChatGPT", "DeepL", + "DeepLX", "Google", "Reverso", } @@ -78,6 +80,8 @@ func NewTranslator(name string) Translator { translator = chatgpt.NewTranslator() case "DeepL": translator = deepl.NewTranslator() + case "DeepLX": + translator = deeplx.NewTranslator() case "Google": translator = google.NewTranslator() case "Reverso":