Home / Alt manpages / fc-validate(1)

  • fc-validate(1)
  • User command
  • linux

Check Language Coverage with fc-validate

A font can look fine and still fail the language coverage that fc-validate actually checks, which is the gap this command exists to catch. You will build a repeatable check for one file, then learn to test a single face when a file holds several. The examples use fc-validate from fontconfig 2.15.0, installed here as package version 2.15.0-1.1ubuntu2.

Allow about ten minutes. You need a shell, a readable font file and the fontconfig utilities already installed. Every check here is read-only: nothing gets installed, cached or reconfigured. Run as an ordinary user unless the font file itself is not readable.

1. Check the installed command

Confirm which executable will run and record its version. These are ordinary, read-only commands and need no elevated privileges:

$ command -v fc-validate
/usr/bin/fc-validate
$ fc-validate --version
fontconfig version 2.15.0
  • -i or --index picks a face index.
  • -l or --lang sets the language to test.
  • -v or --verbose asks for more detail.
  • -V or --version prints the version shown above.

Ask the installed binary for the full summary if you are working on another host:

$ fc-validate --help
usage: fc-validate [-Vhv] [-i index] [-l LANG] [--index index] [--lang LANG] [--verbose] [--version] [--help] font-file...

2. Validate one font file

Pick a real, readable font rather than guessing a path. This example uses a font shipped on the machine running this guide:

$ FONT_FILE=/usr/share/fonts/truetype/liberation/LiberationSansNarrow-Italic.ttf
$ test -r "$FONT_FILE" && echo "readable: $FONT_FILE"
readable: /usr/share/fonts/truetype/liberation/LiberationSansNarrow-Italic.ttf
$ fc-validate "$FONT_FILE"
/usr/share/fonts/truetype/liberation/LiberationSansNarrow-Italic.ttf:0 Satisfy the coverage for en language

The output names the file, the face index and the language coverage result. The default language comes from the current locale, which is why en shows up here. Do not treat that as a universal default: the same command produces a different result on a host with a different locale.

Checkpoint

Capture the exit status straight after the validation:

$ printf 'exit status: %s\n' "$?"
exit status: 0

Status 0 means the font parsed successfully and the checked faces satisfied the requested coverage. Status 1 means an error occurred, or at least one face could not be opened. The message is useful evidence, but scripts should check the status as well.

3. Validate several files in one run

Pass more than one path as separate arguments. Use a shell array rather than an unquoted wildcard, since a directory can contain names with spaces:

$ fonts=(/usr/share/fonts/truetype/liberation/*.ttf)
$ fc-validate "${fonts[@]}"
/usr/share/fonts/truetype/liberation/LiberationMono-Bold.ttf:0 Satisfy the coverage for en language
/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf:0 Satisfy the coverage for en language

Your own list and output will differ. If the wildcard matches nothing, some shells pass the literal pattern through and validation fails. Check the list first when this runs in automation:

$ printf '%s\n' "${fonts[@]}"
$ ((${#fonts[@]} > 0)) || { echo 'no font files found' >&2; exit 1; }

Keep the exit status from fc-validate itself: a later diagnostic command overwrites $?, so store it if you need to print more afterwards.

4. Select one face from a font collection

A font file can contain multiple faces. Without --index, fc-validate checks all of them. Use a numeric index to isolate one:

$ fc-validate --index 0 /path/to/font-file.ttf
/path/to/font-file.ttf:0 Satisfy the coverage for en language

The index shown is zero-based. Do not assume index 0 is the face you actually want in a collection: run the command without --index first, then use the reported face numbers and the font's own metadata to decide what to test. An index that does not exist is an input error and returns status 1.

5. Test a specific language

Use --lang when the current locale is not the requirement you need checked:

$ fc-validate --lang en /usr/share/fonts/truetype/liberation/LiberationSansNarrow-Italic.ttf
/usr/share/fonts/truetype/liberation/LiberationSansNarrow-Italic.ttf:0 Satisfy the coverage for en language
$ printf 'exit status: %s\n' "$?"
exit status: 0

Use the language identifier your fontconfig installation expects, such as en for English. This option only changes the language used for the check; it does not edit the locale, the font file or fontconfig's installed orthography data. Omit --lang to get the normal locale-driven behaviour back.

6. Diagnose a failed validation

First tell an unreadable or missing file apart from a genuine coverage failure. None of this changes anything:

$ FONT_FILE=/path/to/font-file.ttf
$ ls -l "$FONT_FILE"
$ test -r "$FONT_FILE" && echo readable
$ fc-validate "$FONT_FILE"
Unable to open /path/to/font-file.ttf
$ printf 'exit status: %s\n' "$?"
exit status: 1

Warning

Correct the path or file permissions through your normal system process. Use sudo only if the file is intentionally restricted and you are authorised to read it; do not use elevated privileges as a general fix for a font that fails language coverage.

If a file opens but fails validation, rerun with the intended --lang value and, for a collection, each relevant --index. --verbose can add detail, though a simple font may still produce the same single-line result:

$ fc-validate --verbose "$FONT_FILE"
/path/to/font-file.ttf:0 Satisfy the coverage for en language

Do not delete or replace a font as part of this diagnostic. A validation result describes the file against the selected language rules; it is not an instruction to change system fonts or rebuild a cache.

Done means

  • Confirmed the version. You know the installed fontconfig version and executable.
  • Validated a readable font. You checked the exit status, not just the message.
  • Understood the default scope. All faces are checked unless --index selects one.
  • Tested the right language. You used --lang when the host locale was not the requirement.
  • Separated the two failure types. A missing or unreadable file is not the same as a coverage result.
  • Changed nothing. No font file, cache, locale or persistent configuration was touched.