Where to start First steps track · 15 stages
Linux Labs

Locale and encoding

4 min Ubuntu 24.04

Language, encoding and formats — LANG/LC_*, generating locales, UTF-8 problems.

Cheat sheet

7 commands Printable version
  • locale current settings
  • locale -a available locales
  • sudo locale-gen ru_RU.UTF-8 generate one
  • sudo update-locale LANG=en_US.UTF-8 system default (or localectl set-locale)
  • export LC_ALL=C stable output in scripts
  • LC_ALL=C sort file a one-off byte-order sort
  • localectl status the systemd view

Overview

A locale sets the language, encoding and formats (dates, numbers, sorting) through the $LANG/$LC_* environment variables. On servers, encoding matters most: correct UTF-8 handling needs a *.UTF-8 locale.

bash
locale                            # current locale settings
locale -a                         # which locales are installed
echo $LANG                        # the main variable

Configuration

6
bash
sudo locale-gen en_US.UTF-8 ru_RU.UTF-8   # generate locales
sudo update-locale LANG=en_US.UTF-8       # the system default locale (/etc/default/locale)
# temporarily, for the current session:
export LANG=ru_RU.UTF-8

localectl status                  # the system locale (systemd)
sudo localectl set-locale LANG=en_US.UTF-8
sudo dpkg-reconfigure locales     # interactive picker (Debian/Ubuntu)

Precedence: LC_ALL (overrides everything) > specific LC_* variables > LANG (the general default).

Variable Affects
LANG the general default for all categories
LC_CTYPE encoding (UTF-8!)
LC_TIME date/time format (see date)
LC_NUMERIC the decimal separator (. or ,)
LC_COLLATE sort order (sort)
LC_ALL overrides everything (for scripts: LC_ALL=C)

Nothing found. Try a shorter query.

Troubleshooting

5

Garbled Cyrillic/characters

A non-UTF-8 locale or terminal. Check locale (it should show *.UTF-8), generate the locale (locale-gen), and make sure the terminal/SSH session is UTF-8.

warning: setlocale: LC_*: cannot change locale

The requested locale hasn't been generated. Run sudo locale-gen <locale>; confirm it shows up in locale -a. A common case over SSH: the client sends LC_* (via SendEnv), but the server doesn't have that locale — either generate it, or stop accepting it (AcceptEnv in sshd).

A script sorts/parses differently on different machines

The locale affects sort, numbers, dates. For predictability: export LC_ALL=C (byte-order sort, dot as the decimal separator). This is often set at the start of scripts.

Dates/numbers in an "unexpected" format

That's LC_TIME/LC_NUMERIC. Pin the locale you want, or use LC_ALL=C for machine-readable output. One-off: LC_ALL=C sort file, LC_TIME=ru_RU.UTF-8 date.

perl: warning setting locale failed

Usually harmless but annoying: the server doesn't have a locale that was forwarded over SSH. Fixed by generating that locale or filtering it with AcceptEnv.

See also

  • env-vars — env, export, $PATH, ~/.bashrc vs profile files; why "command not found" happens.
  • timedatectl — System time, timezone and NTP sync (systemd-timesyncd).
  • files-basics — Navigation and files — ls, cd, cp, mv, rm, cat, less, head, tail, copy-paste in the terminal.
Loading…