Execute script only once to prevent endless loop

The script below quits specified applications if they are running, changes the system spelling language to French, and restarts the app (so that the app registers the change in the spellcheck language setting).

I am triggering the script via a third party app (Shortery) that initiates the script whenever any of the apps is launched. The problem is it creates an endless loop of the app quitting and relaunching.

How do I modify the script so that it stops running once it is executed once?

on isAppRunning(appName)
	tell application "System Events"
		set appProcesses to name of every process
		if appName is in appProcesses then
			return true
		else
			return false
		end if
	end tell
end isAppRunning

-- List of apps to check and restart
set appList to {"Microsoft Word", "Pages", "TextEdit"}

-- Iterate through the app list
repeat with appName in appList
	if isAppRunning(appName) then
		-- Quit the app
		tell application appName to quit
		delay 1
		
		-- Check the current language setting
		set currentLang to do shell script "defaults read -g NSPreferredSpellServerLanguage"
		
		if currentLang is "en" then
			-- Change the language setting to "fr"
			do shell script "defaults write -g NSPreferredSpellServerLanguage fr"
		end if
		delay 1
		
		-- Restart the app
		tell application appName to activate
		delay 1
		
		if appName is "Microsoft Word" then
			tell application "Microsoft Word"
				set track revisions of active document to true
			end tell
			display notification "Track Changes enabled" with title "Microsoft Word"
		end if
		display notification "Spelling language set to French"
	end if
end repeat

-- Check if f4transkript is running
tell application "System Events"
	if (name of processes) contains "f4transkript" then
		-- force quit f4transkript
		do shell script "killall f4transkript"
		
		-- Check the current language setting
		set currentLang to do shell script "defaults read -g NSPreferredSpellServerLanguage"
		
		if currentLang is "en" then
			-- Change the language setting to "fr"
			do shell script "defaults write -g NSPreferredSpellServerLanguage fr"
		end if
		delay 1
		
		-- Restart f4transkript
		tell application "f4transkript" to launch
		delay 1
		display notification "Spelling language set to French"
	end if
end tell

Thank you in advance.

Are you only restating these apps because you want the language set to French?
If so check the language first and only loop thru the apps if the languages wasn’t already French.

My system spelling language is always set to English. It needs to be set to French when those applications are used, but before they are launched as macOS applications cannot register the new setting without being restarted, hence the script.

Here is a cleaned-up version that will only restart the apps once when the language is set to french

set appList to {"Microsoft Word", "Pages", "TextEdit", "f4transkript"} -- List of apps to check and restart

tell application "System Events"
	-- Check the current language setting
	set currentLang to do shell script "defaults read -g NSPreferredSpellServerLanguage"
	
	if currentLang is "en" then
		-- Change the language setting to "fr"
		do shell script "defaults write -g NSPreferredSpellServerLanguage fr"
		display notification "Spelling language set to French"
		delay 1
		restartApps()
	end if
end tell

on restartApps()
	-- Iterate through the app list
	repeat with appName in appList
		if isAppRunning(appName) then
			if appName is "f4transkript" then
				do shell script "killall f4transkript"
			else
				-- Quit the app
				tell application appName to quit
			end if
			delay 1
			
			-- Restart the app
			tell application appName to activate
			delay 1
			
			if appName is "Microsoft Word" then
				tell application "Microsoft Word"
					set track revisions of active document to true
				end tell
				display notification "Track Changes enabled" with title "Microsoft Word"
			end if
		end if
	end repeat
end restartApps

on isAppRunning(appName)
	tell application "System Events"
		set appProcesses to name of every process
		if appName is in appProcesses then
			return true
		else
			return false
		end if
	end tell
end isAppRunning
1 Like

Thank you very much for the help!

Did you manage to find a satisfactory solution?
Just in case, here’s a script that should work:

property appList : {"f4transkript", "TextEdit", "Pages", "Microsoft Word"}
property delayValue : 20 -- waits the app responses up to 2 seconds 

-- toggle the spelling language
(do shell script "defaults write -g NSSpellCheckerAutomaticallyIdentifiesLanguages 0")
set spellingLang to (do shell script "defaults read -g NSPreferredSpellServerLanguage")
if spellingLang = "en" then
	(do shell script "defaults write -g NSPreferredSpellServerLanguage 'fr'")
else
	(do shell script "defaults write -g NSPreferredSpellServerLanguage 'en'")
end if
if (do shell script "defaults read -g NSPreferredSpellServerLanguage") = spellingLang then
	display alert "Something went wrong and prevents spelling language to change." buttons {"Annuler"} cancel button 1
end if

-- restart apps
repeat with appName in appList
	if application appName is running then
		activate application appName -- in case some documents are modified
		quit application appName -- try to quit the app
	end if
	repeat with iLoop from 1 to delayValue
		if application appName is not running then exit repeat
		delay 0.1
	end repeat
	if iLoop = delayValue then do shell script "killall " & quoted form of appName
	
	tell application appName to activate
	repeat with iLoop from 1 to delayValue
		if application appName is running then exit repeat
		delay 0.1
	end repeat
	if iLoop = delayValue then display alert ("Unable to relaunch " & appName) message "Do you want to continue ?" buttons {"Cancel", "Continue"} cancel button 1
end repeat

Hi there,

Thank you for taking the time to write this. I ended up making separate shortcuts for each app. I used a mix of AppleScript and Shell commands, plus a few built-in actions. I just realized the endless loop was most likely caused by a stupid oversight on my part: I had other shorcuts set to automatically run on app quit which changed the spelling language back to EN… thus causing the close-and-open loop. I think my original AppleScript was actually fine… Ugh.