Is there a way to modify the script below (which toggles the spellchecker between English and French in System Settings) so that the GUI is not displayed?
on open_settings_to(settings_pane)
if settings_pane = "Wi-Fi" then
set settings_pane to "Wi‑Fi"
end if
tell application "System Settings"
activate
end tell
tell application "System Events"
tell application process "System Settings"
repeat until window 1 exists
delay 0
end repeat
tell splitter group 1 of group 1 of window 1
tell outline 1 of scroll area 1 of group 1
set row_names to value of static text of UI element 1 of every row
repeat with i from 1 to (count row_names)
if settings_pane is not "Apple ID" then
if item i of row_names = {settings_pane} then
log item i of row_names & I
select row I
exit repeat
end if
else
try
if item 1 of item i of row_names contains settings_pane then
select row I
exit repeat
end if
end try
end if
end repeat
end tell
end tell
end tell
end tell
end open_settings_to
on change_language()
tell application "System Events"
tell application process "System Settings"
tell group 2 of splitter group 1 of group 1 of window 1
repeat until group 3 of scroll area 1 of group 1 exists
delay 0
end repeat
tell group 3 of scroll area 1 of group 1
click button 1
end tell
end tell
repeat until group 2 of splitter group 1 of group 1 of sheet 1 of window 1 exists
delay 0
end repeat
tell group 2 of splitter group 1 of group 1 of sheet 1 of window 1
repeat until group 3 of scroll area 1 exists
delay 0
end repeat
tell group 3 of scroll area 1
click pop up button 1
tell menu 1 of pop up button 1
if selected of menu item "U.S. English" is true then
click menu item "Français"
do shell script "osascript -e 'display notification \"Spelling language set to French\" with title \"Keyboard Settings\"'"
else
click menu item "U.S. English"
do shell script "osascript -e 'display notification \"Spelling language set to English\" with title \"Keyboard Settings\"'"
end if
end tell
end tell
click button 1
end tell
delay 0.1
tell application "System Settings"
quit
end tell
end tell
end tell
end change_language
on run {}
open_settings_to("Keyboard")
change_language()
end run
--Running under AppleScript 2.8, MacOS 13.0.1
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
tell application "System Settings"
activate
end tell
tell application "System Events"
set visible of application process "System Settings" to false
tell application process "System Settings"
--your commands
end tell
end tell
Thank you for the help. Sorry, I’m a layman have next to no idea what I’m doing. I inserted my script under the “your commands” line but am getting a syntax error
Expected “end” or “end tell” but found “on”.
as my script starts with
on open_settings_to(settings_pane)
if settings_pane = "Wi-Fi" then
set settings_pane to "Wi‑Fi"
end if
The whole script is in my original post above. It accesses the keyboard tab in System Settings and set the spelling language to French if it is set to English and vice versa. It works totally fine but displays the GUI.
--------------------------------------------------------
--» MAIN
--------------------------------------------------------
# I never use a run handler, unless I have a need for one.
# For instance – if I also have a n open() handler.
on run {}
open_settings_to("Keyboard")
change_language()
end run
--------------------------------------------------------
--» HANDLERS
--------------------------------------------------------
on change_language()
tell application "System Events"
tell application process "System Settings"
tell group 2 of splitter group 1 of group 1 of window 1
repeat until group 3 of scroll area 1 of group 1 exists
delay 0
end repeat
tell group 3 of scroll area 1 of group 1
click button 1
end tell
end tell
repeat until group 2 of splitter group 1 of group 1 of sheet 1 of window 1 exists
delay 0
end repeat
tell group 2 of splitter group 1 of group 1 of sheet 1 of window 1
repeat until group 3 of scroll area 1 exists
delay 0
end repeat
tell group 3 of scroll area 1
click pop up button 1
tell menu 1 of pop up button 1
if selected of menu item "U.S. English" is true then
click menu item "Français"
do shell script "osascript -e 'display notification \"Spelling language set to French\" with title \"Keyboard Settings\"'"
else
click menu item "U.S. English"
do shell script "osascript -e 'display notification \"Spelling language set to English\" with title \"Keyboard Settings\"'"
end if
end tell
end tell
click button 1
end tell
delay 0.1
tell application "System Settings"
quit
end tell
end tell
end tell
end change_language
--------------------------------------------------------
on open_settings_to(settings_pane)
if settings_pane = "Wi-Fi" then
set settings_pane to "Wi‑Fi"
end if
tell application "System Settings"
if not running then --» •• ccstone ••
run
delay 1
end if
end tell
tell application "System Events"
tell application process "System Settings"
repeat until window 1 exists
delay 0
end repeat
tell splitter group 1 of group 1 of window 1
tell outline 1 of scroll area 1 of group 1
set row_names to value of static text of UI element 1 of every row
repeat with i from 1 to (count row_names)
if settings_pane is not "Apple ID" then
if item i of row_names = {settings_pane} then
log item i of row_names & i
select row i
exit repeat
end if
else
try
if item 1 of item i of row_names contains settings_pane then
select row i
exit repeat
end if
end try
end if
end repeat
end tell
end tell
end tell
end tell
end open_settings_to
--------------------------------------------------------
Look for: --» •• ccstone •• to see where I placed the run code.
As I understand it, the question is posed incorrectly. Because GUI scripting (clicks) can’t work with a hidden GUI. Deciphering: GUI scripting means Scripting the Graphical User Interface (that is, the window on the front) .
That is, the question should be put like this: I need a solution that performs the same task, but without GUI scripting (click / click, etc.)
Thanks for the help. Again, I’m a layman so coding terminology is going right over my head for the most part. The script was written by someone on reddit. If I’m following you correctly, it was not well written and you improved upon it, is that correct?
Ah, that makes sense. Not as simple as I thought. I guess the new question indeed is: is there a way to achieve the same results other than with UI scripting?
Here is the problem I’m running into:
I do have a shell script that toggles the spellchecker language.
# Check the current language setting
currentLang=$(defaults read -g NSPreferredSpellServerLanguage)
# Toggle between English and French
if [ "$currentLang" == "en" ]; then
defaults write -g NSPreferredSpellServerLanguage fr
echo "Spelling language set to French"
osascript -e 'display notification "Spelling language set to French" with title "Keyboard Settings"'
else
defaults write -g NSPreferredSpellServerLanguage en
echo "Spelling language set to English"
osascript -e 'display notification "Spelling language set to English" with title "Keyboard Settings"'
fi
Unfortunately, that script requires apps already running to be restarted for the change to take effect. Problem is, I often only remember to change the spellchecker’s language until after I’ve started working on a new document.
Changing the spellchecker’s language in System Settings (either manually or through UI scripting) solves that problem, but I’d like to find a scripting solution that doesn’t require the UI to be displayed. I’m not even sure that is possible.
I tried your script, but unless I’m doing something wrong (very possible), nothing happens. I Shortcuts is showing it’s initiated it as an AppleScript in the Shortcuts app. The scripts starts but no command is executed. It doesn’t stop either. I copied it as is.
Looking again at the original script in your request, I see that you need code to switch between 2 keyboard sources - English and French.
First set manually Spelling: Automatic By Language in your keyboard settings.
With this setup, the task of switching Spelling Language is reduced to the less complex task of switching Keyboard Language. Then, the following simple solution is enough for you. It switches the two recent used languages in the keyboard. (Of course, you can quickly switch the keyboard language manually in the extra menu without using a script at all.)
If the list of sources for your keyboard is limited to only these two sources, then this is an even more compelling reason for using this simple solution.
.
tell application "System Events" to key code 49 using control down
.
NOTES:
Another, more complex solution is to use the Carbon framework and build a command line tool. In addition, you will need to install Xcode Command Line Tools.
You can download and install read-made third-party input selector tool.
Thank you for your input. I knew of the control + space bar shortcut to change the keyboard input source. The issue here is that I am looking to change the spellchecker’s language without modifying the keyboard layout.
Accented characters are easily accessible via long presses, and my muscle memory so used to the US QWERTY keyboard, changing the layout just results in a big loss of productivity. You have to remember what the differences are or open they keybiarc visualizer, which is very suboptimal. I’m not quite sure why users who primarily use a specific keyboard layout would want that. It’s a different story on devices like the iPad where the actual keyboard changes.
At any rate, that’s the problem I’m facing. Apple makes it easy to toggle the input source and keyboard layout, but offers no practical solution for just changing the spellchecker. The spelling language can be toggled via shell scripting, but the change doesn’t take effect in apps already running, which is not practical as I often have to switch languages after having started to work on a document. The spelling language can also be toggled via AppleScript and UI scripting, but it it is rather slow to execute and displays the GUI/clicks. I’d like a solution that executes faster and in the background like the shell script does (but that makes the change take effect in apps already running). That’s the problem I’m running into, and I’m not even sure there’s a solution for it.
I thought of a solution where I could use the existing shell script but add to it so that any app that uses spellchecking that is already running saves the currently opened document, quits, restarts and reopens the document just saved, but on top of being a pretty inelegant solution, it also seems like a complicated one to implement (plus I have next to zero coding knowledge).