En un proyecto PHP en el que estoy participando tenemos problemas para mostrar las fechas en el idioma que queremos, en este caso en español. En esta entrada te explico cómo localizar fechas y horas en PHP.
setlocale
PHP dispone de la función setlocale, que te permite establecer la información del localismo. Puedes localizar varios elementos, como puedes comprobar en la documentación de referencia de setlocale, pero para fechas y horas es suficiente usar el parámetro «LC_TIME».
Por lo tanto, tendrás que usar la función:
setlocale(LC_TIME, 'es_ES');
donde:
- LC_TIME referencia que quieres localizar fechas y horas.
- es_ES indica que quieres localizar para español (es: código ISO 639-1) de España (ES: código ISO 3166 alpha-2).
Para comprobar si esto funciona uso la función strftime(), que formatea una fecha/hora local según una configuración local. El parámetro «%B» devuelve el nombre completo del mes:
<?php
setlocale(LC_TIME, 'es_ES');
echo strftime('%B') . PHP_EOL;
Si lo ejecuto:
$ php test.php
August
El resultado está en inglés. ¿Por qué sucede esto?
Antes de nada, compruebo qué equipo estoy usando. Las pruebas las estoy ejecutando en un equipo con Ubuntu 20.04 LTS y PHP 7.4.
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 20.04 LTS
Release: 20.04
Codename: focal
$ php -v
PHP 7.4.7 (cli) (built: Jun 12 2020 07:44:38) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
with Zend OPcache v7.4.7, Copyright (c), by Zend Technologies
El problema está en que la máquina no tiene instalada la localización de español de España.
Para comprobar las localizaciones disponibles hay que ejecutar:
$ locale -a
C
C.UTF-8
en_AG
en_AG.utf8
en_AU.utf8
en_BW.utf8
en_CA.utf8
en_DK.utf8
en_GB.utf8
en_HK.utf8
en_IE.utf8
en_IL
en_IL.utf8
en_IN
en_IN.utf8
en_NG
en_NG.utf8
en_NZ.utf8
en_PH.utf8
en_SG.utf8
en_US.utf8
en_ZA.utf8
en_ZM
en_ZM.utf8
en_ZW.utf8
POSIX
Puedes comprobar si entre los locales soportados por el sistema se encuentran los de español ejecutando:
$ more /usr/share/i18n/SUPPORTED | grep es_ES
es_ES.UTF-8 UTF-8
es_ES ISO-8859-1
es_ES@euro ISO-8859-15
Para generar los ficheros de localización desde las plantillas hay que ejecutar:
$ sudo locale-gen es_ES.UTF-8 es_ES es_ES@euro
Generating locales (this might take a while)...
es_ES.ISO-8859-15@euro... done
es_ES.ISO-8859-1... done
es_ES.UTF-8... done
Generation complete.
Ahora ya aparece instalado el locale de español:
$ locale -a | grep es_ES
es_ES
es_ES@euro
es_ES.iso88591
es_ES.iso885915@euro
es_ES.utf8
Si ejecutas el código anterior, puedes ver que ahora la información se muestra en español:
$ php test.php
agosto
Ten en cuenta que la función date() no permite la localización. La propia documentación de PHP indica que:
Para formatear fechas en otros lenguajes debería usar las funciones setlocale() y strftime() en vez de date().
Si ejecutas este código:
<?php
setlocale(LC_TIME, 'es_ES');
echo date('F') . PHP_EOL;
El resultado está en inglés:
$ php test.php
August
Lo mismo ocurre con DateTime():
<?php
setlocale(LC_TIME, 'es_ES');
$date = new DateTime();
echo $date->format('F') . PHP_EOL;
Cuyo resultado es:
$ php test.php
August
Lo que puedes hacer es pasarle el timestamp del objeto a la función strftime:
<?php
setlocale(LC_TIME, 'es_ES');
$date = new DateTime('2020-08-02T15:03:01.012345Z', new DateTimeZone('Europe/Madrid'));
echo strftime("%B", $date->getTimestamp()) . PHP_EOL;
Ahora la salida sí que es correcta
$ php test.php
agosto
Puedes encontrar más información sobre cómo localizar fechas y horas en PHP en este enlace.