polib
polib is a pure Python library designed to manipulate gettext files, specifically .po (Portable Object) and .mo (Machine Object) files. It enables loading, creating, modifying, and saving these translation files. The library is stable, widely used, and supports Python versions from 2.7 to the latest 3.x. Its release cadence is irregular but indicates active maintenance, with version 1.2.0 released in February 2023.
Warnings
- breaking Support for Python versions older than 2.7 was dropped in version 1.1.1.
- gotcha Enabling `check_for_duplicates=True` when adding entries to a POFile can significantly slow down performance, especially with large files.
- gotcha Refactoring of `POEntry.__cmp__` method in version 1.1.0 might affect custom sorting logic or assumptions about entry comparison.
- gotcha Prior to version 1.1.1, `polib` might not correctly handle Message Context (`msgctxt`) in MO files. Additionally, older versions (<=1.0.3) could raise exceptions during `POFile.append()` with `check_for_duplicates=True` if `msgid` was the same but `msgctxt` differed.
- gotcha How `polib` wraps 'occurrences' (the `#: reference...` lines) might differ from `xgettext --no-wrap` output, potentially leading to inconsistencies if strict byte-for-byte matching is expected.
Install
-
pip install polib
Imports
- polib
import polib
- pofile
po = polib.pofile('path/to/catalog.po') - mofile
mo = polib.mofile('path/to/catalog.mo') - POFile
new_po = polib.POFile()
- POEntry
entry = polib.POEntry(msgid='Hello', msgstr='Hola')
Quickstart
import polib
import os
# Create a dummy .po file for demonstration
dummy_po_content = '''\
msgid ""
msgstr ""
"Project-Id-Version: test\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"MIME-Version: 1.0\n"
"X-Generator: Python-polib\n"
#: main.py:10
msgid "Hello, world!"
msgstr ""
#: another.py:5
msgid "Another message"
msgstr "Other message"
'''
# Load an existing PO file (or from a string)
# For a real file, use: pofile = polib.pofile('/path/to/your/file.po')
pofile = polib.pofile(dummy_po_content)
print("\n--- Iterating through entries ---")
for entry in pofile:
print(f"Msgid: {entry.msgid}, Msgstr: {entry.msgstr}")
# Add a new entry
new_entry = polib.POEntry(
msgid='New string',
msgstr='Nueva cadena',
comment='A new comment for this string',
occurrences=[('app.py', '20')]
)
pofile.append(new_entry)
print("\n--- After adding a new entry ---")
for entry in pofile:
print(f"Msgid: {entry.msgid}, Msgstr: {entry.msgstr}")
# Modify an entry
if pofile.find('Hello, world!'):
entry_to_modify = pofile.find('Hello, world!')
entry_to_modify.msgstr = '¡Hola, mundo!'
entry_to_modify.comment = 'Translated by quickstart'
print("\n--- After modifying an entry ---")
for entry in pofile:
print(f"Msgid: {entry.msgid}, Msgstr: {entry.msgstr}")
# Save the modified PO file (to a dummy path for demonstration)
dummy_output_path = 'temp_output.po'
pofile.save(dummy_output_path)
print(f"\nSaved modified PO file to {dummy_output_path}")
# Clean up the dummy file
os.remove(dummy_output_path)
print(f"Cleaned up {dummy_output_path}")