Đưa công cụ Google Translator vào ứng dụng Java để phục vụ cho vài mục đích của bạn như: dịch văn bản khi crawl dữ liệu từ site nước ngoài hay tự động chuyển đổi ngôn ngữ nội dung trong ứng dụng hoặc đơn thuần bạn chỉ muốn viết 1 tool cho phép dịch văn bản trên desktop mà không cần phải bật trình duyệt, tạo ra 1 công cụ mang thương hiệu của "riêng" bạn để chia sẻ cho bạn bè hay ai đó sử dụng.

Nếu bạn đã từng gặp phải những vấn đề về sử dụng Google Translate API để dịch văn bản, ắt hẳn bạn đã search Google để tìm kiếm các bài viết liên quan. Có những bài viết hướng dẫn cách sử dụng Google Translator API để dịch văn bản nhưng tin buồn rằng Google Translate API là dịch vụ mà bạn phải trả phí.



Có dự án open-source cho phép bạn kết nối tới Google Translate API qua secret key sau:
http://code.google.com/p/google-translate-api-v2-java/

Đọc qua source code thì thấy bạn vẫn phải cung cấp API Key để xác thực - cái mà phải mất phí để mua. Thư viện trên chỉ giúp chúng ta bước đầu về kết nối và đóng gói các tính năng của Google Translate API mà thôi.


Làm thế nào để sử dụng miễn phí Google Translate API?

Đây không phải là cách hack / crack API Key để sử dụng miễn phí mà là thủ thuật nhỏ lợi dụng phiên bản dành cho Mobile của Google Translator để viết ra ứng dụng dịch văn bản.

Tôi sẽ hướng dẫn bạn từng bước phân tích và viết mã thực thi chi tiết cho công cụ này.

Như chúng ta đều biết, đây là trang hiển thị chính của công cụ Google Translator (phiên bản web cho desktop):


Trang này sử dụng AJAX để gửi / nhận thông tin trên dịch vụ Google Translator. Trong Java, ta không thể clean một trang có chứa mã AJAX để bóc tách thông tin được (mặc dù trong PHP có thể làm điều này bằng CURL). Vì vậy chúng ta cần phải tìm một giải pháp khác để thay thế và khắc phục khó khăn trên.

Các add-on cần có cho FireFox:
User-Agent Switcher (Giúp chuyển đổi user agent hiện tại sang user agent mobile nào đó)
FireBug (sử dụng để theo dõi Request/Response trả về khi thực hiện thao tác dịch văn bản)

Sau khi bạn đã cài đặt thành công cả 2 addons trên, chúng ta sẽ bắt đầu thực hiện từng bước để nắm rõ cơ chế Google Translator phiên bản mobile này.

Đầu tiên, bạn phải chuyển User-Agent của trình duyệt sang 1 User-Agent mobile nào đó. Ví dụ, tôi chọn User-Agent iPhone 3:



Điều này nói với server chạy dịch vụ Google Translator rằng "Tôi đang sử dụng công cụ này trên iPhone 3. Hãy trả về cho tôi giao diện phù hợp với thiết bị di động của tôi".

Và đây là kết quả mà Google đáp lại:



Bước tiếp theo, chúng ta sẽ phải theo dõi thông tin gửi đi / nhận về khi sử dụng công cụ này để tìm hướng và giải pháp kỹ thuật để viết code xử lý.

Nhấn phím F12 để bật FireBug và chuyển sang tab Net để theo dõi thông tin Request/Response.



Bạn thử gõ 1 câu nào đó rồi nhấn nút Search để dịch văn bản. Ví dụ như sau:




Nhìn vào kết quả trả về như ở trên, bạn hoàn toàn đã biết được khi dịch văn bản gửi lên dịch vụ Google Translator những tham số gì. URL này ta sẽ note lại để lát viết code sử dụng.

Bạn click vào URL bên dưới panel của FireBug sẽ ra các thông tin về Request / Response. Và cái mà chúng ta đang quan tâm đó chính là dữ liệu trả về:




Dữ liệu trả về là JSON Data. Đây là thông tin cuối cùng mà chúng ta muốn biết để có thể thao tác lấy về dữ liệu trong Java Code. Bấy nhiêu là đủ, bây giờ có thể viết code xử lý được rồi.


Viết mã xử lý cho công cụ.

Với phần mã lệnh này tôi cố gắng thiết kế nó ở dạng POJO và đóng gói lại trong 1 class duy nhất để dễ sử dụng. Bạn có thể sử dụng API này cho Swing, Console, JSP / JSF, Web Service....Tôi sẽ không đi sâu vào phần giao diện vì nó tốn khá nhiều thời gian, vì vậy tôi tập trung xử lý phần core của công cụ này.

Thư viện cần có: json_simple_1.1.jar

Tạo dự án mới và đặt tên là GoogleTranslator và import thư viện Json Simple vào dự án.


Mã xử lý: GoogleTranslator.java

package translator;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;

/**
 *
 * @author Code4LifeVn
 */
public class GoogleTranslator {
    
    private final String googleTranslatorURL = "http://translate.google.com/translate_a/t?";
    private LANGUAGE srcLang = LANGUAGE.AUTO;
    private LANGUAGE destLang = LANGUAGE.VIETNAMESE;
    private String userAgent = "Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7A341 Safari/528.16";

    public String translate(String query) throws MalformedURLException, IOException, ParseException {
        URL url = new URL(this.buildURLRequestWith(query));
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.addRequestProperty("User-Agent", this.userAgent);
        conn.setRequestMethod("GET");
        conn.setConnectTimeout(30000);
        conn.connect();

        InputStream inputStream = conn.getInputStream();
        BufferedReader bis = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        String respContent = bis.readLine();
        inputStream.close();
        bis.close();
        conn.disconnect();

        StringBuilder contentBuilder = new StringBuilder();

        JSONParser parser = new JSONParser();
        JSONObject jsonData = (JSONObject) parser.parse(respContent);
        JSONArray sentences = (JSONArray) jsonData.get("sentences");

        for (Object sentence : sentences) {
            contentBuilder.append(((JSONObject) sentence).get("trans").toString().trim());
        }

        return contentBuilder.toString().trim().replace(" .", ". ");
    }

    private String buildURLRequestWith(String query) {
        StringBuilder urlBuilder = new StringBuilder();
        urlBuilder.append(this.googleTranslatorURL);
        urlBuilder.append("client=webapp");
        urlBuilder.append("&sl=auto");
        urlBuilder.append("&tl=").append(this.destLang);
        urlBuilder.append("&hl=").append(this.srcLang);
        urlBuilder.append("&sc=1");
        String queryEncoded = "";
        try {
            queryEncoded = URLEncoder.encode(query, "UTF-8");
        } catch (Exception e) {
        }
        urlBuilder.append("&q=").append(queryEncoded);
        return urlBuilder.toString();
    }

    public LANGUAGE getSrcLang() {
        return srcLang;
    }

    public void setSrcLang(LANGUAGE srcLang) {
        this.srcLang = srcLang;
    }

    public LANGUAGE getDestLang() {
        return destLang;
    }

    public void setDestLang(LANGUAGE destLang) {
        this.destLang = destLang;
    }

    public String getUserAgent() {
        return userAgent;
    }

    public void setUserAgent(String userAgent) {
        this.userAgent = userAgent;
    }
    
    public static enum LANGUAGE {
        ENGLISH("en"),
        VIETNAMESE("vi"), 
        AUTO("auto");
        
        private String lang = "";
        private LANGUAGE(String lang) {
            this.lang = lang;
        }
        @Override
        public String toString() {
            return this.lang;
        }
    }
        
}


Với mã trên, bạn phải chú ý gửi kèm User-Agent khi request lên dịch vụ Google Translator, nếu không dịch vụ sẽ reject request của bạn.

Dữ liệu trả về là JSON nên tôi sẽ dùng thư viện hỗ trợ thao tác với các JSON Object để bóc tách dữ liệu và hiển thị chúng.

Với bài viết này, tôi demo sử dụng 2 ngôn ngữ ENGLISH VIETNAMESE, bạn hoàn toàn có thể thêm các Language Code vào trong LANGUAGE enum.

Để chạy thử mã xử lý trên, tôi tạo 1 Class để test, ví dụ class Demo:

import java.io.IOException;
import translator.GoogleTranslator;
import java.net.MalformedURLException;
import org.json.simple.parser.ParseException;
import static translator.GoogleTranslator.*;

/**
 *
 * @author Code4LifeVn
 */
public class Demo {
    public static void main(String[] args) throws MalformedURLException, IOException, ParseException {
        GoogleTranslator translator = new GoogleTranslator();
        translator.setSrcLang(LANGUAGE.ENGLISH);
        translator.setDestLang(LANGUAGE.VIETNAMESE);
        String data = translator.translate("Hello Java");
        System.out.println(data);
    }
    
    
}


Kết quả trả về như sau:




Do dữ liệu truyền bằng phương pháp GET nên sẽ giới hạn về độ dài ký tự gửi lên. Vì vậy, bạn phải phát triển thêm để xử lý khéo léo các trường hợp URL vượt quá giới hạn ký tự (2kb - 8kb).

Với công cụ này, tôi cảm thấy khá ok về mặt thiết kế cũng như số lượng API cần có để sử dụng, không phức tạp và rườm rà như thư viện hỗ trợ Google Translate API ở phần trên bài viết đã giới thiệu.

Những bạn nào thấy thích thú và muốn phát triển thêm hãy đưa những thông tin bổ ích mà bạn phát hiện hoặc làm mới cho công cụ này để mọi người cùng học hỏi nhé!

19 nhận xét:

  1. cam on ban rat nhieu ve bai viet, rat huu ich

    Trả lờiXóa
  2. a ơi...em làm theo cách của a cũng ra được kết quả rồi ...nhưng kết quả của em bị mã hóa em chưa biết xử lý thế nào ..như hello java của em sẽ ra là xin chà o java
    a giúp em vs ah

    Trả lờiXóa
  3. Hi em, dữ liệu trả về như vậy có thể do em chưa thiết lập Charset Encoding là UTF-8

    Trả lờiXóa
  4. mình chạy nhưng nó cứ báo lỗi chỗ conn.connect(); làm thế nào để sửa lỗi chỗ đấy hả bạn

    Trả lờiXóa
  5. Exception nó bắn ra là gì? Bạn phải nói rõ Exception Message chứ nói chung chung thế sao biết được ^^

    Trả lờiXóa
  6. Lỗi này xảy ra do hết thời gian timeout đợi response từ phía server về.
    MÌnh vừa test ở máy chỗ làm + mạng chỗ làm không có vấn đề gì.
    Bạn thử tăng thời gian timeout lên khoảng 1 phút với mạng nhà bạn xem thế nào nhé.

    (hình demo đính kèm)

    Trả lờiXóa
  7. mình chạy được rồi. cám ơn bạn nhé

    Trả lờiXóa
  8. sao em import thư viện Json Simple vào dự án không được vây anh?

    Trả lờiXóa
  9. Anh ơi cho em hỏi. e cũng bị lỗi như thế thì tăng thời gian timeout như thế nào ? tại e cũng mới học java

    Trả lờiXóa
  10. cảm ơn a...em làm được rồi ah :D

    Trả lờiXóa
  11. ở đoạn này em:

    BufferedReader bis = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));

    Trả lờiXóa
  12. thiết lập cái này ở đoạn nào vậy a...em ko tìm được :(

    Trả lờiXóa
  13. Chào các bạn,

    Các bạn có thể request cái này cho tiện

    http://translate.google.com/translate_a/t?client=gtrans&sl=en&tl=vi&format=html&v=1.0&q=Hello%20Java

    hoặc API 2.0

    http://translate.google.com/translate_a/t?client=gtrans&sl=en&tl=vi&format=html&v=2.0&q=Hello%20Java

    Trả lờiXóa
  14. Google Translate API v1 đã bị Google deprecated. Còn version 2.0 sử dụng không ổn định ở những văn bản dài. Bạn thử dịch bằng API ở trên bài viết với API v2.0 xem có sự khác biệt nào không ^^.

    Trả lờiXóa
  15. Bài viết rất hay và ý nghĩa :) Thanks Đỗ Mạnh nhé

    Trả lờiXóa
  16. Anh ơi cho em hỏi tải thư viện translator.GoogleTranslator; ở đâu ạ? Anh cho em link có được k?

    Trả lờiXóa
  17. Trong tut này anh không sử dụng thư viện GTranslate. Nếu em muốn dùng em tải ở đây: https://code.google.com/p/google-api-translate-java/

    Trả lờiXóa
  18. Cho mình hỏi có Google Search API kiểu giống Translate API như trên không? Xin cảm ơn.

    Trả lờiXóa

 

code4lifevn team

Thanh niên nghiêm túc :)

Name: Manh Do

Age: years old

Job: Senior Java and Mobile Developer

Country: VietNam

Name: Hung Nguyen

Age: years old

Job: Android Developer

Country: VietNam

Name: Trung PH

Age: years old

Job: Senior iOS and Android Developer

Country: VietNam

Name: Điệp NT

Age: years old

Job: Senior .Net and Android Developer

Country: VietNam