Table of Contents

  • File extension: .po, .pot

  • i18n type: 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.

Whenever a PO file is uploaded, Transifex tries to make sure the file is syntaxically correct. 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 (\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/
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 that are 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 both 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 2 ways to define them in your PO file:

  • add entries which have some white space immediately following the # character

  • add entries which 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:


References to the program’s source code

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


Plural Forms in a PO file

There are many languages that have more than one plural form (English, Russian, Arabic etc.).

In order to translate .po files using our localization management platform, you need to make sure that the correct number of plural forms has properly been defined in your .po file for the locale it contains.

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

  • Make sure that 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"

  • Ensure that each pluralized entry contains a msgstr line for each of the plural forms

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 يوم"


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, for the untranslated entries, the msgstr values will be empty so that translators know which are the entries that they need to work on.

  • Download for use: All the entries that have not been translated yet will be included in the file containing 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.


XLIFF support is only offered on the Premium plan and up


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 behaviour of PO files for different download modes:


* Proofeading needs to be enabled as an option 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.

Read more

Continue Reading

Did this answer your question?