{"id":2195,"library":"polib","title":"polib","description":"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.","status":"active","version":"1.2.0","language":"en","source_language":"en","source_url":"https://github.com/izimobil/polib/","tags":["gettext","i18n","l10n","po","mo","translation","internationalization","localization"],"install":[{"cmd":"pip install polib","lang":"bash","label":"Install latest version"}],"dependencies":[],"imports":[{"symbol":"polib","correct":"import polib"},{"note":"Used to load an existing .po file or string.","symbol":"pofile","correct":"po = polib.pofile('path/to/catalog.po')"},{"note":"Used to load an existing .mo file.","symbol":"mofile","correct":"mo = polib.mofile('path/to/catalog.mo')"},{"note":"Class for creating a new .po file object.","symbol":"POFile","correct":"new_po = polib.POFile()"},{"note":"Class for creating a new PO file entry.","symbol":"POEntry","correct":"entry = polib.POEntry(msgid='Hello', msgstr='Hola')"}],"quickstart":{"code":"import polib\nimport os\n\n# Create a dummy .po file for demonstration\ndummy_po_content = '''\\\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: test\\n\"\n\"Content-Type: text/plain; charset=utf-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"MIME-Version: 1.0\\n\"\n\"X-Generator: Python-polib\\n\"\n\n#: main.py:10\nmsgid \"Hello, world!\"\nmsgstr \"\"\n\n#: another.py:5\nmsgid \"Another message\"\nmsgstr \"Other message\"\n'''\n\n# Load an existing PO file (or from a string)\n# For a real file, use: pofile = polib.pofile('/path/to/your/file.po')\npofile = polib.pofile(dummy_po_content)\n\nprint(\"\\n--- Iterating through entries ---\")\nfor entry in pofile:\n    print(f\"Msgid: {entry.msgid}, Msgstr: {entry.msgstr}\")\n\n# Add a new entry\nnew_entry = polib.POEntry(\n    msgid='New string',\n    msgstr='Nueva cadena',\n    comment='A new comment for this string',\n    occurrences=[('app.py', '20')]\n)\npofile.append(new_entry)\n\nprint(\"\\n--- After adding a new entry ---\")\nfor entry in pofile:\n    print(f\"Msgid: {entry.msgid}, Msgstr: {entry.msgstr}\")\n\n# Modify an entry\nif pofile.find('Hello, world!'):\n    entry_to_modify = pofile.find('Hello, world!')\n    entry_to_modify.msgstr = '¡Hola, mundo!'\n    entry_to_modify.comment = 'Translated by quickstart'\n\nprint(\"\\n--- After modifying an entry ---\")\nfor entry in pofile:\n    print(f\"Msgid: {entry.msgid}, Msgstr: {entry.msgstr}\")\n\n# Save the modified PO file (to a dummy path for demonstration)\ndummy_output_path = 'temp_output.po'\npofile.save(dummy_output_path)\nprint(f\"\\nSaved modified PO file to {dummy_output_path}\")\n\n# Clean up the dummy file\nos.remove(dummy_output_path)\nprint(f\"Cleaned up {dummy_output_path}\")","lang":"python","description":"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."},"warnings":[{"fix":"Ensure your project runs on Python 2.7 or a Python 3.x version. Upgrade your Python environment if necessary.","message":"Support for Python versions older than 2.7 was dropped in version 1.1.1.","severity":"breaking","affected_versions":"< 1.1.1"},{"fix":"Use `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.","message":"Enabling `check_for_duplicates=True` when adding entries to a POFile can significantly slow down performance, especially with large files.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Review any code that relies on implicit or explicit comparison of `POEntry` objects after upgrading to version 1.1.0 or later.","message":"Refactoring of `POEntry.__cmp__` method in version 1.1.0 might affect custom sorting logic or assumptions about entry comparison.","severity":"gotcha","affected_versions":"< 1.1.0"},{"fix":"Upgrade 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.","message":"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.","severity":"gotcha","affected_versions":"< 1.1.1 and <= 1.0.3"},{"fix":"If 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.","message":"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.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-09T00:00:00.000Z","next_check":"2026-07-08T00:00:00.000Z"}