PO file (Gettext)


What is a PO file?

PO (an acronym for “portable object”) is a file format for software localization defined by the GNU gettext tool. Gettext is an open-source tool designed to simplify the localization process. It allows you to extract translatable strings from your source code into a PO file for translation.

The PO file contains a list of key-value pairs that define how string keys map to their translations for the target language.

PO file example

This simple PO file example contains minimal content. It shows you how to define a header, plain string entry, entry with placeholders, and pluralized string.

msgid ""
msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: localizely.com\n"
"Last-Translator: localizely.com\n"
"Language-Team: localizely.com\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Language: de\n"

msgid "Demo application"
msgstr "Demo-Anwendung"

#: polls/app.py:105
msgid "Welcome %s"
msgstr "Willkommen %s"

# Since we use 2 placeholders in this example, we marked them with numbers
# so it prints them properly in other languages, where their order maybe be switched
#. First placeholder is current user's name, second one is a name of message sender
msgid "Welcome back, %1$s! You have a new message from %2$s"
msgstr "Willkommen zurück, %1$s! Sie haben eine neue Nachricht von %2$s"

# This is a pluralized string. 
# It chooses one of the plural forms depending on passed parameter
msgid "You have %d new message" 
msgid_plural "You have %d new messages" 
msgstr[0] "Sie haben %d neue Nachricht" 
msgstr[1] "Sie haben %d neue Nachrichten"

# This text is written in two lines
#, fuzzy
msgid "We will guide you throughout the app\n"
"Please select your role:"
msgstr "Wir werden Sie durch die App führen\n"
"Bitte wählen Sie Ihre Rolle:"

PO file format

A two or more key-value pairs define one entry in a PO file. The entry represents how a string key marked with keyword msgid translates to target language marked with keyword msgstr.

A sample PO file entry:

#: polls/app.py:116
msgid "Hello world!"
msgstr "Hallo Welt!"

The values on the right side should be wrapped into “quotes”. New lines should be escaped with \n. However, if the value is too long for one line, you can split it into multiple lines, each quoted separately:

msgid "Hi there, " 
"welcome back"
msgstr "Hallo, "
"willkommen zurück"


The first entry in a PO file that has empty string for msgid is considered as a header. It contains meta-information about the content in the file, and also how plural (line with Plural-Forms) needs to be handled for that language.


A keyword msgid defines the string key that follows in the same line. It can be a UI text in the main language (“Hello world”) or its ID (“hello_world”), depending on what convention you start using in your project. Whatever you decide for msgid, just be consistent.


A keyword msgstr defines the translated string that follows in the same line. A line with msgstr should be under the line with a string key (msgid).


A keyword msgctxt defines the context for msgid and msgstr lines and should be in a line above them. It is optional. It is mostly useful if you use main translations for string keys, for example, “Hello world” instead of using ID like “hello_world”. In such cases you will be able to give different contexts to the same msgid values, that might need different translations in other languages.


PO files support plurals as well. Different languages have different plural forms. PO files define what plural form would be used for a passed parameter according to its plural rule defined in a PO file header.
For example, plural rules for the English language are: Plural-Forms: nplurals=2; plural=(n != 1);.
However, Localizely generates this header automatically for you during the file download so you don’t need to manage that on your own.

According to the plural rules from the header, you can define how each plural form will look like in the target language:

msgid "You have %d new message" 
msgid_plural "You have %d new messages" 
msgstr[0] "Sie haben %d neue Nachricht" 
msgstr[1] "Sie haben %d neue Nachrichten"


A valid PO comment lines start with the character # and relate to the first entry below the comment.

There are few types of comments, defined by how their line starts:

  • # – This is a comment for translators. Usually, this is the only comment you might manually write.
  • #. – Comments extracted from the source code with Gettext tool.
  • #: – Represents references to the source code, where given strings are used.
  • #, – Flags for Gettext tool. If a fuzzy flag is present, Gettext will not use the translation in the app.
  • #| – Represents previous string key, followed by msgid keyword.

What is a POT file?

POT files are the template files for PO files. They are created by Gettext tool. They will have all the translation strings left empty. A POT file is essentially an empty PO file without the translations, with just the original strings.

A sample POT file entry:

msgid "Hello world!"
msgstr ""

Once POT files are translated, you can change the file extension to .po and use in your software.

How to edit PO files?

Instead of manually sending PO files to translators, then fixing syntax errors and merging them back into your source code, you can automate the whole process with Localizely.
Upload your PO files to Localizely and translate missing strings with translators. Once translated download files back to your source code.
To automate the process, integrate Localizely with your Github repository.

Tired of manually editing translation files?

Our platform streamlines software localization for you.

Copyrights 2024 © Localizely