CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-babel

Internationalization utilities for Python providing locale data, date/time/number formatting, and message catalog management

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

plural-language-data.mddocs/

Plural Rules and Language Data

Plural rule handling for different languages, language territory information, and list formatting according to locale conventions. Babel provides comprehensive support for CLDR plural rules and language-specific data.

Capabilities

Plural Rule Class

Represents and evaluates CLDR plural rules for different languages.

class PluralRule:
    """
    Represents a set of language pluralization rules based on CLDR data.
    
    Attributes:
        rules (dict): Rules mapping plural tags to conditions
        tags (set): Set of defined plural tags for this rule
    """
    def __init__(self, rules):
        """
        Initialize plural rule with rule definitions.
        
        Args:
            rules (dict): Mapping of plural tags to rule conditions
        """
    
    @classmethod
    def parse(cls, rules):
        """
        Parse plural rules from various formats.
        
        Args:
            rules (str|dict|PluralRule): Rules in string, dict, or PluralRule format
            
        Returns:
            PluralRule: Parsed plural rule object
        """
    
    def __call__(self, n):
        """
        Get plural form for a number.
        
        Args:
            n (int|float|Decimal): Number to evaluate
            
        Returns:
            str: Plural form tag ('zero', 'one', 'two', 'few', 'many', 'other')
        """

Usage example:

from babel.plural import PluralRule

# English plural rule (simple: one vs other)
en_rule = PluralRule({'one': 'n == 1'})
print(en_rule(1))   # 'one'
print(en_rule(2))   # 'other'

# French plural rule
fr_rule = PluralRule({'one': 'n >= 0 and n < 2'})
print(fr_rule(0))   # 'one'
print(fr_rule(1))   # 'one'
print(fr_rule(2))   # 'other'

CLDR Operand Extraction

Extract operands from numbers for use in CLDR plural rule evaluation.

def extract_operands(source):
    """
    Extract CLDR operands from a number for plural rule evaluation.
    
    Args:
        source (float|Decimal): Number to extract operands from
        
    Returns:
        tuple: (n, i, v, w, f, t, c, e) operands where:
            n: absolute value of the source number
            i: integer digits of n
            v: number of visible fraction digits in n
            w: number of fraction digits in n without trailing zeros
            f: visible fraction digits in n as an integer
            t: fraction digits in n without trailing zeros as an integer
            c: compact decimal exponent value
            e: deprecated, use 'c'
    """

Usage example:

from babel.plural import extract_operands

# Extract operands for different numbers
print(extract_operands(1.23))    # (1.23, 1, 2, 2, 23, 23, 0, 0)
print(extract_operands(5.00))    # (5.0, 5, 2, 0, 0, 0, 0, 0)
print(extract_operands(1000))    # (1000, 1000, 0, 0, 0, 0, 0, 0)

Plural Rule Conversion

Convert plural rules to different formats for use in various systems.

def to_javascript(rule):
    """
    Convert plural rule to JavaScript function code.
    
    Args:
        rule (PluralRule): Plural rule to convert
        
    Returns:
        str: JavaScript function code for evaluating plural forms
    """

def to_python(rule):
    """
    Convert plural rule to Python function.
    
    Args:
        rule (PluralRule): Plural rule to convert
        
    Returns:
        callable: Python function for evaluating plural forms
    """

def to_gettext(rule):
    """
    Convert plural rule to gettext format.
    
    Args:
        rule (PluralRule): Plural rule to convert
        
    Returns:
        str: Gettext plural expression string
    """

Usage example:

from babel.plural import PluralRule, to_javascript, to_python, to_gettext

rule = PluralRule({'one': 'n == 1'})

js_code = to_javascript(rule)
py_func = to_python(rule)
gettext_expr = to_gettext(rule)

print(py_func(1))   # 'one'
print(py_func(2))   # 'other'

Range List Operations

Test if numbers fall within CLDR range specifications.

def in_range_list(num, range_list):
    """
    Test if integer is in a range list.
    
    Args:
        num (int): Integer to test
        range_list (list): List of range specifications
        
    Returns:
        bool: True if number is in any of the ranges
    """

def within_range_list(num, range_list):
    """
    Test if number is within a range list (including decimals).
    
    Args:
        num (float|Decimal): Number to test
        range_list (list): List of range specifications
        
    Returns:
        bool: True if number is within any of the ranges
    """

def cldr_modulo(a, b):
    """
    CLDR-compatible modulo operation.
    
    Args:
        a (float): Dividend
        b (float): Divisor
        
    Returns:
        float: Modulo result following CLDR rules
    """

Language Territory Information

Access information about languages used in different territories.

def get_official_languages(territory, regional=False, de_facto=False):
    """
    Get official languages for a territory.
    
    Args:
        territory (str): Territory code (e.g., 'US', 'CA', 'CH')
        regional (bool): Include regional languages
        de_facto (bool): Include de facto official languages
        
    Returns:
        tuple[str, ...]: Language codes in order of popularity/usage
    """

def get_territory_language_info(territory):
    """
    Get detailed language information for a territory.
    
    Args:
        territory (str): Territory code
        
    Returns:
        dict: Mapping of language codes to detailed information including:
            - population_percent: Percentage of population using language
            - literacy_percent: Literacy rate for language
            - writing_percent: Percentage using written form
            - official_status: Official status information
    """

Usage example:

from babel.languages import get_official_languages, get_territory_language_info

# Get official languages for territories
us_languages = get_official_languages('US')  # ('en',)
ca_languages = get_official_languages('CA')  # ('en', 'fr')
ch_languages = get_official_languages('CH')  # ('de', 'fr', 'it')

# Get detailed language info
us_info = get_territory_language_info('US')
print(us_info['en']['population_percent'])  # Population percentage for English in US

List Formatting

Format sequences of items as lists according to locale conventions.

def format_list(lst, style='standard', locale=default_locale()):
    """
    Format a sequence of items as a list according to locale conventions.
    
    Args:
        lst (Sequence[str]): Sequence of string items to format
        style (str): List style ('standard', 'standard-short', 'or', 'or-short', 'unit', 'unit-short', 'unit-narrow')
        locale (Locale|str): Target locale for formatting
        
    Returns:
        str: Properly formatted list string
    """

Usage example:

from babel.lists import format_list
from babel import Locale

items = ['apples', 'oranges', 'bananas']

# English formatting
en_result = format_list(items, locale='en_US')
print(en_result)  # "apples, oranges, and bananas"

# Different styles
or_result = format_list(items, style='or', locale='en_US')
print(or_result)  # "apples, oranges, or bananas"

# French formatting
fr_result = format_list(items, locale='fr_FR')
print(fr_result)  # "apples, oranges et bananas"

# German formatting  
de_result = format_list(items, locale='de_DE')
print(de_result)  # "apples, oranges und bananas"

# Short styles
short_items = ['NYC', 'LA', 'CHI']
short_result = format_list(short_items, style='standard-short', locale='en_US')
print(short_result)  # "NYC, LA, & CHI"

Different list styles:

  • 'standard': Standard list with "and" (e.g., "A, B, and C")
  • 'standard-short': Short standard list (e.g., "A, B, & C")
  • 'or': Disjunctive list with "or" (e.g., "A, B, or C")
  • 'or-short': Short disjunctive list (e.g., "A, B, or C")
  • 'unit': Unit list for measurements (e.g., "A B C")
  • 'unit-short': Short unit list
  • 'unit-narrow': Narrow unit list

Exception Classes

class RuleError(Exception):
    """Raised when plural rule parsing or evaluation fails."""

Advanced Plural Rule Examples

Different languages have varying plural rule complexity:

from babel.plural import PluralRule

# English: Simple two-form rule
english_rule = PluralRule({
    'one': 'n == 1',
    'other': ''  # default case
})

# Polish: Complex six-form rule
polish_rule = PluralRule({
    'one': 'n == 1',
    'few': 'n % 10 >= 2 and n % 10 <= 4 and (n % 100 < 12 or n % 100 > 14)',
    'many': '(n % 10 == 0 or n % 10 == 1 or n % 10 >= 5 and n % 10 <= 9) and (n % 100 >= 12 and n % 100 <= 14)',
    'other': ''
})

# Arabic: Six-form rule with zero
arabic_rule = PluralRule({
    'zero': 'n == 0',
    'one': 'n == 1', 
    'two': 'n == 2',
    'few': 'n % 100 >= 3 and n % 100 <= 10',
    'many': 'n % 100 >= 11 and n % 100 <= 99',
    'other': ''
})

# Test different numbers
for num in [0, 1, 2, 3, 5, 11, 21, 101]:
    print(f"{num}: {english_rule(num)} (en), {polish_rule(num)} (pl), {arabic_rule(num)} (ar)")

Install with Tessl CLI

npx tessl i tessl/pypi-babel

docs

core-locales.md

date-time-formatting.md

index.md

message-catalogs.md

number-currency-formatting.md

plural-language-data.md

units-utilities.md

tile.json