Transcriba cualquier char convertible utf8 en equivalente ascii

¿Hay alguna buena solución que haga esta transliteración de una buena manera?

He intentado usar iconv() , pero es muy molesto y no se comporta como uno podría esperar.

  • Usando //TRANSLIT intentará reemplazar lo que pueda, dejando todo no convertible como “?”
  • Usando //IGNORE no saldrá “?” en texto, pero tampoco se transcribirá y también boostá E_NOTICE cuando se encuentre un carácter no convertible, por lo que debe usar iconv con @supresor de error
  • Usar //IGNORE//TRANSLIT (como algunas personas sugirieron en el foro de PHP) es realmente igual a //IGNORE (lo probé en las versiones de PHP 5.3.2 y 5.3.13)
  • También usar //TRANSLIT//IGNORE es lo mismo que //TRANSLIT

También utiliza la configuración regional actual para transcribir.

ADVERTENCIA: ¡muchos textos y códigos están siguiendo!

Aquí hay unos ejemplos:

 $text = 'Regular ascii text + čćžšđ + äöüß + éĕěėëȩ + æø€ + $ + ¶ + @'; echo '
original: ' . $text; echo '
regular: ' . iconv("UTF-8", "ASCII//TRANSLIT", $text); //> regular: Regular ascii text + ????? + ???ss + ?????? + ae?EUR + $ + ? + @ setlocale(LC_ALL, 'en_GB'); echo '
en_GB: ' . iconv("UTF-8", "ASCII//TRANSLIT", $text); //> en_GB: Regular ascii text + cczs? + aouss + eeeeee + ae?EUR + $ + ? + @ setlocale(LC_ALL, 'en_GB.UTF8'); // will this work? echo '
en_GB.UTF8: ' . iconv("UTF-8", "ASCII//TRANSLIT", $text); //> en_GB.UTF8: Regular ascii text + cczs? + aouss + eeeeee + ae?EUR + $ + ? + @

Ok, eso sí convirtió č ć ĕ ĕ

 // now specific locales setlocale(LC_ALL, 'hr_Hr'); // this should fix croatian đ, right? echo '
hr_Hr: ' . iconv("UTF-8", "ASCII//TRANSLIT", $text); // wrong > hr_Hr: Regular ascii text + cczs? + aouss + eeeeee + ae?EUR + $ + ? + @ setlocale(LC_ALL, 'sv_SE'); // so this will fix swedish ø? echo '
sv_SE: ' . iconv("UTF-8", "ASCII//TRANSLIT", $text); // will not > sv_SE: Regular ascii text + cczs? + aouss + eeeeee + ae?EUR + $ + ? + @ //this is interesting setlocale(LC_ALL, 'de_DE'); echo '
de_DE: ' . iconv("UTF-8", "ASCII//TRANSLIT", $text); //> de_DE: Regular ascii text + cczs? + aeoeuess + eeeeee + ae?EUR + $ + ? + @ // actually this is what any german would expect since ä ö ü really is same as ae oe ue

Probemos con //IGNORE :

 echo '
ignore: ' . iconv("UTF-8", "ASCII//IGNORE", $text); //> ignore: Regular ascii text + + + + + $ + + @ //+ E_NOTICE: "Notice: iconv(): Detected an illegal character in input string in /var/www/test.server.web/index.php on line 49" // with translit? echo '
ignore/translit: ' . iconv("UTF-8", "ASCII//IGNORE//TRANSLIT", $text); //same as ignore only> ignore/translit: Regular ascii text + + + + + $ + + @ //+ E_NOTICE: "Notice: iconv(): Detected an illegal character in input string in /var/www/test.server.web/index.php on line 54" // translit/ignore? echo '
translit/ignore: ' . iconv("UTF-8", "ASCII//TRANSLIT//IGNORE", $text); //same as translit only> translit/ignore: Regular ascii text + cczs? + aouss + eeeeee + ae?EUR + $ + ? + @

Usar la solución de este tipo tampoco funciona como se desea: Regular ascii text + YYYYY + aous + eYYYeY + aoY + $ + + @

Incluso el uso de la clase PICL intl Normalizer (que no está disponible siempre aunque tenga PHP> 5.3.0, ya que ICU package intl uses puede no estar disponible para PHP, es decir, en ciertos servidores de alojamiento) produce resultados incorrectos:

 echo '
normalize: ' .preg_replace('/\p{Mn}/u', '', Normalizer::normalize($text, Normalizer::FORM_KD)); //>normalize: Regular ascii text + cczsđ + aouß + eeeeee + æø€ + $ + ¶ + @

Entonces, ¿hay alguna otra forma de hacer esto bien o la única cosa adecuada para hacer es hacer preg_replace() o str_replace() y definir tablas de transliteración usted mismo?

// appendix: He encontrado en el debate wiki de ZF de 2008 sobre la propuesta de Zend_Filter_Transliterate, pero el proyecto fue descartado ya que en algunos idiomas no es posible convertirlo (es decir, chino), pero para cualquier idioma latino y cirílico esta opción es IMO debería existir

La función toAscii () de Patchwork \ Utf8 hace exactamente esto, ver:

https://github.com/nicolas-grekas/Patchwork-UTF8/blob/master/src/Patchwork/Utf8.php

Aprovecha iconv y el normalizador de intl para eliminar acentos, dividir ligaduras y hacer muchas otras transcripciones genéricas.

Desde este sitio web , encontré algo que podría ayudarte:

 function removeAccents($str) { $a = array('À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï', 'Ð', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', 'ß', 'à', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', 'è', 'é', 'ê', 'ë', 'ì', 'í', 'î', 'ï', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', 'ø', 'ù', 'ú', 'û', 'ü', 'ý', 'ÿ', 'Ā', 'ā', 'Ă', 'ă', 'Ą', 'ą', 'Ć', 'ć', 'Ĉ', 'ĉ', 'Ċ', 'ċ', 'Č', 'č', 'Ď', 'ď', 'Đ', 'đ', 'Ē', 'ē', 'Ĕ', 'ĕ', 'Ė', 'ė', 'Ę', 'ę', 'Ě', 'ě', 'Ĝ', 'ĝ', 'Ğ', 'ğ', 'Ġ', 'ġ', 'Ģ', 'ģ', 'Ĥ', 'ĥ', 'Ħ', 'ħ', 'Ĩ', 'ĩ', 'Ī', 'ī', 'Ĭ', 'ĭ', 'Į', 'į', 'İ', 'ı', 'IJ', 'ij', 'Ĵ', 'ĵ', 'Ķ', 'ķ', 'Ĺ', 'ĺ', 'Ļ', 'ļ', 'Ľ', 'ľ', 'Ŀ', 'ŀ', 'Ł', 'ł', 'Ń', 'ń', 'Ņ', 'ņ', 'Ň', 'ň', 'ʼn', 'Ō', 'ō', 'Ŏ', 'ŏ', 'Ő', 'ő', 'Œ', 'œ', 'Ŕ', 'ŕ', 'Ŗ', 'ŗ', 'Ř', 'ř', 'Ś', 'ś', 'Ŝ', 'ŝ', 'Ş', 'ş', 'Š', 'š', 'Ţ', 'ţ', 'Ť', 'ť', 'Ŧ', 'ŧ', 'Ũ', 'ũ', 'Ū', 'ū', 'Ŭ', 'ŭ', 'Ů', 'ů', 'Ű', 'ű', 'Ų', 'ų', 'Ŵ', 'ŵ', 'Ŷ', 'ŷ', 'Ÿ', 'Ź', 'ź', 'Ż', 'ż', 'Ž', 'ž', 'ſ', 'ƒ', 'Ơ', 'ơ', 'Ư', 'ư', 'Ǎ', 'ǎ', 'Ǐ', 'ǐ', 'Ǒ', 'ǒ', 'Ǔ', 'ǔ', 'Ǖ', 'ǖ', 'Ǘ', 'ǘ', 'Ǚ', 'ǚ', 'Ǜ', 'ǜ', 'Ǻ', 'ǻ', 'Ǽ', 'ǽ', 'Ǿ', 'ǿ'); $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', 'l', 'L', 'l', 'L', 'l', 'l', 'l', 'N', 'n', 'N', 'n', 'N', 'n', 'n', 'O', 'o', 'O', 'o', 'O', 'o', 'OE', 'oe', 'R', 'r', 'R', 'r', 'R', 'r', 'S', 's', 'S', 's', 'S', 's', 'S', 's', 'T', 't', 'T', 't', 'T', 't', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'W', 'w', 'Y', 'y', 'Y', 'Z', 'z', 'Z', 'z', 'Z', 'z', 's', 'f', 'O', 'o', 'U', 'u', 'A', 'a', 'I', 'i', 'O', 'o', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'A', 'a', 'AE', 'ae', 'O', 'o'); return str_replace($a, $b, $str); } 

Ejemplo de uso:

 $text = 'Regular ascii text + čćžšđ + äöüß + éĕěėëȩ + æø€ + $ + ¶ + @'; echo removeAccents($text); 

Muestra:

 Regular ascii text + cczsd + aous + eeeeeȩ + aeo€ + $ + ¶ + @ 

Necesitarás mejorarlo, pero entiendes la idea … Si hay una manera directa de hacer ese trabajo, no lo sé.

Como ninguna de las soluciones anteriores funcionó para mí (necesitaba transcribir muchos juegos de caracteres europeos en ASCII), finalmente encontré este viejo paquete PECL que parecía funcionar http://derickrethans.nl/projects.html#translit . Tuve problemas especialmente con los juegos de caracteres cirílicos, y esto parece manejarlos perfectamente.

Si lo he entendido correctamente, es posible que tenga una respuesta para usted: he escrito una clase PHP básica que le permite convertir la mayoría de los caracteres en sus equivalentes ASCII.

A continuación se muestra una captura de pantalla de su salida convirtiendo varios nombres de compositores con acentos en su nombre.

Puede bifurcarlo desde github aquí https://github.com/LukeMadhanga/transliterator .

NB: Todavía no está documentado, pero debería ser fácil de entender.

Ejemplo

Creo que establecer el lugar correcto es el camino a seguir. Tenga en cuenta que la configuración regional específica también debe estar disponible en el sistema, verifíquela utilizando la locale -a . Si solo tiene de_DE.utf8 , también debe usar set_locale ( de_DE.utf8 )