Différences entre iconv() sur Windows et Unix

Pour mon utilitaire de conversion d'unités, j'avais besoin de constituer un index sous la forme d'un tableau PHP. La recherche dans ce tableau s'effectuant à partir d'une saisie utilisateur, il me fallait une fonction pour supprimer les accents et les caractères spéciaux, de façon à ce qu'une saisie utilisateur comme mètre produise le même résultat que metre et que soit équivalent à m2.

Après quelques recherches sur Internet, je me suis intéressé à la fonction PHP iconv. Cette fonction permet de convertir un texte d'un jeu de caractère à un autre. En choisissant ASCII avec l'option TRANSLIT pour la sortie, on obtient en partie l'effet désiré. Le problème, c'est que le résultat dépend de la bibliothèque iconv utilisée. Sur les systèmes Unix, c'est généralement glibc qui est utilisé, alors que sous Windows, c'est libiconv.

<?php
// Affiche metre sous Linux et m`etre sous Windows
echo iconv('UTF-8''ASCII//TRANSLIT''mètre');

// Affiche m? sous Linux et m^2 sous Windows 
echo iconv('UTF-8''ASCII//TRANSLIT''m²');    
?>

En fait, libiconv tente de fournir une version approchée, alors que glibc va au plus simple en supprimant directement l'accent. Pour le symbole carré (²), glibc ne sait pas gérer le caractère et le remplace par un point d'interrogation, alors que libiconv le remplace par ^2.

Au final, ni la version Windows, ni la version Unix ne correspondent à mon besoin. En plus c'est assez gênant de constater que le résultat diffère d'une plateforme à l'autre, ce qui rends à mon avis l'option //TRANSLIT assez peu utile.

J'ai donc utilisé une combinaison de str_ireplace et preg_replace. Évidemment, il faut alors essayer de penser à tous les cas de figure.

En conclusion, méfiez vous de iconv et de son option //TRANSLIT. Ce qui fonctionne chez vous ne fonctionnera peut-être pas ailleurs...

Mise à jour du 24/12/2010 Finalement, j'utilise la fonction suivante :

<?php
public function removeDiacritics($str)
{
    
$str str_ireplace(array('²''³'), array('2''3'), $str);
    
$str iconv('UTF-8''ASCII//TRANSLIT//IGNORE'$str);
    return 
str_replace(array('\'e''`''^''"'), array('e'''), $str);
}
?>

Etiquettes:

Commentaires

À mon avis, c'est en partie du à la configuration par défaut de la locale et à la gestion différente des locales d'une machine à une autre et encore plus d'un système à un autre [1].
Sinon pour faire de la translitération, il existe l'extension PECL translit [2] bien plus souple que iconv().
[1] http://msdn.microsoft.com/en-us/library/39cwe7zf.aspx [2] http://derickrethans.nl/translit.php

Oui sur un de mes systèmes Gentoo, j'ai observé que iconv ne fonctionnait pas correctement si la locale n'était pas disponible. Après avoir généré la locale avec locale-gen, iconv retournait les résultats attendus.

Ajouter un commentaire