Страницы

Поиск по вопросам

четверг, 2 января 2020 г.

Почему нужно переопределять локаль для вывода локализованнах строк (например strftime())?

#python #локализация #datetime #локаль


В соответствии с документацией, strftime() должен возвращать локализованные значения
даты и времени (название месяцев и дней недели и т.д.), однако делает это лишь после
явной установки локали:

>>> locale.getlocale() # Проверим текущую локаль
('ru_RU', 'UTF-8')
>>> d1.strftime('%A')
'Sunday'
>>> locale.setlocale(locale.LC_ALL, 'ru_RU.UTF-8')
'ru_RU.UTF-8'
>>> locale.getlocale()
('ru_RU', 'UTF-8')
>>> d1.strftime('%A')
'Воскресенье'


Почему на русском начинает выводить только после переопределения локали, хотя до
этого она и так была ('ru_RU', 'UTF-8')? Более того, достаточно просто сделать resetlocale:

>>> import locale
>>> locale.getdefaultlocale()
('ru_RU', 'UTF-8')
>>> locale.getlocale()
('ru_RU', 'UTF-8')
>>> d1.strftime('%A')
'Sunday'
>>> locale.resetlocale()
>>> d1.strftime('%A')
'Воскресенье'

    


Ответы

Ответ 1



Все программы на *nix системах (не только python) стартуют, используя C (POSIX) locale до тех пор пока они не вызовут setlocale(LC_ALL, ''), чтобы активировать пользовательскую locale. Если не хотите locale активировать для процесса, то можно использовать библиотеки, которые явно позволяют язык выбрать, такие как PyICU (пример использования)—есть полегче библиотеки, которые могут работать для конкретной задачи, например humanize: >>> import datetime >>> import humanize # $ pip install humanize >>> _ = humanize.i18n.activate('ru_RU') >>> humanize.naturaltime(datetime.datetime.now()) 'сейчас' В: но почему же locale.getlocale() выдаёт ru_RU? Я бы также ожидал, что-нибудь вроде (None, None) вместо ('ru_RU', 'UTF-8') до того как setlocale(LC_ALL, '') вызвано в программе. Из документации: "Returns the current setting for the given locale category" не очевидно, что пользовательские настройки из переменных окружения (LC_*, LANG) читаются, а не текущая локаль по умолчанию ("The POSIX locale is the default global locale at entry to main()") возвращается до вызова setlocale(LC_ALL, ''). locale модуль это тонкая обёртка вокруг соответствующей C функциональности, в частности, поведение может зависеть от платформы. Текущая реализация locale.getlocale() эквивалентна C setlocale(category, NULL), которая запрашивает текущую настройку для локали ("query the current global locale setting"). Почему "the current global locale setting" не равна "the default global locale" до вызова setlocale(LC_ALL, '') я не понимаю. Может дело в слове setting vs. locale, то есть текущая настройка до вызова setlocale(LC_ALL, '') берётся из переменных окружения (LC_*, etc), а текущая локаль до вызова setlocale(LC_ALL, ''), используемая strftime(), является C (как и положено). Но это чистая спекуляция с моей стороны.

Комментариев нет:

Отправить комментарий