mirror of
https://github.com/eeeXun/GTT.git
synced 2025-05-19 09:10:42 -07:00
feat(translator): add BingTranslate (#16)
This commit is contained in:
parent
7773bb3e8f
commit
e0c5569adf
@ -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 available languages on:
|
||||
|
||||
- [Apertium Translate](https://www.apertium.org/) for `ApertiumTranslate`
|
||||
- [argosopentech/argos-translate](https://github.com/argosopentech/argos-translate#supported-languages) for `ArgosTranslate`
|
||||
- [Bing language-support](https://learn.microsoft.com/en-us/azure/cognitive-services/translator/language-support#translation) 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",
|
||||
|
320
internal/translate/bingtranslate/lang.go
Normal file
320
internal/translate/bingtranslate/lang.go
Normal file
@ -0,0 +1,320 @@
|
||||
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",
|
||||
"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",
|
||||
"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",
|
||||
}
|
||||
voiceName = map[string]string{
|
||||
"Afrikaans": "af-ZA-AdriNeural",
|
||||
"Amharic": "am-ET-MekdesNeural",
|
||||
"Arabic": "ar-SA-HamedNeural",
|
||||
"Bangla": "bn-IN-TanishaaNeural",
|
||||
"Bulgarian": "bg-BG-BorislavNeural",
|
||||
"Cantonese (Traditional)": "zh-HK-HiuGaaiNeural",
|
||||
"Catalan": "ca-ES-JoanaNeural",
|
||||
"Chinese Simplified": "zh-CN-XiaoxiaoNeural",
|
||||
"Chinese Traditional": "zh-CN-XiaoxiaoNeural",
|
||||
"Croatian": "hr-HR-SreckoNeural",
|
||||
"Czech": "cs-CZ-AntoninNeural",
|
||||
"Danish": "da-DK-ChristelNeural",
|
||||
"Dutch": "nl-NL-ColetteNeural",
|
||||
"English": "en-US-AriaNeural",
|
||||
"Estonian": "et-EE-AnuNeural",
|
||||
"Finnish": "fi-FI-NooraNeural",
|
||||
"French": "fr-FR-DeniseNeural",
|
||||
"French (Canada)": "fr-CA-SylvieNeural",
|
||||
"German": "de-DE-KatjaNeural",
|
||||
"Greek": "el-GR-NestorasNeural",
|
||||
"Gujarati": "gu-IN-DhwaniNeural",
|
||||
"Hebrew": "he-IL-AvriNeural",
|
||||
"Hindi": "hi-IN-SwaraNeural",
|
||||
"Hungarian": "hu-HU-TamasNeural",
|
||||
"Icelandic": "is-IS-GudrunNeural",
|
||||
"Indonesian": "id-ID-ArdiNeural",
|
||||
"Irish": "ga-IE-OrlaNeural",
|
||||
"Italian": "it-IT-DiegoNeural",
|
||||
"Japanese": "ja-JP-NanamiNeural",
|
||||
"Kannada": "kn-IN-SapnaNeural",
|
||||
"Kazakh": "kk-KZ-AigulNeural",
|
||||
"Khmer": "km-KH-SreymomNeural",
|
||||
"Korean": "ko-KR-SunHiNeural",
|
||||
"Lao": "lo-LA-KeomanyNeural",
|
||||
"Latvian": "lv-LV-EveritaNeural",
|
||||
"Lithuanian": "lt-LT-OnaNeural",
|
||||
"Macedonian": "mk-MK-MarijaNeural",
|
||||
"Malay": "ms-MY-OsmanNeural",
|
||||
"Malayalam": "ml-IN-SobhanaNeural",
|
||||
"Maltese": "mt-MT-GraceNeural",
|
||||
"Marathi": "mr-IN-AarohiNeural",
|
||||
"Myanmar (Burmese)": "my-MM-NilarNeural",
|
||||
"Norwegian": "nb-NO-PernilleNeural",
|
||||
"Pashto": "ps-AF-LatifaNeural",
|
||||
"Persian": "fa-IR-DilaraNeural",
|
||||
"Polish": "pl-PL-ZofiaNeural",
|
||||
"Portuguese (Brazil)": "pt-BR-FranciscaNeural",
|
||||
"Portuguese (Portugal)": "pt-PT-FernandaNeural",
|
||||
"Romanian": "ro-RO-EmilNeural",
|
||||
"Russian": "ru-RU-DariyaNeural",
|
||||
"Serbian (Cyrillic)": "sr-RS-SophieNeural",
|
||||
"Slovak": "sk-SK-LukasNeural",
|
||||
"Slovenian": "sl-SI-RokNeural",
|
||||
"Spanish": "es-ES-ElviraNeural",
|
||||
"Swedish": "sv-SE-SofieNeural",
|
||||
"Tamil": "ta-IN-PallaviNeural",
|
||||
"Telugu": "te-IN-ShrutiNeural",
|
||||
"Thai": "th-TH-NiwatNeural",
|
||||
"Turkish": "tr-TR-EmelNeural",
|
||||
"Ukrainian": "uk-UA-PolinaNeural",
|
||||
"Urdu": "ur-IN-GulNeural",
|
||||
"Uzbek (Latin)": "uz-UZ-MadinaNeural",
|
||||
"Vietnamese": "vi-VN-NamMinhNeural",
|
||||
"Welsh": "cy-GB-NiaNeural",
|
||||
}
|
||||
)
|
214
internal/translate/bingtranslate/translator.go
Normal file
214
internal/translate/bingtranslate/translator.go
Normal file
@ -0,0 +1,214 @@
|
||||
package bingtranslate
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/eeeXun/gtt/internal/translate/core"
|
||||
"github.com/hajimehoshi/go-mp3"
|
||||
"github.com/hajimehoshi/oto/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
setUpURL = "https://www.bing.com/translator"
|
||||
textURL = "https://www.bing.com/ttranslatev3?IG=%s&IID=%s"
|
||||
posURL = "https://www.bing.com/tlookupv3?IG=%s&IID=%s"
|
||||
ttsURL = "https://www.bing.com/tfettts?IG=%s&IID=%s"
|
||||
ttsSSML = "<speak version='1.0' xml:lang='%[1]s'><voice xml:lang='%[1]s' xml:gender='Female' name='%s'><prosody rate='-20.00%%'>%s</prosody></voice></speak>"
|
||||
)
|
||||
|
||||
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"])
|
||||
|
||||
// request part of speech
|
||||
userData.Del("fromLang")
|
||||
userData.Add("from", langCode[t.GetSrcLang()])
|
||||
req, err = http.NewRequest("POST",
|
||||
fmt.Sprintf(posURL, 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
|
||||
}
|
||||
// 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)
|
||||
}
|
||||
partOfSpeech = poses.format()
|
||||
}
|
||||
|
||||
return translation, definition, partOfSpeech, nil
|
||||
}
|
||||
|
||||
func (t *BingTranslate) PlayTTS(lang, message string) error {
|
||||
defer t.ReleaseLock()
|
||||
|
||||
name, ok := voiceName[lang]
|
||||
if !ok {
|
||||
return errors.New(t.GetEngineName() + " does not support text to speech of " + lang)
|
||||
}
|
||||
initData, err := t.setUp()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
userData := url.Values{
|
||||
// lang='%s' in ssml should be xx-XX, e.g. en-US
|
||||
// But xx also works, e.g. en
|
||||
// So don't do extra work to get xx-XX
|
||||
"ssml": {fmt.Sprintf(ttsSSML, langCode[lang], name, message)},
|
||||
"key": {initData.key},
|
||||
"token": {initData.token},
|
||||
}
|
||||
req, err := http.NewRequest("POST",
|
||||
fmt.Sprintf(ttsURL, 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
|
||||
}
|
||||
decoder, err := mp3.NewDecoder(res.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
otoCtx, readyChan, err := oto.NewContext(decoder.SampleRate(), 2, 2)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
<-readyChan
|
||||
player := otoCtx.NewPlayer(decoder)
|
||||
player.Play()
|
||||
for player.IsPlaying() {
|
||||
if t.IsStopped() {
|
||||
return nil
|
||||
}
|
||||
time.Sleep(time.Millisecond)
|
||||
}
|
||||
if err = player.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
40
internal/translate/bingtranslate/utils.go
Normal file
40
internal/translate/bingtranslate/utils.go
Normal file
@ -0,0 +1,40 @@
|
||||
package bingtranslate
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type posWords struct {
|
||||
target string
|
||||
backTargets []string
|
||||
}
|
||||
|
||||
func (t *posWords) add(s string) {
|
||||
t.backTargets = append(t.backTargets, s)
|
||||
}
|
||||
|
||||
type posSet map[string][]posWords
|
||||
|
||||
func (set posSet) add(tag string, words posWords) {
|
||||
set[tag] = append(set[tag], words)
|
||||
}
|
||||
|
||||
func (set posSet) format() (s string) {
|
||||
for tag := range set {
|
||||
s += fmt.Sprintf("[%s]\n", tag)
|
||||
for _, words := range set[tag] {
|
||||
s += fmt.Sprintf("\t%s:", words.target)
|
||||
firstWord := true
|
||||
for _, backTarget := range words.backTargets {
|
||||
if firstWord {
|
||||
s += fmt.Sprintf(" %s", backTarget)
|
||||
firstWord = false
|
||||
} else {
|
||||
s += fmt.Sprintf(", %s", backTarget)
|
||||
}
|
||||
}
|
||||
s += "\n"
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
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