// 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") }