Internationalization utilities for Python providing locale data, date/time/number formatting, and message catalog management
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
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.
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'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)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'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
"""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 USFormat 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 listclass RuleError(Exception):
"""Raised when plural rule parsing or evaluation fails."""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