Python (PO)

gettext PO localization for Python applications.

Translate the .po catalog of your application, reuse earlier translations, check placeholders, and write a translated .po file for each language. Your Python project keeps extraction, msgfmt, and runtime loading.

Translated with another tool? See how migration works

PO localization: Professional and higher

Your source PO messages.po Lingobit Localizer Project SourceGerman New Order Neue Bestellung Customer: Kunde: Quantity: Menge: Each string, translated in the project You get messages.po de\messages.po fr\messages.po ja\messages.po A translated file for each language; msgfmt compiles .mo Your source PO messages.po Translate in Lingobit Project SourceGerman New Order Neue Bestellung Customer: Kunde: Quantity: Menge: You get messages.po source de\messages.po fr\messages.po ja\messages.po
Input
An English .po file: msgid is the key, msgstr the text
Output
Translated .po files, such as de\messages.po
Runtime
.mo files built by msgfmt, loaded by gettext
Preview
None: strings are translated in the table
On this page

Tutorial

Localize PO files with Lingobit, step by step.

Four steps from the English .po file to translated files for msgfmt.

Your source PO messages.po Project DE FR JA LOC MyApp.loc messages.poPO New Order Customer: reports.poPO Export %d pages to %s. Report Format PO Files PO Your source PO messages.po Project DE FR JA LOC MyApp.loc messages.poPO New Order Customer: reports.poPO Export %d pages to %s. Report Format PO Files PO
  1. Your source PO messages.po Project DE FR JA LOC MyApp.loc messages.poPO New Order Customer: reports.poPO Export %d pages to %s. Report Format PO Files PO Your source PO messages.po Project DE FR JA LOC MyApp.loc messages.poPO New Order Customer: reports.poPO Export %d pages to %s. Report Format PO Files PO

Translation Hints match Source Order {0} has been saved. Order %1 has been saved. Order %s has been saved. Current Bestellung {0} wurde gesichert. Bestellung %1 wurde gesichert. Bestellung %s wurde gesichert. DeepL Bestellung {0} wurde gespeichert. Bestellung %1 wurde gespeichert. Bestellung %s wurde gespeichert. 86% Google Translate Bestellung wurde gespeichert. Missing {0} Missing %1 Missing %s 71% ! Azure Translator Die Bestellung {0} wurde gespeichert. Die Bestellung %1 wurde gespeichert. Die Bestellung %s wurde gespeichert. 79% Translation memory Bestellung {0} gespeichert. Bestellung %1 gespeichert. Bestellung %s gespeichert. 68% Translation Hints match Source Order {0} has been saved. Order %1 has been saved. Order %s has been saved. Current Bestellung {0} wurde gesichert. Bestellung %1 wurde gesichert. Bestellung %s wurde gesichert. DeepL 86% Bestellung {0} wurde gespeichert. Bestellung %1 wurde gespeichert. Bestellung %s wurde gespeichert. Google Translate 71% ! Bestellung wurde gespeichert. Missing {0} Missing %1 Missing %s Azure Translator 79% Die Bestellung {0} wurde gespeichert. Die Bestellung %1 wurde gespeichert. Die Bestellung %s wurde gespeichert. Translation memory 68% Bestellung {0} gespeichert. Bestellung %1 gespeichert. Bestellung %s gespeichert.
Your files TMX XLIFF CSV Open file Ship today 100% Print preview Notify the customer. 95% Microsoft terms Cancel Folder Quantity only what matches the project Project Translation memory Ship today Noch heute versenden Notify the customer. Kunde benachrichtigen. Terminology Cancel Abbrechen Quantity Menge Your files TMX XLIFF CSV Open file Ship today100% Print preview Notify the customer.95% Microsoft terms CancelFolderQuantity only what matches the project Project Translation memory Ship today Noch heute versenden Notify the customer. Kunde benachrichtigen. Terminology Cancel→Abbrechen Quantity→Menge
ProjectDEFRJAMyApp.locmessages.poNew Orderreports.po PrepareTranslationTaskImportTranslationResults TranslatorDENew OrderNeue BestellungCustomer:Kunde:CreateErstellenSourceGermanNew OrderNeue BestellungCustomer:Kunde:Quantity:Menge:Validation on save Or their CAT toolXLIFF 1.2for the tool the translatoralready uses ProjectDEFRJAMyApp.locmessages.poNew Orderreports.po PrepareTranslation Task TranslatorDENew OrderNeue BestellungCustomer:Kunde:CreateErstellenSourceGermanNew OrderNeue BestellungCustomer:Kunde:Quantity:Menge:Validation on save Or their CAT toolXLIFF 1.2for the tool the translatoralready uses ImportResults
  1. Translation Hints match Source Order {0} has been saved. Order %1 has been saved. Order %s has been saved. Current Bestellung {0} wurde gesichert. Bestellung %1 wurde gesichert. Bestellung %s wurde gesichert. DeepL Bestellung {0} wurde gespeichert. Bestellung %1 wurde gespeichert. Bestellung %s wurde gespeichert. 86% Google Translate Bestellung wurde gespeichert. Missing {0} Missing %1 Missing %s 71% ! Azure Translator Die Bestellung {0} wurde gespeichert. Die Bestellung %1 wurde gespeichert. Die Bestellung %s wurde gespeichert. 79% Translation memory Bestellung {0} gespeichert. Bestellung %1 gespeichert. Bestellung %s gespeichert. 68% Translation Hints match Source Order {0} has been saved. Order %1 has been saved. Order %s has been saved. Current Bestellung {0} wurde gesichert. Bestellung %1 wurde gesichert. Bestellung %s wurde gesichert. DeepL 86% Bestellung {0} wurde gespeichert. Bestellung %1 wurde gespeichert. Bestellung %s wurde gespeichert. Google Translate 71% ! Bestellung wurde gespeichert. Missing {0} Missing %1 Missing %s Azure Translator 79% Die Bestellung {0} wurde gespeichert. Die Bestellung %1 wurde gespeichert. Die Bestellung %s wurde gespeichert. Translation memory 68% Bestellung {0} gespeichert. Bestellung %1 gespeichert. Bestellung %s gespeichert.
  2. Your files TMX XLIFF CSV Open file Ship today 100% Print preview Notify the customer. 95% Microsoft terms Cancel Folder Quantity only what matches the project Project Translation memory Ship today Noch heute versenden Notify the customer. Kunde benachrichtigen. Terminology Cancel Abbrechen Quantity Menge Your files TMX XLIFF CSV Open file Ship today100% Print preview Notify the customer.95% Microsoft terms CancelFolderQuantity only what matches the project Project Translation memory Ship today Noch heute versenden Notify the customer. Kunde benachrichtigen. Terminology Cancel→Abbrechen Quantity→Menge
  3. ProjectDEFRJAMyApp.locmessages.poNew Orderreports.po PrepareTranslationTaskImportTranslationResults TranslatorDENew OrderNeue BestellungCustomer:Kunde:CreateErstellenSourceGermanNew OrderNeue BestellungCustomer:Kunde:Quantity:Menge:Validation on save Or their CAT toolXLIFF 1.2for the tool the translatoralready uses ProjectDEFRJAMyApp.locmessages.poNew Orderreports.po PrepareTranslation Task TranslatorDENew OrderNeue BestellungCustomer:Kunde:CreateErstellenSourceGermanNew OrderNeue BestellungCustomer:Kunde:Quantity:Menge:Validation on save Or their CAT toolXLIFF 1.2for the tool the translatoralready uses ImportResults

Output · Validation Inconsistent format string messages.po · Export Fixed Resource messages.po · Export Source Export {0} pages to {1}. Export %d pages to %s. Export <b>all</b> pages. Export %1 pages to %2. German {0} Seiten nach {2} exportieren. %d Seiten nach %d exportieren. <b>Alle</i> Seiten exportieren. %1 Seiten nach %3 exportieren. {0} Seiten nach {1} exportieren. %d Seiten nach %s exportieren. <b>Alle</b> Seiten exportieren. %1 Seiten nach %2 exportieren. Output · Validation Inconsistent format string messages.po · Export Fixed messages.po · Export Source Export {0} pages to {1}. Export %d pages to %s. Export <b>all</b> pages. Export %1 pages to %2. German {0} Seiten nach {2} exportieren. %d Seiten nach %d exportieren. <b>Alle</i> Seiten exportieren. %1 Seiten nach %3 exportieren. {0} Seiten nach {1} exportieren. %d Seiten nach %s exportieren. <b>Alle</b> Seiten exportieren. %1 Seiten nach %2 exportieren.
  1. Output · Validation Inconsistent format string messages.po · Export Fixed Resource messages.po · Export Source Export {0} pages to {1}. Export %d pages to %s. Export <b>all</b> pages. Export %1 pages to %2. German {0} Seiten nach {2} exportieren. %d Seiten nach %d exportieren. <b>Alle</i> Seiten exportieren. %1 Seiten nach %3 exportieren. {0} Seiten nach {1} exportieren. %d Seiten nach %s exportieren. <b>Alle</b> Seiten exportieren. %1 Seiten nach %2 exportieren. Output · Validation Inconsistent format string messages.po · Export Fixed messages.po · Export Source Export {0} pages to {1}. Export %d pages to %s. Export <b>all</b> pages. Export %1 pages to %2. German {0} Seiten nach {2} exportieren. %d Seiten nach %d exportieren. <b>Alle</i> Seiten exportieren. %1 Seiten nach %3 exportieren. {0} Seiten nach {1} exportieren. %d Seiten nach %s exportieren. <b>Alle</b> Seiten exportieren. %1 Seiten nach %2 exportieren.

Project Open Öffnen Save Speichern Print Drucken Export Exportieren Removed Help Hilfe Scan for Changes New build Open Öffnen Save Speichern Print all Updated Help Hilfe Share New Project Öffnen Speichern Drucken Exportieren Hilfe Removed Scan for Changes New build Open Öffnen Save Speichern Print all Updated Help Hilfe Share New
  1. Project Open Öffnen Save Speichern Print Drucken Export Exportieren Removed Help Hilfe Scan for Changes New build Open Öffnen Save Speichern Print all Updated Help Hilfe Share New Project Öffnen Speichern Drucken Exportieren Hilfe Removed Scan for Changes New build Open Öffnen Save Speichern Print all Updated Help Hilfe Share New

Your tools extract, Lingobit translates, msgfmt compiles.

xgettext or pybabel extract collects the marked strings into messages.pot, and msgen turns it into an English messages.po, in which every msgstr holds the English text. Lingobit translates those texts and writes one .po file for each language. msgfmt or your framework compiles them into .mo files, which gettext loads at runtime.

Your Python projectLingobit msgenPOmessages.potranslate, checkDEde\messages.pomsgfmt Extract, then msgenLingobit translates the PO filemsgfmt compiles .mo Your Python project msgenPOmessages.poLingobittranslate, checkDEde\messages.pomsgfmt

Lingobit does

  • Translates the msgstr text of every message; msgid stays the key.
  • Reuses earlier translations and the translation memory.
  • Checks placeholders such as %s and %d, line breaks, empty and too long translations, and more.
  • Writes a translated .po file for each language and keeps the rest of the file as it was.

Your Python project keeps

  • Marking strings with _(), extracting them, and making the English .po file.
  • Compiling .po into .mo with msgfmt, pybabel compile, or compilemessages.
  • Loading the catalog at runtime and choosing the language.
  • The final test in the running application.

Reference

At startup, gettext finds the catalog by its folder.

msgfmt turns de\messages.po into messages.mo in locale\de\LC_MESSAGES, and gettext.translation looks for it there. For German (Germany) it tries de_DE first, then de, so one German catalog serves every German-speaking country.

Your code asksGerman (Germany)de_DE gettext looks inlocale\de_DEnot shippedlocale\deloaded Your application Neue BestellungKunde:Report Without a translation, a string shows its source text. Your code asksGerman (Germany)de_DE gettext looks inlocale\de_DEnot shippedlocale\deloaded Neue BestellungKunde:Report Without a translation, a string shows its source text.
  • A missing message shows the source text. A string that is new or still untranslated appears in English; it does not break the application.
  • A missing catalog is an error unless you pass fallback=True; then the whole application stays in English.
import gettext

t = gettext.translation("messages", localedir="locale",
                        languages=["de_DE"], fallback=True)
t.install()   # _() now returns the German text

Write the files into the locale folder.

By default Lingobit writes de\messages.po into the output folder of the project. To get the full layout gettext expects, change the output path in the project settings for PO, on the Encoding / Output page, so the files go into locale\de\LC_MESSAGES.

  • Language folders follow gettext. German writes de, German (Germany) writes de_DE; gettext finds both.
  • Compile next to the .po file with msgfmt -o messages.mo messages.po in each folder, or with pybabel compile -d locale.

Choose the language in your app.

On Windows, gettext does not read the Windows language: it looks at the LANGUAGE, LC_ALL, LC_MESSAGES, and LANG variables, which are usually not set there. Pass the language yourself:

  1. List the languages you ship from the folders in locale.
  2. Read the saved choice or a command-line switch; otherwise use the language you detect for the user.
  3. Install the catalog first before you import modules that call _() at import time.
  4. Switch while running by installing another catalog and rebuilding the windows, or restart.
import gettext, sys

lang = sys.argv[1] if len(sys.argv) > 1 else saved_language()
gettext.translation("messages", localedir="locale",
                    languages=[lang], fallback=True).install()

from myapp.main_window import MainWindow   # after install()

What Lingobit reads in a PO file.

Lingobit translates the msgstr text and writes the rest back as it was, apart from the fuzzy flag of translated messages. A .pot template, or a .po file with empty msgstr, has nothing to translate: make the English file with msgen first.

PO elements, how Lingobit uses them, and what the translated file contains
In the PO fileIn LingobitIn the translated file
msgidThe message key in the tree, also when it is wrapped over several lines; translations are matched by itUnchanged
msgstrThe text that is translated, also when it spans several lines; \" and \n are handledThe translation
Plural forms: msgstr[0], msgstr[1]Each form is translatedThe translated forms, with the forms and the Plural-Forms header of the English file: right for German, Spanish, or Italian. Russian, Polish, or French keep the English rule
msgctxtPart of the key: the same msgid in two contexts gets two translationsUnchanged
Comments #.Shown to translators in Translation HintsUnchanged
Flags #,Not shownfuzzy removed from translated messages; other flags unchanged
HeaderNot translated; its charset is used to read the fileWritten in UTF-8, with charset=UTF-8
msgen messages.pot -o messages.po

Do and don't.

Do

  • Refresh the English messages.po with msgen before every handoff, and run Scan for Changes.
  • Use %s, %d, or named %(count)d placeholders, and ask translators to keep the names.
  • Keep the domain and folder names in line with your loading code.

Don't

  • Add the .pot template or a .po file with empty msgstr.
  • Edit the translated .po files by hand: the next Create overwrites them.
  • Build sentences in code from translated pieces.
  • Send Python code or templates to translators.

Troubleshooting.

Symptoms, causes, and what to do
SymptomLikely causeWhat to do
Messages have no text to translate in LingobitThe file is a .pot template, or a .po file whose msgstr is emptyMake the English file with msgen and add it instead
The application stays in EnglishNo .mo file was built, it is not in locale\de\LC_MESSAGES, the domain differs, or no language was passed on WindowsCompile the translated .po files, check the folder and the domain, and pass the language to gettext.translation
The application fails with one languageA translation breaks a placeholder: a lost %s, or a translated name inside %(count)d or {name}Run Validation: it reports %s and %d that do not match the source. Check named placeholders in the running application
German text is cut off in the application.po files have no preview, so long text shows only in the running applicationSet a maximum length for the strings in Lingobit; Validation reports translations that exceed it

More about Python gettext localization.

PO, POT, and MO files

.pot templates are written by extraction tools from Python code, templates, or framework sources; their msgstr entries are empty. .po files are the translation catalogs: Lingobit reads the English one, made with msgen, and writes a translated one for each language. .mo files are the compiled runtime catalogs that developer or framework tools build from the translated .po files.

messages.pot
messages.po                         (English, made with msgen)
locale/de/LC_MESSAGES/messages.po
locale/de/LC_MESSAGES/messages.mo
Babel, Django, and framework workflows

Python projects reach gettext catalogs through different toolchains, and all of them lead to the same English .po handoff:

  • Plain gettext: generate the .pot template, make the English .po with msgen, compile the translated catalogs into .mo.
  • Babel / pybabel: run pybabel extract, make the English .po with msgen, compile with pybabel compile.
  • Django and similar frameworks: make the English catalog with makemessages and fill it with msgen, build the runtime catalogs with compilemessages.
Clear boundaries
  • Lingobit does not replace xgettext, pybabel, Django makemessages and compilemessages, or the framework's own i18n setup.
  • It does not compile or load runtime catalogs, and Python source files or templates are not the translator's handoff.
  • Packaging the locale folders and loading the translations at runtime stay with the application.