0

How can I select a specific (English in my case) language in the upper right menu on a Mac using an apple script. My code is really slow. It take about 5 sec for it. Do you have fast and smart ideas?)

tell application "System Events" to ¬
    tell application process "TextInputMenuAgent" to ¬
        tell menu bar item 1 of menu bar 2
            click
            click menu item 1 of menu 1
        end tell
MrBot
  • 11
  • 1
  • Have a look at my answer https://apple.stackexchange.com/questions/423354/applescript-cant-get-rid-of-delay-after-click/423440#423440 as you may be able to incorporate something in it to work around your issue. – user3439894 Aug 10 '21 at 17:14

3 Answers3

0

You might be able to use the standard keyboard shortcut used for selecting keyboard layouts.

The defaults are Ctrl-Space (previous layout) and Alt-Ctrl-Space (next layout), although it wraps around, so if you have only two languages, either will simply toggle the layout.

This can be scripted thusly:

tell application "System Events"
    key code 49 using control down
end tell

Please be aware that this shortcut may be disabled (or changed) by a given user in the System Preferences->Keyboard->Shortcuts->Input Source although If you are the only user, this wont be a problem.

Some more ideas may be found at Change OSX keyboard layout("input source") programmatically via terminal or AppleScript?

brennanyoung
  • 6,243
  • 3
  • 26
  • 44
  • 1
    Thank you, but I need to choose a specific language, regardless of which one is currently selected. So the Ctrl-Space solution doesn't work for me. Not the best solution in my code too. I now have two languages installed: eng / rus. The code just picks the first one (English which I need). Of course, ideally it would be to choose not just the first, but specifically English. + my code is very slow, apparently this part of the "TextInputMenuAgent" code is slow on its own. Therefore, I am looking for a more elegant solution. But thanks for taking the time to answer my question. – MrBot Aug 10 '21 at 12:35
0

The example AppleScript code, shown below, was tested in Script Editor and as an Automator Service/Quick Action under macOS Catalina and macOS Big Sur with Language & Region settings in System Preferences set to English (US) — Primary and worked for me without issue1.

  • 1 Assumes necessary and appropriate settings in System Preferences > Security & Privacy > Privacy have been set/addressed as needed.

Example AppleScript code:

ignoring application responses
    tell application "System Events" to ¬
        click menu bar item 1 of ¬
            menu bar 2 of ¬
            application process "TextInputMenuAgent"
end ignoring

delay 0.1
do shell script "killall 'System Events'"
delay 0.2

tell application "System Events"
    launch
    click menu item 1 of ¬
        menu 1 of ¬
        menu bar item 1 of ¬
        menu bar 2 of ¬
        application process "TextInputMenuAgent"
end tell

Notes:

In the second tell application "System Events" block:

Change:

click menu item 1 of ¬

To:

The actual name of the menu item, e.g click menu item "U.S." of ¬ or whatever the actual name is.

You can also change the number e.g. 1 to whatever number is appropriate.

As tested, this works for me without issue and, sans the built-in three tenths of a second combined delay, was instantaneous.

If the example AppleScript code shown above does not work for you, then use the Using: cliclick method shown in my answer AppleScript - Can't get rid of delay after click

Or for a more robust solution also using cliclick, a third-party command line utility, the following example AppleScript code can be used for more than the immediate menu item you are trying to click.

Example AppleScript code:

--  # This script works on menu bar items in menu bar 2. 
--  # Set the name of the application process and the
--  # name of the target menu item. It will use cliclick
--  # a third-party command line utility to perform the
--  # clicks as a workaround to the 5 second delay bug.
--  # 
--  # Note that this requires the target menu item to have
--  # a name that System Events can retrieve properties for.
--  # It is from these properties it position and size is
--  # ascertained in order to calculate where to click it.


--  # User set properties.

property appProcessName : "TextInputMenuAgent"
property menuItemName : "U.S."
property cliclick : "/usr/local/bin/cliclick"

--  # The code below is tokenized and 
--  # should not need to modified.

property xPos : missing value
property yPos : missing value

tell application "System Events" to ¬
    set thePositionSizeList to ¬
        the {position, size} of ¬
            menu bar item 1 of ¬
            menu bar 2 of ¬
            application process ¬
                appProcessName

my setXposYposFrom(thePositionSizeList)
my clickAtXposYpos()

tell application "System Events"
    set theTargetMenuItemProperties to ¬
        properties of ¬
        first menu item of ¬
        menu 1 of ¬
        menu bar item 1 of ¬
        menu bar 2 of ¬
        application process ¬
            appProcessName whose ¬
        name is menuItemName
    set thePositionSizeList to ¬
        the {position, size} of ¬
            theTargetMenuItemProperties
end tell

my setXposYposFrom(thePositionSizeList)
my clickAtXposYpos()


--  ## Handlers ##

to setXposYposFrom(thisList)
    set xPos to ¬
        (item 1 of item 1 of thisList) + ¬
        (item 1 of item 2 of thisList) / 2 ¬
        as integer
    set yPos to ¬
        (item 2 of item 1 of thisList) + ¬
        (item 2 of item 2 of thisList) / 2 ¬
        as integer
end setXposYposFrom

to clickAtXposYpos()
    set shellCMD to {¬
        cliclick, " -r c:", ¬
        xPos, ",", yPos} as string
    do shell script shellCMD
end clickAtXposYpos


Note: The example AppleScript code is just that and sans any included error handling does not contain any additional error handling as may be appropriate. The onus is upon the user to add any error handling as may be appropriate, needed or wanted. Have a look at the try statement and error statement in the AppleScript Language Guide. See also, Working with Errors. Additionally, the use of the delay command may be necessary between events where appropriate, e.g. delay 0.5, with the value of the delay set appropriately.

user3439894
  • 7,266
  • 3
  • 17
  • 28
  • Automator hangs when executing this code on Big Sur. And this code also uses application process command "TextInputMenuAgent", I assume the code will also be executed for a long time about 5-6 seconds. But thanks for the tip: click menu item "U.S." of I tried to add this part to my code and add a second writing of English language name in Russian. Like this: click menu item ("U.S." or "США") of but it didn't work. – MrBot Aug 11 '21 at 07:39
  • @MrBot, I've tested in both **Script Editor** and **Automator**, in **macOS Catalina** and **macOS Big Sur**, and have no problem using the _example_ **AppleScript** _code_ in my answer. I also have no problem with the **Using: cliclick** _method_ in the linked answer to another question experiencing the 5 second delay. If the _example_ **AppleScript** _code_ herein is not working for you then use the **Using: cliclick** _method_ in my other answer. See the updated answer, in particular the... If the _example_ **AppleScript** _code_ shown above does not work for you, ... section. – user3439894 Aug 12 '21 at 21:51
-1

You don't say what OS version you're on but this works on Sierra; no idea whether it works on other versions. Per comments, apparently this should work up to Movaje, but not in Catalina or newer.

You may have to tweak this for your own setup as the status menu items will likely be in a different order than mine. Try setting it to item 1 first and then work your way up to the correct menu.

Of course, it assumes that you have enabled 'Show input menu in menu bar' in System Preferences > Keyboard > Input Sources. The delays are required for it to work but you could probably reduce their duration.

What this does is click the relevant menu and then type the first letters of the desired input. You may have to fiddle around with this depending upon what other items there are in your menu. It can work with a single letter but using a longer string, for example 'eng', helps avoid confusion. It then types the 'return' key to set your choice. Using letters to select allows you to work around whatever order or current setting is.

tell application "System Events"
    tell application process "SystemUIServer"
        
        click menu bar item 6 of menu bar 1
        delay 0.3
        keystroke "e"
        delay 0.3
        keystroke return
        
    end tell
end tell
Mockman
  • 966
  • 2
  • 6
  • 11
  • While the OP didn't state what version of **macOS**, nonetheless, it is as least **macOS Catalina**, as that is when **Apple** started using **TextInputMenuAgent** as shown in the _code_ in the OP. Also, the 5 second delay mentioned in the OP is a well known issue and my answer is one of the workarounds for it. One can also use a _third-party utility_ as described in the linked answer in my **Notes:** _section_. – user3439894 Aug 10 '21 at 20:28
  • Thank you for your answer. I'm sorry I didn't specify - OS Big Sur. This is the error: Syntax Error. System Events got an error: Can't get menu bar 1 of application process "SystemUIServer". Invalid index. – MrBot Aug 11 '21 at 07:46