Need Help with AutoHotkey Script for DeepL API Translation

Get help with using AutoHotkey (v2 or newer) and its commands and hotkeys
User avatar
tiska
Posts: 26
Joined: 21 Mar 2024, 10:48

Need Help with AutoHotkey Script for DeepL API Translation

21 Mar 2024, 11:26

Dear AutoHotkey Community,

I'm reaching out to seek assistance with an AutoHotkey script for translating selected text from German to English with the free DeepL API.
https://developers.deepl.com/docs/getting-started/your-first-api-request

Despite my best efforts, the newbie script I have tried to write doesn't seem to be functioning as expected, and I'm hoping someone with more experience in both AutoHotkey and API integration could lend a hand.
The example below of an HTTP request uses the free API endpoint https://api-free.deepl.com

POST /v2/translate HTTP/2
Host: api-free.deepl.com
Authorization: DeepL-Auth-Key [yourAuthKey]
User-Agent: YourApp/1.2.3
Content-Length: 45
Content-Type: application/json

{"text":["Hello, world!"],"target_lang":"DE"}

-----

{
"translations": [
{
"detected_source_language": "EN",
"text": "Hallo, Welt!"
}
]
}
User avatar
mikeyww
Posts: 26981
Joined: 09 Sep 2014, 18:38

Re: Need Help with AutoHotkey Script for DeepL API Translation

21 Mar 2024, 12:47

Welcome to this AutoHotkey forum!

Code: Select all

#Requires AutoHotkey v2.0
MsgBox translate("Hello, world!", "DE")

translate(str, lang) {
 Static url   := 'https://api-free.deepl.com/v2/translate'
      , token := 'My API token' ; Change
      , regex := '"text":"(.+?)"'
 json := '{"text":["' str '"],"target_lang":"' lang '"}'
 whr  := ComObject('Msxml2.XMLHTTP.6.0')
 whr.Open('POST', url, False)
 whr.SetRequestHeader('Content-Type', 'application/json')
 whr.SetRequestHeader('Authorization', 'DeepL-Auth-Key ' token)
 whr.Send(json)
 status := whr.status
 If RegExMatch(whr.ResponseText, regex, &m)
  Return m[1]
}
User avatar
tiska
Posts: 26
Joined: 21 Mar 2024, 10:48

Re: Need Help with AutoHotkey Script for DeepL API Translation

21 Mar 2024, 20:01

Thanks @mikeyww for getting back to me quickly and for your helpful assistance. I updated the API key and now it's working!

I'm currently attempting to make the script translate the text selected in a text box (Trados CAT Tool) and replace it with the translation. I have made some progress, but it's not quite right. I would really appreciate any assistance you can provide! :)

Code: Select all

#Requires AutoHotkey 2.0.2+
#SingleInstance
Persistent

backup := ClipboardAll
    Clipboard := ""
    Send ^c
    ClipWait 0
    if ErrorLevel
        InputBox query, Input text to translate,,, 300, 100
    else query := Clipboard
    Run % translate
    Clipboard := backup
	
F8::SendInput translate("Clipboard", "EN")

translate(str, lang) {
 Static url   := 'https://api-free.deepl.com/v2/translate'
      , token := 'xxxxx-xxxxx-xxxxx' ; Change API Key
      , regex := '"text":"(.+?)"'
 json := '{"text":["' str '"],"target_lang":"' lang '"}'
 whr  := ComObject('Msxml2.XMLHTTP.6.0')
 whr.Open('POST', url, False)
 whr.SetRequestHeader('Content-Type', 'application/json')
 whr.SetRequestHeader('Authorization', 'DeepL-Auth-Key ' token)
 whr.Send(json)
 status := whr.status
 If RegExMatch(whr.ResponseText, regex, &m)
  Return m[1]
}
User avatar
mikeyww
Posts: 26981
Joined: 09 Sep 2014, 18:38

Re: Need Help with AutoHotkey Script for DeepL API Translation

21 Mar 2024, 20:24

What does "not quite right" mean? When you run the script that you posted, what happens? Be specific. Provide details. Explain it. If an error message appears, post a screenshot.

V1 and V2 are actually different programs that use different syntax. The AHK documentation includes descriptions and examples of all functions, directives, and statements.

Code: Select all

F8:: {
 A_Clipboard := '', Send('^c')
 If ClipWait(1) {
  If '' != str := translate(A_Clipboard, 'EN')
   SendText str
 } Else MsgBox 'An error occurred while waiting for the clipboard.', 'Error', 'Icon!'
}
User avatar
tiska
Posts: 26
Joined: 21 Mar 2024, 10:48

Re: Need Help with AutoHotkey Script for DeepL API Translation

21 Mar 2024, 23:38

Sorry for being vague earlier. I'm actually a newbie at this and don't know much about coding. Basically, the script wasn't working as expected. When I ran it, nothing happened or sometimes I got error messages popping up.

But thanks a ton for your valuable help! The script is running now! :)

I'll provide more specific details next time. And yeah, I'll dive into the AHK documentation for better understanding. :thumbup:
User avatar
tiska
Posts: 26
Joined: 21 Mar 2024, 10:48

Re: Need Help with AutoHotkey Script for DeepL API Translation

24 Mar 2024, 02:03

This script now translates selected text, replaces it with the translation and also sends it to the clipboard. All good so far...
However, If the selected text contains line breaks / new lines, the script does not generate a translation.
I have been trying to solve this issue by adding the following lines, but have not had any success:

Code: Select all

F8:: {
    A_Clipboard := ''
    Send('^c')
    If ClipWait(1) {
        If '' != str := translate(A_Clipboard, 'EN') {
            ; Remove newlines and carriage returns from the translated text
            str := StrReplace(str, "`n", " ")
            str := StrReplace(str, "\n", " ")
            str := StrReplace(str, "`r", " ")
            SendText str
            A_Clipboard := str
        }
    } Else {
        MsgBox 'An error occurred while waiting for the clipboard.', 'Error', 'Icon!'
    }
    Sleep 100
}
Here is the full script:

Code: Select all

#Requires AutoHotkey 2.0.2+
#SingleInstance
Persistent

F8:: {
 A_Clipboard := '',
 Send('^c')
 If ClipWait(1) {
  If '' != str := translate(A_Clipboard, 'EN')
   SendText str
   A_Clipboard := str ;(((Copy translated text to clipboard)))
 } Else MsgBox 'An error occurred while waiting for the clipboard.', 'Error', 'Icon!'
 Sleep 100
}

translate(str, lang) {
 Static url   := 'https://api-free.deepl.com/v2/translate'
      , token := 'xxxxxxxxxxxxx' ; DeepL API Key
      , regex := '"text":"(.+?)"'
 json := '{"text":["' str '"],"target_lang":"' lang '"}'
 whr  := ComObject('Msxml2.XMLHTTP.6.0')
 whr.Open('POST', url, False)
 whr.SetRequestHeader('Content-Type', 'application/json')
 whr.SetRequestHeader('Authorization', 'DeepL-Auth-Key ' token)
 whr.Send(json)
 status := whr.status
 If RegExMatch(whr.ResponseText, regex, &m)
  Return m[1]
}

[Mod edit: Added [code][/code] tags to the first piece of code as well. Please use them for all code so indentation is preserved, in addition to the many other features of the code box that make reviewing your code much easier for potential helpers.]
User avatar
boiler
Posts: 16985
Joined: 21 Dec 2014, 02:44

Re: Need Help with AutoHotkey Script for DeepL API Translation

24 Mar 2024, 04:27

Your full script does not contain the key lines from the code you showed right before it. It contains none of the StrReplace lines, which is the main point of that code.
User avatar
tiska
Posts: 26
Joined: 21 Mar 2024, 10:48

Re: Need Help with AutoHotkey Script for DeepL API Translation

24 Mar 2024, 04:35

I added those 3 lines and tested the code but it does not work...
I also tried with these lines, but also no luck:

Code: Select all

  str := StrReplace(str, '(\\|")+', '\$1') ; Clean back spaces and quotes
  str := StrReplace(str, "`n", "\n") ; Clean newlines
  str := StrReplace(str, "`r", "") ; Remove carriage returns
User avatar
boiler
Posts: 16985
Joined: 21 Dec 2014, 02:44

Re: Need Help with AutoHotkey Script for DeepL API Translation

24 Mar 2024, 04:43

You are trying to use RegEx syntax with StrReplace, which doesn’t make sense. You would need to use RegExReplace for that. It’s not clear that what you’re trying to accomplish with that is what you would expect, btw. You should describe exactly what before and after you are expecting. You can (and should) easily check the resulting string yourself, of course.

Also, what you showed before in the full script is missing braces that were marking the inner if block in the code you were trying to copy from. Indenting doesn’t create a block of code. You should post your full script again.
User avatar
tiska
Posts: 26
Joined: 21 Mar 2024, 10:48

Re: Need Help with AutoHotkey Script for DeepL API Translation

24 Mar 2024, 05:08

Thanks for your response and thank you for your patience, I have very little experience with AHK.

I have tried to implement the changes you suggested but it still does not accept new lines etc., here is the new full script:

Code: Select all

#Requires AutoHotkey 2.0.2+
#SingleInstance
Persistent

F8:: {
 A_Clipboard := '',
 Send('^c')
 If ClipWait(1) {
  If '' != str := translate(A_Clipboard, 'EN')
  str := RegExReplace(str, '(\\|")+', '\$1') ; Clean back spaces and quotes
  str := RegExReplace(str, "`n", "\n") ; Clean newlines
  str := RegExReplace(str, "`r", "") ; Remove carriage returns
  SendText str
  A_Clipboard := str ;(((Copy translated text to clipboard)))
 } Else MsgBox 'An error occurred while waiting for the clipboard.', 'Error', 'Icon!'
 Sleep 100
}

translate(str, lang) {
 Static url   := 'https://api-free.deepl.com/v2/translate'
      , token := 'xxxxxxxxxxxxxx' ; DeepL API Key
      , regex := '"text":"(.+?)"'
 json := '{"text":["' str '"],"target_lang":"' lang '"}'
 whr  := ComObject('Msxml2.XMLHTTP.6.0')
 whr.Open('POST', url, False)
 whr.SetRequestHeader('Content-Type', 'application/json')
 whr.SetRequestHeader('Authorization', 'DeepL-Auth-Key ' token)
 whr.Send(json)
 status := whr.status
 If RegExMatch(whr.ResponseText, regex, &m)
  Return m[1]
}
User avatar
boiler
Posts: 16985
Joined: 21 Dec 2014, 02:44

Re: Need Help with AutoHotkey Script for DeepL API Translation

24 Mar 2024, 05:26

Only the first StrReplace line was attempting to use RegEx syntax, so that is the only one that should have been changed to RegExReplace. Why do you expect that ReExReplace line to do what you said in the comment (clean backspaces and quotes)? It doesn’t look like it would do anything of the sort. And as I said, you can view the new contents of str to see if those things are having the “cleaning” effect you are expecting.

You still have not included the braces in the inner if block from the code you said you were inserting. Here’s a tip: copy and paste code rather than retyping it so you don’t lose details like that.

Please address all the points the helpers make so they don’t have to repeat themselves.
User avatar
tiska
Posts: 26
Joined: 21 Mar 2024, 10:48

Re: Need Help with AutoHotkey Script for DeepL API Translation

24 Mar 2024, 05:49

Well thank you for your feedback, but now I'm even more confused about how to remove newlines etc...
User avatar
mikeyww
Posts: 26981
Joined: 09 Sep 2014, 18:38

Re: Need Help with AutoHotkey Script for DeepL API Translation

24 Mar 2024, 07:08

  1. Perhaps the script below helps.
  2. I would read from top to bottom: :arrow: If

Code: Select all

#Requires AutoHotkey v2.0
MsgBox translate("Hello, world!`n`n`r`nGoodbye.", "DE")

F8:: {
 A_Clipboard := '', Send('^c')
 If ClipWait(1) {
  If '' != str := translate(A_Clipboard, 'EN')
   SendText str
 } Else MsgBox 'An error occurred while waiting for the clipboard.', 'Error', 'Icon!'
}

translate(str, lang) {
 Static url   := 'https://api-free.deepl.com/v2/translate'
      , token := 'My API token' ; Change
      , regex := '"text":"(.+?)"'
 json := '{"text":["' Trim(RegExReplace(str, '\R', ' ')) '"],"target_lang":"' lang '"}'
 whr  := ComObject('Msxml2.XMLHTTP.6.0')
 whr.Open('POST', url, False)
 whr.SetRequestHeader('Content-Type', 'application/json')
 whr.SetRequestHeader('Authorization', 'DeepL-Auth-Key ' token)
 whr.Send(json)
 status := whr.status
 If RegExMatch(whr.ResponseText, regex, &m)
  Return m[1]
}
User avatar
tiska
Posts: 26
Joined: 21 Mar 2024, 10:48

Re: Need Help with AutoHotkey Script for DeepL API Translation

24 Mar 2024, 21:27

@mikeyww thank you so much for your help with this! :)

The V2 of the script now works with newlines and most special characters. From my testing, the characters that it does not recognise are the German «quotes» and \backslash\ mark. Do you know how I could make the script accept these, and for the German quotes, to translate them to "curly quotes"?

Here is the V2:

Code: Select all

#Requires AutoHotkey 2.0.2+
#SingleInstance
Persistent

/*
====================================================
V2 CHANGES:
- Modified json := '{"text":["' Trim(RegExReplace(str, '\R', ' ')) '"],"target_lang":"' lang '"}'
  RegExReplace(str, '\R', ' '): Replaces all newline characters (\R) in the input text (str) with a space.
  Trim(...): Trims any leading or trailing spaces from the modified text obtained from the previous step.
- Added comments
- Added hotkeys to edit and reload script
====================================================
*/

/*
====================================================
Define hotkeys and trigger translation
====================================================
*/

^e:: Edit ; Ctr+E will edit this script

^r:: Reload ; Ctr+R will reload this script

F8:: {
 A_Clipboard := '', Send('^c')
 If ClipWait(1) {
  If '' != str := translate(A_Clipboard, 'EN')
  SendText str ; Replace the original text with the translated version
  MsgBox str ; Display a message box with the translated text
  A_Clipboard := str ; Copy translated text to clipboard
 } Else MsgBox 'An error occurred while waiting for the clipboard.', 'Error', 'Icon!'
 Sleep 100
}

/*
====================================================
Connect to DeepL API and process request
====================================================
*/

translate(str, lang) {
 Static url   := 'https://api-free.deepl.com/v2/translate' ; DeepL API endpoint
 Static token := 'xxxxxxxxxxxxxxxxxxx' ; DeepL API Key
 Static regex := '"text":"(.+?)"' ; Regular expression to extract translated text
 ; RegExReplace(str, '\R', ' '): Replaces all newline characters (\R) in the input text (str) with a space.
 ; Trim(...): Trims any leading or trailing spaces from the modified text obtained from the previous step.
 json := '{"text":["' Trim(RegExReplace(str, '\R', ' ')) '"],"target_lang":"' lang '"}'
 whr  := ComObject('Msxml2.XMLHTTP.6.0') ; Create an XMLHTTP object
 whr.Open('POST', url, False) ; Set up a POST request to the DeepL API
 whr.SetRequestHeader('Content-Type', 'application/json') ; Specify JSON content type
 whr.SetRequestHeader('Authorization', 'DeepL-Auth-Key ' token) ; Include API key in the request
 whr.Send(json) ; Send the JSON payload
 status := whr.status ; Get the HTTP status code
 If RegExMatch(whr.ResponseText, regex, &m) ; Extract translated text from the API response
  Return m[1]
}
User avatar
mikeyww
Posts: 26981
Joined: 09 Sep 2014, 18:38

Re: Need Help with AutoHotkey Script for DeepL API Translation

24 Mar 2024, 21:55

Below is an example of how you can substitute unrecognized characters if needed.

Code: Select all

; Save script as UTF-8 with BOM signature
#Requires AutoHotkey v2.0

F8:: {
 A_Clipboard := '', Send('^c')
 If ClipWait(1) {
  If '' != str := translate(A_Clipboard, 'EN')
   SendText str
 } Else MsgBox 'An error occurred while waiting for the clipboard.', 'Error', 'Icon!'
}

translate(str, lang) {
 Static url   := 'https://api-free.deepl.com/v2/translate'
      , token := 'My API token' ; Change
      , regex := '"text":"(.+?)"'
 json := '{"text":["' fix(str) '"],"target_lang":"' lang '"}'
 whr  := ComObject('Msxml2.XMLHTTP.6.0')
 whr.Open('POST', url, False)
 whr.SetRequestHeader('Content-Type', 'application/json')
 whr.SetRequestHeader('Authorization', 'DeepL-Auth-Key ' token)
 whr.Send(json)
 status := whr.status
 If RegExMatch(whr.ResponseText, regex, &m)
  Return StrReplace(m[1], ';;;', '"')
}

fix(str) {
 str := RegExReplace(str, '[«»]', ';;;')
 Return Trim(RegExReplace(str, '\R', ' '))
}
User avatar
tiska
Posts: 26
Joined: 21 Mar 2024, 10:48

Re: Need Help with AutoHotkey Script for DeepL API Translation

25 Mar 2024, 04:26

I have applied the changes, and now German quotes «» are correctly translated into English straight quotes ", but only sometimes and seemingly at random. I have noticed that short German phrases or sentences containing German quotes are translated correctly. However, longer texts or paragraphs occasionally omit one or more quotation marks, or they are replaced by a semi-colon or backslash instead. :think:

Moreover, if a text contains backslashes, it returns nothing at all.

While reading the DeepL documentation (https://developers.deepl.com/docs/api-reference/translate), I came across information regarding In-Text Markup:
One should be cautious with uncommon characters embedded in texts. Uncommon character sequences, which may serve as markers within your system, might be translated or removed, leading to a corrupted structure. In such cases, it is recommended to either split the text to avoid sending markers, or to convert the markers to XML tags and enable XML handling or HTML handling.

I believe this script has a lot of potential if it can handle special characters and translate larger texts and multiple sentences. There is a wealth of information on their website (https://developers.deepl.com/docs/api-reference/translate), but unfortunately, as a novice AHK coder, I find it very challenging to integrate these useful functions (e.g. glossaries). Your help is greatly appreciated, and I am sincerely grateful for your valuable support.
User avatar
mikeyww
Posts: 26981
Joined: 09 Sep 2014, 18:38

Re: Need Help with AutoHotkey Script for DeepL API Translation

25 Mar 2024, 07:10

This revision uses XML to ignore the special characters. It looks like the translator might add a space after the backslash. There is probably a way to use StrSplit to fix that if needed.

Code: Select all

; This script translates text.
; Save script as UTF-8 with BOM signature.
; https://www.autohotkey.com/boards/viewtopic.php?f=82&t=127623&p=564800#p564800
; https://developers.deepl.com/docs
#Requires AutoHotkey v2.0
token := token ?? 'My API token'

F8:: {
 A_Clipboard := '', Send('^c')
 If ClipWait(1) {
  If '' != str := translate(A_Clipboard, 'EN')
   SendText str
 } Else MsgBox 'An error occurred while waiting for the clipboard.', 'Error', 'Icon!'
}

translate(str, lang) {
 Static url    := 'https://api-free.deepl.com/v2/translate'
      , regex  := '"text":"(.+?)"'
      , ignore := '«»\'                                                   ; Special characters to be ignored
 Loop Parse ignore
  str := StrReplace(str, A_LoopField, '<ignore>' A_LoopField '</ignore>') ; Add XML tags for special chars
 str  := Trim(RegExReplace(str, '\R', ' '))                               ; Change line breaks to spaces
 str  := StrReplace(str, '\', '\\')                                       ; Fix backslash for XML
 ; MsgBox str, 'Input'
 json := '{"text":["' str '"],"target_lang":"' lang '", "tag_handling": "xml", "ignore_tags": ["ignore"]}'
 whr  := ComObject('Msxml2.XMLHTTP.6.0')
 whr.Open('POST', url, False)
 whr.SetRequestHeader('Content-Type', 'application/json')
 whr.SetRequestHeader('Authorization', 'DeepL-Auth-Key ' token)
 whr.Send(json)
 status := whr.status
 ; MsgBox whr.ResponseText, 'Output'
 If RegExMatch(whr.ResponseText, regex, &m) {
  str := RegExReplace(m[1], '<ignore>(.+?)</ignore>', '$1')               ; Strip XML tags for special chars
  Return StrReplace(str, '\\', '\')                                       ; Restore backslashes
 }
}
User avatar
tiska
Posts: 26
Joined: 21 Mar 2024, 10:48

Re: Need Help with AutoHotkey Script for DeepL API Translation

25 Mar 2024, 09:33

Wow, this works really well!! Now the backslashes get handled correctly and no quotation marks are omitted, the only thing is the English translation again has German quotes «» now, but at least it is consistent – even with larger paragraphs. It also seems to be processing the translation a lot faster :) I will dm you my API key so you can test it if you like. Thanks again for all your input!
User avatar
mikeyww
Posts: 26981
Joined: 09 Sep 2014, 18:38

Re: Need Help with AutoHotkey Script for DeepL API Translation

25 Mar 2024, 09:41

I tested the script. Only the selected text would be affected. Enjoy!
User avatar
tiska
Posts: 26
Joined: 21 Mar 2024, 10:48

Re: Need Help with AutoHotkey Script for DeepL API Translation

27 Mar 2024, 04:27

Do you know what might be causing the following error?

AHK Error: (0x80072EE7)
The server name or address could not be resolved
Source: WinHttp.WinHttpRequest Specifically: WaitForResponse
HTTP_Request.WaitForResponse()

I get this error from time to time.

Return to “Ask for Help (v2)”

Who is online

Users browsing this forum: Bing [Bot], CraigM and 52 guests