Skip to main content
Gettext (PO)

Information about how Transifex handles the Gettext (.po, .pot) file format.

Jacob Doulkeridis avatar
Written by Jacob Doulkeridis
Updated over a month ago

File Extension(s)

.po, .pot

i18n type(s)

PO

PO files are used by the gettext i18n system. The gettext system has many features, including support for developer comments, context, and the ability to specify the location of a string in the source code.

Transifex tries to make sure the file is syntactically correct whenever a PO file is uploaded. However, you can still check the file for syntax errors using the msgfmt tool that comes with gettext.


Sample data

# FIRST AUTHOR <email@address>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: Transifex\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-03-29 12:41+0000\n"
"PO-Revision-Date: 2018-03-29 12:43+0000\n"
"Last-Translator: Transifex\n"
"Language-Team: English (https://app.transifex.com/transifex/transifex/language/en/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: en\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"


#: actionlog/templates/object_action_list.html:7 txpermissions/forms.py:18
msgid "User"
msgstr ""

#: actionlog/templates/object_action_list.html:8
msgid "Action"
msgstr ""

#: foo/templates/bar.html:180
msgid "{0} result"
msgid_plural "{0} results"
msgstr[0] ""
msgstr[1] ""


Syntax in PO files

Transifex needs the PO files uploaded to Transifex to be syntactically correct.

The gettext toolchain comes with a utility to check a PO file for syntax errors, msgfmt, which is available for Windows and Unix. However, the latest version of the utility (and the one Transifex uses) is available only for UNIX systems.

You can check a PO file for syntax errors by running the command:

msgfmt -c <file.po>


Comments in a PO file

Transifex supports developer comments in PO files. A valid PO comment should start with the character #

Comments are handled as developers' notes in Transifex, and there are two ways to define them in your PO file:

  • Add entries that have some white space immediately following the # character.

  • Add entries that start with #.

So, for example, if a source string contains the following entries:

#  comments #1
#. comments #2

msgid "User"
msgstr "User"

Both comments above will be exposed in Transifex Web Editor and be available to translators throughout the translation process as follows:

developer_notes_PO.png#asset:4901


Context in a PO file

Context in PO files can be used to differentiate entries with the same source text and key. Context is identified with msgctxt.

Example:

msgctxt "Additional context...."

msgid "total_files"
msgstr "Total Files"


References to the program’s source code

Comment lines starting with #: e.g. (#: accounts/forms.py:92, accounts/forms.py:363) contain references to the program’s source code. This information can be found under the Context tab in Transifex Web Editor as Occurrences.

occurrences_PO.png#asset:4906


Plural Forms in a PO file

Many languages have multiple plural forms (English, Russian, Arabic, etc.).

To translate .po files using our localization management platform, you must ensure that the correct number of plural forms has properly been defined in your .po file for the locale it contains.

So, there are two things you need to take care of:

1) Ensure your .po file contains the Plural-Forms line in the header entry. This line contains the number of plural forms and a formula.

Example #1: English (one, other)

"Plural-Forms: nplurals=2; plural=(n != 1);\n"

Example #2: Croatian (one, few, other)

"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"

Example #3: Russian (one, few, many, other)

"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n"

Example #4: Arabic (zero, one, two, few, many, other)

"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"

2) Ensure that each pluralized entry contains a msgstr line for each plural form.

Example #1: English (one, other)

#, python-format
msgid "%s day"
msgid_plural "%s days"
msgstr[0] "%s day"
msgstr[1] "%s days"

Example #2: Croatian (one, few, other)

#, python-format
msgid "%s day"
msgid_plural "%s days"
msgstr[0] "%s dan"
msgstr[1] "%s dana"
msgstr[2] "%s dana"

Example #3: Russian (one, few, many, other)

#, python-format
msgid "%s day"
msgid_plural "%s days"
msgstr[0] "%s день"
msgstr[1] "%s дня"
msgstr[2] "%s дней"
msgstr[3] "%s дней"

Example #4: Arabic (zero, one, two, few, many, other)

#, python-format
msgid "%s day"
msgid_plural "%s days"
msgstr[0] "%.0sأقل من يوم"
msgstr[1] "%.0sيوم واحد"
msgstr[2] "%.0sيومان"
msgstr[3] "%s أيام"
msgstr[4] "%s يومًا"
msgstr[5] "%s يوم"

📝Note: Do you want to find out more about plurals in Transifex? Please check here.


Download options

  • Download file to translate: Both translated and untranslated strings will be included in the file. However, the msgstr values will be empty for the untranslated entries so that translators know which entries they need to work on.

  • Download for use: All the entries that have yet to be translated will be included in the file as empty msgstr values. The already translated strings will also be included in the file.

  • Download only reviewed translations: The file will contain all the strings of the original file. However, for the unreviewed strings, the msgstr values will be empty.

  • Download for translation as XLIFF: The translation file will be generated in the .xliff format and include both translated and untranslated strings. The latter ones will be returned without containing target elements.

  • Download untranslated strings as XLIFF: The translation file will be generated in the .xliff format and include only the untranslated strings.

📝Note: XLIFF support is only offered on the Growth plan and up

only_download_options.png#asset:4916

In addition to the above Interface options, you can use the API or Client to download the translation files according to your localization needs.

The following table summarizes the behavior of PO files for different download modes:

* The results are compatible with parser version 2.

📝Note: Proofreading must be enabled for this logic to take effect. To learn how to enable proofreading, click here.


Fuzzy Matches

#, fuzzy is the mark that gettext uses to determine that a translation content has to be reviewed. While this mark is there, the translation won't show up in run-time.

As long as the fuzzy label is part of the PO entry you provide in the PO translation file, our parser ignores this translation, and no changes are applied to the corresponding entry in Transifex.


Default Placeholders

Transifex automatically recognizes common placeholders frequently used in PO files. Such placeholders are listed below:

match: ['%1$s', '%(key1)s', '%s', '%d', '%.2f', '%-5d', '%+2d']

If you use a placeholder that Transifex doesn't detect automatically, you can configure your settings and request Transifex to detect them. The process for doing so is described here.


Parser Behavior when "msgstr" = "/n"

The parser's behavior for PO or POT files varies depending on the usage of the /n character. The table below illustrates the various scenarios when uploading PO/POT files and the corresponding outcome the parser will produce.

We are looking at the first msgstr values in particular, to decide how the /n character will be treated during parsing once it's found in a PO entry.

For example, if the first PO entry in a source file is empty, i.e., msgstr="" and the next one is msgstr="\n" then the value of the second msgstr will be considered empty during parsing, and the text included in the msgid will be considered the translatable text.

If now the first PO entry in a source file is msgstr="\n" and the second one is msgstr="some text", then the value of the first msgstr will also be considered non-empty during parsing.


Why does my PO file fail to upload?

The most common issue is that the file you are trying to upload contains translations instead of just source content.

To resolve this issue, you must first remove any translations from your file using a text or PO file editor of your choice.

Specifically, you will need to replace every msgstr tag that contains translations with an empty msgstr tag. For example:

msgstr "translation" ---> Will cause your source fail to fail to upload.
mgstr "" ---> Your file will be uploaded succeesfully.

You can keep a copy of the original file and upload it as a translation file for the target language it contains.


Additional Reading


💡Tip

Looking for more help? Get support from our Transifex Community Forum!

Find answers or post to get help from Transifex Support and our Community.

Did this answer your question?