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. This is a new one.
Requeres Unicode version of AutoHotkey.
Code:
;--------------------------------------------------
; 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!Code:
;--------------------------------------------------
; 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