ambas cosas:
$result = iconv('UTF-8', 'UTF-16LE//IGNORE//TRANSLIT', $str); y mb_convert_encoding() no logran convertir un ndash (–) en el signo menos largo.
El resultado irá a un csv, por lo que reemplazarlo con una entidad html no es una opción. ¿Algunas ideas?
código:
$data = $eventHelper->getProgramForCsvExport($event); $response = new StreamedResponse(); $response->setCharset('UTF-16LE'); $filename = 'program-' . $event->getShortName() . $event->getShortYear() . '.csv'; $utf16Data = []; foreach ($data as $row) { $utf16row = []; foreach ($row as $entry) { $utf16row[] = iconv('UTF-8', 'UTF-16LE//IGNORE//TRANSLIT', $entry); } $utf16Data[] = $utf16row; } $response->setCallback(function () use ($utf16Data) { $output = fopen('php://output', 'w+'); foreach ($utf16Data as $row) { fputcsv($output, $row, ';'); } fclose($output); }); $response->headers->set('Content-Type', 'text/csv; charset=utf-16'); $response->headers->set('Content-Disposition', 'attachment; filename="' . $filename . '"'); return $response;Editar: es una exportación para la gran oficina 365 que ya no es compatible con UTF-8 pero está en UTF-16LE de manera predeterminada (por lo que leí). Las diéresis alemanas (äöüß) funcionan bien (y no lo hacían antes de la conversión), pero ndash (y tal vez algunos otros caracteres especiales) no. Los guiones están en blanco (en Mac) o se convierten en corchetes (más o menos) en Windows.
Creo que el problema es que su código no genera una BOM UTF-16LE (marca de orden de bytes) al comienzo del archivo, por lo que los programas que lo leen no saben en qué codificación está y (aparentemente) están adivinando mal.
Un BOM UTF-16LE es la secuencia de bytes 0xFF 0xFE (en ese orden) justo al principio del archivo. Haz que eso sea lo primero que escribas en tu salida. Más información sobre las listas de materiales en estas preguntas frecuentes sobre Unicode .
Para probar mi teoría, escribí la secuencia de bytes para un archivo UTF-16LE que contiene solo los caracteres 0–0 :
FF FE 30 00 13 20 30 00
El FF FE es la lista de materiales, el 30 00 es el dígito cero, el 13 20 es el guión N y el 30 00 final es el último dígito cero. (Los ceros están ahí para que pueda encontrar fácilmente el guión, aunque en un archivo tan corto no sería realmente difícil).
Pude abrir eso con Office 365 en Windows sin problemas.
Luego escribí un archivo sin la lista de materiales:
30 00 13 20 30 00
De hecho, Office 365 malinterpretó el guión N y lo mostró como un carácter que parece un par de corchetes.