2011-03-22 62 views
43

estoy haciendo una aplicación que recupera Javascript .json archivos con jQuery e inyecta datos en la página web que está incrustado en.¿Cómo convierto caracteres UTF-8 especiales a su equivalente iso-8859-1 usando javascript?

Los archivos .json están codificados con UTF-8 y contiene caracteres como E, O y acentuado a.

El problema es que no controlo el juego de caracteres en las páginas que van a utilizar la aplicación.

Algunos usarán UTF-8, pero otros usarán el juego de caracteres iso-8859-1. Esto, por supuesto, distorsionará los caracteres especiales de los archivos .json.

¿Cómo convierto los caracteres especiales UTF-8 a su equivalente iso-8859-1 usando javascript?

Respuesta

119

En realidad, todo se almacena típicamente como Unicode de algún tipo internamente, pero no vamos a entrar en eso. Supongo que obtendrás las emblemáticas cadenas de caracteres "à ¥ äÃ" "porque estás usando un ISO-8859 como codificación de tu personaje. Hay un truco que puedes hacer para convertir esos personajes. Las funciones escape y unescape utilizadas para codificar y decodificar cadenas de consulta se definen para caracteres ISO, mientras que las más recientes encodeURIComponent y decodeURIComponent que hacen lo mismo, se definen para caracteres UTF8.

escape codifica caracteres extendidos ISO-8859-1 (puntos de código UTF U + 0080-U + 00ff) como %xx (hexadecimal de dos dígitos), mientras que codifica puntos de código UTF U + 0100 y por encima de como %uxxxx (%u seguido de cuatro -digit hex.) Por ejemplo, escape("å") == "%E5" y escape("あ") == "%u3042".

encodeURIComponent porcentaje-codifica los caracteres extendidos como una secuencia de bytes UTF8. Por ejemplo, encodeURIComponent("å") == "%C3%A5" y encodeURIComponent("あ") == "%E3%81%82".

lo que puede hacer:

fixedstring = decodeURIComponent(escape(utfstring)); 

Por ejemplo, un carácter "A" incorrectamente codificado convierte en "¥". El comando hace escape("Ã¥") == "%C3%A5" que son los dos caracteres ISO incorrectos codificados como bytes individuales. Luego decodeURIComponent("%C3%A5") == "å", donde los dos bytes codificados por ciento se interpretan como una secuencia UTF8.

Si había necesidad de hacer a la inversa, por alguna razón, que funciona también:

utfstring = unescape(encodeURIComponent(originalstring)); 

¿Hay una manera de diferenciar entre cadenas UTF8 y malas y cadenas ISO? Resulta que hay. La función decodeURIComponent utilizada anteriormente lanzará un error si se le da una secuencia codificada mal formada. Podemos usar esto para detectar con gran probabilidad si nuestra cadena es UTF8 o ISO.

var fixedstring; 

try{ 
    // If the string is UTF-8, this will work and not throw an error. 
    fixedstring=decodeURIComponent(escape(badstring)); 
}catch(e){ 
    // If it isn't, an error will be thrown, and we can asume that we have an ISO string. 
    fixedstring=badstring; 
} 
+1

He hecho referencia a tu respuesta sobre la respuesta por mi cuenta pregunta aquí: http://stackoverflow.com/questions/18847191/is-there-a-uniform-method-in-both-php-and-js-to-convert-unicode-characters/18863966#18863966 – hsuk

+0

@nitro : ¿Javascript considera todos los caracteres utf-8 como ISO latino? – hsuk

+2

'escape' codifica caracteres extendidos ISO-8859-1 (puntos de código UTF U + 0080-U + 00ff) como'% xx' (hex de dos dígitos) mientras que codifica los puntos de codificación UTF U + 0100 y superiores como '% uxxxx' ('% u' seguido de cuatro dígitos hex.) Por ejemplo,' escape ("å") == "% E5" 'y' escape ("あ") == "% u3042" '. El porcentaje de codificación 'encodeURIComponent' codifica los caracteres extendidos como una secuencia de bytes UTF8. Por ejemplo, 'encodeURIComponent (" å ") =="% C3% A5 "' y 'encodeURIComponent (" あ ") =="% E3% 81% 82 "'. Espero que aclare cualquier pregunta. – nitro2k01

7

El problema es que una vez que se haya servido la página, el contenido estará en la codificación descrita en la metaetiqueta del tipo de contenido. El contenido en codificación "incorrecta" ya está distorsionado.

Es mejor que lo haga en el servidor antes de abrir la página. O como he dicho, decir: UTF-8 de extremo a extremo o morir.

+0

Aunque mi encabezado de página ya dice que está en utf-8, tuve que convertirlo a ISO Latin para obtener más cifrado. http://stackoverflow.com/questions/18786025/mcrypt-js-encryption-value-is-different-than-that-produced-by-php-mcrypt-mcryp – hsuk

1

Internamente, cadenas JavaScript son Unicode (UCS-2 en realidad, un subconjunto de UTF-16).

Si está recuperando los archivos JSON por separado a través de AJAX, solo necesita asegurarse de que los archivos JSON se publiquen con el tipo de contenido y juego de caracteres correctos: Content-Type: application/json; charset="utf-8"). Si haces eso, jQuery ya debería haberlos interpretado correctamente para cuando accedes a los objetos deserializados.

¿Podría publicar un ejemplo del código que está utilizando para recuperar los objetos JSON?

+0

Es irrelevante, ya que establece solo el tipo de contenido o también el juego de caracteres: jQuery interpreta el archivo json servido exactamente de la misma manera. Probablemente porque la especificación (http://www.ietf.org/rfc/rfc4627.txt) dice que 'el texto JSON DEBERÁ estar codificado en Unicode. La codificación predeterminada es UTF-8'. Así que estableciendo el encabezado en 'Content-Type: application/json; charset = "iso-8859-1" 'después de que el texto de codificación json de una variable obtenga de un archivo codificado en iso-8859-1 y enviarlo por ajax a una página html codificada iso-8859-1 produce el mismo resultado que no especificar cualquier cosa: las cadenas interpretadas por el navegador como 'NULL' – Pere

-1

se debe añadir esta línea por encima de su página

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
+0

¿Le faltan algunos detalles a esta respuesta? –

1

Desde el question sobre cómo convertir de ISO-8859-1 a UTF-8 está cerrado debido a esto que yo voy a publicar mi solución aquí.

El problema es cuando intenta OBTENER algo utilizando XMLHttpRequest, si XMLHttpRequest.responseType es "texto" o está vacío, XMLHttpRequest.response se transforma en DOMString y eso es lo que se rompió. Después, es casi imposible trabajar de manera confiable con esa cadena.

Ahora, si el contenido del servidor es ISO-8859-1, deberá forzar la respuesta para que sea del tipo "Blob" y luego convertir esto a DOMSTring. Por ejemplo:

var ajax = new XMLHttpRequest(); 
ajax.open('GET', url, true); 
ajax.responseType = 'blob'; 
ajax.onreadystatechange = function(){ 
    ... 
    if(ajax.responseType === 'blob'){ 
     // Convert the blob to a string 
     var reader = new window.FileReader(); 
     reader.addEventListener('loadend', function() { 
      // For ISO-8859-1 there's no further conversion required 
      Promise.resolve(reader.result); 
     }); 
     reader.readAsBinaryString(ajax.response); 
    } 
} 

parece que la magia está sucediendo en readAsBinaryString así que tal vez alguien puede arrojar algo de luz sobre por qué esto funciona.

0

que estaba buscando esta respuesta, pero que en una línea en contra de muchas de código, podría ser algo como esto:

var converted = "<?php echo mb_convert_encoding($str_to_convert, 'UTF-8', 'ISO-8859-1'); ?>"; 

que trabajó para mí, pero si pones el var en php, como este:

document.write("<?php $str_to_convert = " + your_str + " ?>"); 

Espero que esto ayude a cualquiera.

Cuestiones relacionadas