The Road to Delphi

Delphi – Free Pascal – Oxygene

Using the Google Translate API V2 (Labs) from Delphi

19 Comments

UPDATE

The Google Translate API has been officially deprecated  an alternative  is the Microsoft Translator V2, check this article for more details.

 

In this post i will show you how work with the Google Translate API V2 (Labs),  this API lets you automatically translates text from one language to another.

Disclaimer

  • This version of the Google Translate API is in Labs, and its features might change unexpectedly until it graduates.
  • The Google Translate API requires the use of an API key, which you can get from the Google APIs console
  • Before to use this API check the Google Translate API Terms of Use.

To use the Google Translate API you must send a HTTP GET request to its URI.

The URI for a request has the following format:

https://www.googleapis.com/language/translate/v2?parameters

Example to making a request to translate the Hello World text from English (en) to Spanish (es) the URI must be constructed in this way

https://www.googleapis.com/language/translate/v2?key=INSERT-YOUR-KEY&source=en&target=es&q=Hello%20world

The response in JSON format will be

{"data":{"translations":[{"translatedText":"Hola Mundo"}]}}

To activate the auto-detection of the source language you must avoid the use of the source keyword

https://www.googleapis.com/language/translate/v2?key=INSERT-YOUR-KEY&target=es&q=Hello%20world

and the JSON response in this case will be

{"data":{"translations":[{"translatedText":"Hola a todos","detectedSourceLanguage":"en"}]}

if you pass incorrect parameters the response will look like this

{"error":{"errors":[{"domain":"global","reason":"invalid","message":"Invalid Value"}],"code":400,"message":"Invalid Value"}}

some conversions between languages are not allowed by the API, in thi case you will get a response of this type

{"error":{"errors":[{"domain":"global","reason":"badRequest","message":"Bad language pair: en|zh-TW"}],"code":400,"message":"Bad language pair: en|zh-TW"}}

Now I will show 3 ways to process the data

Using the JSON – SuperObject , this library is very well written and is very easy to use, also is compatible with olders versions of Delphi and Freepascal (win32/64 linux32/64).

function Translate_JSONsuperobject(const Text:string;Source,Dest:TGoogleLanguages):string;
var
  XMLHTTPRequest: IXMLHTTPRequest;
  EncodedRequest: string;
  Response      : string;
begin
  Result:='';
  if Source=Autodetect then //build the URI
    EncodedRequest:=Format(GoogleTranslateUrlAuto,[GoogleLanguageApiKey,GoogleLanguagesArr[Dest],HTTPEncode(Text)])
  else
    EncodedRequest:=Format(GoogleTranslateUrl,[GoogleLanguageApiKey,HTTPEncode(Text),GoogleLanguagesArr[Source],GoogleLanguagesArr[Dest]]);

  XMLHTTPRequest := CoXMLHTTP.Create;
  XMLHTTPRequest.open('GET', EncodedRequest, False, EmptyParam, EmptyParam); //Make the request
  XMLHTTPRequest.send('');
  Response:=XMLHTTPRequest.responseText;
  if Response<>'' then
  begin
    if SO(Response)['error']=nil then //all ok
     Result := SO(Response)['data.translations[0].translatedText'].AsString
    else //exist an error response
     Result := Format('Error Code %d message %s',[SO(Response)['error.code'].AsInteger,SO(Response)['error.message'].AsString]);
     Result:=HTMLDecode(Result);
  end;

end;

Using the DBXJSON unit included since Delphi 2010

function Translate_DBXJSON(const Text:string;Source,Dest:TGoogleLanguages):string;
var
  XMLHTTPRequest: IXMLHTTPRequest;
  EncodedRequest: string;
  json          : TJSONObject;
  jPair         : TJSONPair;
  jValue        : TJSONValue;
  Response      : string;
begin
  Result:='';
  if Source=Autodetect then //buil the URI
    EncodedRequest:=Format(GoogleTranslateUrlAuto,[GoogleLanguageApiKey,GoogleLanguagesArr[Dest],HTTPEncode(Text)])
  else
    EncodedRequest:=Format(GoogleTranslateUrl,[GoogleLanguageApiKey,HTTPEncode(Text),GoogleLanguagesArr[Source],GoogleLanguagesArr[Dest]]);

  XMLHTTPRequest := CoXMLHTTP.Create;
  XMLHTTPRequest.open('GET', EncodedRequest, False, EmptyParam, EmptyParam); //make the request
  XMLHTTPRequest.send('');
  Response:=XMLHTTPRequest.responseText;

  if Response<>'' then
  begin
      json    := TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(Response),0) as TJSONObject; //create a TJSONObject instance
    try
      jPair   := json.Get(0);
      if jPair.JsonString.value='error' then //if error in response
        Result := Format('Error Code %s message %s',[TJSONObject(jPair.JsonValue).Get(1).JsonValue.Value,TJSONObject(jPair.JsonValue).Get(2).JsonValue.Value])
      else //all ok, show the response,
      begin
        jValue := TJSONArray(TJSONObject(jPair.JsonValue).Get(0).JsonValue).Get(0);
        Result := TJSONObject(jValue).Get(0).JsonValue.Value;
      end;
    finally
       json.Free;
    end;

      Result:=HTMLDecode(Result);
  end;
end;

and finally without using JSON, a very ugly way, but works.

function Translate_JSONLess(const Text:string;Source,Dest:TGoogleLanguages):string;
const
  TagIOk='{"data":{"translations":[{"translatedText":"';
  TagFOk='"}]}}';
  TagErr='{"error":{"errors":[{';
  TagAut=',"detectedSourceLanguage":"';
var
  XMLHTTPRequest: IXMLHTTPRequest;
  EncodedRequest: string;
  Response      : string;
begin
  Result:='';

  if Source=Autodetect then //build the URI
    EncodedRequest:=Format(GoogleTranslateUrlAuto,[GoogleLanguageApiKey,GoogleLanguagesArr[Dest],HTTPEncode(Text)])
  else
    EncodedRequest:=Format(GoogleTranslateUrl,[GoogleLanguageApiKey,HTTPEncode(Text),GoogleLanguagesArr[Source],GoogleLanguagesArr[Dest]]);

  XMLHTTPRequest := CoXMLHTTP.Create;
  XMLHTTPRequest.open('GET', EncodedRequest, False, EmptyParam, EmptyParam); //make the request
  XMLHTTPRequest.send('');
  Response:=XMLHTTPRequest.responseText;
  if Response<>'' then
  begin
    if StartsStr(TagErr,(Response)) then  //Response  Error
    begin
      Result:='Error'
    end
    else
    begin  //Response Ok
      if Source=Autodetect then
      begin
        Result:=StringReplace(Response,TagIOk,'',[rfReplaceAll]); //remove tags
        Result:=Copy(Result,1,Pos(TagAut,Result)-2);//remove tags
      end
      else
      begin
        Result:=StringReplace(Response,TagIOk,'',[rfReplaceAll]);//remove tags
        Result:=StringReplace(Result,TagFOk,'',[rfReplaceAll]);//remove tags
      end;
    end;

    Result:=HTMLDecode(Result);
  end;
end;

Check the full source showing the 3 ways to access the Google Translate API, listed in this entry.

program GoogleAPITranslate;
//Author  : Rodrigo Ruz V. 2010-12-03  03;30 A.M

{$APPTYPE CONSOLE}
{$DEFINE USE_SUPER_OBJECT}
{$DEFINE USE_DBXJSON}
{$DEFINE USE_JSONLess}

uses
   msxml
  ,Activex
  ,HTTPApp
  ,Variants
  ,SysUtils
  {$IFDEF USE_JSONLess}
  ,StrUtils
  {$ENDIF}
  {$IFDEF USE_SUPER_OBJECT}
  ,superobject
  {$ENDIF}
  {$IFDEF USE_DBXJSON}
  ,DBXJSON
  {$ENDIF}
  ;

  type
  TGoogleLanguages=
  (Autodetect,Afrikaans,Albanian,Arabic,Basque,Belarusian,Bulgarian,Catalan,Chinese,Chinese_Traditional,
  Croatian,Czech,Danish,Dutch,English,Estonian,Filipino,Finnish,French,Galician,German,Greek,
  Haitian_Creole,Hebrew,Hindi,Hungarian,Icelandic,Indonesian,Irish,Italian,Japanese,Latvian,
  Lithuanian,Macedonian,Malay,Maltese,Norwegian,Persian,Polish,Portuguese,Romanian,Russian,
  Serbian,Slovak,Slovenian,Spanish,Swahili,Swedish,Thai,Turkish,Ukrainian,Vietnamese,Welsh,Yiddish);

  const
  GoogleLanguagesArr : array[TGoogleLanguages] of string =
  ( 'Autodetect','af','sq','ar','eu','be','bg','ca','zh-CN','zh-TW','hr','cs','da','nl','en','et','tl','fi','fr','gl',
    'de','el','ht','iw','hi','hu','is','id','ga','it','ja','lv','lt','mk','ms','mt','no','fa','pl','pt',
    'ro','ru','sr','sk','sl','es','sw','sv','th','tr','uk','vi','cy','yi');

  //¡¡¡¡¡¡Please be nice and create your own Google Api Key ¡¡¡¡¡¡¡
  GoogleLanguageApiKey   ='AIzaSyDb18pd1IfkYyupC2XUIANcRoB3f9J2DJg';
  GoogleTranslateUrl     ='https://www.googleapis.com/language/translate/v2?key=%s&q=%s&source=%s&target=%s';
  GoogleTranslateUrlAuto ='https://www.googleapis.com/language/translate/v2?key=%s&target=%s&q=%s';

{$IFDEF USE_DBXJSON}
function Translate_DBXJSON(const Text:string;Source,Dest:TGoogleLanguages):string;
var
  XMLHTTPRequest: IXMLHTTPRequest;
  EncodedRequest: string;
  json          : TJSONObject;
  jPair         : TJSONPair;
  jValue        : TJSONValue;
  Response      : string;
begin
  Result:='';
  if Source=Autodetect then
    EncodedRequest:=Format(GoogleTranslateUrlAuto,[GoogleLanguageApiKey,GoogleLanguagesArr[Dest],HTTPEncode(Text)])
  else
    EncodedRequest:=Format(GoogleTranslateUrl,[GoogleLanguageApiKey,HTTPEncode(Text),GoogleLanguagesArr[Source],GoogleLanguagesArr[Dest]]);

  XMLHTTPRequest := CoXMLHTTP.Create;
  XMLHTTPRequest.open('GET', EncodedRequest, False, EmptyParam, EmptyParam);
  XMLHTTPRequest.send('');
  Response:=XMLHTTPRequest.responseText;

  if Response<>'' then
  begin
      json    := TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(Response),0) as TJSONObject;
    try
      jPair   := json.Get(0);
      if jPair.JsonString.value='error' then
        //{"error":{"errors":[{"domain":"global","reason":"invalid","message":"Invalid Value"}],"code":400,"message":"Invalid Value"}}
        Result := Format('Error Code %s message %s',[TJSONObject(jPair.JsonValue).Get(1).JsonValue.Value,TJSONObject(jPair.JsonValue).Get(2).JsonValue.Value])
      else
      begin
        //{"data":{"translations":[{"translatedText":"Hola a todos","detectedSourceLanguage":"en"}]}}
        jValue := TJSONArray(TJSONObject(jPair.JsonValue).Get(0).JsonValue).Get(0);
        Result := TJSONObject(jValue).Get(0).JsonValue.Value;
      end;
    finally
       json.Free;
    end;

      Result:=HTMLDecode(Result);
  end;
end;
{$ENDIF}

{$IFDEF USE_SUPER_OBJECT}
function Translate_JSONsuperobject(const Text:string;Source,Dest:TGoogleLanguages):string;
var
  XMLHTTPRequest: IXMLHTTPRequest;
  EncodedRequest: string;
  Response      : string;
begin
  Result:='';
  if Source=Autodetect then
    EncodedRequest:=Format(GoogleTranslateUrlAuto,[GoogleLanguageApiKey,GoogleLanguagesArr[Dest],HTTPEncode(Text)])
  else
    EncodedRequest:=Format(GoogleTranslateUrl,[GoogleLanguageApiKey,HTTPEncode(Text),GoogleLanguagesArr[Source],GoogleLanguagesArr[Dest]]);

  XMLHTTPRequest := CoXMLHTTP.Create;
  XMLHTTPRequest.open('GET', EncodedRequest, False, EmptyParam, EmptyParam);
  XMLHTTPRequest.send('');
  Response:=XMLHTTPRequest.responseText;
  if Response<>'' then
  begin
  //{"data":{"translations":[{"translatedText":"Hola a todos","detectedSourceLanguage":"en"}]}}
    if SO(Response)['error']=nil then
     Result := SO(Response)['data.translations[0].translatedText'].AsString
    else
     //{"error":{"errors":[{"domain":"global","reason":"invalid","message":"Invalid Value"}],"code":400,"message":"Invalid Value"}}
     //{"error":{"errors":[{"domain":"global","reason":"badRequest","message":"Bad language pair: en|zh-TW"}],"code":400,"message":"Bad language pair: en|zh-TW"}}
     Result := Format('Error Code %d message %s',[SO(Response)['error.code'].AsInteger,SO(Response)['error.message'].AsString]);
     Result:=HTMLDecode(Result);
  end;

end;
{$ENDIF}

{$IFDEF USE_JSONLess}
function Translate_JSONLess(const Text:string;Source,Dest:TGoogleLanguages):string;
const
  TagIOk='{"data":{"translations":[{"translatedText":"';
  TagFOk='"}]}}';
  TagErr='{"error":{"errors":[{';
  TagAut=',"detectedSourceLanguage":"';
var
  XMLHTTPRequest: IXMLHTTPRequest;
  EncodedRequest: string;
  Response      : string;
begin
  Result:='';

  if Source=Autodetect then
    EncodedRequest:=Format(GoogleTranslateUrlAuto,[GoogleLanguageApiKey,GoogleLanguagesArr[Dest],HTTPEncode(Text)])
  else
    EncodedRequest:=Format(GoogleTranslateUrl,[GoogleLanguageApiKey,HTTPEncode(Text),GoogleLanguagesArr[Source],GoogleLanguagesArr[Dest]]);

  XMLHTTPRequest := CoXMLHTTP.Create;
  XMLHTTPRequest.open('GET', EncodedRequest, False, EmptyParam, EmptyParam);
  XMLHTTPRequest.send('');
  Response:=XMLHTTPRequest.responseText;
  if Response<>'' then
  begin
    if StartsStr(TagErr,(Response)) then  //Response  Error
    begin
      Result:='Error'
    end
    else
    begin  //Response Ok
      if Source=Autodetect then
      begin
        Result:=StringReplace(Response,TagIOk,'',[rfReplaceAll]);
        Result:=Copy(Result,1,Pos(TagAut,Result)-2);
      end
      else
      begin
        Result:=StringReplace(Response,TagIOk,'',[rfReplaceAll]);
        Result:=StringReplace(Result,TagFOk,'',[rfReplaceAll]);
      end;
    end;

    Result:=HTMLDecode(Result);
  end;
end;
{$ENDIF}

Const
 Text ='"Hello  World"';
Var
 TranslatedText : string;
begin
  try
    CoInitialize(nil);
    try
       {$IFDEF USE_JSONLess}
       Writeln('Without JSON (very ugly)');
       Writeln('');
       TranslatedText:=Translate_JSONLess(Text,Autodetect,Spanish);
       Writeln(TranslatedText);
       TranslatedText:=Translate_JSONLess(Text,English,Chinese_Traditional);
       Writeln(TranslatedText);
       TranslatedText:=Translate_JSONLess(Text,English,German);
       Writeln(TranslatedText);
       TranslatedText:=Translate_JSONLess(Text,English,Danish);
       Writeln(TranslatedText);
       TranslatedText:=Translate_JSONLess(Text,English,Portuguese);
       Writeln(TranslatedText);
       Writeln('');
       {$ENDIF}

       {$IFDEF USE_SUPER_OBJECT}
       Writeln('Using the superobject library');
       Writeln('');
       TranslatedText:=Translate_JSONsuperobject(Text,Autodetect,Spanish);
       Writeln(TranslatedText);
       TranslatedText:=Translate_JSONsuperobject(Text,English,Chinese_Traditional);
       Writeln(TranslatedText);
       TranslatedText:=Translate_JSONsuperobject(Text,English,German);
       Writeln(TranslatedText);
       TranslatedText:=Translate_JSONsuperobject(Text,English,Danish);
       Writeln(TranslatedText);
       TranslatedText:=Translate_JSONsuperobject(Text,English,Portuguese);
       Writeln(TranslatedText);
       Writeln('');
       {$ENDIF}

       {$IFDEF USE_DBXJSON}
       Writeln('Using the DBXJSON unit');
       Writeln('');
       TranslatedText:=Translate_DBXJSON(Text,Autodetect,Spanish);
       Writeln(TranslatedText);
       TranslatedText:=Translate_DBXJSON(Text,English,Chinese_Traditional);
       Writeln(TranslatedText);
       TranslatedText:=Translate_DBXJSON(Text,English,German);
       Writeln(TranslatedText);
       TranslatedText:=Translate_DBXJSON(Text,English,Danish);
       Writeln(TranslatedText);
       TranslatedText:=Translate_DBXJSON(Text,English,Portuguese);
       Writeln(TranslatedText);
       Writeln('');
       {$ENDIF}

    finally
     CoUninitialize;
    end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.
Check this link  <a href=”http://code.google.com/apis/language/translate/terms.html&#8221; rel=”nofollow”>Google Translate API Terms of Use</a>.

Author: Rodrigo

Just another Delphi guy.

19 thoughts on “Using the Google Translate API V2 (Labs) from Delphi

  1. Rodrigo,

    As usual, you gave explicit examples and of general interest! Keep up the good job, is always a pleasure to visit your site and see a lot of goodies :)

    Have a nice day!

  2. Pingback: Tweets that mention Using the Google Translate API V2 (Labs) from Delphi « The Road to Delphi – a Blog About Delphi Programming (mostly) -- Topsy.com

  3. Nice article.

    Do anyone know something about the legal permissions when code like this is used in a commercial application? Is it still free when it’s used commercially?

  4. hi
    very thanks for your post.
    do you know any solution for testing internet connection availability in delphi?
    it means that internet is available or not , disconnect?
    thanks

  5. Pingback: Detecting the language from a text using the Google translate API v1 « The Road to Delphi – a Blog About Delphi Programming (mostly)

  6. Rodrigo,

    I used to code in Delphi (since version 1) but now I just do ‘pet projects’ in D2010. I am doing a little application to speed up my German studies and your code just nailed it. I was amazed to find your code, so well documented and robust. Thank you so much!!!

    Fernando

  7. Not work

    from portuguese to japanese, Yiddish, urdu

  8. Thank you, colegue! I have been searching this for my DLLs for some time already… :)

  9. Rodrigo,
    I try your example and it worked with the expected results.
    I obtained my own application key and pasted it over yours and I now get
    “Error Code 400 message Bad Request”
    after each request.
    Do you have any idea why this is?
    My key was 86 characters long, where yours was 39. I’m not sure if that is the reason.

    Thanks,
    Simon

  10. Dear Rodrigo,

    Very outstanding job you did. But it does not compiles on D2007 which I fixed the following line, after changing this one, compiles and run perfectly.

    XMLHTTPRequest := CoXMLHTTPRequest.Create;

    instead of

    XMLHTTPRequest := CoXMLHTTP.Create;

    thanks

    Muhammad Shoaib

  11. Does this code work with the new paid API key?

  12. Dear Rodrigo, thank you for your very constructive examples. Unfortunately, the DBXJSON example doesn’t seem to work with unicode. Example: German word “Groß” becomes “Gro?”.

    Am I missing something?

  13. Very thanks for your post. – :-D –

  14. These 2 units need to be added to the implementation (Delphi Seattle +) : System.JSON, System.JSONConsts

    And if you look for the Google types, go directly to the last code fragment: they are defined there.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s