PHP date localisation with setlocale· 5 minute read
Localising sites can be a chore, but PHP has the venerable
setlocale() to use system locales. These are like templates or profiles that describe how various types of data should be displayed. Should a price have a comma or point to indicate the decimals? When printing a date should PHP output Monday or Montag?
All of these considerations are locale specific and they map to a geographical area. Various cultures have their own standards for displaying this kind of information not to mention different languages to accommodate. This is why the locale name first specifies the language (
en - English) and then the geographic location (
GB - Great Britain).
To find the list of locales that your system has available you can run a simple Linux command.
This will return a simple list of locale files; something like the following:
C C.UTF-8 POSIX en_AG en_AG.utf8 en_AU.utf8 en_BW.utf8 en_CA.utf8 en_DK.utf8 en_GB.utf8
If the locale you need is not there then you will need to install it on your machine. In my case I wanted to use a Spanish locale (
es_ES) and as you can see from the list above it is not currently available.
First check if your system can install the required locale by browsing through the supported locales with:
Having spotted the locale you wish to install you can now compile it from the sources on your machine.
sudo locale-gen es_ES es_ES.utf8
Alternatively, if you’re on Ubuntu, you can install it from the package repository using
sudo apt-get install language-pack-es
es at the end is the language you want to install.
You can now run
locale -a again and you will see your new locale available in the returned list. A further test you can do before moving to PHP is to run the locale from the command line. Firstly though you need to take a note of you current locale:
Make sure you keep the local that is printed to hand as you’re going to want to switch back to it later.
To change the default locale to
es_ES on the command line you would first set value of the
LC_ALL environment variable.
Now we can do a simple test by printing out the current month and ensuring it is using our desired locale.
The month should have been printed out in the language of the current locale - in my case this is Spanish so it would be
Now that is tested we can switch back to your original locale using that same
export method from before.
In my case I am switching back to
en_GB, but you will want to substitute that for the locale you noted down earlier - you did note it down didn’t you?
This is great - we’ve now got a working locale that we can use from PHP to localise our content. (You may need to restart the webserver if you’re using one).
My concern here is to change the locale for dates (
LC_TIME), but you can find out the other constants by looking at the relevant PHP manual page. For the remainder of this article I will concentrate on the time.
The first thing we must do is set the locale against the time.
Now to actually print a date you will need to make use of the
strftime() function which basically wraps the
date command we were using from the command line earlier.
echo strftime('%B'); // junio
You should note that the defacto PHP date handling functionality does not respect the prevailing locale like
echo date('F'); // June
Also the same is true of PHP’s
DateTime classes too.
$date = new DateTime(); echo $date->format('F'); // June
One way around this is to pass the date out as a timestamp from
DateTime and then format it using the
$date = new DateTime(); echo strftime("%B", $date->getTimestamp()); // junio
This is fine, but it does mean that you’re going to miss out on the time zone power of the
DateTime library and have to revert back to using
date_default_timezone_set to set the current time zone instead. By doing this you will miss out on the time zone conversion trick I wrote about previously; Convert UTC to local time.
strftime() does not support dates before the UNIX epoch (January 1, 1970). If these caveats are not a concern the
setlocale() can provide a helpful way of localising the output of your PHP code.
Finally, there is a big red warning on the PHP manual page for
setlocale() that applies to those running multithreaded servers:
Warning The locale information is maintained per process, not per thread. If you are running PHP on a multithreaded server API like IIS, HHVM or Apache on Windows, you may experience sudden changes in locale settings while a script is running, though the script itself never called setlocale(). This happens due to other scripts running in different threads of the same process at the same time, changing the process-wide locale using setlocale().
Another way around this is to use the Intl extension for PHP with its
IntlDateFormatter class, but that is another post!
Image credit: www.flickr.com/photos/58939349@N00/3753289404