The strings are the bytes that the descriptors of the two tables point to. Each is followed by a NUL byte that the length does not count. A catalogue holds the pairs of a PO file with a few changes: the entries are sorted, a context is joined to its message, the forms of a plural are joined, and entries that are not translated are left out.
The header entry
The empty string is the original of the
header entry, and its translation
is the block of header fields: Content-Type: text/plain; charset=UTF-8\n
and the others, each line ended by a line feed. It is the first entry of both tables,
since the empty string sorts before every other string, and it carries the
information that a loader needs: the encoding of the strings and the plural rule. The
manual says the empty original is translated to system information attached to the
catalogue. msgfmt 1.0 leaves the field POT-Creation-Date out
of what it writes.
Contexts
The original of an entry with a context is the context, then one byte
0x04 (EOT), then the message:
menu 04 Open 00
msgctxt "menu" and msgid "Open"A context that is empty (msgctxt "") gives an original that starts with the
0x04 byte, which is different from the message alone. The strings are sorted
as they are stored, so the entries of one context are not together unless the contexts
sort together.
Plural forms
The original of a plural entry is the singular, a NUL byte and the plural original; its stored length covers both, counting the NUL between them but not the one at the end. Only the singular takes part in the hash lookup, because the string that is hashed and compared ends at the first NUL.
The translation holds the translations of the forms, each ended by a NUL byte, one after
the other, and the length covers all of them but the last NUL. A program that has the
number of the form to use skips that many NULs and reads the string there. If it runs off
the end, the first form is the answer. How the number of the form comes from
n is the Plural-Forms
rule of the header entry.
original: One file 00 %d files 00
translation: Un fichier 00 %d fichiers 00
An entry can have both a context and plural forms: the context, 0x04, the
singular, a NUL and the plural original.
Order
The originals are sorted by the byte values of the whole stored string, context
included, as strcmp compares them. The translation with the same number
follows its original. Entries that msgfmt leaves out are the untranslated
ones (an empty msgstr), the ones marked fuzzy unless it is told
otherwise, and the obsolete ones.
Encoding
The strings are in any encoding that keeps the ASCII characters as they are, as long as
the header entry names it in charset=. From gettext 0.22 msgfmt
writes UTF-8 unless it is given --no-convert. Wide characters are not used,
because their size depends on the platform. A reader decodes each string with the
encoding named in the header; the header’s own text is ASCII.
Worked example
A catalogue written by msgfmt 1.0 from a file with these entries, without a
header entry. The fuzzy “File %d” is left out; the entry with an empty context sorts
first, then the plural one, then the entry with the context menu, and
the one that starts with tab:
| Number | Original, as stored | Translation, as stored |
|---|---|---|
| 0 | 04 Open 00 | Ouvrir (vide) 00 |
| 1 | One file 00 %d files 00 | Un fichier 00 %d fichiers 00 |
| 2 | menu 04 Open 00 | Ouvrir 00 |
| 3 | tab 09 hereAA\ "q" 00 | ab 00 |
The file is little-endian, N is 4, the hash table has 5 entries, and the strings start at
0x70.
Not described
Known, not yet covered
- Reference: the conversion that
msgfmtmakes between encodings, and the encodings it accepts; the manual lists them in another chapter.