web-dev-qa-db-fra.com

Comment convertir des caractères spéciaux UTF-8 en leur équivalent iso-8859-1 à l'aide de javascript?

Je fais une application javascript qui récupère .json fichiers avec jquery et injecte des données dans la page Web dans laquelle il est intégré.

Le .json Les fichiers sont codés avec UTF-8 et contiennent des caractères accentués tels que é, ö et å.

Le problème est que je ne contrôle pas le jeu de caractères sur les pages qui vont utiliser l'application.

Certains utiliseront UTF-8, mais d'autres utiliseront le jeu de caractères iso-8859-1. Cela va bien sûr brouiller les caractères spéciaux du .json des dossiers.

Comment convertir des caractères spéciaux UTF-8 en leur équivalent iso-8859-1 à l'aide de javascript?

50
Hobhouse

En fait, tout est typiquement stocké sous forme d’Unicode de manière interne, mais n’y allons pas. Je suppose que vous obtenez les chaînes emblématiques du type "à ¥ ä" parce que vous utilisez un ISO-8859 comme encodage de caractères. Il y a une astuce que vous pouvez faire pour convertir ces personnages. Les fonctions escape et unescape utilisées pour l'encodage et le décodage des chaînes de requête sont définies pour les caractères ISO, tandis que les plus récentes encodeURIComponent et decodeURIComponent font la même chose, sont définis pour les caractères UTF8.

escape code les caractères ISO-8859-1 étendus (points de code UTF U + 0080-U + 00ff) sous la forme %xx (hex à deux chiffres) alors qu'il code les points de code UTF U + 0100 et supérieurs comme %uxxxx (%u Suivi d'un code hexadécimal à quatre chiffres.) Par exemple, escape("å") == "%E5" et escape("あ") == "%u3042".

encodeURIComponent pourcent-code les caractères étendus comme une séquence d'octets UTF8. Par exemple, encodeURIComponent("å") == "%C3%A5" et encodeURIComponent("あ") == "%E3%81%82".

Alors tu peux faire:

fixedstring = decodeURIComponent(escape(utfstring));

Par exemple, un caractère mal codé "å" devient "Ã ¥". La commande effectue escape("Ã¥") == "%C3%A5", qui correspond aux deux caractères ISO incorrects codés sous forme d'octets simples. Ensuite, decodeURIComponent("%C3%A5") == "å", où les deux octets codés pour cent sont interprétés comme une séquence UTF8.

Si vous devez faire l'inverse pour une raison quelconque, cela fonctionne aussi:

utfstring = unescape(encodeURIComponent(originalstring));

Existe-t-il un moyen de différencier les chaînes UTF8 incorrectes et les chaînes ISO? Il s'avère que c'est. La fonction decodeURIComponent utilisée ci-dessus générera une erreur si une séquence codée mal formée est donnée. Nous pouvons l'utiliser pour détecter avec une grande probabilité si notre chaîne est au format UTF8 ou 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 assume that we have an ISO string.
    fixedstring=badstring;
}
136
nitro2k01

Le problème est qu’une fois la page servie, le contenu sera dans le codage décrit dans la balise méta de type contenu. Le contenu en "mauvais" encodage est déjà tronqué.

Vous feriez mieux de le faire sur le serveur avant de servir la page. Ou, comme je l’ai su, à dire: TF-8 de bout en bout ou mourir.

Puisque la question sur la conversion de ISO-8859-1 en UTF-8 est fermée à cause de celle-ci, je vais poster ma solution ici.

Le problème est que lorsque vous essayez d'obtenir quelque chose en utilisant XMLHttpRequest, si XMLHttpRequest.responseType est "text" ou vide, XMLHttpRequest.response est transformé en une chaîne DOMString et que ce n'est pas le cas. Après, il est presque impossible de travailler de manière fiable avec cette chaîne.

Maintenant, si le contenu du serveur est ISO-8859-1, vous devrez forcer la réponse à être du type " Blob " et à la convertir ultérieurement en DOMSTring. Par exemple:

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);
    }
}

On dirait que la magie se passe sur readAsBinaryString , alors peut-être que quelqu'un pourra nous expliquer pourquoi cela fonctionne.

2
Eldelshell

En interne, les chaînes Javascript sont toutes au format Unicode (en fait, UCS-2, un sous-ensemble de UTF-16).

Si vous récupérez les fichiers JSON séparément via AJAX, il vous suffit de vous assurer que les fichiers JSON sont servis avec le type de contenu et le jeu de caractères corrects: Content-Type: application/json; charset="utf-8"). Si vous faites cela, jQuery aurait déjà dû les interpréter correctement au moment où vous accédez aux objets désérialisés.

Pourriez-vous publier un exemple du code que vous utilisez pour récupérer les objets JSON?

1
Martijn