Skip to content

Instantly share code, notes, and snippets.

@ernstki
Last active May 25, 2025 18:14
Show Gist options
  • Select an option

  • Save ernstki/2ae279ad89888e4099c9852bf0ba5d11 to your computer and use it in GitHub Desktop.

Select an option

Save ernstki/2ae279ad89888e4099c9852bf0ba5d11 to your computer and use it in GitHub Desktop.
Easily disable fonts that aren't in your language, for Debian and derivatives (and possibly other Linux distros)
#!/usr/bin/env perl
##
## Easily disable fonts that aren't for your language, or language-specific
## variants from large font families like Noto -- WITHOUT uninstalling them
##
## Authors: Kevin Ernst <ernstki -at- mail.uc.edu>, @wdoekes
## License: MIT or CC-BY-SA-4.0, at your option
## Source: https://gist.github.com/ernstki/2ae279ad89888e4099c9852bf0ba5d11
##
## Usage:
## ./fc-reject.pl > ~/.config/fontconfig/conf.d/88-reject.conf.new && \
## mv ~/.config/fontconfig/conf.d/88-reject.conf{.new,}
##
use v5.12;
use warnings;
use autodie;
my $rejectlist = {};
# languages I want to keep, e.g., my native language plus 'und-zsye' for emoji
# (ref: https://www.unicode.org/reports/tr35)
my $mylangs = 'en|de|und-zsye';
# reject these fonts unconditionally, even if they claim to support my language
# (easier than uninstalling; they may be depends/recommends for other packages)
my $rejectfam = '^(Kacst|AR PL|Noto.*CJK)'; # Arabic and East Asian scripts
# filter out language-specific font variants for languages I don't use from any
# font family matched by the $filterfam regexp
my $filterfam = '^Noto';
# always keep fonts that match the $keepfam regexp, regardless of lang. support
my $keepfam = '^Noto (Music|Symbols|Sans Linear [AB])';
open my $fh, '-|', 'fc-cat';
while (<$fh>) {
# a typical line of output from `fc-cat` looks like this:
# "NotoSerifHebrew-Regular.ttf" 0 "Noto Serif Hebrew:…:lang=he(|…):…
# …which would yield $name = 'Noto Serif Hebrew' and @langs = ('he')
if (/.* "([^:,]+).*:lang=([^:]*)/) {
my ($name, @langs) = ($1, split(/\|/, $2));
next if $name =~ /$keepfam/;
if ($name =~ /$rejectfam/) {
$rejectlist->{$name} = 1;
next;
}
if ($name =~ /$filterfam/) {
unless (@langs) {
# if you want to retain any of these, add to $keepfam, above
warn "Family '$name' specified no languages\n";
$rejectlist->{$name} = 1;
next;
}
$rejectlist->{$name} = 1 unless map { /$mylangs/ } @langs;
}
}
}
close $fh;
print <<EOF;
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
<selectfont>
<rejectfont>
EOF
foreach my $name (sort keys %$rejectlist) {
print <<EOF;
<pattern>
<patelt name="family">
<string>$name</string>
</patelt>
</pattern>
EOF
}
print <<EOF;
</rejectfont>
</selectfont>
</fontconfig>
EOF
# vim: shiftwidth=4 tabstop=4 expandtab
@wdoekes
Copy link

wdoekes commented Apr 30, 2024

On Ubuntu 22.04 you might want to re-enable the emoji by removing Noto Color Emoji from the output. Otherwise you won't even see the 👍 in GitHub.

And maybe Noto Music and Noto Sans Symbols and Noto Sans Symbols2 -- although I'm not sure how often you run into those.

As for the harmless warning, I suggest:

fc-reject.pl > ~/.config/fontconfig/conf.d/88-reject.conf.new &&
  mv ~/.config/fontconfig/conf.d/88-reject.conf{.new,}

The atomic mv ensures that only the complete file is read.

Thanks for this gist, @ernstki !

My changes:

--- fc-reject.pl	2024-04-30 12:15:16.573580587 +0200
+++ /usr/local/bin/remove-noto-fonts	2024-04-30 12:18:46.764030790 +0200
@@ -1,6 +1,6 @@
 #!/usr/bin/env perl
 ##
-##  Usage:    fc-reject.pl > ~/.config/fontconfig/conf.d/88-reject.conf
+##  Usage:    fc-reject.pl > ~/.config/fontconfig/conf.d/88-reject.conf.new && mv ~/.config/fontconfig/conf.d/88-reject.conf{.new,}
 ##  Author:   Kevin Ernst <ernstki -at- mail.uc.edu>
 ##  License:  MIT or CC-BY-SA-4.0, at your option
 ##  Source:   https://gist.github.com/ernstki/2ae279ad89888e4099c9852bf0ba5d11
@@ -9,17 +9,30 @@ use v5.12;
 use warnings;
 use autodie;
 
-my $mylang = 'en';       # use '(en|lang1|lang2)' for other languages
-my $rejectfam = 'Noto';  # use '(Noto|Other Family|Another Family)' for others
+my $mylang = 'en|nl|und-zsye';  # use 'en|lang1|lang2' for other languages
+                                # 'und-zsye' is for Emoji
+my $rejectfam = '^Noto';        # use '^(Noto|Other Family|Another Family)' for others
+my $keepfam = '^Noto Music';	# use '^(Noto Music|Others to keep)' for others
 my $rejectlist = {};
 
 open my $fh, '-|', 'fc-cat';
 while (<$fh>) {
-    if (/.* "([^:,]+).*:lang=([^:]*):.*/) {
-        my ($name, $lang) = ($1, $2);
-        if ($name =~ /$rejectfam/ and (!$lang or $lang !~ /$mylang/)) {
-            $rejectlist->{$name} = 1;
-        }
+    if (/.* "([^:,]+).*:lang=([^:]*)/) {
+        my ($name, @langs) = ($1, split(/\|/, $2));
+        if ($name =~ /$rejectfam/) {
+	    my $keep = 0;
+	    foreach my $lang (@langs) {
+		if ($lang =~ /^($mylang)$/) {
+		    $keep = 1;
+		}
+	    }
+	    if ($name =~ /$keepfam/) {
+		$keep = 1;
+	    }
+	    if ($keep == 0) {
+		$rejectlist->{$name} = 1;
+	    }
+	}
     }
 }
 close $fh;
@@ -32,7 +45,7 @@ print <<EOF;
     <rejectfont>
 EOF
 
-foreach my $name (keys %$rejectlist) {
+foreach my $name (sort keys %$rejectlist) {
     print <<EOF;
       <pattern>
         <patelt name="family">

@DJGoossens
Copy link

DJGoossens commented Dec 18, 2024

Many thanks! Solved my problem. I confess I inserted the key bit of 88-reject.conf into the 78-Reject.conf that Font Manager generates when you uncheck a font in the GUI, just so that Font Manager would know about the changes and still work as a management tool. I think it must only read 78-Reject.conf. (Says not to edit it manually, but no harm does as far as I can see.)

@ernstki
Copy link
Author

ernstki commented Jan 19, 2025

On Ubuntu 22.04 you might want to re-enable the emoji by removing Noto Color Emoji from the output. Otherwise you won't even see the 👍 in GitHub.

Thanks, @wdoekes. I updated the script with your helpful suggestions, so it's maybe less of a dirty hack now. Hope you're OK with the original license (MIT).

@DJGoossens I'm glad it helped, and that's a great idea of re-using Font Manager's own config so you can tweak it with a GUI later.

@wdoekes
Copy link

wdoekes commented Jan 19, 2025

Hope you're OK with the original license (MIT).

Anything is fine. Thanks for asking.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment