Quickly switch Smart Quotes style in System Prefs

This macro group allows you to quickly switch the smart quotes style (in System Preferences > Keyboard > Text) according to the language you are writing in.


The macro group consists of a main macro and several “trigger” macros that let you set the specific quotes style. A trigger macro just calls the main macro and passes a parameter to it.

This makes it easy for you to set your custom trigger for each quote style (hotkey, typed string, or both). You can also launch the macros from the group palette.

By default is has these settings:

Language Quotes String trigger
English, Spanish “abc”, ‘abc’ ;qen
German „abc“, ‚abc‘ ;qde
French « abc », ‹ abc › ;qfr
German (Chevrons) »abc«, ›abc‹ ;qdec
Switzerland (de, fr, it) «abc», ‹abc› ;qch
Spanish (Latinas) «abc», ‘abc’ ;qes
Typewriter (Code) "abc", 'abc' ;qty
Toggle Smart Quotes & Dashes ;qqq

Of course, this is a language selection that suits my personal needs. But it is very easy to customize it:

  1. At the beginning of the AppleScript (the large if…then…else block) set your desired quotes combination, as you find it in the pop-up menu in System Preferences.
    • The value of the theLanguage variable is what you have to pass via the trigger macro parameter.
  2. Adapt the trigger macro accordingly and set the typed string / hotkey trigger.

Set Smart Quotes via System Prefs Macros.kmmacros (22.9 KB)

Requires KM 8.0.3+; tested on macOS 10.13.

As always with GUI scripts, if you are using a non-English system you may have to adapt the names of GUI elements to your system language.


Main macro:

One of the trigger macros:

The AppleScript:

set SPwasRunning to false
set counter to 0

tell application "Keyboard Maestro Engine"
	set theLanguage to getvariable "Local Language" instance system attribute "KMINSTANCE"
end tell

if theLanguage is "en" then
	set {dQuote, sQuote} to {"“abc”", "‘abc’"}
else if theLanguage is "de" then
	set {dQuote, sQuote} to {"„abc“", "‚abc‘"}
else if theLanguage is "fr" then
	set {dQuote, sQuote} to {"« abc »", "‹ abc ›"}
else if theLanguage is "es" then
	set {dQuote, sQuote} to {"«abc»", "‘abc’"}
else if theLanguage is "de-alt" then
	set {dQuote, sQuote} to {"»abc«", "›abc‹"}
else if theLanguage is "CH" then
	set {dQuote, sQuote} to {"«abc»", "‹abc›"}
else if theLanguage is "none" then
	set {dQuote, sQuote} to {"\"abc\"", "'abc'"}
end if

tell application id "com.apple.systempreferences"
	if running then set SPwasRunning to true
	reveal anchor "Text" of pane id "com.apple.preference.keyboard"
end tell

tell application id "com.apple.systemevents"
	tell application process "System Preferences"
		repeat until title of first window is "Keyboard"
			delay 0.1
			set counter to counter + 1
			if counter > 40 then
				display alert "Failed to open the Keyboard pane of System Preferences!"
				error number -128
			end if
		end repeat
		tell first window
			tell tab group 1
				if theLanguage is "toggle" then
					tell checkbox "Use smart quotes and dashes"
						click # Toggle
						# if value is not 0 then click # Disable
					end tell
				else
					tell checkbox "Use smart quotes and dashes"
						if value is not 1 then click
					end tell
					tell pop up button 1
						perform action "AXShowMenu"
						tell menu 1
							click menu item dQuote
						end tell
					end tell
					tell pop up button 2
						perform action "AXShowMenu"
						tell menu 1
							click menu item sQuote
						end tell
					end tell
				end if
			end tell
		end tell
	end tell
end tell

if not SPwasRunning then tell application id "com.apple.systempreferences" to quit

Technical note (and question):

As you see, the macro works by ugly GUI scripting.

A more elegant way would be to set the preferences directly via UserDefaults, for example…

Bash:

defaults write -globalDomain NSUserQuotesArray -array "« " " »" "‹ " " ›"

Swift:

CFPreferencesSetValue("NSUserQuotesArray" as CFString, ["« " " »" "‹ " " ›"] as CFPropertyList, kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesAnyHost)

Both methods work fine, but with a big caveat: If the text editor was already running I had to restart it to make it recognize the new settings, which defeats the purpose of the macro to switch quickly. So I decided to go the GUI way.

If anybody knows how to set GlobalDomain preferences in a way that they get pushed to running applications then I will happily rewrite the macro.


Update (Oct 18, 2017 at 10:02 UTC)

  • Added a timeout while waiting for the Keyboard preferences pane.
4 Likes

What did you get that first screenshot with? I love the torn paper edges.

See here:

1 Like