Linux: setlocale: LC_ALL: cannot change locale (en_US.utf8) и кирилица

Автор: | 02/02/2021

Локали (locale) – набор переменных, которые отвечают за времени и даты (например – первый день недели), кодировка символов (например – отображение кирилических символов в консоли), дефолтный порядок отображения файлов (отображать ли скрытые. сортировать по имени или размеру и т.д.).

Например, при запуске vifm в KDE Konsole на Arch Linux – не отображается кирилица:

А в консоли после выхода их vifm появляется сообщение:

[simterm]

$ vifm
/bin/bash: warning: setlocale: LC_ALL: cannot change locale (en_US.utf8)

[/simterm]

Генерирование locale

Проверяем содержимое каталога /usr/lib/locale/, в которой должны хранится сгенерированные локали:

[simterm]

$ ll /usr/lib/locale/
total 0

[/simterm]

Или используем locale -a, что бы отобразить доступные сейчас в системе локали:

[simterm]

$ locale -a        
C
POSIX

[/simterm]

Проверяем файл locales.gen – ищем en_US.UTF-8:

[simterm]

$ cat /etc/locale.gen | grep en_US.UTF-8
#  en_US.UTF-8 UTF-8
#en_US.UTF-8 UTF-8

[/simterm]

Раскоментируем en_US.UTF-8 UTF-8, и генерируем локали:

[simterm]

$ sudo locale-gen
/bin/sh: warning: setlocale: LC_ALL: cannot change locale (en_US.utf8)
Generating locales...
  en_US.UTF-8... done
Generation complete.

[/simterm]

Проверяем ещё раз:

[simterm]

$ file /usr/lib/locale/locale-archive 
/usr/lib/locale/locale-archive: locale archive 11 strings

[/simterm]

И locale -a:

[simterm]

$ locale -a        
C
en_US.utf8
POSIX

[/simterm]

Либо с помощью localedef:

[simterm]

$ localedef --list-archive
en_US.utf8

[/simterm]

Проверяем vifm:

Параметры файлов локализации

Узнать дефолтную сортировку дней недели – какой будет первым, вторым и т.д.:

[simterm]

$ locale -k LC_TIME 
abday="Sun;Mon;Tue;Wed;Thu;Fri;Sat"
day="Sunday;Monday;Tuesday;Wednesday;Thursday;Friday;Saturday"
...
first_weekday=1
first_workday=2

[/simterm]

Локализации описываются в файлах в каталоге /usr/share/i18n/locales/, из которого генерируется локаль во время выполнения locale-gen, например для en_US локаль LC_TIME описана как:

LC_TIME
abday   "Sun";"Mon";"Tue";"Wed";"Thu";"Fri";"Sat"
day     "Sunday";/
        "Monday";/
        "Tuesday";/
        "Wednesday";/
        "Thursday";/
        "Friday";/
        "Saturday"

week 7;19971130;1
abmon   "Jan";"Feb";/
        "Mar";"Apr";/
        "May";"Jun";/
        "Jul";"Aug";/
        "Sep";"Oct";/
        "Nov";"Dec"
mon     "January";/
        "February";/
        "March";/
        "April";/
        "May";/
        "June";/
        "July";/
        "August";/
        "September";/
        "October";/
        "November";/
        "December"
% Appropriate date and time representation (%c)
d_t_fmt "%a %d %b %Y %r %Z"
%
% Appropriate date representation (%x)
d_fmt   "%m//%d//%Y"
%
% Appropriate time representation (%X)
t_fmt   "%r"
%
% Appropriate AM/PM time representation (%r)
t_fmt_ampm "%I:%M:%S %p"
%
% Appropriate date and time representation for date(1).  This is
% different from d_t_fmt for historical reasons and has been different
% since 2000 when date_fmt was added as a GNU extension.  At the end
% of 2018 it was adjusted to use 12H time (bug 24046) instead of 24H.
date_fmt "%a %b %e %r %Z %Y"
%
% Strings for AM/PM
%
am_pm   "AM";"PM"
END LC_TIME

А для ru_RU в LC_TIME имеется опция first_weekday, см. man 5 locale, которая указывает первый день недели, т.е. понедельник (второй день из списка дней недели, который всё-таки начинается с воскресенья):

...
week 7;19971130;1
first_weekday 2
END LC_TIME
...

Что бы задать по дефолту первым днём понедельник – устанавливаем LC_TIME в ru_RU.UTF-8, в файле /etc/locale.conf, предварительно раскоментировав в /etc/locale.gen и выполнив locale-gen:

LANG=en_US.UTF-8
LC_TIME=ru_RU.UTF-8

Либо используя localectl:

[simterm]

$ localectl set-locale LC_TIME=ru_RU.UTF-8

[/simterm]

В целом, на этом всё.

Ссылки по теме