[v2] GoogleTranslate /_/TranslateWebserverUi

Post your working scripts, libraries and tools.
MrDoge
Posts: 151
Joined: 27 Apr 2020, 21:29

[v2] GoogleTranslate /_/TranslateWebserverUi

Post by MrDoge » 05 Feb 2023, 17:59

motivation:
viewtopic.php?f=6&t=63835 incorrectly detects 門 as Chinese Simplified, it uses url path: /translate_a/single
there's another url path of translate.google.com which detects this correctly: /_/TranslateWebserverUi
it is the same url path that the website https://translate.google.com/ uses, which also detects it correctly: Chinese (Traditional)

Code: Select all

MsgBox JSON_stringify(GoogleTranslate("hello world", "zh-CH")) ;{"fromLanguage": "en","text": "你好世界"}
MsgBox JSON_stringify(GoogleTranslate("门", "zh-TW")) ;{"fromLanguage": "zh-CN","text": "門"}
; good luck finding out what 门 means

GoogleTranslate(text, languageTo:="en", languageFrom:="auto") {
    if (!GoogleTranslate.HasOwnProp("extracted")) {
        hObject:=ComObject("WinHttp.WinHttpRequest.5.1")
        hObject.Open("GET","https://translate.google.com")
        hObject.SetRequestHeader("User-Agent", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)")
        hObject.Send()
        lol:=hObject.ResponseText

        pos_FdrFJe := InStr(lol, "FdrFJe", true)
        pos_quote_FdrFJe := InStr(lol, "`"", true, pos_FdrFJe + 9)
        value_FdrFJe := SubStr(lol, pos_FdrFJe + 9, pos_quote_FdrFJe - (pos_FdrFJe + 9))

        pos_cfb2h := InStr(lol, "cfb2h", true)
        pos_quote_cfb2h := InStr(lol, "`"", true, pos_cfb2h + 8)
        value_cfb2h := SubStr(lol, pos_cfb2h + 8, pos_quote_cfb2h - (pos_cfb2h + 8))
        GoogleTranslate.extracted:={ FdrFJe: value_FdrFJe, cfb2h: value_cfb2h }
    }

    hObject:=ComObject("WinHttp.WinHttpRequest.5.1")
    hObject.Open("POST","https://translate.google.com/_/TranslateWebserverUi/data/batchexecute?rpcids=MkEWBc&source-path=%2F&f.sid=" GoogleTranslate.extracted.FdrFJe "&bl=" GoogleTranslate.extracted.cfb2h "&hl=en-US&soc-app=1&soc-platform=1&soc-device=1&_reqid=" Random(1000,9999) "&rt=c")
    hObject.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8")
    hObject.Send("f.req=" encodeURIComponent(JSON_stringify([[["MkEWBc",JSON_stringify([[text, languageFrom, languageTo, {Base:{__Class:"JSON_false"}}], [{Base:{__Class:"JSON_null"}}]]), {Base:{__Class:"JSON_null"}}, 'generic']]])))
    lol:=hObject.ResponseText

    pos_newline := InStr(lol,"`n",true,8)
    fwef:=SubStr(lol,7,pos_newline - 7)
    size := Integer(SubStr(lol,7,pos_newline - 7)) - 2
    jsonTemp := JSON_parse(SubStr(lol,pos_newline+1,size))
    json := JSON_parse(jsonTemp[1][3])

    if (type(json[1][2])=="JSON_null" || type(json[1][2][1])=="JSON_null") {
        fromText:=false
    } else {
        fromText:=json[1][2][1][5]
    }
    ;fromText is the autocorrected
    return {text:json[2][1][1][6][1][1],fromLanguage:json[3],fromText:fromText}
}

JSON_parse(str) {

    c_:=1

    return JSON_value()

    JSON_value() {

        char_:=SubStr(str, c_, 1)
        Switch char_ {
            case "{":
                obj_:=Map()
                ;object
                c_++
                loop {
                    skip_s()
                    if (SubStr(str, c_, 1) == "}") {
                        c_++
                        return obj_
                    }

                    ; key_:=JSON_objKey()
                    ; a or "a"
                    if (SubStr(str, c_, 1) == "`"") {
                        RegExMatch(str, "(?:\\.|.)*?(?=`")", &OutputVar, c_ + 1)
                        key_:=StrReplace(StrReplace(StrReplace(StrReplace(StrReplace(StrReplace(StrReplace(OutputVar.0, "\`"", "`"", true), "\f", "`f", true), "\r", "`r", true), "\n", "`n", true), "\b", "`b", true), "\t", "`t", true), "\\", "\", true)
                        c_+=OutputVar.Len
                    } else {
                        RegExMatch(str, ".*?(?=[\s:])", &OutputVar, c_)
                        key_:=OutputVar.0
                        c_+=OutputVar.Len
                    }

                    c_:=InStr(str, ":", true, c_) + 1
                    skip_s()

                    value_:=JSON_value()
                    obj_[key_]:=value_
                    obj_.DefineProp(key_, {Value: value_})

                    skip_s()
                    if (SubStr(str, c_, 1) == ",") {
                        c_++, skip_s()
                    }
                }
            case "[":
                arr_:=[]
                ;array
                c_++
                loop {
                    skip_s()
                    if (SubStr(str, c_, 1) == "]") {
                        c_++
                        return arr_
                    }

                    value_:=JSON_value()
                    arr_.Push(value_)

                    skip_s()
                    char_:=SubStr(str, c_, 1)
                    if (char_ == ",") {
                        c_++, skip_s()
                    }
                }
            case "`"":
                RegExMatch(str, "(?:\\.|.)*?(?=`")", &OutputVar, c_ + 1)
                unquoted:=StrReplace(StrReplace(StrReplace(StrReplace(StrReplace(StrReplace(StrReplace(OutputVar.0, "\`"", "`"", true), "\f", "`f", true), "\r", "`r", true), "\n", "`n", true), "\b", "`b", true), "\t", "`t", true), "\\", "\", true)
                c_+=OutputVar.Len + 2
                return unquoted
            case "-", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9":
                ; -100
                ; 100.0
                ; 1.0E+2
                ; 1E-2
                RegExMatch(str, "[0-9.eE\-+]*", &OutputVar, c_)
                c_+=OutputVar.Len
                return Number(OutputVar.0)
            case "t":
                ;"true"
                c_+=4
                return {Base:{__Class:"JSON_true"}}
            case "f":
                ;"false"
                c_+=5
                return {Base:{__Class:"JSON_false"}}
            case "n":
                ;"null"
                c_+=4
                return {Base:{__Class:"JSON_null"}}

        }
    }

    skip_s() {
        RegExMatch(str, "\s*", &OutputVar, c_)
        c_+=OutputVar.Len
    }
}

JSON_stringify(obj, maxDepth := 5) {

    stringified := ""

    escape(str) {
        str:=StrReplace(str, "\", "\\", true)
        str:=StrReplace(str, "`t", "\t", true)
        str:=StrReplace(str, "`b", "\b", true)
        str:=StrReplace(str, "`n", "\n", true)
        str:=StrReplace(str, "`r", "\r", true)
        str:=StrReplace(str, "`f", "\f", true)
        str:=StrReplace(str, "`"", "\`"", true)
        return str
    }
    ok(obj, depth) {
        switch (Type(obj)) {
            case 'Map':
                if (depth > maxDepth) {
                    stringified.="`"[DEEP ...Map]`""
                } else {
                    stringified.="{"
                    for k, v in obj {
                        (A_Index > 1 && stringified.=",")
                        stringified.="`"" escape(k) "`": "
                        ok(v, depth+1)
                    }
                    stringified.="}"
                }
            case 'Object':
                if (depth > maxDepth) {
                    stringified.="`"[DEEP ...Object]`""
                } else {
                    stringified.="{"
                    for k, v in obj.OwnProps() {
                        (A_Index > 1 && stringified.=",")
                        stringified.="`"" escape(k) "`": "
                        ok(v, depth+1)
                    }
                    stringified.="}"
                }
            case 'Array':
                if (depth > maxDepth) {
                    stringified.="`"[DEEP ...Array]`""
                } else {
                    stringified.="["
                    for v in obj {
                        (A_Index > 1 && stringified.=",")
                        ok(v, depth+1)
                    }
                    stringified.="]"
                }
            case 'String':
                stringified.="`"" escape(obj) "`"" ;in order to escape \n and etc
            case "Integer", "Float":
                stringified.=obj
            case "JSON_true":
                stringified.="true"
            case "JSON_false":
                stringified.="false"
            case "JSON_null":
                stringified.="null"
        }

    }
    ok(obj, 0)

    return stringified

}

encodeURIComponent(str) {
    static arr:=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"!",0,0,0,0,0,"'","(",")","*",0,0,"-",".",0,"0","1","2","3","4","5","6","7","8","9",0,0,0,0,0,0,0,"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z",0,0,0,0,"_",0,"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z",0,0,0,"~",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,]

    size:=StrPut(str, "UTF-8")
    buf := Buffer(size)
    StrPut(str, buf, "UTF-8")

    i_ := 0
    sizeMinusOne := size - 1
    finalStr:=""

    while (i_ < sizeMinusOne) {
        uChar:=NumGet(buf, i_, "UChar")
        if (type(arr[uChar + 1])=="String") { ;I REALLY don't know how to get : "0"!==0 -> to give me false
            finalStr.=arr[uChar + 1]
        } else {
            finalStr.="%" Format("{:02X}",uChar)
        }
        ++i_
    }

    return finalStr
}

Exitapp

f3::Exitapp
edit: added autocorrect, use it to correct dia to día for example
fromText is the autocorrected

Return to “Scripts and Functions (v2)”