Google Translate code slow and erroneous

Get help with using AutoHotkey and its commands and hotkeys
memberAHK
Posts: 4
Joined: 30 Nov 2017, 01:06

Google Translate code slow and erroneous

03 Dec 2017, 23:35

The following code translates a Japanese phrase to English. It has two issues:

1. It takes too long (5 seconds) just to get a simple translation.

2. If I run it again the second time immediately, I get an error instead (0x8150002E), which also displays my code and asks me if I want to continue executing the code.

I'm running it on my Windows 10 laptop.

Any suggestion how I can improve? Thanks.

Code: Select all

^+y::
   phrase := "今日の天気はとても良いです"
   msgbox % GoogleTranslate(phrase)
return

GoogleTranslate(phrase)
{
path := "https://translate.google.com/#ja/en/" . phrase
IE := ComObjCreate("InternetExplorer.Application")
IE.Navigate(path)
While IE.readyState!=4 || IE.document.readyState!="complete" || IE.busy
        Sleep 50
Result := IE.document.all.result_box.innertext
IE.Quit
return Result
}

A_AhkUser
Posts: 1070
Joined: 06 Mar 2017, 16:18
GitHub: AAhkUser
Location: France

Re: Google Translate code slow and erroneous

04 Dec 2017, 01:17

Hi memberAHK,

First you have to make sure Google allows automation of its site, even for personal use. Whatever it could be, concerning your code:
1. It takes too long (5 seconds) just to get a simple translation.
It is probably due to the fact that your function creates and delete an instance of IE each time it is actually called. You should rather consider to create once and for all an instance, in the auto-execute part of the script - it will be more efficient. You can use an InputBox in order to give an input to the script. Consider a Traytip as a good alternative to the MsgBox in some case. You can also make your script put a result in the clipboard.

Code: Select all

global IE ; make IE object super-global (specifically, accessible from any function)
(IE:=ComObjCreate("InternetExplorer.Application")).visible := false ; create a new hidden instance of IE, if 'true' IE will be visible
OnExit("IEQuit") ; registers a  function to run automatically when the script exits
return ; end of the auto-execute part of the script

^+y::
; InputBox, var ; uncomment to use an inputbox instead to ask the user to enter a word
var := "今日の天気はとても良いです"
if not (result:=GoogleTranslate(var, "ja", "fr", 5))
	TrayTip, GoogleTranslate script, % "Could not translate " . var . "."
else
	TrayTip, GoogleTranslate script, % (clipboard:=result) . "`r`nThe result has been copied to the clipboard" ; displays the result in a traytip and put it in the clipboard
return

GoogleTranslate(query, src, trgt, timeout:=5) {

static rootUrl := "https://translate.google.com" ; the value of a static variables is remembered between calls

	IE.Navigate(rootUrl . "/#" . src . "/" . trgt . "/" . query)
	
	timeout *= 10 ; ex.: 5*10*100 --> 5000ms = 5s
	Loop {
		sleep, 100
	} Until ((boolean:=(a_index > timeout)) or (not IE.busy) or (IE.readyState == 4)) ; if any of theses condition are met the loop is broken 
	if (boolean) {
		IE.Stop() ; cancels pending navigation
	return false
	}
	return IE.document.getElementByID("result_box").innertext
	
}

IEQuit() { ; onexit callback
IE.Quit() ; close the instance of IE
}
teadrinker
Posts: 678
Joined: 29 Mar 2015, 09:41
Contact:

Re: Google Translate code slow and erroneous

04 Dec 2017, 02:21

The same through WinHttpRequest:

Code: Select all

MsgBox, % GoogleTranslate("今日の天気はとても良いです")

GoogleTranslate(str, from := "", to := "")  {
   (from = "" && from := "auto")
   (to = "" && to := "en")
   
   json := SendRequest(str, to, from, proxy:="")
   JS := new ActiveScript("JScript")
   JS.eval("delete ActiveXObject; delete GetObject;")
   oJSON := JS.eval("(" . JSON . ")")

   if !IsObject(oJSON[1])
      Loop % oJSON[0].length
         trans .= oJSON[0][A_Index - 1][0]
   else  {
      MainTransText := oJSON[0][0][0]
      Loop % oJSON[1].length  {
         trans .= "`n+"
         obj := oJSON[1][A_Index-1][1]
         Loop % obj.length  {
            txt := obj[A_Index - 1]
            trans .= (MainTransText = txt ? "" : "`n" txt)
         }
      }
   }
   if !IsObject(oJSON[1])
      MainTransText := trans := Trim(trans, ",+`n ")
   else
      trans := MainTransText . "`n+`n" . Trim(trans, ",+`n ")

   from := oJSON[2]
   trans := Trim(trans, ",+`n ")
   Return trans
}

SendRequest(str, tl := "", sl := "", proxy := "") {
   ComObjError(false)
   http := ComObjCreate("WinHttp.WinHttpRequest.5.1")
   proxy ? http.SetProxy(2, proxy) : "", tl ? "" : tl := "en"
   http.open( "POST", "https://translate.google.com/translate_a/single?client=t&sl="
      . (sl ? sl : "auto") "&tl=" tl "&hl=" tl
      . "&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t&ie=UTF-8&oe=UTF-8&otf=1&ssel=3&tsel=3&pc=1&kc=2"
      . "&tk=" TK(str), 1 )

   http.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8")
   http.SetRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0")
   http.send("q=" URIEncode(str))
   http.WaitForResponse(-1)
   Return http.responsetext
}

TK(string)  {
   js := new ActiveScript("JScript")
   js.Exec(GetJScript())
   Return js.tk(string)
}

URIEncode(str, encoding := "UTF-8")  {
   VarSetCapacity(var, StrPut(str, encoding))
   StrPut(str, &var, encoding)

   While code := NumGet(Var, A_Index - 1, "UChar")  {
      bool := (code > 0x7F || code < 0x30 || code = 0x3D)
      UrlStr .= bool ? "%" . Format("{:02X}", code) : Chr(code)
   }
   Return UrlStr
}

GetJScript()
{
   script =
   (
      var TKK = ((function() {
        var a = 561666268;
        var b = 1526272306;
        return 406398 + '.' + (a + b);
      })());

      function b(a, b) {
        for (var d = 0; d < b.length - 2; d += 3) {
            var c = b.charAt(d + 2),
                c = "a" <= c ? c.charCodeAt(0) - 87 : Number(c),
                c = "+" == b.charAt(d + 1) ? a >>> c : a << c;
            a = "+" == b.charAt(d) ? a + c & 4294967295 : a ^ c
        }
        return a
      }

      function tk(a) {
          for (var e = TKK.split("."), h = Number(e[0]) || 0, g = [], d = 0, f = 0; f < a.length; f++) {
              var c = a.charCodeAt(f);
              128 > c ? g[d++] = c : (2048 > c ? g[d++] = c >> 6 | 192 : (55296 == (c & 64512) && f + 1 < a.length && 56320 == (a.charCodeAt(f + 1) & 64512) ?
              (c = 65536 + ((c & 1023) << 10) + (a.charCodeAt(++f) & 1023), g[d++] = c >> 18 | 240,
              g[d++] = c >> 12 & 63 | 128) : g[d++] = c >> 12 | 224, g[d++] = c >> 6 & 63 | 128), g[d++] = c & 63 | 128)
          }
          a = h;
          for (d = 0; d < g.length; d++) a += g[d], a = b(a, "+-a^+6");
          a = b(a, "+-3^+b+-f");
          a ^= Number(e[1]) || 0;
          0 > a && (a = (a & 2147483647) + 2147483648);
          a `%= 1E6;
          return a.toString() + "." + (a ^ h)
      }
   )
   Return script
}

class ActiveScript extends ActiveScript._base
{
    __New(Language)
    {
        if this._script := ComObjCreate(Language, ActiveScript.IID)
            this._scriptParse := ComObjQuery(this._script, ActiveScript.IID_Parse)
        if !this._scriptParse
            throw Exception("Invalid language", -1, Language)
        this._site := new ActiveScriptSite(this)
        this._SetScriptSite(this._site.ptr)
        this._InitNew()
        this._objects := {}
        this.Error := ""
        this._dsp := this._GetScriptDispatch()  ; Must be done last.
        try
            if this.ScriptEngine() = "JScript"
                this.SetJScript58()
    }

    SetJScript58()
    {
        static IID_IActiveScriptProperty := "{4954E0D0-FBC7-11D1-8410-006008C3FBFC}"
        if !prop := ComObjQuery(this._script, IID_IActiveScriptProperty)
            return false
        VarSetCapacity(var, 24, 0), NumPut(2, NumPut(3, var, "short") + 6)
        hr := DllCall(NumGet(NumGet(prop+0)+4*A_PtrSize), "ptr", prop, "uint", 0x4000
            , "ptr", 0, "ptr", &var), ObjRelease(prop)
        return hr >= 0
    }

    Eval(Code)
    {
        pvar := NumGet(ComObjValue(arr:=ComObjArray(0xC,1)) + 8+A_PtrSize)
        this._ParseScriptText(Code, 0x20, pvar)  ; SCRIPTTEXT_ISEXPRESSION := 0x20
        return arr[0]
    }

    Exec(Code)
    {
        this._ParseScriptText(Code, 0x42, 0)  ; SCRIPTTEXT_ISVISIBLE := 2, SCRIPTTEXT_ISPERSISTENT := 0x40
        this._SetScriptState(2)  ; SCRIPTSTATE_CONNECTED := 2
    }

    AddObject(Name, DispObj, AddMembers := false)
    {
        static a, supports_dispatch ; Test for built-in IDispatch support.
            := a := ((a:=ComObjArray(0xC,1))[0]:=[42]) && a[0][1]=42
        if IsObject(DispObj) && !(supports_dispatch || ComObjType(DispObj))
            throw Exception("Adding a non-COM object requires AutoHotkey v1.1.17+", -1)
        this._objects[Name] := DispObj
        this._AddNamedItem(Name, AddMembers ? 8 : 2)  ; SCRIPTITEM_ISVISIBLE := 2, SCRIPTITEM_GLOBALMEMBERS := 8
    }

    _GetObjectUnk(Name)
    {
        return !IsObject(dsp := this._objects[Name]) ? dsp  ; Pointer
            : ComObjValue(dsp) ? ComObjValue(dsp)  ; ComObject
            : &dsp  ; AutoHotkey object
    }

    class _base
    {
        __Call(Method, Params*)
        {
            if ObjHasKey(this, "_dsp")
                try
                    return (this._dsp)[Method](Params*)
                catch e
                    throw Exception(e.Message, -1, e.Extra)
        }

        __Get(Property, Params*)
        {
            if ObjHasKey(this, "_dsp")
                try
                    return (this._dsp)[Property, Params*]
                catch e
                    throw Exception(e.Message, -1, e.Extra)
        }

        __Set(Property, Params*)
        {
            if ObjHasKey(this, "_dsp")
            {
                Value := Params.Pop()
                try
                    return (this._dsp)[Property, Params*] := Value
                catch e
                    throw Exception(e.Message, -1, e.Extra)
            }
        }
    }

    _SetScriptSite(Site)
    {
        hr := DllCall(NumGet(NumGet((p:=this._script)+0)+3*A_PtrSize), "ptr", p, "ptr", Site)
        if (hr < 0)
            this._HRFail(hr, "IActiveScript::SetScriptSite")
    }

    _SetScriptState(State)
    {
        hr := DllCall(NumGet(NumGet((p:=this._script)+0)+5*A_PtrSize), "ptr", p, "int", State)
        if (hr < 0)
            this._HRFail(hr, "IActiveScript::SetScriptState")
    }

    _AddNamedItem(Name, Flags)
    {
        hr := DllCall(NumGet(NumGet((p:=this._script)+0)+8*A_PtrSize), "ptr", p, "wstr", Name, "uint", Flags)
        if (hr < 0)
            this._HRFail(hr, "IActiveScript::AddNamedItem")
    }

    _GetScriptDispatch()
    {
        hr := DllCall(NumGet(NumGet((p:=this._script)+0)+10*A_PtrSize), "ptr", p, "ptr", 0, "ptr*", pdsp)
        if (hr < 0)
            this._HRFail(hr, "IActiveScript::GetScriptDispatch")
        return ComObject(9, pdsp, 1)
    }

    _InitNew()
    {
        hr := DllCall(NumGet(NumGet((p:=this._scriptParse)+0)+3*A_PtrSize), "ptr", p)
        if (hr < 0)
            this._HRFail(hr, "IActiveScriptParse::InitNew")
    }

    _ParseScriptText(Code, Flags, pvarResult)
    {
        VarSetCapacity(excp, 8 * A_PtrSize, 0)
        hr := DllCall(NumGet(NumGet((p:=this._scriptParse)+0)+5*A_PtrSize), "ptr", p
            , "wstr", Code, "ptr", 0, "ptr", 0, "ptr", 0, "uptr", 0, "uint", 1
            , "uint", Flags, "ptr", pvarResult, "ptr", 0)
        if (hr < 0)
            this._HRFail(hr, "IActiveScriptParse::ParseScriptText")
    }

    _HRFail(hr, what)
    {
        if e := this.Error
        {
            this.Error := ""
            throw Exception("`nError code:`t" this._HRFormat(e.HRESULT)
                . "`nSource:`t`t" e.Source "`nDescription:`t" e.Description
                . "`nLine:`t`t" e.Line "`nColumn:`t`t" e.Column
                . "`nLine text:`t`t" e.LineText, -3)
        }
        throw Exception(what " failed with code " this._HRFormat(hr), -2)
    }

    _HRFormat(hr)
    {
        return Format("0x{1:X}", hr & 0xFFFFFFFF)
    }

    _OnScriptError(err) ; IActiveScriptError err
    {
        VarSetCapacity(excp, 8 * A_PtrSize, 0)
        DllCall(NumGet(NumGet(err+0)+3*A_PtrSize), "ptr", err, "ptr", &excp) ; GetExceptionInfo
        DllCall(NumGet(NumGet(err+0)+4*A_PtrSize), "ptr", err, "uint*", srcctx, "uint*", srcline, "int*", srccol) ; GetSourcePosition
        DllCall(NumGet(NumGet(err+0)+5*A_PtrSize), "ptr", err, "ptr*", pbstrcode) ; GetSourceLineText
        code := StrGet(pbstrcode, "UTF-16"), DllCall("OleAut32\SysFreeString", "ptr", pbstrcode)
        if fn := NumGet(excp, 6 * A_PtrSize) ; pfnDeferredFillIn
            DllCall(fn, "ptr", &excp)
        wcode := NumGet(excp, 0, "ushort")
        hr := wcode ? 0x80040200 + wcode : NumGet(excp, 7 * A_PtrSize, "uint")
        this.Error := {HRESULT: hr, Line: srcline, Column: srccol, LineText: code}
        static Infos := "Source,Description,HelpFile"
        Loop Parse, % Infos, `,
            if pbstr := NumGet(excp, A_Index * A_PtrSize)
                this.Error[A_LoopField] := StrGet(pbstr, "UTF-16"), DllCall("OleAut32\SysFreeString", "ptr", pbstr)
        return 0x80004001 ; E_NOTIMPL (let Exec/Eval get a fail result)
    }

    __Delete()
    {
        if this._script
        {
            DllCall(NumGet(NumGet((p:=this._script)+0)+7*A_PtrSize), "ptr", p)  ; Close
            ObjRelease(this._script)
        }
        if this._scriptParse
            ObjRelease(this._scriptParse)
    }

    static IID := "{BB1A2AE1-A4F9-11cf-8F20-00805F2CD064}"
    static IID_Parse := A_PtrSize=8 ? "{C7EF7658-E1EE-480E-97EA-D52CB4D76D17}" : "{BB1A2AE2-A4F9-11cf-8F20-00805F2CD064}"
}

class ActiveScriptSite
{
    __New(Script)
    {
        ObjSetCapacity(this, "_site", 3 * A_PtrSize)
        NumPut(&Script
        , NumPut(ActiveScriptSite._vftable("_vft_w", "31122", 0x100)
        , NumPut(ActiveScriptSite._vftable("_vft", "31125232211", 0)
            , this.ptr := ObjGetAddress(this, "_site"))))
    }

    _vftable(Name, PrmCounts, EIBase)
    {
        if p := ObjGetAddress(this, Name)
            return p
        ObjSetCapacity(this, Name, StrLen(PrmCounts) * A_PtrSize)
        p := ObjGetAddress(this, Name)
        Loop Parse, % PrmCounts
        {
            cb := RegisterCallback("_ActiveScriptSite", "F", A_LoopField, A_Index + EIBase)
            NumPut(cb, p + (A_Index-1) * A_PtrSize)
        }
        return p
    }
}

_ActiveScriptSite(this, a1:=0, a2:=0, a3:=0, a4:=0, a5:=0)
{
    Method := A_EventInfo & 0xFF
    if A_EventInfo >= 0x100  ; IActiveScriptSiteWindow
    {
        if Method = 4  ; GetWindow
        {
            NumPut(0, a1+0) ; *phwnd := 0
            return 0 ; S_OK
        }
        if Method = 5  ; EnableModeless
        {
            return 0 ; S_OK
        }
        this -= A_PtrSize     ; Cast to IActiveScriptSite
    }
    ;else: IActiveScriptSite
    if Method = 1  ; QueryInterface
    {
        iid := _AS_GUIDToString(a1)
        if (iid = "{00000000-0000-0000-C000-000000000046}"  ; IUnknown
         || iid = "{DB01A1E3-A42B-11cf-8F20-00805F2CD064}") ; IActiveScriptSite
        {
            NumPut(this, a2+0)
            return 0 ; S_OK
        }
        if (iid = "{D10F6761-83E9-11cf-8F20-00805F2CD064}") ; IActiveScriptSiteWindow
        {
            NumPut(this + A_PtrSize, a2+0)
            return 0 ; S_OK
        }
        NumPut(0, a2+0)
        return 0x80004002 ; E_NOINTERFACE
    }
    if Method = 5  ; GetItemInfo
    {
        a1 := StrGet(a1, "UTF-16")
        , (a3 && NumPut(0, a3+0))  ; *ppiunkItem := NULL
        , (a4 && NumPut(0, a4+0))  ; *ppti := NULL
        if (a2 & 1) ; SCRIPTINFO_IUNKNOWN
        {
            if !(unk := Object(NumGet(this + A_PtrSize*2))._GetObjectUnk(a1))
                return 0x8002802B ; TYPE_E_ELEMENTNOTFOUND
            ObjAddRef(unk), NumPut(unk, a3+0)
        }
        return 0 ; S_OK
    }
    if Method = 9  ; OnScriptError
        return Object(NumGet(this + A_PtrSize*2))._OnScriptError(a1)

    ; AddRef and Release don't do anything because we want to avoid circular references.
    ; The site and IActiveScript are both released when the AHK script releases its last
    ; reference to the ActiveScript object.

    ; All of the other methods don't require implementations.
    return 0x80004001 ; E_NOTIMPL
}

_AS_GUIDToString(pGUID)
{
    VarSetCapacity(String, 38*2)
    DllCall("ole32\StringFromGUID2", "ptr", pGUID, "str", String, "int", 39)
    return String
}
memberAHK
Posts: 4
Joined: 30 Nov 2017, 01:06

Re: Google Translate code slow and erroneous

05 Dec 2017, 04:02

Thanks folks. Will try.
teadrinker
Posts: 678
Joined: 29 Mar 2015, 09:41
Contact:

Re: Google Translate code slow and erroneous

05 Dec 2017, 22:32

The shorter version:

Code: Select all

MsgBox, % GoogleTranslate("今日の天気はとても良いです")

GoogleTranslate(str, from := "auto", to := "en")  {
   static JS := GetJScripObject(), _ := JS.( GetJScript() ) := JS.("delete ActiveXObject; delete GetObject;")
   
   json := SendRequest(JS, str, to, from, proxy := "")
   oJSON := JS.("(" . json . ")")

   if !IsObject(oJSON[1])  {
      Loop % oJSON[0].length
         trans .= oJSON[0][A_Index - 1][0]
   }
   else  {
      MainTransText := oJSON[0][0][0]
      Loop % oJSON[1].length  {
         trans .= "`n+"
         obj := oJSON[1][A_Index-1][1]
         Loop % obj.length  {
            txt := obj[A_Index - 1]
            trans .= (MainTransText = txt ? "" : "`n" txt)
         }
      }
   }
   if !IsObject(oJSON[1])
      MainTransText := trans := Trim(trans, ",+`n ")
   else
      trans := MainTransText . "`n+`n" . Trim(trans, ",+`n ")

   from := oJSON[2]
   trans := Trim(trans, ",+`n ")
   Return trans
}

SendRequest(JS, str, tl, sl, proxy) {
   ComObjError(false)
   http := ComObjCreate("WinHttp.WinHttpRequest.5.1")
   ( proxy && http.SetProxy(2, proxy) )
   http.open( "POST", "https://translate.google.com/translate_a/single?client=t&sl="
      . sl . "&tl=" . tl . "&hl=" . tl
      . "&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t&ie=UTF-8&oe=UTF-8&otf=1&ssel=3&tsel=3&pc=1&kc=2"
      . "&tk=" . JS.("tk").(str), 1 )

   http.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8")
   http.SetRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0")
   http.send("q=" . URIEncode(str))
   http.WaitForResponse(-1)
   Return http.responsetext
}

URIEncode(str, encoding := "UTF-8")  {
   VarSetCapacity(var, StrPut(str, encoding))
   StrPut(str, &var, encoding)

   While code := NumGet(Var, A_Index - 1, "UChar")  {
      bool := (code > 0x7F || code < 0x30 || code = 0x3D)
      UrlStr .= bool ? "%" . Format("{:02X}", code) : Chr(code)
   }
   Return UrlStr
}

GetJScript()
{
   script =
   (
      var TKK = ((function() {
        var a = 561666268;
        var b = 1526272306;
        return 406398 + '.' + (a + b);
      })());

      function b(a, b) {
        for (var d = 0; d < b.length - 2; d += 3) {
            var c = b.charAt(d + 2),
                c = "a" <= c ? c.charCodeAt(0) - 87 : Number(c),
                c = "+" == b.charAt(d + 1) ? a >>> c : a << c;
            a = "+" == b.charAt(d) ? a + c & 4294967295 : a ^ c
        }
        return a
      }

      function tk(a) {
          for (var e = TKK.split("."), h = Number(e[0]) || 0, g = [], d = 0, f = 0; f < a.length; f++) {
              var c = a.charCodeAt(f);
              128 > c ? g[d++] = c : (2048 > c ? g[d++] = c >> 6 | 192 : (55296 == (c & 64512) && f + 1 < a.length && 56320 == (a.charCodeAt(f + 1) & 64512) ?
              (c = 65536 + ((c & 1023) << 10) + (a.charCodeAt(++f) & 1023), g[d++] = c >> 18 | 240,
              g[d++] = c >> 12 & 63 | 128) : g[d++] = c >> 12 | 224, g[d++] = c >> 6 & 63 | 128), g[d++] = c & 63 | 128)
          }
          a = h;
          for (d = 0; d < g.length; d++) a += g[d], a = b(a, "+-a^+6");
          a = b(a, "+-3^+b+-f");
          a ^= Number(e[1]) || 0;
          0 > a && (a = (a & 2147483647) + 2147483648);
          a `%= 1E6;
          return a.toString() + "." + (a ^ h)
      }
   )
   Return script
}

GetJScripObject()  {
   VarSetCapacity(tmpFile, (MAX_PATH := 260) << !!A_IsUnicode, 0)
   DllCall("GetTempFileName", Str, A_Temp, Str, "AHK", UInt, 0, Str, tmpFile)
   
   FileAppend,
   (
   <component>
   <public><method name='eval'/></public>
   <script language='JScript'></script>
   </component>
   ), % tmpFile
   
   JS := ObjBindMethod( ComObjGet("script:" . tmpFile), "eval" )
   FileDelete, % tmpFile
   Return JS
}
Last edited by teadrinker on 06 Dec 2017, 02:04, edited 3 times in total.
A_AhkUser
Posts: 1070
Joined: 06 Mar 2017, 16:18
GitHub: AAhkUser
Location: France

Re: Google Translate code slow and erroneous

05 Dec 2017, 22:35

teadrinker wrote:The same through WinHttpRequest[...]
I don't understand how you get translations that's impressive :salute:
User avatar
noname
Posts: 508
Joined: 19 Nov 2013, 09:15

Re: Google Translate code slow and erroneous

06 Dec 2017, 03:38

Thanks teadrinker for posting , impressive it will take a while unraveling this code :shock:
soundcloud.com/user-32706894
kunkel321
Posts: 176
Joined: 30 Nov 2015, 21:19
Facebook: https://www.facebook.com/kunkel321
Google: kunkel321

Re: Google Translate code slow and erroneous

25 Jan 2018, 14:31

Hi Teadrinker and All,
I was referred here from https://autohotkey.com/boards/viewtopic ... 28#p196628.

That Javacode is super complicated! I love it! :D Hopfully I'm not "hijacking" this thread too much, but here are a couple of questions about the JS:
I told it to use the clipboard and convert to Spanish. That worked fine. But then I tried to save the converted text to variable asEsprather than sending it to a MsgBox. That didn't work. This thing is a "function" --yes?

A related question: I'd like to convert from Eng to Esp, then take those Spanish results and convert them back to English. Most of this code can get "reused" for the two conversions yes? Am I seeing five separate functions? I'm guessing that the top function is the only one that needs to be duplicated(?)

Or am I way off?

Code: Select all

#NoEnv
#SingleInstance force
;############## https://autohotkey.com/boards/viewtopic.php?f=5&t=40876

toConvert := Clipboard
asEsp := % GoogleTranslate(toConvert)
MsgBox, As Spanish: %asEsp%

GoogleTranslate(str, from := "auto", to := "es")  {
   static JS := GetJScripObject(), _ := JS.( GetJScript() ) := JS.("delete ActiveXObject; delete GetObject;")
   
   json := SendRequest(JS, str, to, from, proxy := "")
   oJSON := JS.("(" . json . ")")

   if !IsObject(oJSON[1])  {
      Loop % oJSON[0].length
         trans .= oJSON[0][A_Index - 1][0]
   }
   else  {
      MainTransText := oJSON[0][0][0]
      Loop % oJSON[1].length  {
         trans .= "`n+"
         obj := oJSON[1][A_Index-1][1]
         Loop % obj.length  {
            txt := obj[A_Index - 1]
            trans .= (MainTransText = txt ? "" : "`n" txt)
         }
      }
   }
   if !IsObject(oJSON[1])
      MainTransText := trans := Trim(trans, ",+`n ")
   else
      trans := MainTransText . "`n+`n" . Trim(trans, ",+`n ")

   from := oJSON[2]
   trans := Trim(trans, ",+`n ")
   Return trans
}

SendRequest(JS, str, tl, sl, proxy) {
   ComObjError(false)
   http := ComObjCreate("WinHttp.WinHttpRequest.5.1")
   ( proxy && http.SetProxy(2, proxy) )
   http.open( "POST", "https://translate.google.com/translate_a/single?client=t&sl="
      . sl . "&tl=" . tl . "&hl=" . tl
      . "&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t&ie=UTF-8&oe=UTF-8&otf=1&ssel=3&tsel=3&pc=1&kc=2"
      . "&tk=" . JS.("tk").(str), 1 )

   http.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8")
   http.SetRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0")
   http.send("q=" . URIEncode(str))
   http.WaitForResponse(-1)
   Return http.responsetext
}

URIEncode(str, encoding := "UTF-8")  {
   VarSetCapacity(var, StrPut(str, encoding))
   StrPut(str, &var, encoding)

   While code := NumGet(Var, A_Index - 1, "UChar")  {
      bool := (code > 0x7F || code < 0x30 || code = 0x3D)
      UrlStr .= bool ? "%" . Format("{:02X}", code) : Chr(code)
   }
   Return UrlStr
}

GetJScript()
{
   script =
   (
      var TKK = ((function() {
        var a = 561666268;
        var b = 1526272306;
        return 406398 + '.' + (a + b);
      })());

      function b(a, b) {
        for (var d = 0; d < b.length - 2; d += 3) {
            var c = b.charAt(d + 2),
                c = "a" <= c ? c.charCodeAt(0) - 87 : Number(c),
                c = "+" == b.charAt(d + 1) ? a >>> c : a << c;
            a = "+" == b.charAt(d) ? a + c & 4294967295 : a ^ c
        }
        return a
      }

      function tk(a) {
          for (var e = TKK.split("."), h = Number(e[0]) || 0, g = [], d = 0, f = 0; f < a.length; f++) {
              var c = a.charCodeAt(f);
              128 > c ? g[d++] = c : (2048 > c ? g[d++] = c >> 6 | 192 : (55296 == (c & 64512) && f + 1 < a.length && 56320 == (a.charCodeAt(f + 1) & 64512) ?
              (c = 65536 + ((c & 1023) << 10) + (a.charCodeAt(++f) & 1023), g[d++] = c >> 18 | 240,
              g[d++] = c >> 12 & 63 | 128) : g[d++] = c >> 12 | 224, g[d++] = c >> 6 & 63 | 128), g[d++] = c & 63 | 128)
          }
          a = h;
          for (d = 0; d < g.length; d++) a += g[d], a = b(a, "+-a^+6");
          a = b(a, "+-3^+b+-f");
          a ^= Number(e[1]) || 0;
          0 > a && (a = (a & 2147483647) + 2147483648);
          a `%= 1E6;
          return a.toString() + "." + (a ^ h)
      }
   )
   Return script
}

GetJScripObject()  {
   VarSetCapacity(tmpFile, (MAX_PATH := 260) << !!A_IsUnicode, 0)
   DllCall("GetTempFileName", Str, A_Temp, Str, "AHK", UInt, 0, Str, tmpFile)
   
   FileAppend,
   (
   <component>
   <public><method name='eval'/></public>
   <script language='JScript'></script>
   </component>
   ), % tmpFile
   
   JS := ObjBindMethod( ComObjGet("script:" . tmpFile), "eval" )
   FileDelete, % tmpFile
   Return JS
}
teadrinker
Posts: 678
Joined: 29 Mar 2015, 09:41
Contact:

Re: Google Translate code slow and erroneous

25 Jan 2018, 16:57

kunkel321 wrote:here are a couple of questions about the JS
Hi kunkel321

Yuor questions are not about JS, they are about the AHK syntax.
1. Use asEsp := GoogleTranslate(toConvert), the percent sign is not needed in this case. Read Variables and Expressions.
Yes, this thing is a function.
2:

Code: Select all

toConvert := Clipboard
asEsp := GoogleTranslate(toConvert, "en", "es")
MsgBox, As Spanish: %asEsp%
asEng := GoogleTranslate(asEsp, "es", "en")
MsgBox, As English: %asEng%
The rest of code doesn't need to be duplicated.
kunkel321
Posts: 176
Joined: 30 Nov 2015, 21:19
Facebook: https://www.facebook.com/kunkel321
Google: kunkel321

Re: Google Translate code slow and erroneous

25 Jan 2018, 17:51

Thanks for the fast reply and the resources!

This works like a charm! It can convert a 500 word paragraph in just one or two seconds! :lol: Also, it preserves carriage returns, which is really nice!!!

I'm curious now though: In the code below, line 12 has "es" in there statically GoogleTranslate(str, from := "auto", to := "es").
Does this functional call asEng := GoogleTranslate(asEsp, "es", "en") simply override that? It seems like the "es" would cause it to just keep returning Spanish results.

Code: Select all

#NoEnv
#SingleInstance force
;############## https://autohotkey.com/boards/viewtopic.php?f=5&t=40876

toConvert := Clipboard
asEsp := GoogleTranslate(toConvert, "en", "es")
asEng := GoogleTranslate(asEsp, "es", "en")

MsgBox, Started with: `t %toConvert%`n`nAs Spanish:`t %asEsp%`n`nBack to English: `t %asEng%
;Clipboard := asEsp

GoogleTranslate(str, from := "auto", to := "es")  {
   static JS := GetJScripObject(), _ := JS.( GetJScript() ) := JS.("delete ActiveXObject; delete GetObject;")
   
   json := SendRequest(JS, str, to, from, proxy := "")
   oJSON := JS.("(" . json . ")")

   if !IsObject(oJSON[1])  {
      Loop % oJSON[0].length
         trans .= oJSON[0][A_Index - 1][0]
   }
   else  {
      MainTransText := oJSON[0][0][0]
      Loop % oJSON[1].length  {
         trans .= "`n+"
         obj := oJSON[1][A_Index-1][1]
         Loop % obj.length  {
            txt := obj[A_Index - 1]
            trans .= (MainTransText = txt ? "" : "`n" txt)
         }
      }
   }
   if !IsObject(oJSON[1])
      MainTransText := trans := Trim(trans, ",+`n ")
   else
      trans := MainTransText . "`n+`n" . Trim(trans, ",+`n ")

   from := oJSON[2]
   trans := Trim(trans, ",+`n ")
   Return trans
}

SendRequest(JS, str, tl, sl, proxy) {
   ComObjError(false)
   http := ComObjCreate("WinHttp.WinHttpRequest.5.1")
   ( proxy && http.SetProxy(2, proxy) )
   http.open( "POST", "https://translate.google.com/translate_a/single?client=t&sl="
      . sl . "&tl=" . tl . "&hl=" . tl
      . "&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t&ie=UTF-8&oe=UTF-8&otf=1&ssel=3&tsel=3&pc=1&kc=2"
      . "&tk=" . JS.("tk").(str), 1 )

   http.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8")
   http.SetRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0")
   http.send("q=" . URIEncode(str))
   http.WaitForResponse(-1)
   Return http.responsetext
}

URIEncode(str, encoding := "UTF-8")  {
   VarSetCapacity(var, StrPut(str, encoding))
   StrPut(str, &var, encoding)

   While code := NumGet(Var, A_Index - 1, "UChar")  {
      bool := (code > 0x7F || code < 0x30 || code = 0x3D)
      UrlStr .= bool ? "%" . Format("{:02X}", code) : Chr(code)
   }
   Return UrlStr
}

GetJScript()
{
   script =
   (
      var TKK = ((function() {
        var a = 561666268;
        var b = 1526272306;
        return 406398 + '.' + (a + b);
      })());

      function b(a, b) {
        for (var d = 0; d < b.length - 2; d += 3) {
            var c = b.charAt(d + 2),
                c = "a" <= c ? c.charCodeAt(0) - 87 : Number(c),
                c = "+" == b.charAt(d + 1) ? a >>> c : a << c;
            a = "+" == b.charAt(d) ? a + c & 4294967295 : a ^ c
        }
        return a
      }

      function tk(a) {
          for (var e = TKK.split("."), h = Number(e[0]) || 0, g = [], d = 0, f = 0; f < a.length; f++) {
              var c = a.charCodeAt(f);
              128 > c ? g[d++] = c : (2048 > c ? g[d++] = c >> 6 | 192 : (55296 == (c & 64512) && f + 1 < a.length && 56320 == (a.charCodeAt(f + 1) & 64512) ?
              (c = 65536 + ((c & 1023) << 10) + (a.charCodeAt(++f) & 1023), g[d++] = c >> 18 | 240,
              g[d++] = c >> 12 & 63 | 128) : g[d++] = c >> 12 | 224, g[d++] = c >> 6 & 63 | 128), g[d++] = c & 63 | 128)
          }
          a = h;
          for (d = 0; d < g.length; d++) a += g[d], a = b(a, "+-a^+6");
          a = b(a, "+-3^+b+-f");
          a ^= Number(e[1]) || 0;
          0 > a && (a = (a & 2147483647) + 2147483648);
          a `%= 1E6;
          return a.toString() + "." + (a ^ h)
      }
   )
   Return script
}

GetJScripObject()  {
   VarSetCapacity(tmpFile, (MAX_PATH := 260) << !!A_IsUnicode, 0)
   DllCall("GetTempFileName", Str, A_Temp, Str, "AHK", UInt, 0, Str, tmpFile)
   
   FileAppend,
   (
   <component>
   <public><method name='eval'/></public>
   <script language='JScript'></script>
   </component>
   ), % tmpFile
   
   JS := ObjBindMethod( ComObjGet("script:" . tmpFile), "eval" )
   FileDelete, % tmpFile
   Return JS
}
FanaticGuru
Posts: 1355
Joined: 30 Sep 2013, 22:25

Re: Google Translate code slow and erroneous

25 Jan 2018, 19:04

kunkel321 wrote:I'm curious now though: In the code below, line 12 has "es" in there statically GoogleTranslate(str, from := "auto", to := "es").
Does this functional call asEng := GoogleTranslate(asEsp, "es", "en") simply override that? It seems like the "es" would cause it to just keep returning Spanish results.
If the function parameters have := that means they are optional and will default to that if those parameters are not provided in the function call.
https://autohotkey.com/docs/Functions.htm#optional

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts

AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon

[Function] Timer - Create and Manage Timers
kunkel321
Posts: 176
Joined: 30 Nov 2015, 21:19
Facebook: https://www.facebook.com/kunkel321
Google: kunkel321

Re: Google Translate code slow and erroneous

26 Jan 2018, 11:16

Ah yes! Good to know.
IMEime
Posts: 750
Joined: 20 Sep 2014, 06:15

Re: Google Translate code slow and erroneous

16 Mar 2019, 03:58

Hmmm
This is really Nice
Thanks Guys
garry
Posts: 1815
Joined: 22 Dec 2013, 12:50

Re: Google Translate code slow and erroneous

19 Apr 2019, 16:35

thank you all for the examples , must try them all
@teadrinker , thank you , I tried this
added dropdownlist and edit
start script , select language , copy marked text (ctrl+c)

Code: Select all

;- from user teadrinker
;- https://www.autohotkey.com/boards/viewtopic.php?f=5&t=40876#p186877

/*
modified=20190420
created =20190419
select language , copy marked text ctrl+c > see translation in selected language
*/

#Warn
setworkingdir,%a_scriptdir%

Gui,1: +AlwaysOnTop  
Gui,1: -DPIScale
SS_REALSIZECONTROL := 0x40
Gui,1:Color,Black,Black
Gui, Font,s12 cYellow ,Lucida Console 

rssini=%a_scriptdir%\translate.ini
ifnotexist,%rssini%
    IniWrite,en, %rssini% ,Lang1  ,key1
IniRead, val1, %rssini%,Lang1 ,key1

clipboard=
cl=
ex:=""
tl1:=""
global tl1
transform,s,chr,32
gosub,language
Gui,add,dropdownlist, x10 y10 w320 vDDL1 gddl2,%e5x%
Gui,add,edit,x10 y50  w1100 h590 vED1  -vscroll -border -E0x200,
Gui,add,text,x0 y0 w0 vT1 ,
GuiControl, Focus,T1
;Gui, Show,x10 y10 w1150 h600 minimize,TRANSLATE
Gui, Show,x10 y10 w1150 h650 ,TRANSLATE
GuiControl,1:Choose,ddl1,%val1%
WinID := WinExist("A")
WinSetTitle, ahk_id %WinID%,, TRANSLATE_to_%val1%
tl1:=val1
E0x200 = WS_EX_CLIENTEDGE
RETURN
;--------------------------
esc::exitapp
;--------------------------
Guiclose:
exitapp
;--------------------------
OnClipboardChange:
If (A_EventInfo=1)
 {
 Gui, Show,
 cl:=clipboard
 aa:=GoogleTranslate(cl)
 ControlSetText,edit1,%aa%, ahk_class AutoHotkeyGUI
 aa=
 cl=
 clipboard=
 }
return
;--------------------------
ddl2:
Gui,1:submit,nohide
h1:=""
h2:=""
if DDL1<>
{
StringSplit,h,ddl1,`_
if h1<>
  {
  IniWrite,%h1%, %rssini% ,Lang1  ,key1
  tl1:=h1
  WinSetTitle, ahk_id %WinID%,, TRANSLATE_to_%h2%
  }
}
return
;----------------------------------------


;MsgBox, % GoogleTranslate("今日の天気はとても良いです")
;return
;-------------------------------------------
GoogleTranslate(str, from := "auto", to := "en")  {
   static JS := GetJScripObject(), _ := JS.( GetJScript() ) := JS.("delete ActiveXObject; delete GetObject;")
   json := SendRequest(JS, str, to, from, proxy := "")
   oJSON := JS.("(" . json . ")")
   if !IsObject(oJSON[1])  {
      trans:=""
      Loop % oJSON[0].length
         trans .= oJSON[0][A_Index - 1][0]
   }
   else  {
      MainTransText := oJSON[0][0][0]
      trans:=""
      Loop % oJSON[1].length  {
         trans .= "`n+"
         obj := oJSON[1][A_Index-1][1]
         Loop % obj.length  {
            txt := obj[A_Index - 1]
            trans .= (MainTransText = txt ? "" : "`n" txt)
         }
      }
   }
   if !IsObject(oJSON[1])
      MainTransText := trans := Trim(trans, ",+`n ")
   else
      trans := MainTransText . "`n+`n" . Trim(trans, ",+`n ")
   from := oJSON[2]
   trans := Trim(trans, ",+`n ")
   Return trans
}
SendRequest(JS, str, tl, sl, proxy) {
   ComObjError(false)
   http := ComObjCreate("WinHttp.WinHttpRequest.5.1")
   ( proxy && http.SetProxy(2, proxy) )
   http.open( "POST", "https://translate.google.com/translate_a/single?client=t&sl="
      . sl . "&tl=" . tl1 . "&hl=" . tl1
      . "&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t&ie=UTF-8&oe=UTF-8&otf=1&ssel=3&tsel=3&pc=1&kc=2"
      . "&tk=" . JS.("tk").(str), 1 )
   http.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8")
   http.SetRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0")
   http.send("q=" . URIEncode(str))
   http.WaitForResponse(-1)
   Return http.responsetext
}
URIEncode(str, encoding := "UTF-8")  {
   urlstr:=""
   VarSetCapacity(var, StrPut(str, encoding))
   StrPut(str, &var, encoding)
   While code := NumGet(Var, A_Index - 1, "UChar")  {
      bool := (code > 0x7F || code < 0x30 || code = 0x3D)
      UrlStr .= bool ? "%" . Format("{:02X}", code) : Chr(code)
   }
   Return UrlStr
}
GetJScript()
{
   script =
   (
      var TKK = ((function() {
        var a = 561666268;
        var b = 1526272306;
        return 406398 + '.' + (a + b);
      })());
      function b(a, b) {
        for (var d = 0; d < b.length - 2; d += 3) {
            var c = b.charAt(d + 2),
                c = "a" <= c ? c.charCodeAt(0) - 87 : Number(c),
                c = "+" == b.charAt(d + 1) ? a >>> c : a << c;
            a = "+" == b.charAt(d) ? a + c & 4294967295 : a ^ c
        }
        return a
      }
      function tk(a) {
          for (var e = TKK.split("."), h = Number(e[0]) || 0, g = [], d = 0, f = 0; f < a.length; f++) {
              var c = a.charCodeAt(f);
              128 > c ? g[d++] = c : (2048 > c ? g[d++] = c >> 6 | 192 : (55296 == (c & 64512) && f + 1 < a.length && 56320 == (a.charCodeAt(f + 1) & 64512) ?
              (c = 65536 + ((c & 1023) << 10) + (a.charCodeAt(++f) & 1023), g[d++] = c >> 18 | 240,
              g[d++] = c >> 12 & 63 | 128) : g[d++] = c >> 12 | 224, g[d++] = c >> 6 & 63 | 128), g[d++] = c & 63 | 128)
          }
          a = h;
          for (d = 0; d < g.length; d++) a += g[d], a = b(a, "+-a^+6");
          a = b(a, "+-3^+b+-f");
          a ^= Number(e[1]) || 0;
          0 > a && (a = (a & 2147483647) + 2147483648);
          a `%= 1E6;
          return a.toString() + "." + (a ^ h)
      }
   )
   Return script
}
GetJScripObject()  {
   VarSetCapacity(tmpFile, (MAX_PATH := 260) << !!A_IsUnicode, 0)
   DllCall("GetTempFileName", Str, A_Temp, Str, "AHK", UInt, 0, Str, tmpFile)
   
   FileAppend,
   (
   <component>
   <public><method name='eval'/></public>
   <script language='JScript'></script>
   </component>
   ), % tmpFile
   
   JS := ObjBindMethod( ComObjGet("script:" . tmpFile), "eval" )
   FileDelete, % tmpFile
   Return JS
}
;----------------------- end function ----------------------

language:
e5x:=""
e5x=
(Ltrim join|
nl_Nederlands
af_Suid-Afrika
fy_Fryslân
eu_Basque
ca_Catalan
da_Dansk
sv_Sverige
no_Norge
is_Iceland
fi_Suomen
en_English
pt_Portugues
es_Español
it_Italia
fr_Français
ru_Rossija
zh-CN_Chinese
ja_Nippon
ko_Korea
ro_Romania
bg_Bulgaria
mc_Macedonia
el_Greek
tr_Turkiye
sq_Albania
hr_Croatia
sr_Serbia
sl_Slovenia
hu_Hungary
cs_Czech
pl_Poland
be_Belarus
uk_Ukraina
et_Estonia
lv_Latvija
lt_Lituania
az_Azerbaijan 
ka_Georgian
ar_Arabic
iw_Hebrew
hi_Hindi
id_Indonesia
ms_Malaysia
vi_Vietnam
th_Thai
ta_Tamil
ur_Urdu
sw_Swahili
%s%

)
return
;====================== END SCRIPT ==================================================
Last edited by garry on 20 Apr 2019, 08:19, edited 1 time in total.
Osprey
Posts: 453
Joined: 18 Nov 2017, 05:50

Re: Google Translate code slow and erroneous

19 Apr 2019, 22:14

Many thanks to teadrinker for his script.

I've slightly modified it in a few ways to suit my purposes, but also make it more adaptable for others:

1. It'll now automatically translate to the user's system language. In other words, if you don't supply any parameters to the GoogleTranslate function other than the string, it'll translate it to your Windows language, rather than to English. This makes it easier to use for non-English speakers and for people writing scripts that they want to be automatically translated for all end users.

2. If you supply the original language as the 2nd parameter and that happens to be the same as the user's system language, no attempt at translation will be performed. That improves performance by not sending unneeded translation requests to Google. So, for example, if your messages are in English, you can improve performance for yourself and other English speakers by doing GoogleTranslate("Sample text", "en").

3. If a response isn't received back from Google, it'll return the original, untranslated string. This way, your scripts won't break if there's no internet or Google's servers detect spam. Strings will just be in the script's original language until the connection is restored.

Code: Select all

; Google Translate script
; Take a string in any language and translate to any other language.
;
; Credited to teadrinker: https://www.autohotkey.com/boards/viewtopic.php?f=5&t=40876#p186877
; Slightly modified by Osprey to allow for determining and using the system language.
; Should be run with the Unicode version of AutoHotkey.
;
; Sample usage
; MsgBox, % GoogleTranslate("今日の天気はとても良いです")				; Translate string from auto-detected language to system language
; MsgBox, % GoogleTranslate("今日の天気はとても良いです", "jp", "en")	; Translate string from Japanese to English

GoogleTranslate(str, from := "auto", to := 0) {
   static JS := GetJScripObject(), _ := JS.( GetJScript() ) := JS.("delete ActiveXObject; delete GetObject;")
   
   if(!to)						; If no "to" parameter was passed
      to := GetISOLanguageCode()	; Assign the system (OS) language to "to"
      
   if(from = to)					; If the "from" and "to" parameters are the same
      Return str					; Abort translation and return the original string

   json := SendRequest(JS, str, to, from, proxy := "")
   if(!json or InStr(json, "document.getElementById('captcha-form')"))	; If no response (ex. internet down) or spam is detected
      Return str					; Return the original, untranslated string
   oJSON := JS.("(" . json . ")")

   if !IsObject(oJSON[1])  {
      Loop % oJSON[0].length
         trans .= oJSON[0][A_Index - 1][0]
   }
   else  {
      MainTransText := oJSON[0][0][0]
      Loop % oJSON[1].length  {
         trans .= "`n+"
         obj := oJSON[1][A_Index-1][1]
         Loop % obj.length  {
            txt := obj[A_Index - 1]
            trans .= (MainTransText = txt ? "" : "`n" txt)
         }
      }
   }
   if !IsObject(oJSON[1])
      MainTransText := trans := Trim(trans, ",+`n ")
   else
      trans := MainTransText . "`n+`n" . Trim(trans, ",+`n ")

   from := oJSON[2]
   trans := Trim(trans, ",+`n ")
   Return trans
}

; Take a 4-digit language code or (if no parameter) the current language code and return the corresponding 2-digit ISO code
GetISOLanguageCode(lang := 0) {
   LanguageCodeArray := { 0436: "af" ; Afrikaans
			, 041c: "sq" ; Albanian
			, 0401: "ar" ; Arabic_Saudi_Arabia
			, 0801: "ar" ; Arabic_Iraq
			, 0c01: "ar" ; Arabic_Egypt
			, 1001: "ar" ; Arabic_Libya
			, 1401: "ar" ; Arabic_Algeria
			, 1801: "ar" ; Arabic_Morocco
			, 1c01: "ar" ; Arabic_Tunisia
			, 2001: "ar" ; Arabic_Oman
			, 2401: "ar" ; Arabic_Yemen
			, 2801: "ar" ; Arabic_Syria
			, 2c01: "ar" ; Arabic_Jordan
			, 3001: "ar" ; Arabic_Lebanon
			, 3401: "ar" ; Arabic_Kuwait
			, 3801: "ar" ; Arabic_UAE
			, 3c01: "ar" ; Arabic_Bahrain
			, 042c: "az" ; Azeri_Latin
			, 082c: "az" ; Azeri_Cyrillic
			, 042d: "eu" ; Basque
			, 0423: "be" ; Belarusian
			, 0402: "bg" ; Bulgarian
			, 0403: "ca" ; Catalan
			, 0404: "zh-CN" ; Chinese_Taiwan
			, 0804: "zh-CN" ; Chinese_PRC
			, 0c04: "zh-CN" ; Chinese_Hong_Kong
			, 1004: "zh-CN" ; Chinese_Singapore
			, 1404: "zh-CN" ; Chinese_Macau
			, 041a: "hr" ; Croatian
			, 0405: "cs" ; Czech
			, 0406: "da" ; Danish
			, 0413: "nl" ; Dutch_Standard
			, 0813: "nl" ; Dutch_Belgian
			, 0409: "en" ; English_United_States
			, 0809: "en" ; English_United_Kingdom
			, 0c09: "en" ; English_Australian
			, 1009: "en" ; English_Canadian
			, 1409: "en" ; English_New_Zealand
			, 1809: "en" ; English_Irish
			, 1c09: "en" ; English_South_Africa
			, 2009: "en" ; English_Jamaica
			, 2409: "en" ; English_Caribbean
			, 2809: "en" ; English_Belize
			, 2c09: "en" ; English_Trinidad
			, 3009: "en" ; English_Zimbabwe
			, 3409: "en" ; English_Philippines
			, 0425: "et" ; Estonian
			, 040b: "fi" ; Finnish
			, 040c: "fr" ; French_Standard
			, 080c: "fr" ; French_Belgian
			, 0c0c: "fr" ; French_Canadian
			, 100c: "fr" ; French_Swiss
			, 140c: "fr" ; French_Luxembourg
			, 180c: "fr" ; French_Monaco
			, 0437: "ka" ; Georgian
			, 0407: "de" ; German_Standard
			, 0807: "de" ; German_Swiss
			, 0c07: "de" ; German_Austrian
			, 1007: "de" ; German_Luxembourg
			, 1407: "de" ; German_Liechtenstein
			, 0408: "el" ; Greek
			, 040d: "iw" ; Hebrew
			, 0439: "hi" ; Hindi
			, 040e: "hu" ; Hungarian
			, 040f: "is" ; Icelandic
			, 0421: "id" ; Indonesian
			, 0410: "it" ; Italian_Standard
			, 0810: "it" ; Italian_Swiss
			, 0411: "ja" ; Japanese
			, 0412: "ko" ; Korean
			, 0426: "lv" ; Latvian
			, 0427: "lt" ; Lithuanian
			, 042f: "mk" ; Macedonian
			, 043e: "ms" ; Malay_Malaysia
			, 083e: "ms" ; Malay_Brunei_Darussalam
			, 0414: "no" ; Norwegian_Bokmal
			, 0814: "no" ; Norwegian_Nynorsk
			, 0415: "pl" ; Polish
			, 0416: "pt" ; Portuguese_Brazilian
			, 0816: "pt" ; Portuguese_Standard
			, 0418: "ro" ; Romanian
			, 0419: "ru" ; Russian
			, 081a: "sr" ; Serbian_Latin
			, 0c1a: "sr" ; Serbian_Cyrillic
			, 041b: "sk" ; Slovak
			, 0424: "sl" ; Slovenian
			, 040a: "es" ; Spanish_Traditional_Sort
			, 080a: "es" ; Spanish_Mexican
			, 0c0a: "es" ; Spanish_Modern_Sort
			, 100a: "es" ; Spanish_Guatemala
			, 140a: "es" ; Spanish_Costa_Rica
			, 180a: "es" ; Spanish_Panama
			, 1c0a: "es" ; Spanish_Dominican_Republic
			, 200a: "es" ; Spanish_Venezuela
			, 240a: "es" ; Spanish_Colombia
			, 280a: "es" ; Spanish_Peru
			, 2c0a: "es" ; Spanish_Argentina
			, 300a: "es" ; Spanish_Ecuador
			, 340a: "es" ; Spanish_Chile
			, 380a: "es" ; Spanish_Uruguay
			, 3c0a: "es" ; Spanish_Paraguay
			, 400a: "es" ; Spanish_Bolivia
			, 440a: "es" ; Spanish_El_Salvador
			, 480a: "es" ; Spanish_Honduras
			, 4c0a: "es" ; Spanish_Nicaragua
			, 500a: "es" ; Spanish_Puerto_Rico
			, 0441: "sw" ; Swahili
			, 041d: "sv" ; Swedish
			, 081d: "sv" ; Swedish_Finland
			, 0449: "ta" ; Tamil
			, 041e: "th" ; Thai
			, 041f: "tr" ; Turkish
			, 0422: "uk" ; Ukrainian
			, 0420: "ur" ; Urdu
			, 042a: "vi"} ; Vietnamese
   If(lang)
     Return LanguageCodeArray[lang]
   Else Return LanguageCodeArray[A_Language]
}

SendRequest(JS, str, tl, sl, proxy) {
   ComObjError(false)
   http := ComObjCreate("WinHttp.WinHttpRequest.5.1")
   ( proxy && http.SetProxy(2, proxy) )
   http.open( "POST", "https://translate.google.com/translate_a/single?client=t&sl="
      . sl . "&tl=" . tl . "&hl=" . tl
      . "&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t&ie=UTF-8&oe=UTF-8&otf=1&ssel=3&tsel=3&pc=1&kc=2"
      . "&tk=" . JS.("tk").(str), 1 )

   http.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8")
   http.SetRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0")
   http.send("q=" . URIEncode(str))
   http.WaitForResponse(-1)
   Return http.responsetext
}

URIEncode(str, encoding := "UTF-8")  {
   VarSetCapacity(var, StrPut(str, encoding))
   StrPut(str, &var, encoding)

   While code := NumGet(Var, A_Index - 1, "UChar")  {
      bool := (code > 0x7F || code < 0x30 || code = 0x3D)
      UrlStr .= bool ? "%" . Format("{:02X}", code) : Chr(code)
   }
   Return UrlStr
}

GetJScript()
{
   script =
   (
      var TKK = ((function() {
        var a = 561666268;
        var b = 1526272306;
        return 406398 + '.' + (a + b);
      })());

      function b(a, b) {
        for (var d = 0; d < b.length - 2; d += 3) {
            var c = b.charAt(d + 2),
                c = "a" <= c ? c.charCodeAt(0) - 87 : Number(c),
                c = "+" == b.charAt(d + 1) ? a >>> c : a << c;
            a = "+" == b.charAt(d) ? a + c & 4294967295 : a ^ c
        }
        return a
      }

      function tk(a) {
          for (var e = TKK.split("."), h = Number(e[0]) || 0, g = [], d = 0, f = 0; f < a.length; f++) {
              var c = a.charCodeAt(f);
              128 > c ? g[d++] = c : (2048 > c ? g[d++] = c >> 6 | 192 : (55296 == (c & 64512) && f + 1 < a.length && 56320 == (a.charCodeAt(f + 1) & 64512) ?
              (c = 65536 + ((c & 1023) << 10) + (a.charCodeAt(++f) & 1023), g[d++] = c >> 18 | 240,
              g[d++] = c >> 12 & 63 | 128) : g[d++] = c >> 12 | 224, g[d++] = c >> 6 & 63 | 128), g[d++] = c & 63 | 128)
          }
          a = h;
          for (d = 0; d < g.length; d++) a += g[d], a = b(a, "+-a^+6");
          a = b(a, "+-3^+b+-f");
          a ^= Number(e[1]) || 0;
          0 > a && (a = (a & 2147483647) + 2147483648);
          a `%= 1E6;
          return a.toString() + "." + (a ^ h)
      }
   )
   Return script
}

GetJScripObject()  {
   VarSetCapacity(tmpFile, (MAX_PATH := 260) << !!A_IsUnicode, 0)
   DllCall("GetTempFileName", Str, A_Temp, Str, "AHK", UInt, 0, Str, tmpFile)
   
   FileAppend,
   (
   <component>
   <public><method name='eval'/></public>
   <script language='JScript'></script>
   </component>
   ), % tmpFile
   
   JS := ObjBindMethod( ComObjGet("script:" . tmpFile), "eval" )
   FileDelete, % tmpFile
   Return JS
}
garry
Posts: 1815
Joined: 22 Dec 2013, 12:50

Re: Google Translate code slow and erroneous

20 Apr 2019, 14:29

I think all examples are interesting
Maybe add them in 'Scripts and functions' > Translator ( google )
( I just used an example from 'teadrinker' , added a GUI , select a language )
teadrinker
Posts: 678
Joined: 29 Mar 2015, 09:41
Contact:

Re: Google Translate code slow and erroneous

20 Apr 2019, 19:26

Hi, Osprey and garry

Thank for your replies. :wave: I created the topic «Using Google Translate to automate text translation». You could add your examples to it.
Osprey
Posts: 453
Joined: 18 Nov 2017, 05:50

Re: Google Translate code slow and erroneous

20 Apr 2019, 19:53

Very good, teadrinker. I've reposted my reply there. Thanks for the offer and thanks again for the awesome script. I've already implemented it into a project that I'm working on. It's pretty wild how simple it is. In fact, it's so simple that using it a little too much triggers Google's servers to require a captcha, which is why I had to add the option to simply return the untranslated string when that happens :lol:.
garry
Posts: 1815
Joined: 22 Dec 2013, 12:50

Re: Google Translate code slow and erroneous

21 Apr 2019, 05:16

Thank you teadrinker , if you find it's ok I'll add my reply there ( just added a GUI to your script to select some languages , copy text , translate ) .

Return to “Ask For Help”

Who is online

Users browsing this forum: andylysm, Bing [Bot], flyingDman, Google [Bot], Kenn_Guilstorf, MannyKSoSo, Relayer, Samantha, sinkfaze and 127 guests