Google Translate V2 cannot hanlde large text translations from C#
Asked Answered
B

3

6

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;
    }
Bitumen answered 24/2, 2012 at 14:32 Comment(1)
Can you show us your code you're using now? The strategy is a bit different if you're using WebClient vs WebRequest.Liquate
L
7

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);
}
Liquate answered 24/2, 2012 at 14:46 Comment(5)
Thanks for your quick response. I've added the code I'm executing. I've also digged into the code you posted and I was able to update mine to make the post as you pointed out. However, when executing the "request.GetResponse();" the following error is raised:"The remote server returned an error: (400) Bad Request". Will look into this.Bitumen
@George_21: you need to get rid of the parameters from the URL and put them all in the post body.Liquate
You're my hero! :P . I finally was able to re-write my code following your suggestion and also adding a missing line: "request.ContentType="application/x-www-form-urlencoded"; Really appreciate your help on this! Thankssss!Bitumen
i used your method but there is nothing return by json. json variables are emptyMarquetry
I was also missing the ContentTypeHofer
X
3

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);
    }
} 
Xray answered 22/1, 2015 at 16:35 Comment(0)
H
-3

? What? it is trivial to post using C# - it is right there in the documentation.

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
{
    // Set type to POST
    request.Method = "POST";

From there on you bascially put the data into fom fields into the content stream.

This is not "simulate a post meethod", it is fully doing a post request as per specifications.

Btw. hwhere does json enter here? You say "in C#". There is no need to use json?

Hip answered 24/2, 2012 at 14:43 Comment(1)
Does not handle the "X-HTTP-Method-Override" part.Milkmaid

© 2022 - 2024 — McMap. All rights reserved.