113 votes

Comment puis-je supprimer les accents des caractères dans une chaîne PHP ?

Je tente de supprimer les accents des caractères dans une chaîne PHP comme première étape pour rendre la chaîne utilisable dans une URL.

Je utilise le code suivant:

$input = "Fóø Bår";

setlocale(LC_ALL, "en_US.utf8");
$output = iconv("utf-8", "ascii//TRANSLIT", $input);

print($output);

La sortie que je m'attendrais serait quelque chose comme ceci:

F'oo Bar

Cependant, au lieu d'être transcrits en caractères sans accent, les caractères accentués sont remplacés par des points d'interrogation:

F?? B?r

Tout ce que je trouve en ligne indique que le paramétrage de la localisation résoudrait ce problème, cependant je le fais déjà. J'ai déjà vérifié les détails suivants:

  1. La localisation que je paramètre est supportée par le serveur (incluse dans la liste produite par locale -a)
  2. Les encodages source et cible (UTF-8 et ASCII) sont supportés par la version de iconv du serveur (inclus dans la liste produite par iconv -l)
  3. La chaîne d'entrée est encodée en UTF-8 (vérifiée en utilisant la fonction mb_check_encoding de PHP, comme suggéré dans la réponse de mercator)
  4. L'appel à setlocale est réussi (il retourne 'en_US.utf8' plutôt que FALSE)

La cause du problème:

Le serveur utilise une mauvaise implémentation de iconv. Il a la version glibc au lieu de la version libiconv requise.

Notez que la fonction iconv sur certains systèmes peut ne pas fonctionner comme vous vous attendez. Dans ce cas, il serait judicieux d'installer la bibliothèque GNU libiconv. Il aboutira probablement à des résultats plus cohérents.
Introduction de la fonction iconv du manuel PHP

Des détails sur l'implémentation de iconv utilisée par PHP sont inclus dans la sortie de la fonction phpinfo.

(Je ne suis pas en mesure de recompiler PHP avec la bonne bibliothèque iconv sur le serveur sur lequel je travaille pour ce projet, donc la réponse que j'ai acceptée ci-dessous est celle qui était la plus utile pour supprimer les accents sans prise en charge d'iconv.)

0 votes

Notez que si vous exécutez ceci sur une chaîne qui ne peut pas être en ASCII, cela aura des effets dramatiques. Par exemple, une chaîne russe ne fonctionnera pas avec ASCII.

0 votes

J'ai la version glibc installée et le réglage de la locale fonctionne pour moi.

0 votes

Alors vous avez dû le compiler? Je ne trouve pas de paquet deb nulle part. Exactement à cause de la raison que "C'EST" dans glibc déjà :-(

124voto

dynamic Points 16778

Et concernant l'implémentation de WordPress ?

function remove_accents($string) {
    if ( !preg_match('/[\x80-\xff]/', $string) )
        return $string;

    $chars = array(
    // Décompositions pour Latin-1 Supplément
    chr(195).chr(128) => 'A', chr(195).chr(129) => 'A',
    chr(195).chr(130) => 'A', chr(195).chr(131) => 'A',
    chr(195).chr(132) => 'A', chr(195).chr(133) => 'A',
    chr(195).chr(135) => 'C', chr(195).chr(136) => 'E',
    chr(195).chr(137) => 'E', chr(195).chr(138) => 'E',
    chr(195).chr(139) => 'E', chr(195).chr(140) => 'I',
    chr(195).chr(141) => 'I', chr(195).chr(142) => 'I',
    chr(195).chr(143) => 'I', chr(195).chr(145) => 'N',
    chr(195).chr(146) => 'O', chr(195).chr(147) => 'O',
    ...
    );

    $string = strtr($string, $chars);

    return $string;
}

Pour comprendre ce que cette fonction fait, vérifiez le tableau de conversion :

À => A
Á => A
 => A
à => A
Ä => A
Å => A
Ç => C
È => E
É => E
Ê => E
Ë => E
Ì => I
Í => I
Î => I
Ï => I
Ñ => N
Ò => O
Ó => O
Ô => O
Õ => O
Ö => O
Ù => U
Ú => U
Û => U
Ü => U
Ý => Y
ß => s
à => a
á => a
â => a
ã => a
...

Vous pouvez générer le tableau de conversion vous-même en parcourant simplement le tableau $chars de la fonction :

foreach($chars as $k=>$v) {
   printf("%s -> %s", $k, $v);
}

1 votes

Fonctionne très bien +1, dommage que le lien soit cassé.

5 votes

Ce devrait être la réponse acceptée, car elle a été mise en œuvre de manière plus sûre (en utilisant la fonction chr()) au lieu de coder en dur des caractères accentués, qui pourraient être écrasés dans certains éditeurs de texte.

2 votes

Notez que la nouvelle implémentation se trouve désormais ici : core.trac.wordpress.org/browser/tags/4.1/src/wp-includes/…. Le code nécessite d'autres fonctions fournies par le noyau wordpress, et ne peut être copié/collé sans un certain (léger) travail.

59voto

Version UTF-8 de la fonction simple postée ci-dessus par Gino:

function stripAccents($str) {
    return strtr(utf8_decode($str), utf8_decode('àáâãäçèéêëìíîïñòóôõöùúûüýÿÀÁÂÃÄÇÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜÝ'), 'aaaaaceeeeiiiinooooouuuuyyAAAAACEEEEIIIINOOOOOUUUUY');
}

J'ai dû arriver à cela car mon document php était encodé en UTF-8.

J'espère que cela vous aidera.

1 votes

Certains caractères en UTF8 ne fonctionnent pas correctement pour moi en utilisant cette fonction. Je pense que cela est dû à utf8_decode(), qui convertit de l'UTF8 en ISO-8859-1.

0 votes

@trevor-gehman: strtr() ne fonctionne que sur des caractères mono-octets, d'où ceux en Unicode Latin-1 Supplement.

1 votes

Strtr fonctionne bien pour remplacer les caractères UTF8 multioctets, mais vous devez utiliser la variante où vous fournissez un tableau associatif comme second argument. Ensuite, vous pouvez avoir un caractère multi-octet en tant que clé ou valeur à n'importe quelle position de ce tableau. Assurez-vous que votre éditeur de texte est en mode UTF8 ou encodez en utilisant la syntaxe de type "\xc2\x81".

49voto

Gino Points 664

Ceci est un morceau de code que j'ai trouvé et que j'utilise souvent :

function stripAccents($stripAccents){
  return strtr($stripAccents,'àáâãäçèéêëìíîïñòóôõöùúûüýÿÀÁÂÃÄÇÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜÝ','aaaaaceeeeiiiinooooouuuuyyAAAAACEEEEIIIINOOOOOUUUUY');
}

17 votes

Comme strtr() n'est pas multibyte, si votre fichier de script est encodé dans un format multibyte (par exemple UTF-8), cette fonction produit des résultats incorrects.

0 votes

Vrai. J'ai essayé de forker un projet github juste pour éditer une seule ligne, même pas liée aux caractères accentués, mais quand j'ai enregistré les modifications et créé une demande de tirage, cela incluait les modifications supplémentaires sur toutes les lignes qui avaient des caractères accentués intégrés. La manière la plus sûre est d'utiliser chr().

2 votes

...de plus - cette liste ne contient pas beaucoup de caractères accentués, par exemple u, ž, r, c, ...

17voto

langpavel Points 311

Lors de l'utilisation de iconv, le paramètre de localisation doit être défini :

function test_enc($text = 'ěščřžýáíé ĚŠČŘŽÝÁÍÉ fóø bår FÓØ BÅR æ')
{
    echo '';
    echo iconv('utf8', 'ascii//TRANSLIT', $text);
    echo '';
} 

test_enc();
setlocale(LC_ALL, 'cs_CZ.utf8');
test_enc();
setlocale(LC_ALL, 'en_US.utf8');
test_enc();

Donne :

????????? ????????? f?? b?r F?? B?R ae
escrzyaie ESCRZYAIE fo? bar FO? BAR ae
escrzyaie ESCRZYAIE fo? bar FO? BAR ae

Je n'ai pas installé d'autres paramètres régionaux que cs_CZ et en_US et je ne peux pas les tester.

En C#, je vois une solution utilisant la translation en forme normalisée Unicode - les accents sont séparés puis filtrés via la catégorie Unicode non accentuée.

10voto

Junior Mayhé Points 5202

En effet, c'est une question de goût. Il existe de nombreux choix pour convertir de telles lettres.

function replaceAccents($str)
{
  $a = array('À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï', 'Ð', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', 'ß', 'à', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', 'è', 'é', 'ê', 'ë', 'ì', 'í', 'î', 'ï', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', 'ø', 'ù', 'ú', 'û', 'ü', 'ý', 'ÿ', 'Ā', 'ā', 'Ă', 'ă', 'Ą', 'ą', 'Ć', 'ć', 'Ĉ', 'ĉ', 'Ċ', 'ċ', 'Č', 'č', 'Ď', 'ď', 'Đ', 'đ', 'Ē', 'ē', 'Ĕ', 'ĕ', 'Ė', 'ė', 'Ę', 'ę', 'Ě', 'ě', 'Ĝ', 'ĝ', 'Ğ', 'ğ', 'Ġ', 'ġ', 'Ģ', 'ģ', 'Ĥ', 'ĥ', 'Ħ', 'ħ', 'Ĩ', 'ĩ', 'Ī', 'ī', 'Ĭ', 'ĭ', 'Į', 'į', 'İ', 'ı', 'IJ', 'ij', 'Ĵ', 'ĵ', 'Ķ', 'ķ...

  $b = array('A', 'A', 'A', 'A', 'A', 'A', 'AE', 'C', 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I', 'D', 'N', 'O', 'O', 'O', 'O', 'O', 'O', 'U', 'U', 'U', 'U', 'Y', 's', 'a', 'a', 'a', 'a', 'a', 'a', 'ae', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', 'n', 'o', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', 'y', 'y', 'A', 'a', 'A', 'a', 'A', 'a', 'C', 'c', 'C', 'c', 'C', 'c', 'C', 'c', 'D', 'd', 'D', 'd', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'G', 'g', 'G', 'g', 'G', 'g', 'G', 'g', 'H', 'h', 'H', 'h', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i', 'IJ', 'ij', 'J', 'j', 'K', 'k', 'L', 'l', 'L', '...

  return str_replace($a, $b, $str);
}

0 votes

C'est une implémentation très incomplète, voir la réponse de John R

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X