An entry is the keyword lines of one message: its context, the original text, the
plural original and the translations, each a quoted string. The comments that may come
before them are on their own page.
This page follows the GNU gettext manual and the reader in gettext’s own source,
read-po-lex.c.
Keywords
| Keyword | Holds | Notes |
|---|---|---|
msgctxt | The context | Optional. Tells apart messages with the same msgid that mean different things. An empty context (msgctxt "") is not the same as no msgctxt line. |
msgid | The original message | Required. Empty only in the header entry. |
msgid_plural | The plural form of the original | Present only in plural entries, straight after msgid. |
msgstr | The translation | Required in an entry without msgid_plural. Empty means not yet translated. |
msgstr[N] | The translation for plural form N | N is a number counted from 0, written in square brackets, for a plural entry. |
The reader also knows the keyword domain, which switches the domain the
following entries belong to. The manual does not describe it and msgfmt
handles it in its own way; this site does not describe it either.
The keywords come in the order of the table. In the reader, msgstr[N] is
read as the keyword msgstr, an opening bracket, a number and a closing
bracket.
Strings
Each msgctxt, msgid, msgid_plural and
msgstr is followed by a string in the syntax of C: it is enclosed in
double quotes and may use backslash escapes. White space outside the quotes does not
matter.
Escape sequences
| Written | Gives |
|---|---|
\n | Line feed, 0x0A |
\t | Tab, 0x09 |
\b | Backspace, 0x08 |
\r | Carriage return, 0x0D |
\f | Form feed, 0x0C |
\v | Vertical tab, 0x0B |
\a | Alert (bell), 0x07 |
\\ | A backslash |
\" | A double quote |
\0 to \7 and up to two more octal digits | The byte with that octal value; at most three octal digits in all |
\x and hexadecimal digits | The byte with that value; at least one digit is needed, and the reader stops at the first character that is not a hexadecimal digit, with no limit on how many it takes |
Any other character after a backslash is an error: the reader reports “invalid
control sequence” and carries on with a space in its place. The universal character
escapes \u and \U are not allowed; the reader has
a note that they are not handled, so they give the same error. A string holds
bytes, so an octal or hexadecimal escape gives one byte of the file’s encoding, not
a character.
Run on a test file, msgfmt 1.0 turned "tab\there\x41\101" into
a tab, here and AA, and reported
invalid control sequence for "Bad\q" with the line and
column.
Several lines for one string
A string can be cut over several lines by closing the quote at the end of a line and opening it again on the next. Strings that follow each other are joined into one:
msgid ""
"A long message that is cut "
"over two lines\n"
msgstr ""
"Un long message coupé "
"sur deux lignes\n"
- An empty first string, as above, is allowed, and is how a long message is
lined up. The manual says that the empty string can only be left out when the
first real string stands on the keyword’s line, a limit of the Solaris
msgfmt. - A
\ninside the quotes is part of the string. A line break outside the quotes is not. - A line break inside the quotes ends the string early. The reader reports “end-of-line within string” and keeps what it has read. The manual tells writers not to end a line with a backslash to carry on the string, but to close and reopen the quotes instead. The reader does drop a backslash that is followed by a line break before it reads the string, so such a file is still read.
- The reader reads
CR LFline ends asLF.
Characters
The file is text in one encoding for the whole file, the charset in
the Content-Type field of the
header entry.
In a template the field says charset=CHARSET, which is not an encoding,
and the tools do not convert until it is filled in. The reader gives the strings
their bytes as they are; the compiled catalogue keeps the same bytes unless
msgfmt converts them, and from gettext 0.22 it converts to UTF-8 unless it
is told --no-convert.
Contexts
A short message such as “Open” can mean different things as a menu command and as an
adjective. msgctxt names the use, and the pair of context and message is
what identifies the entry:
msgctxt "menu"
msgid "Open"
msgstr "Ouvrir"
msgctxt "state"
msgid "Open"
msgstr "Ouvert"
In a compiled MO file the
two are joined as context, byte 0x04, message.
Plural entries
An entry with msgid_plural has one translation for each plural form of
the language, written msgstr[0], msgstr[1] and so on. The
number of forms and the rule that picks one for a number n are the
nplurals and plural values of the
Plural-Forms field
of the header entry.
msgid "One file"
msgid_plural "%d files"
msgstr[0] "Un fichier"
msgstr[1] "%d fichiers"
The singular msgid is what identifies the entry; the plural original is
carried along. In the binary catalogue the two originals are joined with a NUL byte
and the translations are written one after the other, each ended by a NUL.
Obsolete entries
An entry that the program no longer needs is kept, commented out, so that the
translation is not lost if the message returns. The tools do it (msgmerge
makes entries obsolete) and an editor can do it. An obsolete entry is recognised by
#~ at the start of every one of its lines, the keyword lines included:
#~ msgid "Gone"
#~ msgstr "Parti"
The reader strips the #~. A line starting #~| is the previous
string comment of an obsolete entry. Obsolete entries are not compiled into the MO
file.
Rules for a valid file
- Two entries without a context may not have the same
msgid(or the same singularmsgid). Two entries with a context may not have the same context andmsgid. - The empty
msgidis for the header entry, which comes first. It may not be used for anything else. - Every entry needs its
msgstr, or itsmsgstr[N]strings for a plural.msgfmt1.0 reportedmissing 'msgstr' sectionandduplicate message definition, each with the line, for test files.
An entry whose translation is empty is valid: it is untranslated, and
msgfmt 1.0 leaves it out of the MO file. It also leaves out an entry
marked fuzzy,
unless it is given -f, and every obsolete entry.
Not described
Known, not yet covered
- Reference: the
domainkeyword, and the checksmsgfmtmakes for plural entries (the number ofmsgstr[N]strings againstnplurals), which the sources read for this page do not state.