La norme MIME permet d'étiqueter un
message en
indiquant la langue, avec l'en-tête
Content-Language:
(RFC 4021). Mais
comment faire si on veut envoyer le même message en plusieurs
langues, pour s'adapter à une audience variée, ou bien si on n'est
pas sûr des langues parlées par le destinataire ? C'est ce que
permet le nouveau type de
message multipart/multilingual
qui permet d'étiqueter les messages multilingues.
C'est le premier
RFC du groupe de travail
SLIM, chargé de créer des normes pour indiquer la langue
utilisée dans le courrier et pour les
communications synchrones (téléphonie sur
IP, par exemple, couverte depuis par le RFC 8373), dans le cas où plusieurs langues
sont en présence.
Le type de premier niveau multipart/
(RFC 2046, section 5.1, enregistré à
l'IANA) permet d'indiquer un message (ou une partie de
message, en cas de récursivité) composé de plusieurs
parties. Ainsi, multipart/mixed
(RFC 2046, section 5.1.3) indique un message dont
les dfférentes parties sont indépendantes (un texte et une image,
par exemple). Alors que multipart/alternative
(RFC 2046, section 5.1.4) est utilisé pour
le cas où les différentes parties veulent dire la même chose, mais
avec des formats différentes (une version texte
seul et une version HTML, par
exemple, ou bien une image en JPEG et la
même en PNG). Normalement, le lecteur de courrier ne va afficher qu'une
seule des parties d'une
multipart/alternative
, celle qui convient le
mieux, selon les capacités du logiciel de lecture et les
préférences de l'utilisateur. Ce sera la même chose avec ce
nouveau multipart/multilingual
: l'émetteur
enverra le message en plusieurs langues, le logiciel de lecture
n'affichera que celle qui colle le mieux aux choix de
l'utilisateur. Ce type est désormais enregistré
à l'IANA (section 9 du RFC).
Rappelez-vous que MIME est
récursif : un
multipart/
peut contenir un autre
multipart/
. Voici, par exemple, vu par le
MUA mutt, un
multipart/mixed
, dont la première partie est
un multipart/alternative
et la seconde un
fichier PDF :
I 1 [multipart/alternative, 7bit, 45K]
I 2 ├─> [text/plain, 8bit, utf-8, 1,8K]
I 3 └─> [text/html, 8bit, utf-8, 43K]
A 4 35378031645-672029836-registration.pdf [application/pdf, base64, 84K]
Cette première partie du corps du message, de type
multipart/alternative
, a à son tour deux
parties, une en texte brut et l'autre en HTML. Comme ma
configuration mutt inclut la directive
alternative_order
text/plain
, seule la version texte sera affichée, le
HTML étant ignoré.
Revenons aux messages multilingues. Avant ce RFC 8255, la solution la plus fréquente,
quand on envoyait un message à quelqu'un dont on n'était pas sûr
des préférences linguistiques, était de mettre toutes les versions
dans un même message. Du genre :
(English translation at the end)
Bonjour, ceci est un message.
Hello, this is a message.
(La première ligne ayant pour but d'éviter que le lecteur
anglophone se décourage en ne voyant au début que du
français.)
Cette solution n'est pas satisfaisante : elle passe mal
à l'échelle dès qu'il y a plus de deux langues. Et
elle ne permet pas la sélection automatique de la langue par le
logiciel du destinataire.
Le type MIME d'un message est mis dans un en-tête
Content-Type:
. Par exemple, un message de
plusieurs parties représentant le même contenu serait :
Content-Type: multipart/alternative; boundary="------------E6043EF6F3B557567F3B18F4"
Où
boundary
indique le texte qui sera le
séparateur entre les parties (RFC 2046,
section 5.1). La section 2 du RFC décrit ce qu'on peut désormais
mettre dans le
Content-Type:
, avec le nouveau
type
multipart/multilingual
.
Il ressemble beaucoup au
multipart/alternative
et, comme tous les
multipart/quelquechose
(RFC 2046, section 5.1.1), a une chaîne de
caractères qui indique le passage d'une partie à une autre :
Content-Type: multipart/multilingual; boundary=01189998819991197253
Chacune des parties d'un message en plusieurs langues doit
indiquer la langue de la partie, avec l'en-tête
Content-Language:
. Mais attention, comme il
faut tenir compte des vieux clients de messagerie qui ne
connaissent pas ce RFC, la première partie ne doit
pas avoir de
Content-Language:
, elle sert de solution de
repli, car c'est elle qui sera affichée en premier par les logiciels qui ne
connaissent pas multipart/multilingual
. Comme
elle sert de secours, il est recommandé qu'elle soit dans le
format le plus simple, donc text/plain
, en
UTF-8 (car il faut pouvoir représenter
diverses langues). Cette partie se nomme la préface. En la
lisant, l'utilisateur pourra donc comprendre qu'il doit mettre à
jour vers un logiciel plus récent.
Les parties suivantes, après la préface, vont être écrites dans
des langues différentes. Le RFC recommande de les mettre dans
l'ordre, avec celles qui ont le plus de chance d'être
pertinentes en premier. (Ainsi, une société française ayant une
activité européenne, avec une
majorité de clients français, et envoyant un message en anglais,
allemand et français, mettra sans doute le français en premier,
suivi de l'anglais.)
Chacune de ces parties aura un en-tête
Content-Language:
, pour indiquer la langue,
et Content-Type:
pour indiquer le type
MIME. (Rappelez-vous toujours que MIME est récursif.) Il est
recommandé que chaque partie soit un message complet (avec
notamment le champ Subject:
, qui a besoin
d'être traduit, lui aussi, et le champ From:
,
dont une partie peut être utilement traduite). Le type conseillé est donc
message/rfc822
(RFC 2046, section 5.2.1), mais on peut aussi utiliser le
plus récent message/global
(RFC 6532).
Notez bien que ce RFC ne spécifie évidemment
pas comment se fera la traduction : il ne s'occupe que d'étiqueter
proprement le résultat.
Le message peut se terminer par une section « indépendante de
la langue » (par exemple une image ne comportant pas de
texte, si le message peut être porté par une image). Dans ce cas, son Content-Language:
doit indiquer zxx
, ce qui veut dire
« information non pertinente » (RFC 5646,
section 4.1). C'est elle qui sera sélectionnée si aucune partie ne
correspond aux préférences de l'utilisateur.
Maintenant, que va faire le client de
messagerie qui reçoit un tel message multilingue ? La
section 4 de notre RFC décrit les différents cas. D'abord, avec
les logiciels actuels, le client va afficher les différentes
parties de multipart/multilingual
dans
l'ordre où elles apparaissent (donc, en commençant par la
préface).
Mais le cas le plus intéressant est évidemment celui d'un
client plus récent, qui connait les messages multilingues. Il va
dans ce cas sauter la préface (qui n'a pas de langue indiquée,
rappelez-vous) et sélectionner une des
parties, celle qui convient le mieux à l'utilisateur.
Un moment. Arrêtons-nous un peu. C'est quoi, la « meilleure »
version ? Imaginons un lecteur francophone, mais qui parle anglais
couramment. Il reçoit un message multilingue, en français et en
anglais. S'il choisissait manuellement, il prendrait forcément le
français, non ? Eh bien non, car cela dépend de la qualité du
texte. Comme peut le voir n'importe quel utilisateur du Web, les
différentes versions linguistiques d'un site Web ne sont pas de
qualité égale. Il y a le texte original, les traductions faites
par un professionnel
compétent, les traductions faites par le stagiaire, et
celles faites par un programme (en général, les plus
drôles). Sélectionner la meilleure version uniquement sur la
langue n'est pas une bonne idée, comme le montre la mauvaise expérience de
HTTP. Ici, pour reprendre notre exemple, si la version en
anglais est la version originale, et que le
français est le résultat d'une mauvaise traduction par un amateur,
notre francophone qui comprend bien l'anglais va sans doute
préférer la version en anglais.
Il est donc crucial d'indiquer le type de traduction effectuée,
ce que permet le Content-Translation-Type:
exposé plus loin, en section 6. (Les premières versions du projet
qui a mené à ce RFC, naïvement, ignoraient complètement ce
problème de la qualité de la traduction, et de la version
originale.)
Donc, le mécanisme de sélection par le
MUA de la « meilleure » partie dans un
message multilingue n'est pas complètement spécifié. Mais il va
dépendre des préférences de l'utilisateur, et sans doute des
règles du RFC 4647.
Si aucune partie ne correspond aux choix de l'utilisateur, le
RFC recommande que le MUA affiche la partie indépendante de la
langue, ou, si elle n'existe pas, la partie après la préface. Le MUA peut également
proposer le choix à l'utilisateur (« Vous n'avez indiqué qu'une
langue, le français. Ce message est disponible en anglais et en
chinois. Vous préférez lequel ? »)
La section 5 du RFC présente en détail l'utilisation de l'en-tête
Content-Language:
. Il doit suivre la norme
existante de cet en-tête, le RFC 3282, et sa valeur doit
donc être une étiquette de langue du RFC 5646. Des exemples (en pratique, il ne faut
évidemment en mettre qu'un) :
Content-Language: fr
Content-Language: sr-Cyrl
Content-Language: ay
Content-Language: aaq
Le premier exemple concerne le français, le
second le serbe écrit en alphabet
cyrillique, le troisième
l'aymara et le quatrième
l'abénaqui oriental.
La section décrit le nouvel en-tête
Content-Translation-Type:
qui indique le type
de traduction réalisé. Il peut prendre trois valeurs,
original
(la version originale),
human
(traduit par un humain) et
automated
(traduit par un programme). Notez
que les humains (les programmes aussi, d'ailleurs) varient
considérablement dans leurs compétences de traducteur. J'aurais
personnellement préféré qu'on distingue un traducteur
professionnel d'un amateur, mais la traduction fait partie des
métiers mal compris, où beaucoup de gens croient que si on parle
italien et allemand, on peut traduire de l'italien en allemand
correctement. C'est loin d'être le cas. (D'un autre côté, comme
pour tous les étiquetages, si on augmente le nombre de choix, on
rend l'étiquetage plus difficile et il risque d'être incorrect.)
Voici un exemple complet, tel qu'il apparait entre deux
logiciels de messagerie. Il est fortement inspiré du premier
exemple de la section 8 du RFC, qui comprend également des
exemples plus complexes. Dans ce message, l'original est en anglais, mais
une traduction française a été faite par un humain.
From: jeanne@example.com
To: jack@example.com
Subject: Example of a message in French and English
Date: Thu, 7 Apr 2017 21:28:00 +0100
MIME-Version: 1.0
Content-Type: multipart/multilingual;
boundary="01189998819991197253"
--01189998819991197253
Content-Type: text/plain; charset="UTF-8"
Content-Disposition: inline
Content-Transfer-Encoding: 8bit
This is a message in multiple languages. It says the
same thing in each language. If you can read it in one language,
you can ignore the other translations. The other translations may be
presented as attachments or grouped together.
Ce message est disponible en plusieurs langues, disant la même chose
dans toutes les langues. Si vous le lisez dans une des langues, vous
pouvez donc ignorer les autres. Dans votre logiciel de messagerie, ces
autres traductions peuvent se présenter comme des pièces jointes, ou
bien collées ensemble.
--01189998819991197253
Content-Type: message/rfc822
Content-Language: en
Content-Translation-Type: original
Content-Disposition: inline
From: Manager
Subject: Example of a message in French and English
Content-Type: text/plain; charset="US-ASCII"
Content-Transfer-Encoding: 7bit
MIME-Version: 1.0
Hello, this message content is provided in your language.
--01189998819991197253
Content-Type: message/rfc822
Content-Language: fr
Content-Translation-Type: human
Content-Disposition: inline
From: Directrice
Subject: =?utf-8?q?Message_d=27exemple=2C_en_fran=C3=A7ais_et_en_anglais?=
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: 8bit
MIME-Version: 1.0
Bonjour, ce message est disponible dans votre langue.
--01189998819991197253--
On note qu'il y a une préface (la première partie, celle qui
commence par «
This is a message in multiple languages »), que
chacun des deux parties étiquetées a un
From:
(pour pouvoir adapter le titre de
l'expéditrice) et un sujet (celui en français étant encodé selon
le RFC 2047). Les deux dernières parties
ont un
Content-Translation-Type:
.
Actuellement, il ne semble pas qu'il existe de
MUA qui gère cette nouvelle norme. Si vous
voulez envoyer des messages à ce format, vous pouvez copier/coller
l'exemple ci-dessus, ou bien utiliser le programme Python send-multilingual.py
.
Voici le message d'exemple cité plus haut affiché par
mutt (version NeoMutt 20170113 (1.7.2)) :
Thunderbird
affiche à peu près la même chose.
Gmail a stupidement décidé de mettre ce
message dans le dossier Spam. Une fois le
message sorti de ce purgatoire, voici ce que ça donnait :
Notez l'existence d'une FAQ
sur ce format.
Une mise en œuvre dans
mutt a été faite au hackathon
de la réunion IETF 101 par Alexandre Simon. Elle a été soumise en tant que pull
request à mutt. Outre ce travail sur un
MUA, le même auteur a écrit un réflecteur de
courrier permettant de tester ce RFC. Vous envoyez un
message ordinaire en français à
reflector+sl_fr+tl_zh@rfc8255.as-home.fr
(sl
= Source Language, tl = Target
Language, ici, on dit que le message est en français, et
on veut une réponse en chinois), et il répond avec
un message conforme au RFC 8255, traduit par Google Translate. Voici par exemple une demande :
To: reflector+sl_fr+tl_zh@rfc8255.as-home.fr
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Disposition: inline
Content-Transfer-Encoding: 8bit
User-Agent: NeoMutt/20170113 (1.7.2)
Subject: Test je parle la France
From: Stephane Bortzmeyer
Alors, ça donne quoi ?
Surtout s'il y a plusieurs lignes.
Et sa réponse :
Content-Type: multipart/multilingual;
boundary="----------=_1521485603-32194-0"
Content-Transfer-Encoding: binary
MIME-Version: 1.0
To: Stephane Bortzmeyer
Sender:
Subject: Test je parle la France
From: Stephane Bortzmeyer
This is a multi-part message in MIME format...
------------=_1521485603-32194-0
Content-Type: text/plain; charset=utf-8
Content-Disposition: inline
Content-Transfer-Encoding: binary
Alors, ça donne quoi ?
Surtout s'il y a plusieurs lignes.
------------=_1521485603-32194-0
Content-Type: message/rfc822
Content-Disposition: inline
Content-Transfer-Encoding: binary
Content-Language: fr
Content-Translation-Type: original
Content-Type: text/plain; charset=utf-8
From: Stephane Bortzmeyer
Subject: Test je parle la France
Alors, ça donne quoi ?
Surtout s'il y a plusieurs lignes.
------------=_1521485603-32194-0
Content-Type: message/rfc822
Content-Disposition: inline
Content-Transfer-Encoding: binary
Content-Language: zh
Content-Translation-Type: automated
Content-Type: text/plain; charset=utf-8
From: Stephane Bortzmeyer
Subject: =?UTF-8?B?5rWL6K+V5oiR6K6y5rOV5Zu9?=
那么,这给了什么?
特别是如果有几条线。
------------=_1521485603-32194-0
Content-Type: message/rfc822
Content-Disposition: inline
Content-Transfer-Encoding: binary
Content-Language: zxx
Content-Translation-Type: human
Content-Type: text/plain; charset=utf-8
/////|
///// |
///// |
|~~~| M |
|===| U |
| | L |
| R | T |
| F | I |
| C | L |
| 8 | I |
| 2 | N |
| 5 | G |
| 5 | U |
| | A |
| | L |
| | |
| | /
| | /
|===|/
'---'
------------=_1521485603-32194-0--
On notera la dernière partie, qui utilise la langue
zxx
, code qui veut dire « non spécifiée », et
qui sert à mettre du texte qui sera affiché dans tous les
cas. Notez aussi que le message originel est inclus.
Ce message est ainsi affiché par un mutt actuel :
Et par le mutt patché pendant le hackathon :