msgfmt Tutorial: Compile, Validate & Check PO Files
What msgfmt actually checks, executed against GNU gettext 1.0 rather than recalled. Opens with the result that frames everything: two catalogs that both pass msgfmt -c with exit 0, one carrying a hidden placeholder bug and a half-translated plural, the other missing a string entirely. Then the map — fourteen single-fault catalogs run with and without -c, showing that only 3 faults are fatal without it, 9 with it, and 5 pass regardless. Covers the exit-code and staging rules (a duplicate msgid hides a bad placeholder until you delete it, the statistics line prints even when the run failed, and passing several catalogs to one call merges them into false duplicates), the format check family by family and its easy-to-miss precondition that an entry must carry a format flag, the literal-percent trap where xgettext flags “Save 50% today” as c-format and every correct translation then fails, and why msgfmt lets German drop the number in msgstr[0] but not Russian. Then the five blind spots, each reproduced: fuzzy entries are never checked, a plural with an empty second form compiles and returns an empty string at runtime, copies and wrong-but-consistent plural headers pass, a UTF-8 file declared as Latin-1 compiles to mojibake, and strings missing from the catalog are invisible without msgcmp. Plus how --statistics counts each kind of entry, domain directives that silently split the output, the UTF-8 conversion gettext 1.0 applies by default, the checks -c leaves out (--check-accelerators and -C), a seventeen-row message-to-fix table, and a tested three-step CI gate that closes every gap shown.