Php 5.3 : générer une liste de mois localisée

0 commentaires

Par Seb

Dans la suite de notre article sur la génération d’une liste de pays localisée, nous allons maintenant voir comment générer une liste de mois localisée, par exemple pour construire un sélecteur de date sous forme de listes déroulantes.

Pour cela, nous allons de nouveau faire appel à une des classes mises à disposition par Php 5.3 (ou toute version de Php compilées avec la librairie PECL intl) : IntlDateFormatter. Cette classe permet de générer des dates plus ou moins détaillées dans n’importe quelle locale et en respectant les formats locaux. Pour plus de détails, consultez l’excellent article de Pascal Martin, qui a en outre effectué toute une série d’articles sur Php 5.3.

Nous allons voir comment récupérer uniquement les noms de mois afin de construire notre liste déroulante localisée.


Classe de gestion

Pour commencer, nous allons créer une classe afin de packager toutes les fonctionnalités dont nous avons besoin :

<?php
/**
 * Classe de génération de liste de mois dans diverses langues
 * @version	1.0
 */
class ListingMois {

}

Comme pour l’article précédent, nous commenceront par mettre en place un constructeur qui autorise le passage d’une locale afin de définir la langue d’affichage de la liste. On laissera aussi un mode automatique, qui tentera de détecter la locale du navigateur de l’internaute. Attention, tous les navigateurs ne fournissent pas cette information, il convient donc de l’utiliser en connaissance de cause.

/**
 * La locale dans laquelle construire le listing
 * @var		string
 */
protected $_locale;

/**
 * Constructeur de la classe
 * @param	string		la locale à utiliser, ou NULL pour utiliser la locale de l'utilisateur (par défaut)
 */
public function __construct($locale = NULL)
{
	// Si la locale n'est pas fournie
	if (is_null($locale))
	{
		// On tente de la récupérer à partir du useragent de l'utilisateur, sinon on prend la locale par défaut
		if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) and strlen($_SERVER['HTTP_ACCEPT_LANGUAGE']) > 0)
		{
			$locale = Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']);
		}
		else
		{
			$locale = Locale::getDefault();
		}
	}

	// Mémorisation
	$this->_locale = $locale;
}

Construction de la liste

Vient ensuite la construction de la liste à proprement parler. Pour cela, nous allons créer un objet IntlDateFormatter avec la locale définie dans le constructeur, et lui demander de nous fournir uniquement le mois en lui passant le schéma (pattern en anglais) suivant : MMMM.

Nous allons ensuite parcourir tous les mois (de 1 à 12) en créant une date pour chacun avec la fonction mktime et la passer à l’objet IntlDateFormatter pour obtenir le nom textuel du mois :

/**
 * Construction de la liste
 * @param	string		$name			le nom à donner au champ SELECT
 * @param	string		$current		la valeur actuellement sélectionnée
 * @return	string		le code prêt pour affichage
 */
public function build($name = 'mois', $current = NULL)
{
	// Objet de localisation
	$formatter = new IntlDateFormatter($this->_locale, IntlDateFormatter::MEDIUM, IntlDateFormatter::NONE);
	$formatter->setPattern('MMMM');

	// Préparation du listing
	$retour = array();
	$retour[] = '<select name="'.$name.'" id="'.$name.'">';

	// Parcours
	for ($i = 1; $i <= 12; ++$i)
	{
		// Ajout au listing
		$actif = ($current == $i) ? ' selected="selected"' : '';
		$mois = $formatter->format(mktime(0, 0, 0, $i, 1, 1970));
		$retour[] = '<option value="'.$i.'"'.$actif.'>'.htmlspecialchars($mois).'</option>';
	}

	// Finalisation
	$retour[] = '</select>';
	return implode("\n", $retour);
}

Résultat

Notre classe est terminée, il ne vous reste plus qu’à l’inclure dans votre code et à l’appeler de la manière suivante :

<?php
$listing = new ListingMois();
echo $listing->build();
?>

Ce qui nous donne :

Et dans une locale bien différente, c’est nettement plus parlant :

<?php
$listing = new ListingMois('zh');
echo $listing->build();
?>

Ce qui nous donne :

Voici le code complet de la classe :

<?php
/**
 * Classe de génération de liste de mois dans diverses langues
 * @version	1.0
 */
class ListingMois {
	/**
	 * La locale dans laquelle construire le listing
	 * @var		string
	 */
	protected $_locale;

	/**
	 * Constructeur de la classe
	 * @param	string		la locale à utiliser, ou NULL pour utiliser la locale de l'utilisateur (par défaut)
	 */
	public function __construct($locale = NULL)
	{
		// Si la locale n'est pas fournie
		if (is_null($locale))
		{
			// On tente de la récupérer à partir du useragent de l'utilisateur, sinon on prend la locale par défaut
			if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) and strlen($_SERVER['HTTP_ACCEPT_LANGUAGE']) > 0)
			{
				$locale = Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']);
			}
			else
			{
				$locale = Locale::getDefault();
			}
		}

		// Mémorisation
		$this->_locale = $locale;
	}

	/**
	 * Construction de la liste
	 * @param	string		$name			le nom à donner au champ SELECT
	 * @param	string		$current		la valeur actuellement sélectionnée
	 * @return	string		le code prêt pour affichage
	 */
	public function build($name = 'mois', $current = NULL)
	{
		// Objet de localisation
		$formatter = new IntlDateFormatter($this->_locale, IntlDateFormatter::MEDIUM, IntlDateFormatter::NONE);
		$formatter->setPattern('MMMM');

		// Préparation du listing
		$retour = array();
		$retour[] = '<select name="'.$name.'" id="'.$name.'">';

		// Parcours
		for ($i = 1; $i <= 12; ++$i)
		{
			// Ajout au listing
			$actif = ($current == $i) ? ' selected="selected"' : '';
			$mois = $formatter->format(mktime(0, 0, 0, $i, 1, 1970));
			$retour[] = '<option value="'.$i.'"'.$actif.'>'.htmlspecialchars($mois).'</option>';
		}

		// Finalisation
		$retour[] = '</select>';
		return implode("\n", $retour);
	}
}

Petit rappel

Petit rappel lors de l’utilisation des dates (notamment avec mktime) : si vous avez laissé l’affichage des erreurs à son plus haut niveau (E_ALL) et que vous n’avez pas défini de timezone dans votre application, vous allez récolter un beau warning :

Warning: mktime() [function.mktime]: It is not safe to rely on the system’s timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected ‘Europe/Paris’ for ’2.0/DST’ instead

C’est assez explicitement dit, pensez simplement à définir un fuseau horaire via la fonction date_default_timezone_set, par exemple ‘Europe/Paris’ pour la France. C’est une bonne habitude de le faire automatiquement pour chaque projet, cela vous évitera de mauvaises surprises lors du portage sur des configurations différentes de php.

Pour aller plus loin

Nous nous sommes contentés ici de créer un listing des noms de mois, mais il est possible de faire bien plus avec la classe IntlDateFormatter, en jouant sur le pattern fourni. Vous pouvez utiliser par exemple :

  • ‘MMMM’ : nom de mois complet (comme dans l’exemple)
  • ‘MMM’ : nom de mois raccourci, par exemple Jan, Fev…
  • ‘EEEE’ : nom du jour de la semaine complet
  • ‘EEE’ : nom du jour de la semaine raccourci, par exemple Lun, Mar…

A partir de toutes ces combinaisons, vous pourrez composer toutes les listes déroulantes localisées qui vous seront nécessaires, et ce, en quelques lignes de code.

Dans un prochain article, nous aborderons la création d’une classe dédié à la construction de sélecteurs de date complets, et à la récupération et la validation de leur valeurs.


Exprimez vous !


(Ne sera pas publié)

Sur ThemeForest

  • Constellation complete admin skin
  • Blue Earth
  • Blue Earth Wordpress theme