Locale.setlocale: примеры (PYTHON)

Функция setlocale для управления локалью в Python
Раздел: Интернационализация, Локализация
locale.setlocale(category: int, locale: str or None): str

Основы функции locale.setlocale

Функция locale.setlocale() из модуля locale предназначена для установки, изменения или получения текущей локали (языковых и региональных настроек) для данной категории. Локаль влияет на форматирование чисел, дат, времени, валюты и сравнение строк.

Использование функции актуально при разработке интернационализированных приложений, где вывод информации должен соответствовать региональным стандартам пользователя.

Аргументы функции

locale.setlocale(category, locale=None)

  • category (обязательный): Константа, определяющая категорию настроек локали.
    • locale.LC_ALL - все категории.
    • locale.LC_COLLATE - для сравнения строк (strcoll, strxfrm).
    • locale.LC_CTYPE - для символьных классов (isalpha, isdigit и т.д.) и преобразований (toupper, tolower).
    • locale.LC_MONETARY - для форматирования денежных значений.
    • locale.LC_NUMERIC - для форматирования чисел (разделитель дробной части).
    • locale.LC_TIME - для форматирования даты и времени (strftime).
    • locale.LC_MESSAGES - для сообщений системы (обычно для gettext).
  • locale (опциональный): Строка или кортеж, определяющий устанавливаемую локаль. Если равен пустой строке "", локаль берется из переменных окружения пользователя. Если равен None, функция возвращает текущее значение локали для указанной категории. Формат строки: "[language[_territory][.codeset][@modifier]]", например, "ru_RU.UTF-8" или "en_US".

Возвращаемое значение

При вызове с аргументом locale (строкой), функция пытается установить локаль и возвращает ее имя в случае успеха. При вызове с locale=None, функция возвращает текущее значение локали для данной категории в виде строки. Если установить локаль не удалось, генерируется исключение locale.Error.

Краткие примеры использования

Получение текущей локали

import locale

current_locale = locale.setlocale(locale.LC_ALL, None)
print(current_locale)
'C'

Установка системной локали по умолчанию

import locale

# Установка для всех категорий на основе переменных окружения
sys_locale = locale.setlocale(locale.LC_ALL, "")
print(f"Системная локаль: {sys_locale}")
# Проверка форматирования числа
print(locale.format_string("%d", 1234567, grouping=True))
Системная локаль: ru_RU.UTF-8
1 234 567

Установка конкретной локали

import locale

# Установка русской локали для всех категорий
locale.setlocale(locale.LC_ALL, 'ru_RU.UTF-8')
# Форматирование валюты
locale.setlocale(locale.LC_MONETARY, 'ru_RU.UTF-8')
print(locale.currency(1234.56, grouping=True))
1 234,56 руб.

Установка локали только для чисел и времени

import locale
from datetime import datetime

# Локаль для чисел (разделитель дробной части)
locale.setlocale(locale.LC_NUMERIC, 'de_DE')
print("Число:", locale.atof("1,234"))

# Локаль для времени
locale.setlocale(locale.LC_TIME, 'it_IT')
now = datetime.now()
print("Дата:", now.strftime("%A, %d %B %Y"))
Число: 1.234
Дата: giovedì, 06 febbraio 2025

Похожие функции в Python

В Python для решения задач локализации и интернационализации применяют и другие модули.

Модуль gettext

Служит для перевода текстовых сообщений в приложении на разные языки. Работает с файлами переводов (.po, .mo). Применяется, когда требуется перевести строки интерфейса, а не форматировать данные.

import gettext
ru = gettext.translation('messages', localedir='locales', languages=['ru'])
ru.install()
print(_("Hello, world!"))  # Если есть перевод, выведет "Привет, мир!"

Строковые методы с локалью

Некоторые строковые операции, зависящие от локали (сравнение, регистр), могут использовать locale.strxfrm() или locale.strcoll(). Эти функции работают на основе текущей LC_COLLATE.

import locale
locale.setlocale(locale.LC_COLLATE, 'sv_SE')
sorted_list = sorted(["ängel", "zoo", "argo"], key=locale.strxfrm)
print(sorted_list)
['argo', 'zoo', 'ängel']

Модуль babel

Сторонний пакет Babel предоставляет более гибкие и мощные инструменты для интернационализации: форматирование дат, чисел, списков, работа с временными зонами, извлечение строк для перевода. Его выбор предпочтителен для сложных проектов, где возможностей locale недостаточно.

Аналоги в других языках программирования

PHP: setlocale()

Функция setlocale() работает аналогично, принимая категории как целые числа или константы (LC_ALL, LC_TIME и др.). Возвращает установленную локаль или false при ошибке.

// PHP
$current = setlocale(LC_ALL, "0"); // Получить текущую
echo $current . "\n";
$new = setlocale(LC_TIME, "ru_RU.UTF-8");
echo strftime("%A");
C
четверг

JavaScript (Node.js): Intl объект

В JavaScript используется API Intl, который не устанавливает глобальную локаль, а создает форматтеры с конкретными настройками.

// JavaScript
const number = new Intl.NumberFormat('ru-RU').format(1234567.89);
console.log(number);
const date = new Intl.DateTimeFormat('de-DE').format(new Date());
console.log(date);
1 234 567,89
6.2.2025

Java: Locale.setDefault()

В Java есть класс java.util.Locale. Метод setDefault() устанавливает локаль для всего JVM. Форматирование осуществляется через специфические классы (NumberFormat, DateFormat).

// Java
import java.util.Locale;
import java.text.NumberFormat;

Locale.setDefault(new Locale("ru", "RU"));
NumberFormat nf = NumberFormat.getInstance();
System.out.println(nf.format(1234567.89));
1 234 567,89

C#: CultureInfo.CurrentCulture

В C# культура устанавливается для потока через CultureInfo.CurrentCulture (для форматирования) и CultureInfo.CurrentUICulture (для загрузки ресурсов).

// C#
System.Globalization.CultureInfo.CurrentCulture = 
    new System.Globalization.CultureInfo("fr-FR");
Console.WriteLine(12345.67.ToString("N"));
12 345,67

Golang: Изменение локали отсутствует

В стандартной библиотеке Go нет аналога глобальной установки локали. Пакет golang.org/x/text предоставляет функции для специфического форматирования, но обычно используется подход с явной передачей локали в функции.

// Go (использование пакета golang.org/x/text/message)
import "golang.org/x/text/message"

p := message.NewPrinter(message.MatchLanguage("ru"))
p.Printf("%d\n", 1234567)
1 234 567

Kotlin (JVM): java.util.Locale

Kotlin, работая на JVM, использует Java-механизмы локали.

// Kotlin
import java.util.Locale
import java.text.NumberFormat

Locale.setDefault(Locale("de", "DE"))
println(NumberFormat.getInstance().format(1234.56))
1.234,56

Типичные ошибки

Неподдерживаемая локаль

Попытка установить локаль, недоступную в системе, приводит к исключению locale.Error.

import locale

try:
    locale.setlocale(locale.LC_ALL, 'xyz_XYZ.UTF-8')
except locale.Error as e:
    print(f"Ошибка: {e}")
Ошибка: unsupported locale setting

Влияние на другие категории при установке LC_ALL

Установка LC_ALL перезаписывает все категории, что может вызвать неожиданное поведение, если ранее были заданы отдельные категории.

import locale
locale.setlocale(locale.LC_TIME, 'en_US')
locale.setlocale(locale.LC_NUMERIC, 'de_DE')
print("До LC_ALL:", locale.setlocale(locale.LC_TIME))

locale.setlocale(locale.LC_ALL, 'C')  # Сбрасывает все
print("После LC_ALL:", locale.setlocale(locale.LC_TIME))
До LC_ALL: en_US
После LC_ALL: C

Использование не той кодировки в локали

Указание кодировки, которая не совпадает с системной или не поддерживается, может привести к ошибке или некорректному выводу.

import locale, sys

# Если локаль доступна, но с другой кодировкой, может не сработать
try:
    locale.setlocale(locale.LC_ALL, 'ru_RU.CP1251')  # На системе с UTF-8
    print("Успешно")
except locale.Error:
    print("Локаль с такой кодировкой недоступна")
Локаль с такой кодировкой недоступна

Непонимание поведения locale=None

Иногда ожидают, что locale.setlocale(category, None) установит локаль по умолчанию, но на самом деле этот вызов только возвращает текущее значение.

import locale

# Неправильно: локаль не изменится
locale.setlocale(locale.LC_ALL, None)
print("Локаль после None:", locale.setlocale(locale.LC_ALL, None))
Локаль после None: C

Изменения в последних версиях Python

В Python 3.11 была добавлена поддержка категории LC_MESSAGES на платформах Windows (работала только на Unix-подобных системах).

В Python 3.10 и более новых версиях улучшена обработка некорректных аргументов для некоторых функций модуля locale (например, locale.format_string).

Стоит отметить, что само использование модуля locale для форматирования чисел и валюты считается устаревшим подходом в пользу более гибкого и безопасного метода locale.format_string() с явным указанием формата, вместо старого locale.format().

Расширенные примеры

Временная установка локали в контексте

Для временного изменения локали внутри блока кода можно использовать менеджер контекста.

Пример python
import locale
import contextlib
from datetime import datetime

@contextlib.contextmanager
def temporary_locale(category, locale_name):
    original = locale.setlocale(category, None)
    try:
        locale.setlocale(category, locale_name)
        yield
    finally:
        locale.setlocale(category, original)

print("Оригинальная дата:", datetime.now().strftime("%c"))
with temporary_locale(locale.LC_TIME, 'fr_FR'):
    print("Французская дата:", datetime.now().strftime("%c"))
print("Восстановленная дата:", datetime.now().strftime("%c"))
Оригинальная дата: Thu Feb  6 14:25:00 2025
Французская дата: jeu. févr.  6 14:25:00 2025
Восстановленная дата: Thu Feb  6 14:25:00 2025

Автоматическое определение доступных локалей

Можно попытаться найти и установить рабочую локаль, перебирая список возможных имен.

Пример python
import locale

candidate_locales = ['ru_RU.UTF-8', 'ru_RU', 'Russian_Russia.1251', '']
for loc in candidate_locales:
    try:
        locale.setlocale(locale.LC_CTYPE, loc)
        print(f"Установлена локаль: {loc}")
        break
    except locale.Error:
        continue
else:
    print("Не удалось установить русскую локаль.")
Установлена локаль: ru_RU.UTF-8

Изменение только денежного формата для разных валют

Использование разных категорий позволяет тонко настроить вывод.

Пример python
import locale

# Установка базовой локали (например, для США)
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
print("Цена в США:", locale.currency(99.99))

# Временная смена категории LC_MONETARY для евро
original_monetary = locale.setlocale(locale.LC_MONETARY, 'de_DE.UTF-8')
print("Цена в Германии:", locale.currency(99.99, symbol=True))

# Возврат денежного формата
locale.setlocale(locale.LC_MONETARY, original_monetary)
print("Цена снова в США:", locale.currency(99.99))
Цена в США: $99.99
Цена в Германии: 99,99 €
Цена снова в США: $99.99

Сравнение строк с учетом локали для сортировки

Использование locale.strxfrm в качестве ключа сортировки.

Пример python
import locale

words = ["cafe", "café", "caff", "cāfe"]

print("Без учета локали:", sorted(words))

# Установка локали, где акценты влияют на порядок (например, французская)
locale.setlocale(locale.LC_COLLATE, 'fr_FR.UTF-8')
print("С учетом локали (fr_FR):", sorted(words, key=locale.strxfrm))

# Установка локали, где акценты игнорируются (например, английская)
locale.setlocale(locale.LC_COLLATE, 'en_US.UTF-8')
print("С учетом локали (en_US):", sorted(words, key=locale.strxfrm))
Без учета локали: ['cafe', 'café', 'caff', 'cāfe']
С учетом локали (fr_FR): ['cafe', 'café', 'caff', 'cāfe']
С учетом локали (en_US): ['cafe', 'café', 'caff', 'cāfe']

Обработка чисел с разделителями из разных локалей

Функции locale.atoi, locale.atof корректно интерпретируют числа в соответствии с установленной LC_NUMERIC.

Пример python
import locale

# Немецкий формат: запятая как разделитель дробной части
locale.setlocale(locale.LC_NUMERIC, 'de_DE')
num_str_de = "1.234,56"  # Точка - разделитель тысяч, запятая - дробная часть
value_de = locale.atof(num_str_de)
print(f"de_DE: '{num_str_de}' -> {value_de}")

# Английский формат: точка как разделитель дробной части
locale.setlocale(locale.LC_NUMERIC, 'en_US')
num_str_en = "1,234.56"  # Запятая - разделитель тысяч, точка - дробная часть
value_en = locale.atof(num_str_en)
print(f"en_US: '{num_str_en}' -> {value_en}")
de_DE: '1.234,56' -> 1234.56
en_US: '1,234.56' -> 1234.56

питон locale.setlocale function comments

En
Locale.setlocale Set the locale for the current category