mirror of
https://github.com/eeeXun/GTT.git
synced 2025-05-16 15:50:52 -07:00
feat(translator): add BingTranslate
This commit is contained in:
parent
42b01a8cb2
commit
2e41fa800c
@ -5,6 +5,7 @@ Google Translate TUI (Originally)
|
||||
Supported Translator:
|
||||
[`ApertiumTranslate`](https://www.apertium.org/),
|
||||
[`ArgosTranslate`](https://translate.argosopentech.com/),
|
||||
[`BingTranslate`](https://www.bing.com/translator),
|
||||
[`GoogleTranslate`](https://translate.google.com/),
|
||||
[`ReversoTranslate`](https://www.reverso.net/text-translation)
|
||||
|
||||
@ -48,6 +49,7 @@ See language on:
|
||||
|
||||
- [Apertium Translate](https://www.apertium.org/) for `ApertiumTranslate`
|
||||
- [argosopentech/argos-translate](https://github.com/argosopentech/argos-translate#supported-languages) for `ArgosTranslate`
|
||||
- [Bing Translate](https://www.bing.com/translator) for `BingTranslate`
|
||||
- [Google Language support](https://cloud.google.com/translate/docs/languages) for `GoogleTranslate`
|
||||
- [Reverso Translation](https://www.reverso.net/text-translation) for `ReversoTranslate`
|
||||
|
||||
|
@ -22,6 +22,8 @@ func configInit() {
|
||||
"destination.language.apertiumtranslate": "English",
|
||||
"source.language.argostranslate": "English",
|
||||
"destination.language.argostranslate": "English",
|
||||
"source.language.bingtranslate": "English",
|
||||
"destination.language.bingtranslate": "English",
|
||||
"source.language.googletranslate": "English",
|
||||
"destination.language.googletranslate": "English",
|
||||
"source.language.reversotranslate": "English",
|
||||
|
256
internal/translate/bingtranslate/lang.go
Normal file
256
internal/translate/bingtranslate/lang.go
Normal file
@ -0,0 +1,256 @@
|
||||
package bingtranslate
|
||||
|
||||
var (
|
||||
lang = []string{
|
||||
"Afrikaans",
|
||||
"Albanian",
|
||||
"Amharic",
|
||||
"Auto",
|
||||
"Arabic",
|
||||
"Armenian",
|
||||
"Assamese",
|
||||
"Azerbaijani",
|
||||
"Bangla",
|
||||
"Bashkir",
|
||||
"Basque",
|
||||
"Bosnian",
|
||||
"Bulgarian",
|
||||
"Cantonese (Traditional)",
|
||||
"Catalan",
|
||||
"Chinese (Literary)",
|
||||
"Chinese Simplified",
|
||||
"Chinese Traditional",
|
||||
"Croatian",
|
||||
"Czech",
|
||||
"Danish",
|
||||
"Dari",
|
||||
"Divehi",
|
||||
"Dutch",
|
||||
"English",
|
||||
"Estonian",
|
||||
"Faroese",
|
||||
"Fijian",
|
||||
"Filipino",
|
||||
"Finnish",
|
||||
"French",
|
||||
"French (Canada)",
|
||||
"Galician",
|
||||
"Ganda",
|
||||
"Georgian",
|
||||
"German",
|
||||
"Greek",
|
||||
"Gujarati",
|
||||
"Haitian Creole",
|
||||
"Hausa",
|
||||
"Hebrew",
|
||||
"Hindi",
|
||||
"Hmong Daw",
|
||||
"Hungarian",
|
||||
"Icelandic",
|
||||
"Igbo",
|
||||
"Indonesian",
|
||||
"Inuinnaqtun",
|
||||
"Inuktitut",
|
||||
"Inuktitut (Latin)",
|
||||
"Irish",
|
||||
"Italian",
|
||||
"Japanese",
|
||||
"Kannada",
|
||||
"Kazakh",
|
||||
"Khmer",
|
||||
"Kinyarwanda",
|
||||
"Klingon (Latin)",
|
||||
"Korean",
|
||||
"Kurdish (Central)",
|
||||
"Kurdish (Northern)",
|
||||
"Kyrgyz",
|
||||
"Lao",
|
||||
"Latvian",
|
||||
"Lingala",
|
||||
"Lithuanian",
|
||||
"Lower Sorbian",
|
||||
"Macedonian",
|
||||
"Malagasy",
|
||||
"Malay",
|
||||
"Malayalam",
|
||||
"Maltese",
|
||||
"Marathi",
|
||||
"Mongolian (Cyrillic)",
|
||||
"Mongolian (Traditional)",
|
||||
"Myanmar (Burmese)",
|
||||
"Māori",
|
||||
"Nepali",
|
||||
"Norwegian",
|
||||
"Nyanja",
|
||||
"Odia",
|
||||
"Pashto",
|
||||
"Persian",
|
||||
"Polish",
|
||||
"Portuguese (Brazil)",
|
||||
"Portuguese (Portugal)",
|
||||
"Punjabi",
|
||||
"Querétaro Otomi",
|
||||
"Romanian",
|
||||
"Rundi",
|
||||
"Russian",
|
||||
"Samoan",
|
||||
"Serbian (Cyrillic)",
|
||||
"Serbian (Latin)",
|
||||
"Sesotho",
|
||||
"Sesotho sa Leboa",
|
||||
"Setswana",
|
||||
"Shona",
|
||||
"Slovak",
|
||||
"Slovenian",
|
||||
"Somali",
|
||||
"Spanish",
|
||||
"Swahili",
|
||||
"Swedish",
|
||||
"Tahitian",
|
||||
"Tamil",
|
||||
"Tatar",
|
||||
"Telugu",
|
||||
"Thai",
|
||||
"Tibetan",
|
||||
"Tigrinya",
|
||||
"Tongan",
|
||||
"Turkish",
|
||||
"Turkmen",
|
||||
"Ukrainian",
|
||||
"Urdu",
|
||||
"Uyghur",
|
||||
"Uzbek (Latin)",
|
||||
"Vietnamese",
|
||||
"Welsh",
|
||||
"Xhosa",
|
||||
"Yoruba",
|
||||
"Yucatec Maya",
|
||||
"Zulu",
|
||||
}
|
||||
langCode = map[string]string{
|
||||
"Afrikaans": "af",
|
||||
"Albanian": "sq",
|
||||
"Amharic": "am",
|
||||
"Auto": "auto-detect",
|
||||
"Arabic": "ar",
|
||||
"Armenian": "hy",
|
||||
"Assamese": "as",
|
||||
"Azerbaijani": "az",
|
||||
"Bangla": "bn",
|
||||
"Bashkir": "ba",
|
||||
"Basque": "eu",
|
||||
"Bosnian": "bs",
|
||||
"Bulgarian": "bg",
|
||||
"Cantonese (Traditional)": "yue",
|
||||
"Catalan": "ca",
|
||||
"Chinese (Literary)": "lzh",
|
||||
"Chinese Simplified": "zh-Hans",
|
||||
"Chinese Traditional": "zh-Hant",
|
||||
"Croatian": "hr",
|
||||
"Czech": "cs",
|
||||
"Danish": "da",
|
||||
"Dari": "prs",
|
||||
"Divehi": "dv",
|
||||
"Dutch": "nl",
|
||||
"English": "en",
|
||||
"Estonian": "et",
|
||||
"Faroese": "fo",
|
||||
"Fijian": "fj",
|
||||
"Filipino": "fil",
|
||||
"Finnish": "fi",
|
||||
"French": "fr",
|
||||
"French (Canada)": "fr-CA",
|
||||
"Galician": "gl",
|
||||
"Ganda": "lug",
|
||||
"Georgian": "ka",
|
||||
"German": "de",
|
||||
"Greek": "el",
|
||||
"Gujarati": "gu",
|
||||
"Haitian Creole": "ht",
|
||||
"Hausa": "ha",
|
||||
"Hebrew": "he",
|
||||
"Hindi": "hi",
|
||||
"Hmong Daw": "mww",
|
||||
"Hungarian": "hu",
|
||||
"Icelandic": "is",
|
||||
"Igbo": "ig",
|
||||
"Indonesian": "id",
|
||||
"Inuinnaqtun": "ikt",
|
||||
"Inuktitut": "iu",
|
||||
"Inuktitut (Latin)": "iu-Latn",
|
||||
"Irish": "ga",
|
||||
"Italian": "it",
|
||||
"Japanese": "ja",
|
||||
"Kannada": "kn",
|
||||
"Kazakh": "kk",
|
||||
"Khmer": "km",
|
||||
"Kinyarwanda": "rw",
|
||||
"Klingon (Latin)": "tlh-Latn",
|
||||
"Korean": "ko",
|
||||
"Kurdish (Central)": "ku",
|
||||
"Kurdish (Northern)": "kmr",
|
||||
"Kyrgyz": "ky",
|
||||
"Lao": "lo",
|
||||
"Latvian": "lv",
|
||||
"Lingala": "ln",
|
||||
"Lithuanian": "lt",
|
||||
"Lower Sorbian": "dsb",
|
||||
"Macedonian": "mk",
|
||||
"Malagasy": "mg",
|
||||
"Malay": "ms",
|
||||
"Malayalam": "ml",
|
||||
"Maltese": "mt",
|
||||
"Marathi": "mr",
|
||||
"Mongolian (Cyrillic)": "mn-Cyrl",
|
||||
"Mongolian (Traditional)": "mn-Mong",
|
||||
"Myanmar (Burmese)": "my",
|
||||
"Māori": "mi",
|
||||
"Nepali": "ne",
|
||||
"Norwegian": "nb",
|
||||
"Nyanja": "nya",
|
||||
"Odia": "or",
|
||||
"Pashto": "ps",
|
||||
"Persian": "fa",
|
||||
"Polish": "pl",
|
||||
"Portuguese (Brazil)": "pt",
|
||||
"Portuguese (Portugal)": "pt-PT",
|
||||
"Punjabi": "pa",
|
||||
"Querétaro Otomi": "otq",
|
||||
"Romanian": "ro",
|
||||
"Rundi": "run",
|
||||
"Russian": "ru",
|
||||
"Samoan": "sm",
|
||||
"Serbian (Cyrillic)": "sr-Cyrl",
|
||||
"Serbian (Latin)": "sr-Latn",
|
||||
"Sesotho": "st",
|
||||
"Sesotho sa Leboa": "nso",
|
||||
"Setswana": "tn",
|
||||
"Shona": "sn",
|
||||
"Slovak": "sk",
|
||||
"Slovenian": "sl",
|
||||
"Somali": "so",
|
||||
"Spanish": "es",
|
||||
"Swahili": "sw",
|
||||
"Swedish": "sv",
|
||||
"Tahitian": "ty",
|
||||
"Tamil": "ta",
|
||||
"Tatar": "tt",
|
||||
"Telugu": "te",
|
||||
"Thai": "th",
|
||||
"Tibetan": "bo",
|
||||
"Tigrinya": "ti",
|
||||
"Tongan": "to",
|
||||
"Turkish": "tr",
|
||||
"Turkmen": "tk",
|
||||
"Ukrainian": "uk",
|
||||
"Urdu": "ur",
|
||||
"Uyghur": "ug",
|
||||
"Uzbek (Latin)": "uz",
|
||||
"Vietnamese": "vi",
|
||||
"Welsh": "cy",
|
||||
"Xhosa": "xh",
|
||||
"Yoruba": "yo",
|
||||
"Yucatec Maya": "yua",
|
||||
"Zulu": "zu",
|
||||
}
|
||||
)
|
126
internal/translate/bingtranslate/translator.go
Normal file
126
internal/translate/bingtranslate/translator.go
Normal file
@ -0,0 +1,126 @@
|
||||
package bingtranslate
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/eeeXun/gtt/internal/translate/core"
|
||||
)
|
||||
|
||||
const (
|
||||
setUpURL = "https://www.bing.com/translator"
|
||||
textURL = "https://www.bing.com/ttranslatev3?IG=%s&IID=%s"
|
||||
)
|
||||
|
||||
type BingTranslate struct {
|
||||
*core.Language
|
||||
*core.TTSLock
|
||||
core.EngineName
|
||||
}
|
||||
|
||||
type setUpData struct {
|
||||
ig string
|
||||
iid string
|
||||
key string
|
||||
token string
|
||||
}
|
||||
|
||||
func NewBingTranslate() *BingTranslate {
|
||||
return &BingTranslate{
|
||||
Language: core.NewLanguage(),
|
||||
TTSLock: core.NewTTSLock(),
|
||||
EngineName: core.NewEngineName("BingTranslate"),
|
||||
}
|
||||
}
|
||||
|
||||
func (t *BingTranslate) GetAllLang() []string {
|
||||
return lang
|
||||
}
|
||||
|
||||
func (t *BingTranslate) setUp() (*setUpData, error) {
|
||||
var data setUpData
|
||||
|
||||
res, err := http.Get(setUpURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bodyStr := string(body)
|
||||
igData := regexp.MustCompile(`IG:"([^"]+)"`).FindStringSubmatch(bodyStr)
|
||||
if len(igData) < 2 {
|
||||
return nil, errors.New(t.GetEngineName() + " IG not found")
|
||||
}
|
||||
data.ig = igData[1]
|
||||
iidData := regexp.MustCompile(`data-iid="([^"]+)`).FindStringSubmatch(bodyStr)
|
||||
if len(iidData) < 2 {
|
||||
return nil, errors.New(t.GetEngineName() + " IID not found")
|
||||
}
|
||||
data.iid = iidData[1]
|
||||
params := regexp.MustCompile(`params_AbusePreventionHelper = ([^;]+);`).FindStringSubmatch(bodyStr)
|
||||
if len(params) < 2 {
|
||||
return nil, errors.New(t.GetEngineName() + " Key and Token not found")
|
||||
}
|
||||
paramsStr := strings.Split(params[1][1:len(params[1])-1], ",")
|
||||
data.key = paramsStr[0]
|
||||
data.token = paramsStr[1][1 : len(paramsStr[1])-1]
|
||||
|
||||
return &data, nil
|
||||
}
|
||||
|
||||
func (t *BingTranslate) Translate(message string) (translation, definition, partOfSpeech string, err error) {
|
||||
var data []interface{}
|
||||
|
||||
initData, err := t.setUp()
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
userData := url.Values{
|
||||
"fromLang": {langCode[t.GetSrcLang()]},
|
||||
"to": {langCode[t.GetDstLang()]},
|
||||
"text": {message},
|
||||
"key": {initData.key},
|
||||
"token": {initData.token},
|
||||
}
|
||||
req, err := http.NewRequest("POST",
|
||||
fmt.Sprintf(textURL, initData.ig, initData.iid),
|
||||
strings.NewReader(userData.Encode()),
|
||||
)
|
||||
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||
req.Header.Add("User-Agent", core.UserAgent)
|
||||
res, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
if err = json.Unmarshal(body, &data); err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
|
||||
if len(data) <= 0 {
|
||||
return "", "", "", errors.New("Translation not found")
|
||||
}
|
||||
|
||||
// translation
|
||||
translation = fmt.Sprintf("%v",
|
||||
data[0].(map[string]interface{})["translations"].([]interface{})[0].(map[string]interface{})["text"])
|
||||
|
||||
return translation, definition, partOfSpeech, nil
|
||||
}
|
||||
|
||||
func (t *BingTranslate) PlayTTS(lang, message string) error {
|
||||
defer t.ReleaseLock()
|
||||
|
||||
return errors.New(t.GetEngineName() + " does not support text to speech")
|
||||
}
|
5
internal/translate/core/utils.go
Normal file
5
internal/translate/core/utils.go
Normal file
@ -0,0 +1,5 @@
|
||||
package core
|
||||
|
||||
const (
|
||||
UserAgent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36"
|
||||
)
|
@ -19,7 +19,6 @@ import (
|
||||
const (
|
||||
textURL = "https://api.reverso.net/translate/v1/translation"
|
||||
ttsURL = "https://voice.reverso.net/RestPronunciation.svc/v1/output=json/GetVoiceStream/voiceName=%s?voiceSpeed=80&inputText=%s"
|
||||
userAgent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36"
|
||||
)
|
||||
|
||||
type ReversoTranslate struct {
|
||||
@ -65,7 +64,7 @@ func (t *ReversoTranslate) Translate(message string) (translation, definition, p
|
||||
textURL,
|
||||
bytes.NewBuffer([]byte(userData)))
|
||||
req.Header.Add("Content-Type", "application/json")
|
||||
req.Header.Add("User-Agent", userAgent)
|
||||
req.Header.Add("User-Agent", core.UserAgent)
|
||||
res, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
@ -124,7 +123,7 @@ func (t *ReversoTranslate) PlayTTS(lang, message string) error {
|
||||
base64.StdEncoding.EncodeToString([]byte(message)),
|
||||
)
|
||||
req, _ := http.NewRequest("GET", urlStr, nil)
|
||||
req.Header.Add("User-Agent", userAgent)
|
||||
req.Header.Add("User-Agent", core.UserAgent)
|
||||
res, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -3,12 +3,19 @@ package translate
|
||||
import (
|
||||
"github.com/eeeXun/gtt/internal/translate/apertiumtranslate"
|
||||
"github.com/eeeXun/gtt/internal/translate/argostranslate"
|
||||
"github.com/eeeXun/gtt/internal/translate/bingtranslate"
|
||||
"github.com/eeeXun/gtt/internal/translate/googletranslate"
|
||||
"github.com/eeeXun/gtt/internal/translate/reversotranslate"
|
||||
)
|
||||
|
||||
var (
|
||||
AllTranslator = []string{"ApertiumTranslate", "ArgosTranslate", "GoogleTranslate", "ReversoTranslate"}
|
||||
AllTranslator = []string{
|
||||
"ApertiumTranslate",
|
||||
"BingTranslate",
|
||||
"ArgosTranslate",
|
||||
"GoogleTranslate",
|
||||
"ReversoTranslate",
|
||||
}
|
||||
)
|
||||
|
||||
type Translator interface {
|
||||
@ -57,6 +64,8 @@ func NewTranslator(name string) Translator {
|
||||
translator = apertiumtranslate.NewApertiumTranslate()
|
||||
case "ArgosTranslate":
|
||||
translator = argostranslate.NewArgosTranslate()
|
||||
case "BingTranslate":
|
||||
translator = bingtranslate.NewBingTranslate()
|
||||
case "GoogleTranslate":
|
||||
translator = googletranslate.NewGoogleTranslate()
|
||||
case "ReversoTranslate":
|
||||
|
Loading…
x
Reference in New Issue
Block a user