Learn more >
Ian Shields | Published July 21, 2017
In this tutorial, learn to:
There are thousands of different languages used throughout the world. Numbers and dates can be formatted differently, and there are over 40 alphabets, or sets of ideographs, in existence. People use either a 12-hour clock or a 24-hour clock for time. There are also different systems of measurement for everything from building materials to the very paper on which we write or print. This tutorial shows you how to configure your Linux system to adapt it to your locale as these variations are collectively known.
With 24 hours in a day, your time zone is likely to be different than mine, so I also show you how to configure your time zone settings and the associated environment variables.
This series of tutorials helps you learn Linux system administration tasks. You can also use the material in these tutorials to prepare for the Linux Professional Institute’s LPIC-1: Linux Server Professional Certification exams.
See “Learn Linux, 101: A roadmap for LPIC-1” for a description of and link to each tutorial in this series. The roadmap is in progress. This tutorial reflects the Version 5.0 objectives as updated on October 29, 2018. As tutorials are completed, they will be added to the roadmap.
This tutorial helps you prepare for Objective 107.3 in Topic 107 of the Linux Server Professional (LPIC-1) exam 102. The objective has a weight of 3.
To get the most from the tutorials in this series, you need a basic knowledge of Linux and a working Linux system on which you can practice the commands covered in this tutorial. You should be familiar with GNU and UNIX commands. Sometimes different versions of a program format output differently, so your results might not always look exactly like the listings shown here.
Unless otherwise noted, I use Fedora 25 running Wayland and Ubuntu 16.04 LTS running X11 for the examples in this tutorial.
Adapting a system to meet the needs of your particular locale is called localization, often abbreviated to l18n, where the number 18 simply stands for the 18 internal letters between the initial l and the final n. To adapt a system to your locale, the system must be capable of such adaptation. The process of writing software so that it can potentially be adapted to different locales is called internationalization, which is similarly abbreviated to i18n.
When you install a Linux system, you set a language and an appropriate keyboard for the country where it will be used. You can use the localectl command to display the language and keyboard settings, or you can display the value of the LANG environment variable if you just want to see the system language. Listing 1 illustrates these commands on my Fedora 25 system. Note: If you use localectl alone, the default is to display status.
[ian@atticf25 ~]$ localectl status
System Locale: LANG=en_US.UTF‑8
VC Keymap: us
X11 Layout: us
[ian@atticf25 ~]$ echo $LANG
You can see that I have a United States (us) keyboard and that my language is set to enUS.UTF-8. The LANG setting is typically a two-letter lowercase language code, followed by an underscore () and a two-letter uppercase country code. Then a period follows, along with a codepage or character set name — UTF-8 in this example. Where no two-letter ISO 639‑1 code is appropriate for a language, a three-letter ISO 639‑2 code is used instead. For example, fur_IT is used for Friulian in the Friuli region of Italy. Depending on context, some parts might be case-insensitive as some of my examples show.
You can use the locale command with the -a (or --all-locales) option to display a list of all the available locales on your system. On a Fedora system, this list is long, so Listing 2 shows just parts of it. On my Ubuntu 15.04 LTS system, the list is restricted to English locales because I chose English when I installed the system.
[ian@atticf25 ~]$ #Display all French locales
[ian@atticf25 ~]$ locale ‑‑all‑locales | grep fr_
[ian@atticf25 ~]$ #Display all Friulian locales
[ian@atticf25 ~]$ locale ‑‑all‑locales |grep "^fur"
[ian@atticf25 ~]$ #How many locales are on this system?
[ian@atticf25 ~]$ locale ‑a | wc ‑l
I mentioned that there are some other things, such as numeric formatting or currency symbols, that differ by locale. These are grouped into categories. Use the locale command to view your current settings as shown in Listing 3.
[ian@atticf25 ~]$ locale
These settings are often referred to collectively as LC_*. They are not actual environment variables, as you can see if you try to display them using the echo command. However, you can assign values to them.
The values LC_CTYPE, LC_COLLATE, LC_MESSAGES, LC_MONETARY, LC_NUMERIC, and LC_TIME are defined by POSIX. The GNU C library also supports LC_IDENTIFICATION, LC_MEASUREMENT, LC_NAME, LC_PAPER, and LC_TELEPHONE. Be aware that these extra values might not be available on all UNIX variants.
Each category has one or more keywords within it. Use the locale command with one or more category or keyword names to display information about the category or keyword, as shown in Listing 4.
[ian@atticf25 ~]$ locale LC_NUMERIC
[ian@atticf25 ~]$ locale thousands_sep decimal_point
The output display in Listing 4 is not particularly useful, except when you need the value of a single keyword. Add the -c (or --category-name) option to display the category name or the -k (or --keyword-name) to display the keyword name. You can use both keywords, and it is often useful to do so, particularly when displaying multiple categories. Listing 5 shows some examples of these options.
[ian@atticf25 ~]$ locale ‑‑category‑name ‑‑keyword‑name LC_NUMERIC LC_PAPER
[ian@atticf25 ~]$ locale ‑ck thousands_sep decimal_point height
You can change your locale settings by changing the value of LANG; for example, LANG=en_GB.UTF8 changes all of my US ENGLISH locale settings to British English. This changes all the LC_* settings. Listing 6 shows an example on my Ubuntu 16.04 LTS system. Unlike assignment to ordinary environment variables, changes to LANG are inherited by child processes and do not need to be exported.
Note that Debian-based systems, including Ubuntu, have an additional LANGUAGE value that is not changed when you change the LANG value. LANGUAGE is normally the same as your system language, but you can set it to a colon-separated list of languages that can be used for messages. This gives a fallback mechanism if a message is not available in a particular language.
Sometimes you want to change all the LC* categories without changing the system language or locale settings. This is most often done in scripts, but you can override the environment for a single command. Set LC_ALL to change all the LC*c categories at once, or set one or more individual categories, such as LC_MONETARY. Listing 7 shows some examples on my Ubuntu 16.04 LTS system.
ian@attic‑u16:~$ locale ‑ck int_curr_symbol currency_symbol
ian@attic‑u16:~$ LC_ALL=en_GB.UTF8 locale ‑ck int_curr_symbol currency_symbol
ian@attic‑u16:~$ LC_MONETARY=en_ZA.UTF8 locale ‑ck int_curr_symbol currency_symbol
The C (or POSIX) locale provides a basic locale that programs and shell scripts often use, and it is the default locale for C programs. With this locale, programs or scripts can use a well-known environment without needing to worry about localization where this is not needed. Scripts and programs can both set other locales as needed.
Most systems are initially installed with a single language supported. As you add packages to your system, those packages can add language-specific components based on your system language settings. If you are missing language support for something you are trying to do, you will probably see an error message and any output is likely to be in the language of your system. Listing 8 shows how to list the names of the days of the week and their abbreviations in both English and French.
ian@attic‑u16:~$ locale ‑ck day abday
ian@attic‑u16:~$ LC_ALL=fr_FR.UTF8 locale ‑ck day abday
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
Oops! As you see, this system does not seem to have French language support installed. Now, I show you how to install additional language support on Ubuntu and Fedora systems.
Ubuntu has a check-language-support program that you can use to find out which packages are needed for a particular language. With no arguments, it identifies missing language support on your system. Listing 9 shows some examples.
gimp‑help‑en hunspell‑en‑au hunspell‑en‑ca hyphen‑en‑gb libreoffice‑help‑en‑gb
libreoffice‑l10n‑en‑gb libreoffice‑l10n‑en‑za mythes‑en‑au thunderbird‑locale‑en‑gb
ian@attic‑u16:~$ check‑language‑support ‑l en_US
ian@attic‑u16:~$ check‑language‑support ‑l fr
firefox‑locale‑fr gimp‑help‑fr hunspell‑fr hyphen‑fr language‑pack‑fr language‑pack‑gnome‑fr
libreoffice‑help‑fr libreoffice‑l10n‑fr mythes‑fr thunderbird‑locale‑fr wfrench
You can use the output of check-language-support as input to apt-get to install the required packages. Listing 10 shows how to install the packages needed from French.
ian@attic‑u16:~$ sudo apt‑get install $(check‑language‑support ‑l fr)
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
gimp‑help‑common hunspell‑fr‑classical language‑pack‑fr‑base
The following NEW packages will be installed:
firefox‑locale‑fr gimp‑help‑common gimp‑help‑fr hunspell‑fr
hunspell‑fr‑classical hyphen‑fr language‑pack‑fr language‑pack‑fr‑base
language‑pack‑gnome‑fr language‑pack‑gnome‑fr‑base libreoffice‑help‑fr
libreoffice‑l10n‑fr mythes‑fr thunderbird‑locale‑fr wfrench
0 upgraded, 15 newly installed, 0 to remove and 6 not upgraded.
Need to get 41.6 MB of archives.
After this operation, 115 MB of additional disk space will be used.
Do you want to continue? [Y/n] y
Setting up language‑pack‑fr‑base (1:16.04+20160627) ...
Generating locales (this might take a while)...
Setting up language‑pack‑gnome‑fr‑base (1:16.04+20160627) ...
Processing triggers for dictionaries‑common (1.26.3) ...
Processing triggers for bamfdaemon (0.5.3~bzr0+16.04.20160824‑0ubuntu1) ...
Now that you have French language support installed, you can display the day names and abbreviations as shown in Listing 11.
ian@attic‑u16:~$ LC_ALL=fr_FR.UTF8 locale ‑ck day abday
Fedora uses a language meta pack to install language support for a particular language. For example, langpacks-es is the meta package for Spanish language support. Listing 12 shows an example of installing the Spanish language pack on my Fedora 25 system using dnf. On older systems, you might need to use yum instead.
[root@atticf25 ~]#dnf install langpacks‑es
Last metadata expiration check: 0:06:08 ago on Wed May 31 22:16:08 2017.
Package Arch Version Repository
autocorr‑es noarch 1:188.8.131.52‑3.fc25 updates 181 k
glibc‑langpack‑es x86_64 2.24‑4.fc25 updates 411 k
gnome‑getting‑started‑docs‑es noarch 3.22.0‑1.fc25 fedora 10 M
hunspell‑es noarch 1:0.7‑6.fc24 fedora 251 k
hyphen‑es noarch 0.20110222svn‑8.fc24 fedora 16 k
langpacks‑es noarch 1.0‑8.fc25 fedora 8.5 k
libreoffice‑langpack‑es x86_64 1:184.108.40.206‑3.fc25 updates 7.3 M
man‑pages‑es noarch 1.55‑26.fc25 fedora 1.6 M
mythes‑es noarch 0.20150304‑4.fc24 fedora 710 k
Install 9 Packages
Total download size: 21 M
Installed size: 49 M
Is this ok [y/N]: y
(1/9): langpacks‑es‑1.0‑8.fc25.noarch.rpm 27 kB/s | 8.5 kB 00:00
You can now use Spanish locales. For example, Listing 13 shows the day names and their abbreviations in Spanish.
[ian@atticf25 ~]$ LANG=es_ES.UTF8 locale ‑ck day abday
If you want to use a specific language or locale setting whenever you log in, you can set the LANG, LANGUAGE, LCALL, or the individual LC* settings in your .bashrc profile. Of course, you need the appropriate language support packages installed before you do this.
To change the language used as the system default, you need to install the desired language packs and then use the localectl command to change the default system locale settings. You can change the language, LC_* settings, or the keymap used for console or X11 terminals. These settings are used before login and for any user who does not override them.
Early computers did not communicate with other computers, and each manufacturer used a custom way of representing characters internally. In 1963, American Standard Code for Information Interchange (ASCII) was released with the goal of being a common interchange language. With only 127 characters being represented, it had limited use outside English. A variety of code pages were adopted by standards organizations, such as ISO, and by computer manufactures. A document created on one system using a particular code page wasn’t necessarily usable on another system unless that system also supported the same code page or something compatible.
Another widely used standard in the Western world is ISO-8859-1 which is similar but not identical to Windows® code page 1252. It is an 8-bit encoding with the first 127 characters encoded the same as ASCII. ISO-8859-1 supports many Western languages reasonably well, but it is missing some characters and some symbols such as punctuation.
Unicode is a modern encoding standard developed by The Unicode Consortium. Its goal is to help people around the world use computers in any language. Unicode originally started as a 16-bit encoding, but since July 1996, it has encoded characters in the range U+0000..U+10FFFF, which requires at least a 21-bit code space. There are three common encodings in use:
All of the examples you have seen so far in this tutorial use UTF-8 encoding, although you saw some other possibilities, such as fr_BE.iso88591, in the output of locale -alocale-a.
You use the iconv program to convert between character encodings. Obviously, if you go from a large character set to a smaller one, the conversion does not happen properly. You have the option of ignoring the problem, or transliterating the character to some approximation. Transliteration might drop accents from characters, or replace an unsupported currency symbol with its short name, such as EUR for Euro.
Listing 14 shows the difference between transliterating output and ignoring invalid characters as I convert from UTF-8 to ASCII. In the first example, some characters lose accents or cedillas, and two are transliterated to common alternative representations. In the second example, much of the text is lost as it cannot be represented in the limited ASCII character set.
ian@attic‑u16:~$ echo abc ß α € àḃç | iconv ‑f UTF‑8 ‑t ASCII//TRANSLIT
abc ss ? EUR abc
ian@attic‑u16:~$ echo abc ß α € àḃç | iconv ‑f UTF‑8 ‑t ASCII//IGNORE
iconv: illegal input sequence at position 22
If you try the same examples using ISO-8859-1 instead of ASCII, your output has some strange looking characters. In Listing 15, I show an example using a French error message that I capture to a file. Then, I convert the file to ISO-8859-1 and back to UTF-8 so that you can see the differences and that this example does not lose data.
ian@attic‑u16:~$ LANGUAGE=fr_FR ls no‑such‑file 2>ic‑utf8
ian@attic‑u16:~$ cat ic‑utf8
ls: impossible d'accéder à 'no‑such‑file': Aucun fichier ou dossier de ce type
ian@attic‑u16:~$ iconv ‑f ISO‑8859‑1 ‑t UTF‑8 ‑o ic‑utf8 ic‑8859
ian@attic‑u16:~$ iconv ‑f ISO‑8859‑1 ‑t UTF‑8 ‑o ic‑utf8‑out ic‑8859
ian@attic‑u16:~$ ls ‑l ic‑*
‑rw‑rw‑r‑‑ 1 ian ian 79 May 31 17:22 ic‑8859
‑rw‑rw‑r‑‑ 1 ian ian 81 May 31 17:23 ic‑utf8
‑rw‑rw‑r‑‑ 1 ian ian 81 May 31 17:24 ic‑utf8‑out
ian@attic‑u16:~$ diff ic‑utf8 ic‑utf8‑out
ian@attic‑u16:~$ diff ‑q ic‑8859 ic‑utf8
Files ic‑8859 and ic‑utf8 differ
As with language and language related settings, you might need to configure time zone settings. Your system has a hardware clock and, once booted, probably synchronizes its time setting with a Network Time Protocol (NTP) server. Your company can maintain its own NTP server or server pool, or you might use a public server, such as pool.ntp.org, which is a large cluster of time servers.
To be able to synchronize time across millions of computers and appliances, you need a time standard to work with. This standard is called Coordinated Universal Time (UTC). You also need some measure of the difference between UTC and your local time. Because the Earth’s rotation time is 24 hours, time zones usually span a single hour. For example, Eastern Standard time in the United States is five hours behind UTC (written as UTC-5). Some places, such as South Australia, use a half hour granularity in their offset rather than a whole hour.
Greenwich Mean Time (GMT) is the same time as UTC, but it is not the standard. Rather, it is a time zone that is used in the British Isles and elsewhere.
Use the date command to display your current time and date information. You can choose several different output formats, and you can further customize the output format for specific purposes, such as when you are scripting. I show some examples in Listing 16.
ian@attic‑u16:~$ #Date and time in my system format
Wed May 31 18:46:24 EDT 2017
ian@attic‑u16:~$ #Date and time in ISO 8601 format
ian@attic‑u16:~$ date ‑‑iso‑8601
ian@attic‑u16:~$ #Date and time in RFC 2822 format
ian@attic‑u16:~$ date ‑‑rfc‑2822
Wed, 31 May 2017 18:48:27 ‑0400
ian@attic‑u16:~$ #UTC Date and time
ian@attic‑u16:~$ date ‑u
Wed May 31 22:49:21 UTC 2017
ian@attic‑u16:~$ #Date and time at 09:00 next Friday
ian@attic‑u16:~$ date ‑‑date='09:00 next Fri'
Fri Jun 2 09:00:00 EDT 2017
ian@attic‑u16:~$ #What day is today?
ian@attic‑u16:~$ date "+%A"
The timedatectl command is somewhat similar to the localectl command that I used earlier. Used with no arguments, it displays the current status, as shown in Listing 17.
Local time: Wed 2017‑05‑31 19:04:09 EDT
Universal time: Wed 2017‑05‑31 23:04:09 UTC
RTC time: Wed 2017‑05‑31 23:04:09
Time zone: America/New_York (EDT, ‑0400)
Network time on: yes
NTP synchronized: yes
RTC in local TZ: no
Note the time zone specification, which contains three parts. The time zone name is America/New_York. The common abbreviation is EDT (Eastern Daylight Time), and it is 4 hours behind UTC. Use the tzselect command to check the right format for your own time zone or for a time zone somewhere else. This is an interactive command that steps you through a few choices. Listing 18 shows how to check the time zone for South Australia.
Please identify a location so that time zone rules can be set correctly.
Please select a continent, ocean, "coord", or "TZ".
5) Atlantic Ocean
8) Indian Ocean
9) Pacific Ocean
10) coord ‑ I want to use geographical coordinates.
11) TZ ‑ I want to specify the time zone using the Posix TZ format.
Please select one of the following time zone regions.
1) Lord Howe Island 8) Queensland (most areas)
2) Macquarie Island 9) Queensland (Whitsunday Islands)
3) Tasmania (most areas) 10) South Australia
4) Tasmania (King Island) 11) Northern Territory
5) Victoria 12) Western Australia (most areas)
6) New South Wales (most areas) 13) Western Australia (Eucla)
7) New South Wales (Yancowinna)
The following information has been given:
Therefore TZ='Australia/Adelaide' will be used.
Local time is now: Thu Jun 1 08:41:27 ACST 2017.
Universal Time is now: Wed May 31 23:11:27 UTC 2017.
Is the above information OK?
You can make this change permanent for yourself by appending the line
TZ='Australia/Adelaide'; export TZ
to the file '.profile' in your home directory; then log out and log in again.
Here is that TZ value again, this time on standard output so that you
can use the /usr/bin/tzselect command in shell scripts:
Note the reference to the TZ environment variable. You might find that if you attempt to display the TZ environment variable, it is not set. As noted in the output, you can set and export it in your .profile file if you want to use a time zone that is different from your system time zone. As with some of the LC_* variables, you can also use it to affect a single command, such as the date command as I show in Listing 19.
Wed May 31 19:25:06 EDT 2017
ian@attic‑u16:~$ TZ='Australia/Adelaide' date
Thu Jun 1 08:55:08 ACST 2017
Your system maintains time zone information in a few important locations. Some systems (such as Ubuntu) maintain the system time zone name in /etc/timezone. The file /etc/localtime is a link to a timezone file in the /usr/share/zoneinfo directory. And finally, the /usr/share/zoneinfo directory contains subdirectories for major zones, such as Americas, and then either links or files for the individual time zones. Listing 20 shows some examples on Ubuntu and Fedora systems.
ian@attic‑u16:~$ #Ubuntu 16.04 LTS
ian@attic‑u16:~$ cat /etc/timezone
ian@attic‑u16:~$ ls ‑l /etc/localtime
lrwxrwxrwx 1 root root 36 Dec 23 14:54 /etc/localtime ‑> /usr/share/zoneinfo/America/New_York
ian@attic‑u16:~$ ls ‑l /usr/share/zoneinfo/America/New_York
lrwxrwxrwx 1 root root 13 Dec 7 05:59 /usr/share/zoneinfo/America/New_York ‑> ../posixrules
ian@atticf25 ~]$ #Fedora 25
[ian@atticf25 ~]$ ls /etc/timezone
ls: cannot access '/etc/timezone': No such file or directory
[ian@atticf25 ~]$ ls ‑l /etc/localtime
lrwxrwxrwx. 1 root root 38 Apr 26 18:09 /etc/localtime ‑> ../usr/share/zoneinfo/America/New_York
[ian@atticf25 ~]$ ls ‑l /usr/share/zoneinfo/America/New_York
‑rw‑r‑‑r‑‑. 3 root root 3545 Mar 27 22:18 /usr/share/zoneinfo/America/New_York
If you need to change the system date or time zone, use the tmedatectl command. See the man pages for more information on the options and commands available. You can do things like turn NTP synchronization on or foo, as well as control how the system real time clock is updated or used.
This concludes your introduction to localization and time zone settings.
May 14, 2019
IBM Cloud PrivateIBM LinuxONE+
Get the Code »
This article provides the resources to facilitate standard operating systems and network protocols on IBM's leadership supercomputing hardware.
IBM Power SystemsInfrastructure+
Back to top