How to translate PO and POT files

PO and POT files are at the heart of gettext-based localization workflows, powering translations for frameworks like Django, WordPress, GNU projects, and many desktop or CLI apps. They've been around for decades and remain a standard in open-source and enterprise software. But how do you actually translate them?
In this guide, you'll learn how to translate PO and POT files effectively, avoid common issues, and adopt tools that make the workflow faster and safer.
What are PO and POT files?
PO (Portable Object) files store translations for a given language.
POT (Portable Object Template) files act as the source template, they contain original strings (msgid
) but no translations yet.
Together, they form the gettext ecosystem for handling i18n strings.
Here's a basic example:
# SOME DESCRIPTIVE TITLE.
# Copyright (C) 2025 Pillow Hotel
# This file is distributed under the same license as the Pillow Hotel project.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2025.
#
msgid ""
msgstr ""
"Project-Id-Version: Pillow Hotel 1.0\n"
"Language: es\n"
"Content-Type: text/plain; charset=UTF-8\n"
#: templates/index.html:10
msgid "Welcome to Pillow Hotel"
msgstr "Bienvenido al Hotel Almohada"
#: templates/index.html:15
msgid "Book Now"
msgstr "Reservar ahora"
PO/POT files characteristics
Here are some key characteristics of PO/POT files:
- File extensions: .po (translations), .pot (template).
- Structure:
- 'msgid' for source strings.
- 'msgstr' for translated strings.
- Headers store metadata (project, language, encoding, plural forms).
- Comments:
- Default comments (#).
- Translator comments (#.).
- References (#: file:line).
- Flags (#, fuzzy).
- Plural forms handled explicitly with indexed
msgstr[n]
. - Standardized format widely supported across frameworks and tools.
PO/POT in i18n frameworks
PO/POT files are used by many ecosystems:
- Django: uses PO files for translations, with built-in support for extracting and compiling them.
- WordPress: relies on
.po/.mo
files inlanguages
directories for themes and plugins. - GNU/Linux apps: gettext standard across CLI and desktop tools
- Flask, Pyramid, PHP gettext: rely on PO files for translations
- C, C++ projects: GNU gettext-native
Common challenges in translating PO files
Even though PO files are straightforward, translators often face challenges:
- Fuzzy translations: Marked as uncertain, may slip into production unnoticed.
- Plural forms: Different languages have 2–6 plural categories; mismatched rules break logic.
- Encoding issues: UTF-8 vs. ISO-8859-1 can cause corrupted characters.
- Context loss: Same msgid in different places may need different translations.
- Comments ignored: Developers forget to add #. translator notes.
- Sync issues: POT updated, but PO not regenerated → missing translations.
- Merge conflicts: Multiple translators editing the same
.po
file.
Here's a broken example:
#: booking.html:12
msgid "Room"
msgstr "Habitación"
#: stats.html:45
msgid "Room"
msgstr "Sala" # ❌ Inconsistent translation, context missing
msgid "You have %d rooms"
msgid_plural "You have %d rooms"
msgstr[0] "Tienes %d habitación" # ❌ Wrong plural form
msgstr[1] "" # ❌ Empty translation
How to translate PO files
There are several ways to translate PO files, depending on the project size, team skills, and budget.
Manual translation
Small projects may translate PO files manually with a text editor.
- Duplicate the .
pot
into.po
for a target language. - Open the
.po
file in a text editor. - Fill in each
msgstr
with the translation. - Keep plural rules consistent with the language header.
- Compile
.po
into.mo
usingmsgfmt
before deploying.

You can translate .po
files either in a text editor or in a gettext-aware editor that validates syntax and plural rules. This gives you full control but also requires caution to avoid mistakes.
Pros: no extra tools, maximum control.
Cons: error-prone, slow, poor collaboration.
Localization platform (recommended)
Modern localization platforms like SimpleLocalize provide a user-friendly interface for translating PO files.
Here are the steps:
- Import
.po
or.pot
files into the platform. - Pre-translate new strongs using auto-translation.
- Collaborate with translators in a shared UI.
- QA check: placeholders, length, plural rules, fuzzy entries.
- Export clean
.po
files back into your repo. - Automate sync in CI for continuous updates.
Pros: scalable, context-rich, automated sync.
Cons: requires adopting a new tool.
Learn more about translating PO files with SimpleLocalize.
Best practices for translating PO files
When working with PO/POT translation files, follow these best practices:
- Keep POT up to date: Run
xgettext
whenever source changes. - Sync PO files regularly with
msgmerge
or automation. - Freeze source strings before translation to avoid churn.
- Add translator notes (#.) for ambiguous terms.
- Use placeholders consistently:
%s
,%d
, or{name}
should be documented. - Handle plurals correctly: Define plural rules in headers, provide all forms.
- Validate before shipping: Run
msgfmt --check
to catch errors. - Avoid context collisions: Use
pgettext
for identical strings with different meanings. - Review fuzzy entries: Ensure they are accurate before finalizing.
- Backup PO files: Use version control to track changes and revert if needed.
Automate PO translation with SimpleLocalize
You can turn gettext workflows into a smooth CI/CD step with SimpleLocalize:
- Connect your repository with GitHub App, GitLab, Bitbucket, or upload files directly.
- Import and scan all strings, with full msgid/msgstr structure.
- Pre-translate automatically. Run auto-translation for new or changed strings to create a high-quality draft instantly.
- Review with context. Attach screenshots, descriptions, comments.
- Keep translations in sync. Detect new
msgids
and auto-translate using an automation. - Export production-ready PO files with a single click, via CI or API.
- Make it continuous. Wire SimpleLocalize into CI so every push:
- imports updated PO/POT files,
- triggers pre-translation,
- and exports ready-to-deploy files.
Check more examples of AI-powered localization workflows.
FAQ
What is the difference between PO and POT files?
POT files are templates containing all source strings (msgid) but no translations. PO files are language-specific, storing the translated strings (msgstr). Think of POT as the blueprint and PO as the finished translation.
What is the difference between PO and MO files?
PO files are human-readable text files used for translations. MO (Machine Object) files are the compiled binary versions of PO files that gettext libraries use at runtime for faster access.
How do I create a POT file?
You can create a POT file using the xgettext
command-line tool. For example:
xgettext -o messages.pot source_file1.py source_file2.py
How do I update a PO file when the source text changes?
Use the msgmerge
tool to merge changes from the updated POT file into your existing PO files:
msgmerge -U translations.po messages.pot
Or use a localization platform like SimpleLocalize to automate this process.
How do I handle plural forms in PO files?
Define the plural rules in the PO file header. For example, for English:
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
Then provide translations for each plural form:
msgid "You have %d message"
msgid_plural "You have %d messages"
msgstr[0] "Tienes %d mensaje"
msgstr[1] "Tienes %d mensajes"
What is a “fuzzy” translation in a PO file?
Fuzzy translations are marked as uncertain (#, fuzzy
) when gettext cannot confirm accuracy. Review and correct these before deploying.
How often should I update PO files?
Update PO files whenever the source strings change. Regularly sync them with the latest POT file to ensure all translations are current.
Are there tools that help automate PO translations?
Yes, localization platforms like SimpleLocalize, Lokalise, or Crowdin offer collaborative translation, QA checks, auto-translation, and CI/CD integration.
Conclusion
PO and POT files are a cornerstone of gettext localization, powerful but tricky when managed manually. By combining good practices (plural rules, context, regular sync) with automation and collaboration in a platform like SimpleLocalize, you can eliminate fuzzy errors, merge conflicts, and tedious manual edits.
Upload your PO files, auto-translate them, invite reviewers, and export production-ready translations in minutes. Ready to streamline your gettext workflow? Import your PO files to SimpleLocalize and ship multilingual software with confidence.