Help with a multiple text replacement script

Even though this forum so far has been for sharing scripts and not for writing them, I was wondering if I could pick the brains of AHK experts ( and  come to mind right now), to figure something out.

I'm trying to put together a script to do multiple text replacements at a segment level, i.e., for the active segment only, so I can easily see what has been changed, without calling up the Find & Replace window.

I've managed to put together this script (silly examples included):

#r::
ClipSaved := ClipboardAll
Clipboard =
SendInput, ^a^c
ClipWait, 30
FixString := Clipboard
vList := " ;continuation section
(
dog perro

house casa
¿ ¿
/ /
, ,
? ?
. .
pie 2 pie2
m 2 m2
)"
Loop, Parse, vList, `n
{
oTemp := StrSplit(A_LoopField, "`t")
FixString := StrReplace(FixString, oTemp.1, oTemp.2)
}
oTemp := ""
Clipboard := FixString ; load the new string to clipboard
Sleep 200
Send ^v
Return

This works fine in segments with no tags, but when there are tags, they get stripped at some point during the replacement operation and the text that is pasted back into the segment has all the necessary replacements but no tags. Is there any way of preserving the tags in the clipboard?

I came up with a very clumsy workaround for this, which involves using Studio's Delete to Next Tag shortcut, so instead of Select All-Copy, the script would do Delete to Next Tag-Undo-Copy:

#r::
ClipSaved := ClipboardAll
Clipboard =
;SendInput, ^a^c
;ClipWait, 30
Send ^+D ;delete to next tag
Sleep 100
Send ^z ;undo
Sleep 50
Send ^c
ClipWait, 30
FixString := Clipboard
vList := " ;continuation section
(
organisation organization
¿ ¿
/ /
, ,
? ?
. .
pie 2 pie2
m 2 m2
)"
Loop, Parse, vList, `n
{
oTemp := StrSplit(A_LoopField, "`t")
FixString := StrReplace(FixString, oTemp.1, oTemp.2)
}
oTemp := ""
Clipboard := FixString ; load the new string to clipboard
Sleep 200
Send ^v
Return

While this also works in segments with no tags, I would like to optimize it.

My second question is: how would I go about creating a list of all these replacements (CSV? Excel?) and getting the script to take them from there instead of having to add them manually to the script? I've been reading up on arrays but I'm still far away from being able to implement what I need.

I have another simpler script attempt with just multiple StringReplace lines (see below), but again, that would require creating possibly hundreds of replacement lines and I imagine it's not the best solution.

#p:: 
Send, ^a
Send, ^c
StringReplace, clipboard, clipboard, dog, perro, All
StringReplace, clipboard, clipboard, cat, gato, All
StringReplace, clipboard, clipboard, raining, lloviendo, All
Send ^v
Return

So, any help with this would be greatly appreciated.

Thank you!

  • [update]

    It has a small issue when I try

    north america     NA

    United States     US

    U.S.                   US

    The outcome are Na and Us. How can we make it all capital letters for those terms?

    and can I replace - (hyphen or dash) into , (comma)?

    Thank you!

    --------------------

    Dear Rafa Gómez,

    This script really works like a charm.

    Thank you so much (from me and six of my team members).

    I know that it pretty too much of asking but can you do one final favor please? This I just think of a moment ago so I couldn't put it into the previous post (my apologies for that)

    This time, I would like to keep the work smoothly and continuously by adding this line, so I don't need to change windows to paste then press #p and again and again with that loop.

    Send, {CTRLDOWN}c{CTRLUP}{ALTDOWN}{TAB}{ALTUP}{CTRLDOWN}v{CTRLUP}{ENTER}

    I tried to put it in your script but couldn't get it to work.

    Please show me how to do it.

    Many thanks to you!!!

  • Thanks a lot Rafa Gómez!! I'm in love with your kindness in helping me this much!

    I just want to let you know that before asking you here, I had tried to search and to test by any means that I could, and I'm glad that I'm getting better with understanding these lines, yet still not enough.

    For WindowSpy I already searched for it and tested it successfully however only with different programs (one program and another).
    My main tool for working are: 2 monitors, one Chrome on the left and one on the right, I copy data from right one then paste to the left one.
    So the problem is they are the same program: Chome (ahk_class Chrome_WidgetWin_1). I can't figure out how to use WinActive in this case. I searched on internet and found this script:


    CoordMode, Pixel, Screen

    !1::
    ChromeList := GetWinListByClass("Chrome_WidgetWin_1")

    LeftmostPos := 9999
    LeftmostId := ""
    Loop, % ChromeList.MaxIndex()
    {
    currentId := ChromeList[A_Index][1]
    currentX := ChromeList[A_Index][2]

    if (currentX < LeftmostPos)
    {
    LeftmostPos := currentX
    LeftmostId := currentId
    }
    }

    WinActivate, % "ahk_id" LeftmostId
    Return

    !2::
    ChromeList := GetWinListByClass("Chrome_WidgetWin_1")

    RightmostPos := -9999
    RightmostId := ""
    Loop, % ChromeList.MaxIndex()
    {
    currentId := ChromeList[A_Index][1]
    currentX := ChromeList[A_Index][2]

    if (currentX > RightmostPos)
    {
    RightmostPos := currentX
    RightmostId := currentId
    }
    }

    WinActivate, % "ahk_id" RightmostId
    Return


    GetWinListByClass(filterClass)
    {
    WinGet, all, list
    ChromeList := {}
    winCount := 1
    Loop, %all%
    {
    WinGetClass, WClass, % "ahk_id " all%A_Index%
    if (WClass = filterClass)
    {
    winId := all%A_Index%
    WinGetPos, X, Y, W, H, % "ahk_id " winId
    ChromeList[winCount] := [winId, X]
    winCount++
    }
    }
    return ChromeList
    }

    but when I add more lines for sending texts (combine with this), this script doesn't work very well.
    What is your method to switch windows of the same program please?

    Many thanks!
  • Former Member
    0 Former Member in reply to Bruce Campbell
    Unfortunately strings in the Windows registry are ASCII only

    I am not sure about this. The registry has a number of value types to store data in various formats. You can certainly add strings (type REG_SZ) in Unicode, thus UTF-8 (and ANSI, which holds more characters than ASCII). docs.microsoft.com/.../registry-value-types 

  • Dear Raphaël Toussaint, dear Nora Díaz,

    thanks a lot for your script. I have the same problem as Nora and wanted to use such a script while maintaining an external file where the terms to be replaced are.

    However, I am doing something wrong and it doesn't work. My script is the following:

    ___________________________

    #r::
    ClipSaved := ClipboardAll
    Clipboard =

    FileRead, vList, vListFile.txt

    Send, ^a
    Send, ^c
    Loop, Parse, vList, `r, `n
    {
        oTemp := StrSplit(A_LoopField, "`t")
        FixString := StrReplace(FixString, oTemp.1, oTemp.2)
    }
    SendInput, %FixString%

    ;Sleep 200
    ;Send ^v
    Return

    __________________________

    The file vListFile.txt is in the same folder and reads:

    dog    perro
    house    casa

    (There is a tab after dog and after house.)

    __________________________

    • I have an example file open which reads:

    This is a dog and that is a house.

    • I press Windows + R.

    The text is only shortly highlighted and unhighlighted, but «dog» isn't changed to «perro» and «house» not to «casa».

    What am I doing wrong in the script?

    Please help!

    Best regards

    Robert

    emoji
  • Dear Jesús,

    thanks a lot for your answer! That line made my script work.

    I made the script more complete so that it directly copies source to target and applies the word replacement list before sending the content to a machine translation:

    ^#ü::
    ClipSaved := ClipboardAll
    Clipboard =

    FileRead, vList, vListFile.txt
    Send, ^{Ins}
    Send, ^a
    Send, ^c
    FixString := Clipboard
    Loop, Parse, vList, `r, `n
    {
        oTemp := StrSplit(A_LoopField, "`t")
        FixString := StrReplace(FixString, oTemp.1, oTemp.2)
    }
    SendInput, %FixString%

    Sleep 200
    Send, {ctrl down}ä{ctrl up}

    ; This "Ctrl + ä" is for the actual machine translation in an external program like e.g. «KeyCtrl».
    Return

    ----

    However, the script is rather slow when filling in word by word and replacing the words from the replacement list. Then it stops and doesn't complete the additional steps. Any idea to make the replacement process quicker?

    I appreciate any help!

    Cheers

    Rob

    emoji
  •  

    Just for fun I put your exact post into ChatGPT.  I have no idea if the response is correct and have not attempted to test it... but I am curious.  Maybe it'll work, but if not perhaps there will be something in the answer that could be helpful for you:

    ^#ü::
    ClipSaved := ClipboardAll
    Clipboard =
    
    FileRead, vList, vListFile.txt
    Send, ^{Ins}
    Send, ^a
    Send, ^c
    ClipWait, 2 ; Wait for clipboard to be populated
    if ErrorLevel {
        MsgBox, 48, Error, Clipboard was not populated within 2 seconds.
        return
    }
    
    FixString := Clipboard
    
    ; Build a dictionary for faster lookup
    ReplacementDict := {}
    Loop, Parse, vList, `r, `n
    {
        oTemp := StrSplit(A_LoopField, "`t")
        ReplacementDict[oTemp.1] := oTemp.2
    }
    
    ; Replace words using the dictionary
    FixString := RegExReplace(FixString, "\b\w+\b", Func("ReplaceWords"))
    
    SendInput, %FixString%
    
    Sleep 200
    Send, {ctrl down}ä{ctrl up}
    Return
    
    ReplaceWords(m) {
        global ReplacementDict
        word := m.Value
        if (ReplacementDict.HasKey(word)) {
            return ReplacementDict[word]
        }
        return word
    }
    

    Here are the main optimizations used in this script:

    1. Use ClipWait to ensure the clipboard is populated before proceeding with the script.
    2. Build a dictionary (associative array) with the replacement list for faster word lookups.
    3. Use RegExReplace with a function object to handle word replacements more efficiently.

    These optimizations should make the replacement process quicker and allow the script to complete the additional steps.

    Paul Filkin | RWS Group

    ________________________
    Design your own training!

    You've done the courses and still need to go a little further, or still not clear? 
    Tell us what you need in our Community Solutions Hub

    emoji
  • Hi Paul,

    thanks for your efforts. I really appreciate it.

    However, now I get results like:

    "               ,       ." or "    ,       ." or "        ." (only spaces + comma and period).

    I also tried the script when putting

    Sleep 200
    Send, {ctrl down}ä{ctrl up}
    Return

    at the end because this "Ctrl+ä" is the actual machine translation and should be after the word replacement function, I think. But I get the same wrong results...

    Maybe, Jesús Prieto, you can help here?

    Kind regards

    Rob

    emoji
  • Hi ,

    However, now I get results like

    As Paul said, it’s just ChatGPT code and you still need to confirm it’s good or not and take the bits you find useful.

    However, the script is rather slow when filling in word by word and replacing the words from the replacement list.
    How big is your your list of replacements? With a list of 6 replacements, the full loop runs around 50,000 times per second. So unless your list is really huge, this shouldn't be an issue.
    I believe the bottlenecks are the steps of inserting Source in Target, selecting the Target segment, copying Target to the clipboard and sending the replaced text to the Target segment.
    Then it stops and doesn't complete the additional steps.
    So I understand this line doesn't work, right?
    Send, {ctrl down}ä{ctrl up}
    Which external program is it?
    Does it work if you press CTRL+Ä keys in Trados Studio? 
    Do you need to have the text selected in Target before pressing CTRL+Ä? If you do, you'll need to add some lines to your AutoHotkey script,
    Does the external program automatically pastes the MT text in Target after pressing CTRL+Ä? If it doesn't, you'll need to add some lines to the AutoHotkey script,
    Is the Ä key available on your keyboard or you need to press a dead key?
    BTW; I don't quite understand why you run Machine Translation on an already replaced text…
    emoji