Skip to main content

Lib/locale.py

cpython 3.14 @ ab2d84fe1023/Lib/locale.py

locale.py is the Python-level binding to the C library's locale subsystem. It wraps setlocale, localeconv, strcoll, and strxfrm from libc and then builds a substantial pure-Python layer on top for number and currency formatting. The module also includes a hardcoded database of locale aliases that maps informal locale names (e.g. "german") to their canonical POSIX forms (e.g. "de_DE.ISO8859-1").

The formatting layer converts the raw localeconv dictionary into human-readable numbers and currency strings. It handles grouping separators, sign conventions, parenthesised negatives, and the full set of fields defined by POSIX. Locale-aware text sorting is surfaced through strcoll and strxfrm, delegating entirely to libc so that collation tables stay correct for every platform.

Platform detection at import time selects either _locale (the C extension) or a pure-Python fallback. The fallback supports only the "C" and "UTF-8" locales so that the module remains importable everywhere, even when the C extension is absent.

Map

LinesSymbolRolegopy
1-80imports, constants, ErrorModule header, LC_* constant re-exports, Error exception class-
81-140setlocale, localeconvThin wrappers around _locale.setlocale / _locale.localeconv-
141-200format_stringPrintf-style format string with locale number formatting applied to each % conversion-
201-280currencyFormat a number as a currency string using localeconv fields-
281-340atof, atoiParse locale-formatted number strings back to float or int-
341-390strcoll, strxfrmLocale-aware string comparison and transform via libc-
391-440getdefaultlocaleDetect the platform default locale from environment variables-
441-480getpreferredencodingReturn the encoding preferred for text I/O on the current platform-
481-560normalize, locale alias DBNormalise a locale name string; the huge locale_alias dictionary-
561-640resetlocale, getlocaleRestore default locale; split a locale string into (language, encoding)-

Reading

Error and constants (lines 1 to 80)

cpython 3.14 @ ab2d84fe1023/Lib/locale.py#L1-80

The module re-exports every LC_* constant from _locale so callers never need to import the C extension directly. Error is a plain subclass of Exception and is the only exception this module raises.

from _locale import (LC_ALL, LC_COLLATE, LC_CTYPE,
LC_MESSAGES, LC_MONETARY, LC_NUMERIC, LC_TIME,
Error)

setlocale and localeconv (lines 81 to 140)

cpython 3.14 @ ab2d84fe1023/Lib/locale.py#L81-140

setlocale delegates directly to _locale.setlocale. When called with a tuple (language, encoding) it first joins them with a dot before passing to libc. localeconv returns a plain dict whose keys are the POSIX lconv field names: decimal_point, thousands_sep, grouping, currency_symbol, and so on.

def setlocale(category, locale=None):
if locale and not isinstance(locale, _builtin_str):
# convert to string
locale = normalize(_build_localename(locale))
return _locale.setlocale(category, locale)

format_string and currency (lines 141 to 280)

cpython 3.14 @ ab2d84fe1023/Lib/locale.py#L141-280

format_string scans the format string for % conversions with the _percent_re regular expression, formats each matched conversion with _format, then reassembles the pieces. _format inserts grouping separators by calling _group which walks the grouping list from localeconv to place commas (or locale equivalents) at the right positions.

currency reads localeconv once, decides whether the symbol precedes or follows the value, and selects the correct sign format (negative-sign, parentheses, or space) from the n_sign_posn / p_sign_posn fields.

def currency(val, symbol=True, grouping=False, international=False):
conv = localeconv()
# select the symbol
if international:
s = conv['int_curr_symbol']
elif symbol:
s = conv['currency_symbol']
else:
s = ''
...

Locale-aware collation (lines 341 to 390)

cpython 3.14 @ ab2d84fe1023/Lib/locale.py#L341-390

strcoll and strxfrm are direct pass-throughs to the libc functions exposed by _locale. No Python logic is added. When the C extension is not available the fallback implementations use plain < comparison and the identity function, which is correct only for the C locale.

def strcoll(os1, os2):
# Borrowed from _locale.strcoll
return _locale.strcoll(os1, os2)

def strxfrm(string):
return _locale.strxfrm(string)

Locale alias normalisation (lines 481 to 560)

cpython 3.14 @ ab2d84fe1023/Lib/locale.py#L481-560

normalize lower-cases the input, strips spaces, and looks it up in locale_alias. The alias dictionary is several hundred entries mapping short names and Windows-style locale names to their POSIX canonical equivalents. The lookup is case-insensitive and falls back to the input unchanged if no alias is found.

def normalize(localename):
# Normalize locale name
fullname = localename.lower()
fullname = fullname.replace(' ', '')
...
return locale_alias.get(fullname, localename)

gopy mirror

Not yet ported.