使用AutoHotKey(AHK)自动将多行内容转成单行,并翻译,或获取中文拼音

动机

你曾遇到过下面这些情况吗?在上网或看文献时总是会遇到不认识的单词还要打开词典软件或谷歌翻译查词?或者有些汉字不知道它的拼音还要去百度它的拼音?又或者想不起来一个词语的英文翻译?又又或者在复制pdf中的多行文本时还得手动把复制出来的换行删掉?

相信你或多或少都和遇到过上面的烦恼,下面分享一个我使用的AutoHotKey脚本帮大家解决这些问题。如果你认为此脚本可以有更多的可能性或者有更好的实现方式,欢迎在评论区讨论;如果你觉得脚本对你有用,还请顺手点赞收藏,你的支持是对我最大的鼓励😊

脚本功能

该脚本可以实现的功能如下:

  1. 如果选中的内容为多行文本,将其转换为单行,并且会删除从第二行开始每行开头的注释符号(#;%);如果第二行开始的开头除注释符号外的第一个字符为中文或中文符号,则与前一行之间没有空格,否则与前一行之间加空间
  2. 如果选中的内容中的中文字符占全部字符的占比较大(80%以上),且总字符长度较长(我的脚本里是大于4,可以根据需求更改),则弹窗显示已转换为单行的字符串,2s后弹窗自动关闭;如果字符长度较短,则弹窗显示字符串的拼音,3s后弹窗自动关闭
  3. 如果选中的内容中的中文字符占全部字符的占比较少,且总字符长度较短(我的脚本里是小于30,可以根据需求更改),则弹窗显示中文翻译结果,3s后弹窗自动关闭;如果字符长度较长,也会弹窗显示中文翻译结果,但是不会自动关闭
  4. 将选中的文本翻译成英文

脚本使用方法

单击F1键,实现功能1,并根据条件实现功能2或功能3;
双击F1键,实现功能1,并实现功能4;
长按F1键,F1键的原始功能。

功能展示

单击F1:

翻译成中文:

在这里插入图片描述

查询中文拼音:

在这里插入图片描述

双击F1:

翻译成英文:

在这里插入图片描述

脚本

$F1::
    KeyWait, F1, T0.6 ;wait 0.6s
    if (ErrorLevel)
        sendinput {F1} ;long press
    else {
        KeyWait, F1, D T0.3 ;wait 0.3s
        if (ErrorLevel)
            translate("auto","zh-CN") ;single press
        else
            translate("auto","en") ;double press
    }
    KeyWait, F1
return

; Google Translate:
translate(from := "auto", to := "zh-CN")
{
    Clipboard := ""
    SendInput, ^c
    ClipWait, 1
    if ErrorLevel
        Return
    
    ;Later two lines transform multiline string to single line string, and save results in clipboard. This is very useful when copying multiline string from pdf.
    Clipboard:=RegExReplace(Clipboard,"\r\n[ #;%]*([\x{3002}\x{ff1b}\x{ff0c}\x{ff1a}\x{201c}\x{201d}\x{ff08}\x{ff09}\x{3001}\x{ff1f}\x{300a}\x{300b}\x{4e00}-\x{9fa5}])","$1")
    Clipboard:=RegExReplace(Clipboard,"\r\n[ #;%]*"," ")
    ;Clipboard:=RegExReplace(Clipboard,"\r\n[ #;%]*([A-z])"," $1")
    ;Clipboard:=RegExReplace(Clipboard,"\r\n[ #;%]*([^A-z])","$1")
    
    if (to == "en") ;translate other language to english
    {
        MsgBox, ,,% GoogleTranslate(Clipboard,from,to).full, 3
    }
    else ;translate other language to chinese or get chinese pinyin
    { 
        a:=StrLen(RegExReplace(Clipboard,"[^\x{3002}\x{ff1b}\x{ff0c}\x{ff1a}\x{201c}\x{201d}\x{ff08}\x{ff09}\x{3001}\x{ff1f}\x{300a}\x{300b}\x{4e00}-\x{9fa5}]","")) ;calculate chinese charactor length
        b:=StrLen(Clipboard) ;total string length
        c:=a/b ;chinese charactor percent
        if (c >0.8) ;if most charactor is chinese charactor, don't translate to chinese
        {
            if (b>4) ;When string length is long, just show it. 
                msgbox,,,%clipboard% ,2
            else ;When string length is short, show it's pinyin.
                MsgBox, ,,% GoogleTranslate(Clipboard).pinyin, 3
        }
        else ;if most charactor isn't chinese charactor, translate to chinese
        {
            if(b<30) ;When string length is short, show message box just 3 seconds.
                MsgBox, ,,% GoogleTranslate(Clipboard).full, 3
            else ;if not, show message unless user close it.
                MsgBox, ,,% GoogleTranslate(Clipboard).full,
        }
    }
}

GoogleTranslate(str, from := "auto", to := "zh-CN") {
    JSON := new JSON
    JS := JSON.JS, JS.( GetJScript() )
    
    sJson := SendRequest(JS, str, to, from)
    oJSON := JSON.Parse(sJson)
    
    if !IsObject(oJSON[2]) {
        for k, v in oJSON[1]
            trans .= v[1]
    }
    else {
        MainTransText := oJSON[1, 1, 1]
        for k, v in oJSON[2] {
            trans .= "`n+"
            for i, txt in v[2]
                trans .= (MainTransText = txt ? "" : "`n" . txt)
        }
    }
    if !IsObject(oJSON[2])
        MainTransText := trans := Trim(trans, ",+`n ")
    else
        trans := MainTransText . "`n+`n" . Trim(trans, ",+`n ")
    
    from := oJSON[3]    
    pinyin := oJSON[1,2,3]
    trans := Trim(trans, ",+`n ")
Return {main: MainTransText, full: trans, from: from , pinyin: pinyin}
}

SendRequest(JS, str, tl, sl) {
    ComObjError(false)
    url := "https://translate.google.cn/translate_a/single?client=webapp&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)
    body := "q=" . URIEncode(str)
    contentType := "application/x-www-form-urlencoded;charset=utf-8"
    userAgent := "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0"
Return JSON.GetFromUrl(url, body, contentType, userAgent)
}

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 JSON
{
    static JS := JSON._GetJScripObject()
    
    Parse(JsonString) {
        try oJSON := this.JS.("(" JsonString ")")
        catch {
            MsgBox, Wrong JsonString!
            Return
        }
        Return this._CreateObject(oJSON)
    }
    
    GetFromUrl(url, body := "", contentType := "", userAgent := "") {
        XmlHttp := ComObjCreate("Microsoft.XmlHttp")
        XmlHttp.Open("GET", url, false)
        ( contentType && XmlHttp.SetRequestHeader("Content-Type", contentType) )
        ( userAgent && XmlHttp.SetRequestHeader("User-Agent", userAgent) )
        XmlHttp.Send(body)
        Return XmlHttp.ResponseText
    }
    
    _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
        JSON._AddMethods(JS)
        Return JS
    }
    
    _AddMethods(ByRef JS) {
        JScript =
        (
        Object.prototype.GetKeys = function () {
            var keys = []
            for (var k in this)
                if (this.hasOwnProperty(k))
                keys.push(k)
            return keys
        }
        Object.prototype.IsArray = function () {
            var toStandardString = {}.toString
            return toStandardString.call(this) == '[object Array]'
        }
        )
        JS.("delete ActiveXObject; delete GetObject;")
        JS.(JScript)
    }
    
    _CreateObject(ObjJS) {
        res := ObjJS.IsArray()
        if (res = "")
            Return ObjJS
        
        else if (res = -1) {
            obj := []
            Loop % ObjJS.length
                obj[A_Index] := this._CreateObject(ObjJS[A_Index - 1])
        }
        else if (res = 0) {
            obj := {}
            keys := ObjJS.GetKeys()
            Loop % keys.length
                k := keys[A_Index - 1], obj[k] := this._CreateObject(ObjJS[k])
        }
        Return obj
    }
}

参考资料

脚本中的翻译部分代码是从AutoHotKey论坛上copy的,在此附上参考地址:Making this awesome Google Translate Script work for DeepL

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 你可以在 Autohotkey 脚本内使用 Reload 函数来重新加载它自己。该函数的语法如下: Reload 使用该函数的示例如下: ^r:: Reload return 上面的示例中,当用户按下 "Ctrl + R" 组合键时,脚本将会重新加载自身。 ### 回答2: AutoHotkey(简称AHK)是一种自动化脚本语言,常用于自动化操作、自定义快捷键等。如果你想要让一个AHK文件在运行时重新加载自己,可以使用以下方法。 首先,在你的AHK脚本中添加一个快捷键绑定,用于触发重新加载。你可以选择任意一个你喜欢的快捷键,比如"Ctrl + Alt + R"。添加以下代码可以实现这个功能: ^!r:: Reload return 第一行代码中的"^"代表Control键,"!"代表Alt键,"r"代表"R"键。所以 "^!r"即为"Ctrl + Alt + R"。第三行的"Reload"命令用于重新加载脚本。 将以上代码添加至你的AHK脚本中,保存修改。 接下来,在你打开的AHK脚本中,按下设置的快捷键"Ctrl + Alt + R"即可重新加载脚本。这样,你就不需要关闭脚本再重新打开它了,可以直接加载修改后的内容。 需要注意的是,重新加载脚本会终止当前脚本的执行,并重新启动脚本。 希望以上解答对你有所帮助。如有其他问题,请随时提问。 ### 回答3: 要让AutoHotkeyAHK)文件重新加载自己,你可以使用AHK内置的Reload函数。Reload函数可以重启当前运行的脚本,即重新加载脚本文件。 你可以在脚本文件的任何位置使用Reload函数来实现重新加载。以下是一个示例: ```autohotkey ^!r:: Reload return ``` 上述代码将Ctrl+Alt+R绑定到Reload函数。当你按下这个组合键时,AHK脚本会重新加载。 如果你想要自动重载脚本,你可以将Reload函数与文件监视器结合使用。文件监视器可以监视脚本文件的任何更改,并在更改后自动重新加载。 以下是一个将文件监视器与Reload函数结合使用的示例: ```autohotkey #Persistent SetTimer, ReloadCheck, 1000 return ReloadCheck: If (FileExist("脚本文件的完整路径")) { FileGetTime, currentModified, 脚本文件的完整路径 If (currentModified != previousModified) { Reload } } previousModified := currentModified return ``` 在上述代码中,我们首先设置了一个持续的定时器(SetTimer),它每秒钟检查一次脚本文件是否有更改。然后,我们使用FileExist和FileGetTime函数来获取脚本文件的最新修改时间,如果最新修改时间与之前保存的修改时间不同,则重新加载脚本。 请注意,你需要将代码中的"脚本文件的完整路径"替换为你实际的脚本文件路径。 这些是使用AutoHotkey重新加载脚本的两种方法。希望对你有帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值