Reconfiguring the time zone, locales and keymaps in Sabayon Linux

This is an example of how to reconfigure the time zone, locales and keymaps in a Sabayon Linux installation from the command line. Sabayon Linux uses systemd, therefore much of this example should also be applicable in other Linux distributions that use systemd, and will certainly be applicable in Gentoo Linux installations that use systemd rather than OpenRC.

You can check the currently selected keymaps (console and X Windows) and locale using the ‘localectl status‘ command. For example:

user $ localectl status
   System Locale: LANG=en_GB.UTF-8
       VC Keymap: uk
      X11 Layout: gb
       X11 Model: pc105

Let’s say I had previously configured my installation to use only the en_GB and en_US locales but I now want to add Swiss Italian. The steps would be as shown below. I will assume the system being configured is in Switzerland and therefore I will also reconfigure the time zone accordingly, but that is not essential.

Check if the desired time zone exists:

root # timedatectl list-timezones | grep Zurich
Europe/Zurich

Set the desired time zone:

root # timedatectl set-timezone Europe/Zurich

Check if the Swiss Italian locale (it_CH) has already been added:

root # localectl list-locales
C.utf8
en_GB
en_GB.iso88591
en_GB.utf8
en_US
en_US.iso88591
en_US.utf8

If the desired locale is not present, add it:

root # nano /etc/locale.gen
root # grep -v "^#\|^$" /etc/locale.gen
C.UTF-8 UTF-8
en_GB.UTF-8 UTF-8
en_GB ISO-8859-1
en_US.UTF-8 UTF-8
en_US ISO-8859-1
it_CH.UTF-8 UTF-8
it_CH ISO-8859-1

Generate the locales:

root # locale-gen
 * Generating 7 locales (this might take a while) with 1 jobs
 *  (1/7) Generating C.UTF-8 ...                                          [ ok ]
 *  (2/7) Generating en_GB.ISO-8859-1 ...                                 [ ok ]
 *  (3/7) Generating en_GB.UTF-8 ...                                      [ ok ]
 *  (4/7) Generating en_US.ISO-8859-1 ...                                 [ ok ]
 *  (5/7) Generating en_US.UTF-8 ...                                      [ ok ]
 *  (6/7) Generating it_CH.ISO-8859-1 ...                                 [ ok ]
 *  (7/7) Generating it_CH.UTF-8 ...                                      [ ok ]
 * Generation complete
 * Adding locales to archive ...                                          [ ok ]

Check the locales have been added:

root # localectl list-locales
C.utf8
en_GB
en_GB.iso88591
en_GB.utf8
en_US
en_US.iso88591
en_US.utf8
it_CH
it_CH.iso88591
it_CH.utf8

Set the desired locale:

root # localectl set-locale LANG=it_CH.UTF-8

Check which Italian console keymaps are available:

root # localectl list-keymaps | grep it
it
it-ibm
it2
mac-it

But let’s say I want to use a Swiss German keymap (sg) for the console instead of an Italian keymap. Check if a console keymap for Swiss German exists:

root # localectl list-keymaps | grep sg
sg
sg-latin1
sg-latin1-lk450

By the way, Debian, Ubuntu and its derivatives store console keymaps differently to some distributions, and the command ‘localectl list-keymaps‘ in Debian, Ubuntu and its derivatives will return an error message (the command ‘localectl set-keymap’ will still work though):

user $ localectl list-keymaps
Failed to read list of keymaps: No such file or directory

Set the console keymap to Swiss German:

root # localectl set-keymap sg

Let’s say I want to use a Swiss keymap in X Windows. Check if it exists:

root # localectl list-x11-keymap-layouts | grep sg
root # localectl list-x11-keymap-layouts | grep ch
ch

Set the X Windows keymap to Swiss:

root # localectl set-x11-keymap ch

Update the environment variables and profile:

root # env-update && source /etc/profile
>>> Regenerating /etc/ld.so.cache...

Edit /etc/default/grub and change (or add, if none exists) the console keymap entry in GRUB_CMDLINE_LINUX_DEFAULT to be vconsole.keymap=sg, and also rd.vconsole.keymap=sg (‘rd‘ stands for ‘RAM disk’) because Sabayon Linux uses an initramfs:

root # nano /etc/default/grub

Regenerate grub.cfg:

root # grub-mkconfig -o /boot/grub/grub.cfg
Generazione file di configurazione GRUB...
Trovato sfondo: /boot/grub/default-splash.png
Trovata immagine linux: /boot/kernel-genkernel-x86_64-5.4.0-sabayon
Trovata immagine initrd: /boot/initramfs-genkernel-x86_64-5.4.0-sabayon
fatto

Reboot to check if everything is working:

root # systemctl reboot

Check that the list of locales is as expected:

root # eselect locale list
Available targets for the LANG variable:
  [1]   C
  [2]   C.utf8
  [3]   en_GB
  [4]   en_GB.iso88591
  [5]   en_GB.utf8
  [6]   en_US
  [7]   en_US.iso88591
  [8]   en_US.utf8
  [9]   it_CH
  [10]  it_CH.iso88591
  [11]  it_CH.utf8
  [12]  POSIX
  [13]  it_CH.UTF-8 *
  [ ]   (free form)

Check if the current configuration is as expected:

root # localectl status
   System Locale: LANG=it_CH.UTF-8
       VC Keymap: sg
      X11 Layout: ch

If the Desktop Environment is KDE, check the file ~/.config/locale-plasmarc to see if the LANG variable is set to the locale just configured.

root # cat /home/fitzcarraldo/.config/plasma-localerc
[Formats]
LANG=en_GB.UTF-8

If it is not, delete the file:

root # rm /home/fitzcarraldo/.config/plasma-localerc

then logout, login again and re-check the file:

root # cat /home/fitzcarraldo/.config/plasma-localerc
[Formats]
LANG=it_CH.UTF-8

The system should now be ready for use with the new time zone, locale and keymaps.

user $ date
gio 2 lug 2020, 15:55:21, CEST
user $ localectl status
   System Locale: LANG=it_CH.UTF-8
       VC Keymap: sg
      X11 Layout: ch

Using a mixture of locale variables

It is not mandatory for all the locale variables to be for the same locale. For example, suppose I want to use the currency and number formats of one of the other locales I added. That is not so outlandish: I could be a Swiss national whose mother tongue is Swiss Italian, working in the Swiss branch of a British company and I want the currency format and number format on my work computer to be British, but everything else to be Swiss. To achieve this I can additionally do the following:

root # localectl set-locale LC_MONETARY=en_GB.UTF-8
root # localectl set-locale LC_NUMERIC=en_GB.UTF-8
root # env-update && source /etc/profile

Check that the main locale and keymaps remain as they were but that the two locale variables have been changed to the British locale:

root # localectl status
   System Locale: LANG=it_CH.UTF-8
                  LC_NUMERIC=en_GB.UTF-8
                  LC_MONETARY=en_GB.UTF-8
       VC Keymap: sg
      X11 Layout: ch
root # locale
LANG=it_CH.UTF-8
LC_CTYPE="it_CH.UTF-8"
LC_NUMERIC=en_GB.UTF-8
LC_TIME="it_CH.UTF-8"
LC_COLLATE="it_CH.UTF-8"
LC_MONETARY=en_GB.UTF-8
LC_MESSAGES="it_CH.UTF-8"
LC_PAPER="it_CH.UTF-8"
LC_NAME="it_CH.UTF-8"
LC_ADDRESS="it_CH.UTF-8"
LC_TELEPHONE="it_CH.UTF-8"
LC_MEASUREMENT="it_CH.UTF-8"
LC_IDENTIFICATION="it_CH.UTF-8"
LC_ALL=

You can see above that only $LC_NUMERIC and $LC_MONETARY have changed, as I wanted. As I did not change the time zone, the command I used earlier to set the time zone to Europe/Zurich is still in force:

root # date
gio 2 lug 2020, 16:12:18, CEST

By the way, if you try to change one of the variables from en_GB.UTF-8 back to it_CH.UTF-8, the change does not show in the output of the locale command. For example, let’s say you want to change LC_NUMERIC back to it_CH.UTF-8:

root # localectl status
   System Locale: LANG=it_CH.UTF-8
                  LC_NUMERIC=en_GB.UTF-8
                  LC_MONETARY=en_GB.UTF-8
       VC Keymap: sg
      X11 Layout: ch
root # localectl set-locale LC_NUMERIC=it_CH.UTF-8
root # cat /etc/locale.conf   
LANG=it_CH.UTF-8
LC_MONETARY=en_GB.UTF-8
root # cat /etc/env.d/02locale
LANG=it_CH.UTF-8
LC_MONETARY=en_GB.UTF-8
root # localectl status
   System Locale: LANG=it_CH.UTF-8
                  LC_MONETARY=en_GB.UTF-8
       VC Keymap: sg
      X11 Layout: ch
root # locale
LANG=it_CH.UTF-8
LC_CTYPE="it_CH.UTF-8"
LC_NUMERIC=en_GB.UTF-8  <-- Notice it didn't change
LC_TIME="it_CH.UTF-8"
LC_COLLATE="it_CH.UTF-8"
LC_MONETARY=en_GB.UTF-8
LC_MESSAGES="it_CH.UTF-8"
LC_PAPER="it_CH.UTF-8"
LC_NAME="it_CH.UTF-8"
LC_ADDRESS="it_CH.UTF-8"
LC_TELEPHONE="it_CH.UTF-8"
LC_MEASUREMENT="it_CH.UTF-8"
LC_IDENTIFICATION="it_CH.UTF-8"
LC_ALL=
root # env-update && source /etc/profile
>>> Regenerating /etc/ld.so.cache...
root # locale
LANG=it_CH.UTF-8
LC_CTYPE="it_CH.UTF-8"
LC_NUMERIC=en_GB.UTF-8 <-- Notice it still didn't change
LC_TIME="en_GB.UTF-8"
LC_COLLATE="it_CH.UTF-8"
LC_MONETARY=en_GB.UTF-8
LC_MESSAGES="it_CH.UTF-8"
LC_PAPER="it_CH.UTF-8"
LC_NAME="it_CH.UTF-8"
LC_ADDRESS="it_CH.UTF-8"
LC_TELEPHONE="it_CH.UTF-8"
LC_MEASUREMENT="it_CH.UTF-8"
LC_IDENTIFICATION="it_CH.UTF-8"
LC_ALL=

This is one of the reasons I’m not keen on the layer of abstraction added by systemd. The way to get LC_NUMERIC back to it_CH.UTF-8 is to change all the locale variables to en_GB.UTF-8 then back to it_CH.UTF-8:

root # localectl set-locale LANG=en_GB.UTF-8
root # env-update && source /etc/profile
root # localectl set-locale LANG=it_CH.UTF-8
root # env-update && source /etc/profile
root # reboot

After rebooting, the change will have been applied:

root # locale
LANG=it_CH.UTF-8
LC_CTYPE="it_CH.UTF-8"
LC_NUMERIC="it_CH.UTF-8"
LC_TIME="it_CH.UTF-8"
LC_COLLATE="it_CH.UTF-8"
LC_MONETARY="it_CH.UTF-8"
LC_MESSAGES="it_CH.UTF-8"
LC_PAPER="it_CH.UTF-8"
LC_NAME="it_CH.UTF-8"
LC_ADDRESS="it_CH.UTF-8"
LC_TELEPHONE="it_CH.UTF-8"
LC_MEASUREMENT="it_CH.UTF-8"
LC_IDENTIFICATION="it_CH.UTF-8"
LC_ALL=
root # localectl status
   System Locale: LANG=it_CH.UTF-8
       VC Keymap: sh
      X11 Layout: ch

Notice that everything has changed back to it_CH.UTF-8, including $LC_MONETARY, so you’d have to repeat the command ‘localectl set-locale LC_MONETARY=en_GB.UTF-8‘ if you wanted that to still be the British format.

If you use KDE, also check the contents of the file ~/.config/plasma-localerc to make sure it contains the correct locale:

user $ cat ~/.config/plasma-localerc
[Formats]
LANG=it_CH.UTF-8

Optionally you could edit that file to add desired settings. For example:

[Formats]
LANG=it_CH.UTF-8
LC_CTYPE=it_CH.UTF-8
LC_NUMERIC=en_GB.UTF-8
LC_TIME=it_CH.UTF-8
LC_COLLATE=it_CH.UTF-8
LC_MONETARY=en_GB.UTF-8
LC_MESSAGES=it_CH.UTF-8
LC_PAPER=it_CH.UTF-8
LC_NAME=it_CH.UTF-8
LC_ADDRESS=it_CH.UTF-8
LC_TELEPHONE=it_CH.UTF-8
LC_MEASUREMENT=it_CH.UTF-8
LC_IDENTIFICATION=it_CH.UTF-8
useDetailed=true

Alternatively, delete that file then logout and login again to make KDE Plasma pick up the values of the variables from the existing configuration. KDE Plasma will recreate the file.