gtranslate/translate.go

84 lines
1.9 KiB
Go

// Parser for Google Translate
package main
import (
"fmt"
"net/http"
"net/url"
"golang.org/x/net/html"
)
func doRequest(settings *TranslateSettings, reqUrl string) (*http.Response, error) {
client := &http.Client{}
if settings.proxy != nil {
tr := &http.Transport{Proxy: http.ProxyURL(settings.proxy)}
client.Transport = tr
}
req, err := http.NewRequest("GET", reqUrl, nil)
if err != nil {
return nil, err
}
req.Header["User-Agent"] = []string{settings.userAgent}
resp, err := client.Do(req)
return resp, err
}
// Requests and parses translation from Google
func Translate(settings *TranslateSettings, fromLang, toLang, text string) (string, error) {
// Escape parameters before embedding in URL
fromLang = url.QueryEscape(fromLang)
toLang = url.QueryEscape(toLang)
text = url.QueryEscape(text)
reqUrl := fmt.Sprintf("https://translate.google.com/m?sl=%s&tl=%s&q=%s", fromLang, toLang, text)
resp, err := doRequest(settings, reqUrl)
if err != nil {
return "", fmt.Errorf("Request failed: %v", err)
}
doc, err := html.Parse(resp.Body)
if err != nil {
return "", fmt.Errorf("HTML parsing failed: %v", err)
}
res, err := walk(doc)
if err != nil {
return "", fmt.Errorf("Error parsing translation page: %v", err)
}
return res, nil
}
func walk(node *html.Node) (string, error) {
// Check if element has a class of result-container
if node.Type == html.ElementNode && node.Data == "div" {
for _, attr := range node.Attr {
if attr.Key == "class" && attr.Val == "result-container" {
// Retrieve the content of it
if content := node.FirstChild; content != nil {
return content.Data, nil
} else {
return "", fmt.Errorf("result-container is empty")
}
}
}
}
// Recursively walk through subelements
for c := node.FirstChild; c != nil; c = c.NextSibling {
if res, err := walk(c); err == nil {
return res, err
}
}
return "", fmt.Errorf("no result")
}