Strict-typed, dependency-free gettext-compatible i18n library (PO/MO parser, Plural-Forms evaluator, Catalog API).
Project description
pomo-i18n
English | 日本語
A minimal, strictly-typed gettext-compatible internationalization library for Python.
pomo-i18n provides .po and .mo parsing, safe plural-form evaluation, and a clean Pythonic API (gettext, ngettext, translation) — all without external dependencies.
Features
- ✔ Parse
.poand.mofiles (GNU gettext format) - ✔ Full plural-forms support (
Plural-Forms:header) - ✔ Safe plural expression evaluator (C-style → Python AST)
- ✔ Strict typing (mypy / Pylance friendly)
- ✔ Pure Python, no external libraries
- ✔ Works on Linux / macOS / Windows
Installation
pip install pomo-i18n
Or vendor it directly:
src/
└─ pypomo/
Documentation
Quick Example
from pypomo.gettext import translation
t = translation(
domain="messages",
localedir="locales",
languages=["en"],
)
_ = t.gettext
print(_("Hello"))
print(t.ngettext("apple", "apples", 1))
print(t.ngettext("apple", "apples", 3))
Expected directory layout:
locales/
└─ en/
└─ LC_MESSAGES/
└─ messages.po
.po Parsing
pomo-i18n contains a robust standalone .po parser:
-
msgid,msgstr -
plurals (
msgid_plural,msgstr[n]) -
multiline strings
-
Supports standard gettext comments:
#(translator comments)#.(extracted comments)#:(source references)#, flags(parsed as regular comments;fuzzywill be supported in a future release)
-
header extraction (
msgid "")
.mo Writing
Compile a Catalog into a .mo file:
from pypomo.catalog import Catalog
from pypomo.mo.writer import write_mo
from pypomo.parser.types import POEntry
entries = [
POEntry(
msgid="",
msgstr=(
"Language: en\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
),
msgid_plural=None,
msgstr_plural={},
comments=[],
),
POEntry("Hello", "Hello!", None, {}, []),
]
cat = Catalog.from_po_entries(entries)
write_mo("messages.mo", cat)
The generated .mo file is fully compatible with Python’s built-in gettext.GNUTranslations.
.mo Loading
pomo-i18n can also load GNU gettext .mo files back into a Catalog:
from pypomo.mo.loader import load_mo
cat = load_mo("messages.mo")
_ = cat.gettext
print(_("Hello"))
Features:
- verifies magic number (0x9504120E)
- parses msgid/msgstr tables
- handles plural entries correctly
- extracts
Plural-Forms:from the header
Plural Forms
pomo-i18n safely evaluates C-style plural rules:
Example:
Plural-Forms: nplurals=2; plural=(n != 1);
Russian example:
Plural-Forms: nplurals=3;
plural=(n%10==1 && n%100!=11 ? 0 :
n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);
Expressions are converted to safe Python AST and evaluated with an isolated environment.
Benchmarks
Plural-rule evaluation is optimized and supports multiple cache backends:
- none — debugging only
- weak — dict-based cache
- lru — fastest (default)
Set via environment variable:
export PYPOMO_CACHE=lru
export PYPOMO_PLURAL_CACHE_SIZE=512
Roadmap
- Message merging & locale fallbacks
- Richer comment parsing (
#, fuzzy,#.extracted tags) - CLI utilities for generating
.potfiles - Locale auto-detection helpers
License
MIT License © 2025 Kiminori Kato
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pomo_i18n-0.1.7.tar.gz.
File metadata
- Download URL: pomo_i18n-0.1.7.tar.gz
- Upload date:
- Size: 27.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
af37badb8444695379fe6edd4ccbf9f37805ac66211cfb4afdc11fb410e9a2ba
|
|
| MD5 |
79ffd542e804e2ae6a61c3d17177c93c
|
|
| BLAKE2b-256 |
86bce4e5b4ea175205ae3f774f679caf1b96af5172bf540e16c048a3daecd1f7
|
Provenance
The following attestation bundles were made for pomo_i18n-0.1.7.tar.gz:
Publisher:
release.yml on kimikato/pomo-i18n
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pomo_i18n-0.1.7.tar.gz -
Subject digest:
af37badb8444695379fe6edd4ccbf9f37805ac66211cfb4afdc11fb410e9a2ba - Sigstore transparency entry: 742084422
- Sigstore integration time:
-
Permalink:
kimikato/pomo-i18n@d0637cb1ed6f2b4ddf9aa97e8256f4636ec7cde6 -
Branch / Tag:
refs/tags/v0.1.7 - Owner: https://github.com/kimikato
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d0637cb1ed6f2b4ddf9aa97e8256f4636ec7cde6 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pomo_i18n-0.1.7-py3-none-any.whl.
File metadata
- Download URL: pomo_i18n-0.1.7-py3-none-any.whl
- Upload date:
- Size: 3.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
82c12b343b5cae374e15958060f0e23e5d3c3886bdd167f87dde59479e9f8def
|
|
| MD5 |
a7982fa7cd22a891371994a32ba77ee1
|
|
| BLAKE2b-256 |
70e597b8c64e47ff9248d0be223427d583a84d8b53eea61ff4a6c71a6d88a160
|
Provenance
The following attestation bundles were made for pomo_i18n-0.1.7-py3-none-any.whl:
Publisher:
release.yml on kimikato/pomo-i18n
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pomo_i18n-0.1.7-py3-none-any.whl -
Subject digest:
82c12b343b5cae374e15958060f0e23e5d3c3886bdd167f87dde59479e9f8def - Sigstore transparency entry: 742084437
- Sigstore integration time:
-
Permalink:
kimikato/pomo-i18n@d0637cb1ed6f2b4ddf9aa97e8256f4636ec7cde6 -
Branch / Tag:
refs/tags/v0.1.7 - Owner: https://github.com/kimikato
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d0637cb1ed6f2b4ddf9aa97e8256f4636ec7cde6 -
Trigger Event:
push
-
Statement type: