Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Google translate in tooltip [Replaced by standalone app]


  • Please log in to reply
68 replies to this topic
micdelt
  • Members
  • 8 posts
  • Last active: Aug 25 2015 01:17 PM
  • Joined: 11 Dec 2009

Some replacement for Abbyy Lingvo / Stardict. Activated by double press Ctrl+C. First press copies text to clipboard, next translate it. Translated text appears in tooltip.

 

 


Old code no longer works. New one too.

Made standalone app: http://www.micdelt.ru/translate

 

Requeres Unicode version of AutoHotkey.


;--------------------------------------------------

; Translate text using translate.google.com

; after Google Translate API deprecation

;

; Ctrl+C, Ctrl+C

; Author: Mikhail Kuropyatnikov (micdelt@mail.ru),

; Volgograd, Russia

;--------------------------------------------------

#NoEnv



~^C:: DoublePress()



DoublePress()

{

static pressed1 = 0

if pressed1 and A_TimeSincePriorHotkey <= 200

{

pressed1 = 0

; Translate from any language to Russian and from Russian to English if source was in Russian

Translate("ru","en")

}

else

pressed1 = 1



}



; translate to "to" language,

; if source language is "to"

; translate to "anti" language



Translate(To,Anti)

{

UseAnti = 0

TranslateTo := To

if Clipboard =

return



UriCli := UriEncode(Clipboard)



anti_translate:

Url := "http://translate.google.com/translate_a/t?client=x&text="

. UriCli . "&tl=" . TranslateTo



; Simulate Google Chrome

JsonTrans := UrlDownloadToVar(Url,"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/18.6.872.0 Safari/535.2")



; thanks to Grey (http://forum.script-coding.com/profile.php?id=25792)

StringReplace, JsonTrans, JsonTrans, \r\n,`r`n, All

StringReplace, JsonTrans, JsonTrans, \", ", All

FromLang:=JSON(JsonTrans, "src")

ElapsedTime:=JSON(JsonTrans, "server_time")



if (FromLang == To and TranslateTo <> Anti)

{

TranslateTo := Anti

;MsgBox % FromLang . " " . To . " " TranslateTo . " " . Anti

goto anti_translate

}



Loop

{

Sentence:=JSON(JsonTrans, "sentences["(A_Index-1)"].trans")

If Sentence

TransText.=Sentence

Else

Break

}



; Convert To UTF-8

BaseFileEnc := A_FileEncoding

FileEncoding

FileDelete, %A_ScriptDir%\Convert.html

FileAppend, %TransText%, %A_ScriptDir%\Convert.html

FileEncoding, UTF-8

FileRead TransText, %A_ScriptDir%\Convert.html

FileEncoding, %BaseFileEnc%



; split long line to smaller lines about 40-50 symbols length

t := RegExReplace(transText,".{40,50}(\s)","$0`n")



ToolTip %FromLang%: %t%

; copy result to clipboard

clipboard := t



}







~LButton::

ToolTip

return







UrlDownloadToVar(URL, UserAgent = "", Proxy = "", ProxyBypass = "") {

; Requires Windows Vista, Windows XP, Windows 2000 Professional, Windows NT Workstation 4.0,

; Windows Me, Windows 98, or Windows 95.

; Requires Internet Explorer 3.0 or later.

pFix:=a_isunicode ? "W" : "A"

hModule := DllCall("LoadLibrary", "Str", "wininet.dll")



AccessType := Proxy != "" ? 3 : 1

;INTERNET_OPEN_TYPE_PRECONFIG 0 // use registry configuration

;INTERNET_OPEN_TYPE_DIRECT 1 // direct to net

;INTERNET_OPEN_TYPE_PROXY 3 // via named proxy

;INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY 4 // prevent using java/script/INS



io := DllCall("wininet\InternetOpen" . pFix

, "Str", UserAgent ;lpszAgent

, "UInt", AccessType

, "Str", Proxy

, "Str", ProxyBypass

, "UInt", 0) ;dwFlags



iou := DllCall("wininet\InternetOpenUrl" . pFix

, "UInt", io

, "Str", url

, "Str", "" ;lpszHeaders

, "UInt", 0 ;dwHeadersLength

, "UInt", 0x80000000 ;dwFlags: INTERNET_FLAG_RELOAD = 0x80000000 // retrieve the original item

, "UInt", 0) ;dwContext



If (ErrorLevel != 0 or iou = 0) {

DllCall("FreeLibrary", "UInt", hModule)

return 0

}



VarSetCapacity(buffer, 10240, 0)

VarSetCapacity(BytesRead, 4, 0)



Loop

{

;http://msdn.microsoft.com/library/en-us/wininet/wininet/internetreadfile.asp

irf := DllCall("wininet\InternetReadFile", "UInt", iou, "UInt", &buffer, "UInt", 10240, "UInt", &BytesRead)

VarSetCapacity(buffer, -1) ;to update the variable's internally-stored length



BytesRead_ = 0 ; reset

Loop, 4 ; Build the integer by adding up its bytes. (From ExtractInteger-function)

BytesRead_ += *(&BytesRead + A_Index-1) << 8*(A_Index-1) ;Bytes read in this very DllCall



; To ensure all data is retrieved, an application must continue to call the

; InternetReadFile function until the function returns TRUE and the lpdwNumberOfBytesRead parameter equals zero.

If (irf = 1 and BytesRead_ = 0)

break

Else ; append the buffer's contents

{

a_isunicode ? buffer:=StrGet(&buffer, "CP0")

Result .= SubStr(buffer, 1, BytesRead_ * (a_isunicode ? 2 : 1))

}



/* optional: retrieve only a part of the file

BytesReadTotal += BytesRead_

If (BytesReadTotal >= 30000) ; only read the first x bytes

break ; (will be a multiple of the buffer size, if the file is not smaller; trim if neccessary)

*/

}



DllCall("wininet\InternetCloseHandle", "UInt", iou)

DllCall("wininet\InternetCloseHandle", "UInt", io)

DllCall("FreeLibrary", "UInt", hModule)

Return Result

}



JSON(ByRef js, s, v = "") {

j = %js%

Loop, Parse, s, .

{

p = 2

RegExMatch(A_LoopField, "([+\-]?)([^[]+)((?:\[\d+\])*)", q)

Loop {

If (!p := RegExMatch(j, "(?<!\\)(""|')([^\1]+?)(?<!\\)(?-1)\s*:\s*((\{(?:[^{}]++|(?-1))*\})|(\[(?:[^[\]]++|(?-1))*\])|"

. "(?<!\\)(""|')[^\7]*?(?<!\\)(?-1)|[+\-]?\d+(?:\.\d*)?|true|false|null?)\s*(?:,|$|\})", x, p))

Return

Else If (x2 == q2 or q2 == "*") {

j = %x3%

z += p + StrLen(x2) - 2

If (q3 != "" and InStr(j, "[") == 1) {

StringTrimRight, q3, q3, 1

Loop, Parse, q3, ], [

{

z += 1 + RegExMatch(SubStr(j, 2, -1), "^(?:\s*((\[(?:[^[\]]++|(?-1))*\])|(\{(?:[^{\}]++|(?-1))*\})|[^,]*?)\s*(?:,|$)){" . SubStr(A_LoopField, 1) + 1 . "}", x)

j = %x1%

}

}

Break

}

Else p += StrLen(x)

}

}

If v !=

{

vs = "

If (RegExMatch(v, "^\s*(?:""|')*\s*([+\-]?\d+(?:\.\d*)?|true|false|null?)\s*(?:""|')*\s*$", vx)

and (vx1 + 0 or vx1 == 0 or vx1 == "true" or vx1 == "false" or vx1 == "null" or vx1 == "nul"))

vs := "", v := vx1

StringReplace, v, v, ", \", All

js := SubStr(js, 1, z := RegExMatch(js, ":\s*", zx, z) + StrLen(zx) - 1) . vs . v . vs . SubStr(js, z + StrLen(x3) + 1)

}

Return, j == "false" ? 0 : j == "true" ? 1 : j == "null" or j == "nul"

? "" : SubStr(j, 1, 1) == """" ? SubStr(j, 2, -1) : j

}



;-------------------------------------------------

; HTML encode/decode

;------------------------------------------------



StrPutVar(string, ByRef var, encoding)

{

; Ensure capacity.

SizeInBytes := VarSetCapacity( var, StrPut(string, encoding)

; StrPut returns char count, but VarSetCapacity needs bytes.

* ((encoding="utf-16"||encoding="cp1200") ? 2 : 1) )

; Copy or convert the string.

StrPut(string, &var, encoding)

Return SizeInBytes

}



UriEncode(str)

{

b_Format := A_FormatInteger

data := ""

SetFormat,Integer,H

SizeInBytes := StrPutVar(str,var,"utf-8")

Loop, %SizeInBytes%

{

ch := NumGet(var,A_Index-1,"UChar")

If (ch=0)

Break

if ((ch>0x7f) || (ch<0x30) || (ch=0x3d))

s .= "%" . ((StrLen(c:=SubStr(ch,3))<2) ? "0" . c : c)

Else

s .= Chr(ch)

}

SetFormat,Integer,%b_format%

return s

}


This code don't work!



;--------------------------------------------------

; Translate text using translate.google.com

; by Mikhail Kuropyatnikov (micdelt@mail.ru)

;

; Ctrl+C, Ctrl+C

;--------------------------------------------------

#NoEnv



DoublePress() ; Simulate double press

{

static pressed1 = 0

if pressed1 and A_TimeSincePriorHotkey <= 500

{

pressed1 = 0

Translate("en","ru") ; from English to Russian

}

else

pressed1 = 1



}



~^C:: DoublePress()



Translate(from,to)

{

if clipboard =

return



Transform, unicodeClipboard, Unicode

url := "http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q="

. uriEncode(unicodeClipboard) . "&langpair=" . from . "%7C" . to



; simulate UrlDownloadToVAR

UrlDownloadToFile, %url%, %A_ScriptDir%\translate.html

FileRead, json_trans, %A_ScriptDir%\translate.html

json_trans := UTF82Ansi(json_trans)



rgxText = \Q{"translatedText":"\E(?P<Text>.*)\"\}

rgxDetails = \Q"responseDetails": "\E(?P<Details>.*)\"\,

rgxStatus = \Q"responseStatus": \E(?P<Status>\d*)



RegExMatch(json_trans,rgxText,trans)

RegExMatch(json_trans,rgxDetails,trans)

RegExMatch(json_trans,rgxStatus,trans)



if transStatus = 200

{

t := UnHTM(UnSlashUnicode(transText))

; split long line to smaller lines about 40-50 symbols length

t := RegExReplace(t,".{40,50}(\s)","$0`n")

ToolTip %t%

; copy result to clipboard

Clipboard := t

}

else

ToolTip %transDetails%

}



~LButton:: ; Remove tooltip left click

ToolTip

return



;---------------------------------------

; Convert strings

;---------------------------------------



/*

CP_ACP = 0

CP_OEMCP = 1

CP_MACCP = 2

CP_UTF7 = 65000

CP_UTF8 = 65001

*/



Ansi2Oem(sString)

{

Ansi2Unicode(sString, wString, 0)

Unicode2Ansi(wString, zString, 1)

Return zString

}



Oem2Ansi(zString)

{

Ansi2Unicode(zString, wString, 1)

Unicode2Ansi(wString, sString, 0)

Return sString

}



Ansi2UTF8(sString)

{

Ansi2Unicode(sString, wString, 0)

Unicode2Ansi(wString, zString, 65001)

Return zString

}



UTF82Ansi(zString)

{

Ansi2Unicode(zString, wString, 65001)

Unicode2Ansi(wString, sString, 0)

Return sString

}



Ansi2Unicode(ByRef sString, ByRef wString, CP = 0)

{

nSize := DllCall("MultiByteToWideChar"

, "Uint", CP

, "Uint", 0

, "Uint", &sString

, "int", -1

, "Uint", 0

, "int", 0)



VarSetCapacity(wString, nSize * 2)



DllCall("MultiByteToWideChar"

, "Uint", CP

, "Uint", 0

, "Uint", &sString

, "int", -1

, "Uint", &wString

, "int", nSize)

}



Unicode2Ansi(ByRef wString, ByRef sString, CP = 0)

{

nSize := DllCall("WideCharToMultiByte"

, "Uint", CP

, "Uint", 0

, "Uint", &wString

, "int", -1

, "Uint", 0

, "int", 0

, "Uint", 0

, "Uint", 0)



VarSetCapacity(sString, nSize)



DllCall("WideCharToMultiByte"

, "Uint", CP

, "Uint", 0

, "Uint", &wString

, "int", -1

, "str", sString

, "int", nSize

, "Uint", 0

, "Uint", 0)

}



;-------------------------------------------------

; HTML encode/decode

;------------------------------------------------



UriEncode(str)

{ ; v 0.3 / (w) 24.06.2008 by derRaphael / zLib-Style release

b_Format := A_FormatInteger

data := ""

SetFormat,Integer,H

Loop,Parse,str

if ((Asc(A_LoopField)>0x7f) || (Asc(A_LoopField)<0x30) || (asc(A_LoopField)=0x3d))

data .= "%" . ((StrLen(c:=SubStr(ASC(A_LoopField),3))<2) ? "0" . c : c)

Else

data .= A_LoopField

SetFormat,Integer,%b_format%

return data

}



UriDecode(str)

{ ; v 0.1 / (w) 28.06.2008 by derRaphael / zLib-Style release

Loop,Parse,str,`%

txt := (A_Index=1) ? A_LoopField : txt chr("0x" substr(A_LoopField,1,2)) SubStr(A_LoopField,3)

return txt

}



UnHTM( HTM ) { ; Remove HTML formatting / Convert to ordinary text by SKAN 19-Nov-2009

Static HT ; Forum Topic: www.autohotkey.com/forum/topic51342.html

IfEqual,HT,, SetEnv,HT, % "áaâa´?æ?àa&åaãa&au"

. "mla&bdquo„¦¦&bull•çc¸?¢?&circ?©©¤¤&dagger†&dagger‡°"

. "°÷?éeêeèeð?ëe&euro€&fnof?½?¼?¾?>>&h"

. "ellip…íiîi¡?ìi¿?ïi««&ldquo“&lsaquo‹&lsquo‘<<&m"

. "acr?&mdash—µµ··  &ndash–¬¬ñnóoôo&oelig?òo&or"

. "df?º?øoõoöo¶¶&permil‰±±£?"""»»&rdquo”®"

. "®&rsaquo›&rsquo’&sbquo‚&scarons§§­¹?²?³?ß?þ?&tilde?&tim"

. "es?&trade™úuûuùu¨?üuýy¥?ÿy"

TXT := RegExReplace( HTM,"<[^>]+>" ) ; Remove all tags between "<" and ">"

Loop, Parse, TXT, &`; ; Create a list of special characters

L := "&" A_LoopField ";", R .= (!(A_Index&1)) ? ( (!InStr(R,L,1)) ? L:"" ) : ""

StringTrimRight, R, R, 1

Loop, Parse, R , `; ; Parse Special Characters

If F := InStr( HT, A_LoopField ) ; Lookup HT Data

StringReplace, TXT,TXT, %A_LoopField%`;, % SubStr( HT,F+StrLen(A_LoopField), 1 ), All

Else If ( SubStr( A_LoopField,2,1)="#" )

StringReplace, TXT, TXT, %A_LoopField%`;, % Chr(SubStr(A_LoopField,3)), All

Return RegExReplace( TXT, "(^\s*|\s*$)") ; Remove leading/trailing white spaces

}



UnSlashUnicode(s)

{

; unslash unicode sequences like \u0026

; by Mikhail Kuropyatnikov 2009 (micdelt@mail.ru)

rx = \\u([0-9a-fA-F]{4})

pos = 0



loop

{

pos := RegExMatch(s,rx,m,pos+1)

if (pos = 0)

break

StringReplace, s, s, %m%, % Chr("0x" . SubStr(m,3,4))

}



return s

}

add: fixed translation from chinese languages
update: works after API deprecation

 



micdelt
  • Members
  • 8 posts
  • Last active: Aug 25 2015 01:17 PM
  • Joined: 11 Dec 2009
Changed function Translate() to autodetect source language. Detected language code prefixes the translation.

Translate(to)
{
	if clipboard =
		 return

	Transform, unicodeClipboard, Unicode 
	url := "http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=" 
				. uriEncode(unicodeClipboard) . "&langpair=%7C" . to 
				
	; simulate UrlDownloadToVAR
	UrlDownloadToFile, %url%, %A_ScriptDir%\translate.html
	FileRead, json_trans, %A_ScriptDir%\translate.html
	json_trans := UTF82Ansi(json_trans)

	rgxText = \Q{"translatedText":"\E(?P<Text>.*)\"\,
	rgxDetectedLanguage = \Q"detectedSourceLanguage":"\E(?P<DetectedLanguage>.*)\"\}
	rgxDetails = \Q"responseDetails": "\E(?P<Details>.*)\"\,
	rgxStatus = \Q"responseStatus": \E(?P<Status>\d*)

	RegExMatch(json_trans,rgxText,trans)
	RegExMatch(json_trans,rgxDetails,trans)
	RegExMatch(json_trans,rgxStatus,trans)
	RegExMatch(json_trans,rgxDetectedLanguage,trans)
	
	if transStatus = 200
	{
		t := UnHTM(UnSlashUnicode(transText))
		; split long line to smaller lines about 40-50 symbols length
		t := RegExReplace(t,".{40,50}(\s)","$0`n")
		if transDetectedLanguage = 
			ToolTip %t%
		else
			ToolTip %transDetectedLanguage%:%t%
	
		; copy result to clipboard
		Clipboard := t
	}
	else
		ToolTip %transDetails%
}


Tal Giladi
  • Guests
  • Last active:
  • Joined: --
Very useful!

oleg01
  • Members
  • 3 posts
  • Last active: Dec 21 2009 12:39 PM
  • Joined: 27 Nov 2009
Thank you very much for this script, it's really a must have for online translations.

I have a problem though, when I set it to translate to russian the displayed translation in the tooltip is a bunch of ????? (question marks). That's probably because my windows is not in russian. Could there be a way to fix this somehow? I havent' checked but I guess that for japanese or chinese it would happen the same.

Anyway it's great to have this script, absolutely one of my favorites.

ruespe
  • Members
  • 567 posts
  • Last active: Dec 01 2014 07:59 PM
  • Joined: 17 Jun 2008
Thanks a lot. Simple and very useful.

luetkmeyer
  • Members
  • 38 posts
  • Last active: Jul 01 2011 04:11 PM
  • Joined: 26 Feb 2010
Cool :D

RIST
  • Members
  • 39 posts
  • Last active: Aug 17 2012 08:36 PM
  • Joined: 08 May 2008
very nice script.. work with my tech mouse copy button (Y)

Gauss
  • Members
  • 203 posts
  • Last active: Jan 27 2012 12:49 PM
  • Joined: 10 Sep 2009
Thanks for this great script, I'm using it all the time, I also added this to it so it shows translation in big letters on a dark bachground:

Gui,+LastFound -border +AlwaysOnTop +ToolWindow -Caption
Gui,Color,black
Gui,Font, s20
Gui,Add,Text, x0 y0 cWhite vText,%clipboard%
GuiControlGet, text ,pos, text
X := ((A_ScreenWidth  - textW) / 2)
Y := ((A_ScreenHeight  - textH) / 2)
GuiControl, Move, text, x%x% y%Y% w%textW% h%textH%
Gui,Show, x0 y0 W%A_ScreenWidth% H%A_ScreenHeight%, ScreenMask325
WinSet, Transparent, 220, ScreenMask325
return

GuiEscape:
	Gui, Destroy
Return

I have 2 questions though:

-It doesn't retrieve translation if selected text is alittle too long, while the same size can be translated fine if done manually on Google.

-The second question is how to make it show translation in paragraphs with empty lines in between? just like when you do it manually.

Thanks again

Edit:
Now it shows translation in the middle

berban
  • Members
  • 202 posts
  • Last active: Aug 15 2015 01:03 PM
  • Joined: 30 Dec 2009
Nice! :D :D :D

micdelt
  • Members
  • 8 posts
  • Last active: Aug 25 2015 01:17 PM
  • Joined: 11 Dec 2009

Gauss It doesn't retrieve translation if selected text is alittle too long, while the same size can be translated fine if done manually on Google.


Text length is restricted by URL length. Full URL length must be less than about 2000 symbols. I made some tests, maximum length of text was about 1430 symbols.

Gauss
The second question is how to make it show translation in paragraphs with empty lines in between? just like when you do it manually.


This method can be used to translate small amount of text. But you can break text into paragraphs and translate it one by one calling this function for each paragraph. But will be difficult to show all the text in tooltip.

micdelt
  • Members
  • 8 posts
  • Last active: Aug 25 2015 01:17 PM
  • Joined: 11 Dec 2009
Some improvement.
1. If clipboard text is in language we want to translate to function translates text to anti language.
For example:
Translate("ru","en") - translates to russian, but if text already was in russian translates it to english.

2. Prefix shows translation direction "from>to", for example: "en>ru".

; translate to "to" language,
; if source language is "to" 
; translate to "anti" language

Translate(to,anti)
{
	use_anti = 0
	translate_to := to
	if clipboard = 
		 return

	Transform, unicodeClipboard, Unicode 
anti_translate:
	url := "http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=" 
				. uriEncode(unicodeClipboard) . "&langpair=%7C" . translate_to
				
	; simulate UrlDownloadToVAR
	UrlDownloadToFile, %url%, %A_ScriptDir%\translate.html
	FileRead, json_trans, %A_ScriptDir%\translate.html
	json_trans := UTF82Ansi(json_trans)

	rgxText = \Q{"translatedText":"\E(?P<Text>.*)\"\,
	rgxDetectedLanguage = \Q"detectedSourceLanguage":"\E(?P<DetectedLanguage>.*)\"\}
	rgxDetails = \Q"responseDetails": "\E(?P<Details>.*)\"\,
	rgxStatus = \Q"responseStatus": \E(?P<Status>\d*)

	RegExMatch(json_trans,rgxText,trans)
	RegExMatch(json_trans,rgxDetails,trans)
	RegExMatch(json_trans,rgxStatus,trans)
	RegExMatch(json_trans,rgxDetectedLanguage,trans)
	
	if transStatus = 200
	{
		if (transDetectedLanguage = to and translate_to <> anti)
		{
			translate_to := anti
			goto anti_translate
		}
		
		t := UnHTM(UnSlashUnicode(transText))
		; split long line to smaller lines about 40-50 symbols length
		t := RegExReplace(t,".{40,50}(\s)","$0`n")
		if transDetectedLanguage = 
			ToolTip %t%
		else
		{
			ToolTip %transDetectedLanguage%>%translate_to%:%t%
		}
	
		; copy result to clipboard
		Clipboard := t
	}
	else
		ToolTip %transDetails%
}


ithion
  • Guests
  • Last active:
  • Joined: --
for lasy me or if u must compile it to give to friends or whatever:
add
To:
InputBox, to, ,Set language to translate to(default en=english):
if To :=""
Reload

InputBox, anti, ,Set language to translate from (default ru=russian):
if anti :=""
return

return

Just the fastet I could come up with.
Love This script.

Ithion
  • Guests
  • Last active:
  • Joined: --
Use this instead, includes needed change first funcion aswell

To:
InputBox, to, ,Set language to translate to(default en=english):
if To :=""
MsgBox You Failed, Restart script to try again

Anti:
InputBox, anti, ,Set language to translate to if the selected text already is in %to% (default ru=russian):,, 50px, 200px
if anti :=""
Goto, Anti
return

DoublePress() ; Simulate double press
{
   static pressed1 = 0
   if pressed1 and A_TimeSincePriorHotkey <= 500
   {
      pressed1 = 0
      Translate(to, anti) ; from English to Russian
   }
   else
      pressed1 = 1
   
}


Thanks!
  • Guests
  • Last active:
  • Joined: --
Thanks!
My wife is in health care and is using this to help speak overcome the language barrier at work.

Drini
  • Members
  • 6 posts
  • Last active: May 22 2011 11:39 AM
  • Joined: 21 Apr 2010
I realise that I (ithion) probably ****ed up in the last post.
Edit:
***UNBELIEVEBLE*** I FORGOT TO REMOVE A FEW VARS AND PUT GLOBAL IN A FUNC!!!!
Link goes to new exe that works
edited code below
:end edit:


I´ve been using this for awhile though and its very usefull when I'm playing with some brazilian friends e.g to explain what certain words mean.

New tested and working changes:
*user friendly inputboxes to set languages at each startup
*default languages is english and russian
*a few example language codes
*"restart tsl" reloads the script so you can pick two new languages.
*traytip and msgbox to give info to the user for easy sharing

.exe:
<!-- m -->http://www.autohotke.../translator.exe<!-- m -->
code:

;--------------------------------------------------
; Mikhail Kuropyatnikov (micdelt@mail.ru)
; traytip, inputboxes, default languages,restart, and msgbox alert added by drini(ydrini@twitter.com aka ithion) to make it more user friendly
; 
;
; 
;--------------------------------------------------
#NoEnv
Traytip,Translator, Translate text using translate.google.com `n use Ctrl+c `, Ctrl+C ( thats ctrl+c twice you fellows) to translate,5,1

;~ To:
InputBox, to,Translator,Set language to translate to `n by Mikhail Kuropyatnikov (micdelt@mail.ru) `n modified by Drini(yDrini@twitter.com) `n default is en(english) `n examples: Sv=Swedish De=German Pt = Portuguese Es=Spanish Ru=Russian
;set default if needed
if to =
to = en

;~ Anti:
InputBox, anti,Translator,Set language to translate to if the selected text already is in "%to%" `n by Mikhail Kuropyatnikov (micdelt@mail.ru) `n modified by Drini(yDrini@twitter.com) `n default is ru(russian) in respect to the original creator`n examples: Sv=Swedish De=German Pt = Portuguese Es=Spanish Ru=Russian
;set default if needed
if anti =
anti = ru

;alert user 
MsgBox Language to translate to was set to "%to%" and if text is in "%to%" it will be translated to "%anti%" `n type "restart tsl" or rightclick the tray icon to choose new languages

DoublePress() ; Simulate double press
{
   global
   static pressed1 = 0
   if pressed1 and A_TimeSincePriorHotkey <= 500
   {
      pressed1 = 0
      Translate(to, anti) ; from English to Russian
   }
   else
      pressed1 = 1
   
}

::restart tsl::
Reload
Return
~^C:: DoublePress()

; translate to "to" language,
; if source language is "to"
; translate to "anti" language

Translate(to,anti)
{

   use_anti = 0
   translate_to := to
   if clipboard =
       return

   Transform, unicodeClipboard, Unicode
anti_translate:
   url := "http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q="
            . uriEncode(unicodeClipboard) . "&langpair=%7C" . translate_to
            
   ; simulate UrlDownloadToVAR
   UrlDownloadToFile, %url%, %A_ScriptDir%\translate.html
   FileRead, json_trans, %A_ScriptDir%\translate.html
   json_trans := UTF82Ansi(json_trans)

   rgxText = \Q{"translatedText":"\E(?P<Text>.*)\"\,
   rgxDetectedLanguage = \Q"detectedSourceLanguage":"\E(?P<DetectedLanguage>.*)\"\}
   rgxDetails = \Q"responseDetails": "\E(?P<Details>.*)\"\,
   rgxStatus = \Q"responseStatus": \E(?P<Status>\d*)

   RegExMatch(json_trans,rgxText,trans)
   RegExMatch(json_trans,rgxDetails,trans)
   RegExMatch(json_trans,rgxStatus,trans)
   RegExMatch(json_trans,rgxDetectedLanguage,trans)
   
   if transStatus = 200
   {
      if (transDetectedLanguage = to and translate_to <> anti)
      {
         translate_to := anti
         goto anti_translate
      }
      
      t := UnHTM(UnSlashUnicode(transText))
      ; split long line to smaller lines about 40-50 symbols length
      t := RegExReplace(t,".{40,50}(\s)","$0`n")
      if transDetectedLanguage =
         ToolTip %t%
      else
      {
         ToolTip %transDetectedLanguage%>%translate_to%:%t%
      }
   
      ; copy result to clipboard
      Clipboard := t
   }
   else
      ToolTip %transDetails%
}
~LButton:: ; Remove tooltip left click
ToolTip
return

;---------------------------------------
; Convert strings
;---------------------------------------

/*
CP_ACP   = 0
CP_OEMCP = 1
CP_MACCP = 2
CP_UTF7  = 65000
CP_UTF8  = 65001
*/

Ansi2Oem(sString)
{
   Ansi2Unicode(sString, wString, 0)
   Unicode2Ansi(wString, zString, 1)
   Return zString
}

Oem2Ansi(zString)
{
   Ansi2Unicode(zString, wString, 1)
   Unicode2Ansi(wString, sString, 0)
   Return sString
}

Ansi2UTF8(sString)
{
   Ansi2Unicode(sString, wString, 0)
   Unicode2Ansi(wString, zString, 65001)
   Return zString
}

UTF82Ansi(zString)
{
   Ansi2Unicode(zString, wString, 65001)
   Unicode2Ansi(wString, sString, 0)
   Return sString
}

Ansi2Unicode(ByRef sString, ByRef wString, CP = 0)
{
     nSize := DllCall("MultiByteToWideChar"
      , "Uint", CP
      , "Uint", 0
      , "Uint", &sString
      , "int",  -1
      , "Uint", 0
      , "int",  0)

   VarSetCapacity(wString, nSize * 2)

   DllCall("MultiByteToWideChar"
      , "Uint", CP
      , "Uint", 0
      , "Uint", &sString
      , "int",  -1
      , "Uint", &wString
      , "int",  nSize)
}

Unicode2Ansi(ByRef wString, ByRef sString, CP = 0)
{
     nSize := DllCall("WideCharToMultiByte"
      , "Uint", CP
      , "Uint", 0
      , "Uint", &wString
      , "int",  -1
      , "Uint", 0
      , "int",  0
      , "Uint", 0
      , "Uint", 0)

   VarSetCapacity(sString, nSize)

   DllCall("WideCharToMultiByte"
      , "Uint", CP
      , "Uint", 0
      , "Uint", &wString
      , "int",  -1
      , "str",  sString
      , "int",  nSize
      , "Uint", 0
      , "Uint", 0)
}

;-------------------------------------------------
; HTML encode/decode
;------------------------------------------------

UriEncode(str)
{ ; v 0.3 / (w) 24.06.2008 by derRaphael / zLib-Style release
   b_Format := A_FormatInteger
   data := ""
   SetFormat,Integer,H
   Loop,Parse,str
      if ((Asc(A_LoopField)>0x7f) || (Asc(A_LoopField)<0x30) || (asc(A_LoopField)=0x3d))
         data .= "%" . ((StrLen(c:=SubStr(ASC(A_LoopField),3))<2) ? "0" . c : c)
      Else
         data .= A_LoopField
   SetFormat,Integer,%b_format%
   return data
}

UriDecode(str)
{ ; v 0.1 / (w) 28.06.2008 by derRaphael / zLib-Style release
   Loop,Parse,str,`%
      txt := (A_Index=1) ? A_LoopField : txt chr("0x" substr(A_LoopField,1,2)) SubStr(A_LoopField,3)
   return txt
}

UnHTM( HTM ) { ; Remove HTML formatting / Convert to ordinary text     by SKAN 19-Nov-2009
 Static HT     ; Forum Topic: www.autohotkey.com/forum/topic51342.html
 IfEqual,HT,,   SetEnv,HT, % "áaâa´?æ?àa&åaãa&au"
 . "mla&bdquo„¦¦&bull•çc¸?¢?&circ?©©¤¤&dagger†&dagger‡°"
 . "°÷?éeêeèeð?ëe&euro€&fnof?½?¼?¾?>>&h"
 . "ellip…íiîi¡?ìi¿?ïi««&ldquo“&lsaquo‹&lsquo‘<<&m"
 . "acr?&mdash—µµ··  &ndash–¬¬ñnóoôo&oelig?òo&or"
 . "df?º?øoõoöo¶¶&permil‰±±£?"""»»&rdquo”®"
 . "®&rsaquo›&rsquo’&sbquo‚&scarons§§­¹?²?³?ß?þ?&tilde?&tim"
 . "es?&trade™úuûuùu¨?üuýy¥?ÿy"
 TXT := RegExReplace( HTM,"<[^>]+>" )               ; Remove all tags between  "<" and ">"
 Loop, Parse, TXT, &`;                              ; Create a list of special characters
   L := "&" A_LoopField ";", R .= (!(A_Index&1)) ? ( (!InStr(R,L,1)) ? L:"" ) : ""
 StringTrimRight, R, R, 1
 Loop, Parse, R , `;                                ; Parse Special Characters
  If F := InStr( HT, A_LoopField )                  ; Lookup HT Data
    StringReplace, TXT,TXT, %A_LoopField%`;, % SubStr( HT,F+StrLen(A_LoopField), 1 ), All
  Else If ( SubStr( A_LoopField,2,1)="#" )
    StringReplace, TXT, TXT, %A_LoopField%`;, % Chr(SubStr(A_LoopField,3)), All
Return RegExReplace( TXT, "(^\s*|\s*$)")            ; Remove leading/trailing white spaces
}

UnSlashUnicode(s)
{
;~   ; unslash unicode sequences like \u0026
  ; by Mikhail Kuropyatnikov 2009 (micdelt@mail.ru)
   rx = \\u([0-9a-fA-F]{4})
   pos = 0

   loop
   {
   pos := RegExMatch(s,rx,m,pos+1)
   if (pos = 0)
      break
   StringReplace, s, s, %m%, % Chr("0x" . SubStr(m,3,4))
   }
   
   return s
}