Skip to main content

py_intl

Python bindings for FormatJS's high-level Rust internationalization runtime.

python -m pip install py_intl
from datetime import date

from intl import Intl, IntlError, define_message

errors: list[IntlError] = []
intl = Intl(
    ["fr-CA", "fr"],
    "en",
    {"fr": {"hello": "Bonjour"}, "en": {}},
    on_error=errors.append,
)
assert intl.format_message("hello", default_message="Hello") == "Bonjour"

# IDs are optional and generated from the descriptor.
assert intl.format_message(default_message="Welcome") == "Welcome"

greeting = define_message(default_message="Hello, {name}!")
assert intl.format_message(greeting, values={"name": "Ada"}) == "Hello, Ada!"

created = define_message(default_message="Created {value, date, medium}")
assert intl.format_message(created, values={"value": date(2024, 1, 2)}) == "Created Jan 2, 2024"

Use the Intl instance negotiated for the current request. Generated IDs are locale-independent. on_error receives recovered missing-translation and formatting errors while format_message continues through FormatJS fallback. Datetime fields are formatted as supplied; convert timezone-aware values before formatting when another presentation timezone is required.

Reusing catalogs

Build a MessageCatalog once, then share it across request-scoped Intl instances:

from intl import Intl, MessageCatalog

catalog = MessageCatalog({"fr": {"hello": "Bonjour"}, "en": {"hello": "Hello"}})
intl = Intl(["fr-CA"], "en", catalog)
assert intl.format_message("hello") == "Bonjour"
assert catalog.negotiate(["fr-CA"], "en") == "fr"

MessageCatalog takes an immutable snapshot, normalizes locale keys, and converts messages to native storage once. Later changes to the input mapping have no effect. It can be shared across threads; create and use each Intl on its own thread. Each instance keeps its own error callback. Passing a mapping to Intl remains supported and converts it on every construction. Message compilation stays lazy and uses the shared process-wide cache with either input.

Compare construction costs with bazel run -c opt //python/intl:constructor_bench.

Generated message contracts

Generate typed Python wrappers from a FormatJS source catalog:

{
  "cart.total": {"defaultMessage": "{count, plural, other {# items}}"},
  "cart.empty": {"defaultMessage": "Your cart is empty"}
}
python -m intl.codegen en.json --out messages.py

Keep both generated files: messages.py supplies runtime wrappers; messages.pyi supplies message-specific TypedDict contracts. The stub uses typing_extensions.ReadOnly for Python 3.12 compatibility. The wrappers add no runtime dependency on typing_extensions.

from messages import cart_total, cart_empty

cart_total(intl, values={"count": 2})
cart_empty(intl)

# Type errors:
cart_total(intl)
cart_total(intl, values={"count": "two"})

Names derive from catalog IDs by replacing punctuation with underscores; leading digits and Python keywords receive a message_ prefix. Collisions are rejected. String catalogs and descriptors with defaultMessage and an optional string description are supported.

Contracts come from the Rust ICU parser, including apostrophe escapes and every nested branch. Numbers/plurals require int | float; dates/times accept date | datetime | int | float. Repeated arguments must satisfy every role. All contract fields are required and readonly to the type checker. Empty messages allow omitted values. Runtime dictionaries are not frozen.

Python's type system treats bool as an int, so static numeric checks cannot exclude booleans. Runtime formatting still checks values and translated messages. Rich tags are rejected during generation because Python Intl has no rich callback API. Raw Intl.format_message calls keep their existing dynamic interface; use the generated wrappers for per-message checks. Generate from source catalogs, not independently from each translation.

Metadata

Release files for py-intl 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for py-intl 0.4.0
File Actions
py_intl-0.4.0-cp312-abi3-manylinux_2_28_x86_64.whl CPython 3.12 abi3 Linux glibc 2.28+ x86-64 Details for py_intl-0.4.0-cp312-abi3-manylinux_2_28_x86_64.whl
py_intl-0.4.0-cp312-abi3-manylinux_2_28_aarch64.whl CPython 3.12 abi3 Linux glibc 2.28+ ARM64 Details for py_intl-0.4.0-cp312-abi3-manylinux_2_28_aarch64.whl
py_intl-0.4.0-cp312-abi3-macosx_11_0_x86_64.whl CPython 3.12 abi3 macOS 11.0+ x86-64 Details for py_intl-0.4.0-cp312-abi3-macosx_11_0_x86_64.whl
py_intl-0.4.0-cp312-abi3-macosx_11_0_arm64.whl CPython 3.12 abi3 macOS 11.0+ ARM64 Details for py_intl-0.4.0-cp312-abi3-macosx_11_0_arm64.whl

Total release size: 5.9 MB

Release files / py_intl-0.4.0-cp312-abi3-manylinux_2_28_x86_64.whl

Download URL py_intl-0.4.0-cp312-abi3-manylinux_2_28_x86_64.whl
Size 1.6 MB
Tags CPython 3.12 Linux glibc 2.28+ x86-64 abi3
SHA-256 checksum
How to use checksums
d45a7fde9961b8b8dc41053f95731bc963b4045521cd65bcfa8f375cdd64cc66
BLAKE2b-256 checksum
How to use checksums
5826788ddaa724b3b979ee35317a3b2e972eae13f74dc72970b2600c910c4e4e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Release files / py_intl-0.4.0-cp312-abi3-manylinux_2_28_aarch64.whl

Download URL py_intl-0.4.0-cp312-abi3-manylinux_2_28_aarch64.whl
Size 1.6 MB
Tags CPython 3.12 Linux glibc 2.28+ ARM64 abi3
SHA-256 checksum
How to use checksums
cc7b6b220db7a448c9f08c28df2ae8f078249c3ee6cb6fac287edfc150835c43
BLAKE2b-256 checksum
How to use checksums
33f3c9e6c4db6b8a3ea1bbab189833ef0701905605006dc5a35780610d2a8c9a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Release files / py_intl-0.4.0-cp312-abi3-macosx_11_0_x86_64.whl

Download URL py_intl-0.4.0-cp312-abi3-macosx_11_0_x86_64.whl
Size 1.4 MB
Tags CPython 3.12 abi3 macOS 11.0+ x86-64
SHA-256 checksum
How to use checksums
b22b5fd6fd1f625cf9369d43be9bac30abc8f17f84bdd8d36737c4943ae97701
BLAKE2b-256 checksum
How to use checksums
83c215d117eeccd32326394dc948772134e8bfd59460cc57aa9b326d3296b83e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Release files / py_intl-0.4.0-cp312-abi3-macosx_11_0_arm64.whl

Download URL py_intl-0.4.0-cp312-abi3-macosx_11_0_arm64.whl
Size 1.4 MB
Tags CPython 3.12 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
f36142967249fdda689bb837f8057411dd8fcb04373e046b7a4b4982f5f3a179
BLAKE2b-256 checksum
How to use checksums
c58a2fa391afddcf2e29932e2a4514786f0c6437fcd8e2c7acbec555a1f9dd46
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Security for py-intl 0.4.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 4 files in this release have been uploaded with provenance metadata.

Select from 4 files

Attestation for py_intl-0.4.0-cp312-abi3-manylinux_2_28_x86_64.whl

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page