Skip to main content
Sifr treats every boundary between bytes and text as an explicit, typed decision. There is no locale-derived default encoding, no implicit coercion from bytes to str, and no process-global locale mutation. You name the encoding, you get a typed error if the bytes don’t conform, and you can choose an error-recovery handler if you need one. This design makes text bugs visible at compile time rather than hiding them as runtime surprises.

Encoding: sifr.encoding

sifr.encoding is the byte/text conversion surface. Use it to encode a str to bytes or decode bytes to str with an explicitly named codec.

Codec Descriptors

Build a codec descriptor by calling one of the constructor functions:
Available Tier 0 descriptors (always supported): Tier 1 Windows-125x encodings (e.g., windows1252()) are available through encoding_rs. Tier 2 CJK and UTF-32 are deferred to a future release.

Error Handlers

By default, decode raises DecodeError on an invalid byte sequence. Supply an error handler to recover instead:
Error handlers are typed values — you pass them explicitly. Dynamic handler registration by name (as in CPython’s codecs.register_error) is unsupported.

Typed Errors

encode raises EncodeError when a character cannot be represented in the target encoding. decode raises DecodeError on invalid byte sequences. Both expose a .message field:

Text File I/O: sifr.io

Pass a codec descriptor to open_text whenever you open a text file. The encoding= parameter is required — omitting it raises SIFR-IO-0801:
See the I/O & Files page for full filesystem coverage.

Unicode: sifr.unicode

sifr.unicode provides normalization, scalar properties, and text segmentation using Unicode 17.0.0 data tables compiled into the Sifr runtime.

Normalization

normalize accepts a normalization form constant and a str, and returns the normalized form:

Scalar Properties

name returns the Unicode name of a scalar; category returns the two-letter general category:

Grapheme and Word Segmentation

graphemes splits a string into user-perceived grapheme clusters. words splits into word tokens, filtering punctuation and whitespace:
Unicode 17.0.0 data covers normalization, names, scalar properties, numeric values, case folding, grapheme boundaries, and word boundaries. Sentence boundaries and streaming segmentation cursors are deferred to a future release.
sifr.unicodedata is not a production API in this release. Do not import it. Use sifr.unicode instead.

Locale and I18n: sifr.i18n

sifr.i18n provides locale-aware number formatting, plural rules, and translation bundles. All state is scoped to explicit objects — there is no global locale, no locale.setlocale, and no gettext.install.

Locale Identifiers

Create a LocaleId from a BCP 47 tag:
host_locale() returns the host’s current locale as a read-only LocaleId. It cannot be used to make implicit text encodings legal.

Number Formatting

NumberFormatter formats a numeric string according to locale conventions:

Plural Rules

PluralRules selects the grammatical plural category for a given quantity:

Translation Bundles

Load translation catalogs from .mo file bytes and compose them into a Translator with an explicit fallback chain:
The .mo format is a compatibility backend behind the native Bundle / Translator API. Catalog parsing uses the encoding substrate for declared charsets and rejects unsupported plural expressions with CatalogError.
Build Translator chains in order of preference. with_fallback chains are evaluated left-to-right: the primary bundle is tried first, then each fallback in the order you added it.

Full Text and I18n Demo

The following is the complete text/i18n demo from the Sifr repository:

What Is Not in This Release

The following CPython-shaped names are intentionally absent and raise diagnostics if imported: These adapters may be reviewed for future capabilities, but any future compatibility wrappers must wrap the native Sifr substrate without process-global mutation.