Files
voidraft/internal/common/translator/google_translator_free.go
2025-10-01 18:15:22 +08:00

104 lines
2.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package translator
import (
"context"
"encoding/json"
"errors"
"fmt"
"golang.org/x/text/language"
"io"
"net/http"
"net/url"
"time"
)
// NewGoogleTranslatorTokenFree 创建一个新的无token的Google翻译器实例
func NewGoogleTranslatorTokenFree() *GoogleTranslatorTokenFree {
return &GoogleTranslatorTokenFree{
httpClient: &http.Client{Timeout: defaultTimeout},
Timeout: defaultTimeout,
languages: initGoogleLanguages(),
}
}
// SetTimeout 设置请求超时时间
func (t *GoogleTranslatorTokenFree) SetTimeout(timeout time.Duration) {
t.Timeout = timeout
t.httpClient.Timeout = timeout
}
// Translate 使用Go语言提供的标准语言标签进行文本翻译
func (t *GoogleTranslatorTokenFree) Translate(text string, from language.Tag, to language.Tag) (string, error) {
return t.translate(text, from.String(), to.String())
}
// TranslateWithParams 使用简单字符串参数进行文本翻译
func (t *GoogleTranslatorTokenFree) TranslateWithParams(text string, params TranslationParams) (string, error) {
if params.Timeout > 0 {
t.SetTimeout(params.Timeout)
}
return t.translate(text, params.From, params.To)
}
// translate 执行实际翻译操作无token版本
func (t *GoogleTranslatorTokenFree) translate(text, from, to string) (string, error) {
ctx, cancel := context.WithTimeout(context.Background(), t.Timeout)
defer cancel()
// 构建请求URL无token版本
apiURL := "https://translate.googleapis.com/translate_a/t"
params := url.Values{}
params.Set("client", "dict-chrome-ex")
params.Set("sl", from)
params.Set("tl", to)
params.Set("q", text)
fullURL := apiURL + "?" + params.Encode()
// 创建请求
req, err := http.NewRequestWithContext(ctx, "GET", fullURL, nil)
if err != nil {
return "", err
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
// 发送请求
resp, err := t.httpClient.Do(req)
if err != nil {
return "", ErrBadNetwork
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("API error: status code %d", resp.StatusCode)
}
// 读取响应
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}
// 解析JSON响应
var result []interface{}
if err := json.Unmarshal(body, &result); err != nil {
return "", err
}
// 提取翻译文本
var translatedTexts []string
visitArrayItems(result, func(obj interface{}) {
if text, ok := obj.(string); ok {
translatedTexts = append(translatedTexts, text)
}
})
if len(translatedTexts) == 0 {
return "", errors.New("no translation found")
}
// 返回第一个翻译结果
return translatedTexts[0], nil
}