Fixer les problèmes d'encodage
Le 5 septembre 2008, à 10:42 par Ulhume...

Aujourd'hui la majorité des grandes distributions est passée à l'encodage UTF-8, permettant l'affichage propre d'un large panel de symboles linguistiques. Maintenant lorsqu'il s'agit de vieux systèmes mis à jour, ou quant l'on en vient à utiliser des fichiers provenant notamment du monde Windows, il peut être utile de savoir comment unifier les encodages de sorte à garder un système de fichier propre.

Régler l'encodage du système

La première chose à vérifier est que le système est bien en UTF. Certains système que l'on a mis à jour à la main, sans passer par un ré-installation complète restent encore en ISO-8859-15. C'était mon cas pour une vielle configuration que j'avais fait progresser de Mandriva 7.2 jusqu'à aujourd'hui (on ne rigole pas Wink.

Sous Mandriva, il faut vérifier le fichier /etc/sysconfig/i18n qui doit contenir quelque chose comme cela :

  1. LC_TELEPHONE=fr_FR.UTF-8
  2. LC_CTYPE=fr_FR.UTF-8
  3. LANGUAGE=fr_FR.UTF-8:fr
  4. LC_MONETARY=fr_FR.UTF-8
  5. LC_ADDRESS=fr_FR.UTF-8
  6. LC_COLLATE=fr_FR.UTF-8
  7. LC_PAPER=fr_FR.UTF-8
  8. LC_NAME=fr_FR.UTF-8
  9. LC_NUMERIC=fr_FR.UTF-8
  10. SYSFONT=lat0-16
  11. LC_MEASUREMENT=fr_FR.UTF-8
  12. LC_TIME=fr_FR.UTF-8
  13. LANG=fr_FR.UTF-8
  14. LC_IDENTIFICATION=fr_FR.UTF-8
  15. LC_MESSAGES=fr_FR.UTF-8

Après cela, on fait comme pour Windows, on reboot Wink et le système passe tout seul en UTF-8. Une chose de faite...

SI même après cela vous êtes toujours en ISO en tant qu'utilisateur (pour savoir cela, lancez la commande locale dans une console non-root, vous devriez voir des fr_FR.UTF-8 apparaître), c'est sûrement que vous avez une configuration locale à votre compte. Regardez si vous n'auriez pas un fichier ~/.i18n et si c'est le cas, supprimez-le, déconnectez-vous et reconnectez-vous.

Sous un Windows XP récent, les systèmes de fichiers sont je crois maintenant encodés en UTF-8, de même que les partages. En revanche, il y a un hic avec Java qui persiste pour des raisons historiques à rester en ISO. Du coup, un environnement de développement comme Eclipse est spontanément ISO ce qui est loin d'être une idée de génie. Pour changer cela, il faut aller dans le paramétrage d'Eclipse, section Workspace, et changer l'encodage global de l'espace de travail. Cela ne va cependant pas modifier les fichiers déjà écrits en ISO mais juste assurer que l'encodage des prochains seront en UTF.

Les noms de fichiers

Une fois que le système est clairement en UTF-8, le point suivant sont les noms de fichiers. Soit, comme pour le point précédent, il s'agit d'un "vieux" système de fichier, soit plus régulièrement, c'est un Windowsien qui vous envoie une archive type Zip qui contient des encodages ISO et qui se décompresse tel-quel sur votre système de fichiers UTF-8.

Dans un cas, comme dans l'autre, il nous faut donc convertir chaque noms de fichier (pas leur contenu) en les renommant ce qui serait un peu fastidieux. Heureusement, une bonne âme a construit un outil qui remplis parfaitement cette tâche, convmv. Soit vous pouvez directement installer le paquet (ex. sous Mandriva, par un urpmi convmv), soit par les sources. Ensuite, la syntaxe est la suivante :

  1. cd mon_dossier_a_convertir
  2. convmv --notest -r -f iso-8859-15 -t utf-8 *

Les options -f et -t représentent respectivement l'encodage source (iso-8859-15) et cible (utf-8). L'option notest indique à l'outil que ce n'est pas une simulation (enlever cette option si vous voulez vérifier que tout se passe bien). L'option -r demande à traiter le dossier ainsi que tous les sous-dossier (récursif), à enlever donc si vous ne souhaiter traiter que le dossier courant. Enfin * indique qu'il fait traiter tout les fichiers, et il peut être remplacé par le nom d'un fichier unique à convertir.

Une fois l'opération terminé, vos noms fichiers doivent être lisibles.

Conversion des contenus

Là, nous sortons un peu du cadre de l'OS car les contenus textes sont très logiquement géré par les applications idoines. Pour convertir un contenu ISO en UTF, la commande magique est iconv utilisable comme ceci :

iconv --from-code=ISO-8859-1 --to-code=UTF-8 ancien_fichier.java -o ./nouveau_fichier.java

iconv est globalement moins sympa que convmv :

  • Pas de mode récursif.
  • Impossible d'écrire le fichier sur lui-même que ce soit par une redirection ou un -o, la sanction serait un fichier vide Wink
  • Aucune vérification sur le fait que le fichier source soit effectivement codé en ISO.

Au fond, le vrai point problématique est le dernier, mais là, iConv n'y est pour rien. En effet, il n'y a aucun moyen fiable de savoir avec quel format est encodé un fichier texte. Il existe tout au plus des algorithmes permettant de le "deviner" mais plus le texte est cours, moins l'algorithme fonctionnera.

En somme, si vous avez un fichier ISO parmi une série d'UTF à convertir, utilisez la syntaxe précédente, quitte à gommer les deux premiers points par un petit script que vous pouvez par exemple coller dans les scripts Nautilus pour les avoir sur un click-droit :

/.gnome2/nautilus-scripts/ISO to UTF
  1. #! /bin/sh
  2.  
  3. logger $PWD $1
  4. iconv  --from-code=ISO-8859-1 --to-code=UTF-8 "$1" >  ~/tmp/iconv
  5. mv ~/tmp/iconv "$1"

Maintenant si vous tenez à convertir un lot de fichier, cela peut être fait ainsi :

for fichier in $(find -type f . -name "*.java") do iconv --from-code=ISO-8859-1 --to-code=UTF-8 $fichier -c >> ~/tmp/iconv rm $fichier mv ~/tmp/iconv $fichier done

Conclusion

Avec ces deux trois astuces, vous devriez couvrir l'ensemble des cas de figures permettant d'importer chez vous des fichiers non-ISO ou de convertir en UTF des fichiers qui devrait l'être.

Si l'impact UTF/ISO est assez faible pour un utilisateur standard, il est beaucoup plus critique s'agissant par exemple d'un développeur. Dans ce cas, l'UTF devient un encodage commun à tous, quel que soit le pays ou la plateforme utilisée. Et c'est encore plus vrai dans le monde open source.

Commentaires

tuxce , le 5 September, 2008 - 12:21

pour ce qui est du redémarrage, il est meilleur pour avoir la totalité du système en utf8, mais se reconnecter ou relancer un service suffit à passer l'utilisateur ou le service en utf8, /etc/sysconfig/i18n étant lu par le fichier /etc/profile.

Dab, le 5 September, 2008 - 13:15

Et pour la route une petite fonction Perl d'encode en utf8:

  1. sub enc2utf8 {
  2.   my $text = shift;
  3.  
  4.   utf8::decode($text);
  5.   $text = encode('utf-8', $text);
  6.  
  7.   return $text;
  8. }

Ulhume, le 5 September, 2008 - 13:46

@tuxce s'était un peu l'idée, je veux dire d'avoir l'ensemble du système fonctionnel. Ceci dit, sous Mandriva, il ne semble pas que ce soit /etc/profile qui gère cet aspect des choses. Quant à pouvoir dire qui le fait...

Ulhume, le 5 September, 2008 - 13:46

@Dab attention, je vais te mettre la même en java sinon Wink

Dab, le 5 September, 2008 - 14:10

Chiche Wink

tuxce , le 5 September, 2008 - 15:46

ben si normalement, c'est /etc/profile.d/*lang.csh (me rappelle plus du numéro)
mais c'était juste pour indiquer que le redémarrage n'est pas nécessaire Wink

Ulhume, le 5 September, 2008 - 15:51

Je me fais chercher là, bon, ok :

  1. function byte[] toUtf8(byte[] whatever, String from, string to) {
  2.   String src = new String(whatever, from);
  3.   return str.getBytes(to);
  4. }

Vala Smiling en fait le truc en java c'est que les chaînes sont codées, en interne, en java. Donc de manière plus générale, si j'ai par exemple une volée de bytes codant une chaîne ISO, j'obtiens la chaîne UTF par un

String ma_chaîne_utf=new String(mes_octets_iso, "ISO-8859-15");

Dab, le 5 September, 2008 - 16:28

Oh ben fallait pas Smiling
Par contre ça t'oblige à connaitre le codage de la chaine.

Ex de la fonction Perl
j'ai deux fichiers avec des codages différents:
$file -i *
iso8859-1.txt: ISO-8859 text
utf8.txt: UTF-8 Unicode text

#!/usr/bin/perl

use File::Slurp qw( read_file );
use Encode;
use utf8;

my $encoding = "utf-8";

my $iso8859 = scalar read_file( "iso8859-1.txt" );
$iso8859 = encutf8($iso8859);
print $iso8859;

my $utf8 = scalar read_file( "utf8.txt" );
$utf8 = encutf8($utf8);
print $utf8;

Ulhume, le 5 September, 2008 - 16:36

@Dab
certes ça t'obliges à connaître l'encodage de la chaîne mais d'un autre côté, j'ai souvent planté perl qui se trompait d'encodage en cherchant à le deviner (typiquement avec un ou deux accentués sur un paragraphe).

Dab, le 5 September, 2008 - 16:52

Je dois te dire que j'ai uniquement testé en iso8859 et utf8, les seuls que j'utilise, dans ces cas ça traduit correctement. C'est cette méthode que j'utilise pour la traduction des fichiers en texte sur Catapulse.

Ulhume, le 5 September, 2008 - 16:56

@dab non mais ça marche très bien aussi sur les autres encodages, le seul truc c'est que lorsque tu utilises cela sur une phrase courte, ne contenant qu'un ou deux accents, il n'est pas sur de lui. Ce qui est normal je pense car rien de purement rationnel lui permet de déterminer l'encodage, c'est une pure heuristique.

Dab, le 5 September, 2008 - 17:37

Franchement je ne sais pas du tout sa manière d'y parvenir, ni beaucoup plus sur l'encodage:) mais je viens de tester avec une courte phrase et même avec un unique caractère et ... ça fonctionne encore. Maudit Perl, veut pas se tromper Smiling

Ulhume, le 5 September, 2008 - 18:26

@Dab bein moi je veux bien le voir me deviner l'encodage entre deux ISO différents Wink

PS: c'est pas un challenge que je lance, y'a sûrement plus intéressant à faire de son temps Wink

Dab, le 5 September, 2008 - 21:17

hmmm , si tu avais un fichier en esperanto (ISO-8859-3) sous la main, je veux bien tester Wink

fredg , le 6 September, 2008 - 11:35

Excellent, très instructif, merci.

++

Ulhume, le 6 September, 2008 - 22:34

@Dab J'ai pas cela en stock, mais tu dois pouvoir faire cela facilement en sauvant un texte avec gedit ou autre.

Ulhume, le 6 September, 2008 - 22:34

@fredg de rien Smiling

Poster un nouveau commentaire

Le contenu de ce champ est gardé secret et ne sera pas montré publiquement.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • To highlight piece of code, just surround them with <code type="language"> Your code &tl;/code>>. Language can be java,c++,bash,etc... Everything Geshi support.
  • Les lignes et les paragraphes vont à la ligne automatiquement.
  • Textual smileys will be replaced with graphical ones.
  • Les adresses de pages web et de messagerie électronique sont transformées en liens automatiquement.

Plus d'informations sur les options de formatage

Connexion utilisateur
Les derniers bavardages...