Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google Translate V2 cannot hanlde large text translations from C#

I've implemented C# code using the Google Translation V2 api with the GET Method. It successfully translates small texts but when increasing the text length and it takes 1,800 characters long ( including URI parameters ) I'm getting the "URI too large" error.

Ok, I burned down all the paths and investigated the issue across multiple pages posted on Internet. All of them clearly says the GET method should be overriden to simulate a POST method ( which is meant to provide support to 5,000 character URIs ) but there is no way to find out a code example to of it.

Does anyone has any example or can provide some information?

[EDIT] Here is the code I'm using:

String apiUrl = "https://www.googleapis.com/language/translate/v2?key={0}&source={1}&target={2}&q={3}";
            String url = String.Format(apiUrl, Constants.apiKey, sourceLanguage, targetLanguage, text);
            Stream outputStream = null;

        byte[] bytes = Encoding.ASCII.GetBytes(url);

        // create the http web request
        HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
        webRequest.KeepAlive = true;
        webRequest.Method = "POST";
        // Overrride the GET method as documented on Google's docu.
        webRequest.Headers.Add("X-HTTP-Method-Override: GET");
        webRequest.ContentType = "application/x-www-form-urlencoded";

        // send POST
        try
        {
            webRequest.ContentLength = bytes.Length;
            outputStream = webRequest.GetRequestStream();
            outputStream.Write(bytes, 0, bytes.Length);
            outputStream.Close();
        }
        catch (HttpException e)
        {
            /*...*/
        }

        try
        {
            // get the response
            HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
            if (webResponse.StatusCode == HttpStatusCode.OK && webRequest != null)
            {
                // read response stream 
                using (StreamReader sr = new StreamReader(webResponse.GetResponseStream(), Encoding.UTF8))
                {
                    string lista = sr.ReadToEnd();

                    DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(TranslationRootObject));
                    MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(lista));
                    TranslationRootObject tRootObject = (TranslationRootObject)serializer.ReadObject(stream);
                    string previousTranslation = string.Empty;

                    //deserialize
                    for (int i = 0; i < tRootObject.Data.Detections.Count; i++)
                    {
                        string translatedText = tRootObject.Data.Detections[i].TranslatedText.ToString();
                        if (i == 0)
                        {
                            text = translatedText;
                        }
                        else
                        {
                            if (!text.Contains(translatedText))
                            {
                                text = text + " " + translatedText;
                            }
                        }
                    }
                    return text;
                }
            }
        }
        catch (HttpException e)
        {
            /*...*/
        }

        return text;
    }
like image 412
G21 Avatar asked Feb 24 '12 14:02

G21


2 Answers

Apparently using WebClient won't work as you cannot alter the headers as needed, per the documentation:

Note: You can also use POST to invoke the API if you want to send more data in a single request. The q parameter in the POST body must be less than 5K characters. To use POST, you must use the X-HTTP-Method-Override header to tell the Translate API to treat the request as a GET (use X-HTTP-Method-Override: GET).

You can use WebRequest, but you'll need to add the X-HTTP-Method-Override header:

var request = WebRequest.Create (uri);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.Headers.Add("X-HTTP-Method-Override", "GET");

var body = new StringBuilder();
body.Append("key=SECRET");
body.AppendFormat("&source={0}", HttpUtility.UrlEncode(source));
body.AppendFormat("&target={0}", HttpUtility.UrlEncode(target));
 //--
body.AppendFormat("&q={0}", HttpUtility.UrlEncode(text));

var bytes = Encoding.ASCII.GetBytes(body.ToString());
if (bytes.Length > 5120) throw new ArgumentOutOfRangeException("text");

request.ContentLength = bytes.Length;
using (var output = request.GetRequestStream())
{
    output.Write(bytes, 0, bytes.Length);
}
like image 159
user7116 Avatar answered Sep 21 '22 02:09

user7116


The accepted answer appears to be out of date. You can now use the WebClient (.net 4.5) successfully to POST to the google translate API making sure to set the X-HTTP-Method-Override header.

Here is some code to show you how.

using (var webClient = new WebClient())
{
    webClient.Headers.Add("X-HTTP-Method-Override", "GET");
    var data = new NameValueCollection() 
    { 
        { "key", GoogleTranslateApiKey }, 
        { "source", "en" }, 
        { "target", "fr"}, 
        { "q", "<p>Hello World</p>" } 
    };
    try
    {
        var responseBytes = webClient.UploadValues(GoogleTranslateApiUrl, "POST", data);
        var json = Encoding.UTF8.GetString(responseBytes);
        var result = JsonConvert.DeserializeObject<dynamic>(json);
        var translation = result.data.translations[0].translatedText;
    }
    catch (Exception ex)
    {
        loggingService.Error(ex.Message);
    }
} 
like image 44
biofractal Avatar answered Sep 21 '22 02:09

biofractal