Install & Compatibility
Where this runs
tested against v1.2.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.95 runs
installs and imports cleanly · install 0.0s · import 0.006s · 17.9MB
glibcpy 3.10–3.95 runs
installs and imports cleanly · install 1.7s · import 0.006s · 18MB
16MB installed
● package 16MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
pofile
✓ po = polib.pofile('path/to/catalog.po')
Used to load an existing .po file or string.
mofile
✓ mo = polib.mofile('path/to/catalog.mo')
Used to load an existing .mo file.
POFile
✓ new_po = polib.POFile()
Class for creating a new .po file object.
POEntry
✓ entry = polib.POEntry(msgid='Hello', msgstr='Hola')
Class for creating a new PO file entry.
This quickstart demonstrates how to load a PO file (from a string for simplicity), iterate through its entries, add a new entry, modify an existing entry, and save the changes. For real-world use, replace `polib.pofile(dummy_po_content)` with `polib.pofile('/path/to/your/file.po')` to load from a file.
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}")
Debug
Known issues
breakingSupport for Python versions older than 2.7 was dropped in version 1.1.1.fixEnsure your project runs on Python 2.7 or a Python 3.x version. Upgrade your Python environment if necessary.
affects: < 1.1.1
gotchaEnabling `check_for_duplicates=True` when adding entries to a POFile can significantly slow down performance, especially with large files.fixUse `check_for_duplicates=False` if performance is critical and you are confident in your entry uniqueness, or implement custom batching/deduplication logic before adding entries.
affects: All versions
gotchaRefactoring of `POEntry.__cmp__` method in version 1.1.0 might affect custom sorting logic or assumptions about entry comparison.fixReview any code that relies on implicit or explicit comparison of `POEntry` objects after upgrading to version 1.1.0 or later.
affects: < 1.1.0
gotchaPrior 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.fixUpgrade to polib 1.1.1 or later for robust `msgctxt` support. If using `check_for_duplicates=True`, be aware of the older behavior and either upgrade or handle potential exceptions.
affects: < 1.1.1 and <= 1.0.3
gotchaHow `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.fixIf exact `xgettext` output formatting is required for occurrence lines, manual post-processing or specific `wrapwidth` configuration might be necessary. This is an ongoing discussion in the community.
affects: All versions
Errors
Common errors & fixes
ModuleNotFoundError: No module named 'polib'
The 'polib' library is not installed in your current Python environment.
fixInstall the library using pip: `pip install polib`
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x... in position ...: invalid start byte
The PO/MO file you are trying to read or write is not encoded in UTF-8, or has an encoding mismatch, causing Python to fail decoding specific byte sequences.
fixExplicitly specify the correct encoding when loading or saving the file, often after detecting it with `polib.detect_encoding()`. Example: `po = polib.pofile('path/to/file.po', encoding='latin-1')` TypeError: list indices must be integers or slices, not str
This error often occurs when incorrectly trying to assign an empty string directly to `POEntry.msgstr_plural` or attempting to access plural forms with string indices, while it expects a dictionary or a list of strings.
fixAssign `msgstr_plural` an empty dictionary `{}` or a list of empty strings `['', '']` (depending on plural forms) when initializing or clearing plural translations. Example: `entry.msgstr_plural = {'0': ''}` or `entry.msgstr_plural = ['', '']`. Upgrade
Version history
1.2.0latest on PyPI · released Feb 23, 2023
Audit
Dependencies
No dependency data recorded yet.