Scripting Font Book's "English" Smart Collection

Hello all –

My Font Book has a smart collection (?) named “English.” It has a different icon from the other smart collections and it can’t be edited or deleted. And I can’t figure out how to reach it. It does not appear in the names of the font collections or the names of the font libraries. This code


on GetEnglishFontList()
	set EnglishFontList to {}
	set astids to AppleScript's text item delimiters
	set AppleScript's text item delimiters to return
	tell application "Font Book"
		tell font collection named "English"
			set EnglishFontList to name of every font family
		end tell
	end tell
	return EnglishFontList
	set AppleScript's text item delimiters to astids
end GetEnglishFontList

causes an Applescript error: Can’t get Font Collection “English”. I can make another smart collection such that ‘Languages include English’ that I assume is the same, and that I can reach as a work around if this is a dry hole.

Is there something I’m missing?

Thanks, Mick

Hello,

I re-wrote your script quick-and-dirty and it appears that FontBook won’t return any reference to the font collection “English” but will to any other. Since font family can be inside both font collection and the top application object I took into account the latter as well, but still no dice. This is in Mavericks, so if you tried in Big Sur then we’re dealing with a very old bug.

My script was:

tell application "Font Book"
	set EnglishFontFamily to missing value
	repeat with i from 1 to number of items in (every font collection)
		set this_item to item i of (every font collection)
		tell this_item
			set TheName to "English"
			if (the first font family whose name is TheName) exists then
				set EnglishFontFamily to font family TheName
				exit repeat
			end if
		end tell
	end repeat
	if EnglishFontFamily is missing value then
		if (the first font family whose name is TheName) exists then set EnglishFontFamily to font family TheName
	end if
	return EnglishFontFamily
end tell

Model: MacBook Pro
AppleScript: 2.3.2
Browser: Safari 537.86.7
Operating System: macOS 10.9

Hi –

Thanks. Can’t quite follow the font family logic, but I understand that you didn’t reach it, too.

Under the assumption that the only logical condition for “English” is that languages include English, I can create another smart collection that should have the same functionality and be reachable.

I would have thought that font family properties would include the data shown by “Show Font Info” but not so. The only way I see to reach that is via smart collections, and only for some of it.

But I have a way ahead. Thanks again.

…best, Mick

Model: 2019 MacBookPro 16"
AppleScript: 2.4
Browser: Firefox 87.0
Operating System: macOS 10.14

It is more complicated than that.

There is a property of ‘typeface’ called ‘typeface additional info’ (which doesn’t seem to be listed in the dictionary). If you do something like:

set tfp to properties of typeface 1 of font collection 1

You’ll get a bucket of them including an ‘additional’ property called ‘FBFaceLanguages’, which will include ‘English’ for any typeface that supports English. As an aside, regardless of how poor that support is, it still shows up. I find it useless for separating fonts I want from those I don’t. I wish there were ‘primarily for’ and ‘limited support for’ tags as well.

You can further ask for these additional properties with:

set tai to typeface additional info of tfp

This will focus on a reduced set of properties but how to access them individually, I’m not sure as they’re a complex record of some sort.

Meanwhile, if you end up just creating a smart collection containing ‘English’, it may not match the special built-in one exactly. The font counts for the built-in ‘English’ do not match any copy (either using ‘smart collection: english’ or ‘search: english > collection’) on my system.

Hi –

Thank you. I truly didn’t expect the provided ‘English’ collection and ‘My English’ collection to coincide.

With your additional inputs though, I got what I really wanted, which was a list of enabled fonts not designed for English. Here’s my code:


tell application "Font Book"
	set EnglishUsableFonts to {}
	set EnglishUnusableFonts to {}
	set Fontlist to name of every font family whose enabled is true
	repeat with i from 1 to count of Fontlist
		set tfp to (properties of first typeface whose family name is item i of Fontlist as text)
		set tfai to typeface additional info of tfp
		set FBFL to FBFaceLanguages of tfai
		if FBFL contains "English" then
			set the end of EnglishUsableFonts to item i of Fontlist as text
		else
			set the end of EnglishUnusableFonts to item i of Fontlist as text
		end if
	end repeat
end tell

It takes about 33 seconds to run through my 286 enabled fonts, or 9 fonts/second.

Thanks again.
…Mick

Model: 2019 MacBookPro 16"
AppleScript: 2.4
Browser: Firefox 87.0
Operating System: macOS 10.14

Glad it worked out. Your script works well; it took 19 seconds on my system with some 366 fonts (per Script Debugger). This breaks down to about 4 seconds to inhale the fonts and then it seemed to process a font about every .04 or .05 seconds per font so maybe 20-25 per second.

Now that I see what this can do, I think I may see how I might (subjectively) tag fonts so as to differentiate them based upon how complete their support might be. It would be nice to be able to easily look at a collection of English display fonts or text fonts.

Thanks for posting the working script.

Your solution is generally working, but slow. Because you are re-looking for what you have already found.

You can loop directly over the family names that have already been found. Second whose clause is unnecessary, and the following script is almost 2x faster than yours:


set {EnglishUsableFonts, EnglishUnusableFonts} to {{}, {}}

tell application "Font Book"
	set FontFamilyNameList to name of every font family whose enabled is true
	repeat with fontFamilyName in FontFamilyNameList
		set tfp to properties of typeface 1 of font family fontFamilyName
		if (FBFaceLanguages of typeface additional info of tfp) contains "English" then
			set the end of EnglishUsableFonts to contents of fontFamilyName
		else
			set the end of EnglishUnusableFonts to contents of fontFamilyName
		end if
	end repeat
end tell

Hi –

Very neat. Thanks. It was on my list to make it faster. (First, make it right, then make it fast, etc.)

But you did it for me. :cool: Not sure that I would have seen that, though.

Thanks again.

…best, Mick