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 "Sie haben %d neue Nachricht" msgstr "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 "Sie haben %d neue Nachricht" msgstr "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
fuzzyflag is present, Gettext will not use the translation in the app.
#|– Represents previous string key, followed by msgid keyword.
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.
Read next: Flutter localization workflow streamlined