diff --git a/ecrire/inc/filtres.php b/ecrire/inc/filtres.php
index 033b04e5e8bdb729c33b7f3e236f08183c9024c0..33117a0dffa76022f373d2e631d134017d8cc6d2 100644
--- a/ecrire/inc/filtres.php
+++ b/ecrire/inc/filtres.php
@@ -1322,6 +1322,47 @@ function post_autobr($texte, $delim="\n_ ") {
 }
 
 
+define('_EXTRAIRE_MULTI', "@<multi>(.*?)</multi>@sS");
+
+// Extraire et transformer les blocs multi ; on indique la langue courante
+// pour ne pas mettre de span@lang=fr si on est deja en fr
+// http://doc.spip.org/@extraire_multi
+function extraire_multi($letexte, $lang=null) {
+	if (preg_match_all(_EXTRAIRE_MULTI, $letexte, $regs, PREG_SET_ORDER)) {
+		if (!$lang) $lang = $GLOBALS['spip_lang'];
+
+		foreach ($regs as $reg) {
+			// chercher la version de la langue courante
+			$trads = extraire_trads($reg[1]);
+			if ($l = approcher_langue($trads, $lang)) {
+				$trad = $trads[$l];
+			} else {
+				// langue absente, prendre la premiere dispo
+				// mais typographier le texte selon les regles de celle-ci
+				// Attention aux blocs multi sur plusieurs lignes
+				$l = key($trads);
+				$trad = $trads[$l];
+				$typographie = charger_fonction(lang_typo($l), 'typographie');
+				$trad = $typographie($trad);
+				$trad = explode("\n", $trad);
+				foreach($trad as $i => $ligne) {
+					if (strlen($ligne)) {
+						$ligne = code_echappement($ligne, 'multi');
+						$ligne = str_replace("'", '"', inserer_attribut($ligne, 'lang', $l));
+						if (lang_dir($l) !== lang_dir($lang))
+							$ligne = str_replace("'", '"', inserer_attribut($ligne, 'dir', lang_dir($l)));
+						$trad[$i] = $ligne;
+					}
+				}
+				$trad = join("\n", $trad);
+			}
+			$letexte = str_replace($reg[0], $trad, $letexte);
+		}
+	}
+	return $letexte;
+}
+
+
 
 //
 // Ce filtre retourne la donnee si c'est la premiere fois qu'il la voit ;
diff --git a/ecrire/inc/lang.php b/ecrire/inc/lang.php
index 4718c430d141685d835b391d3223461ef3ae814d..7a00f4da8da64445e4f68c5c22e564efcc5ea2bc 100644
--- a/ecrire/inc/lang.php
+++ b/ecrire/inc/lang.php
@@ -66,12 +66,14 @@ function approcher_langue ($trads, $lang='') {
 
 	if (isset($trads[$lang])) {
 		return $lang;
-
-	}	// cas des langues xx_yy
-	else if (preg_match(',^([a-z]+)_,', $lang, $regs) AND isset($trads[$regs[1]])) {
-		return $regs[1];
-	}	
-	else  return '';
+	}
+	// cas des langues xx_yy
+	else {
+		$r = explode('_', $lang);
+		if (isset($trads[$r[0]]))
+			return $r[0];
+	}
+	return '';
 }
 
 // http://doc.spip.org/@traduire_nom_langue
@@ -85,7 +87,6 @@ function traduire_nom_langue($lang) {
 // Filtres de langue
 //
 
-
 // Donne la direction d'ecriture a partir de la langue. Retourne 'gaucher' si
 // la langue est arabe, persan, kurde, pachto, ourdou (langues ecrites en
 // alphabet arabe a priori), hebreu, yiddish (langues ecrites en alphabet
diff --git a/ecrire/inc/texte.php b/ecrire/inc/texte.php
index 3c29fb15c10f93130954d7d6564bf879730b258b..55560f69d26111c1a7bd235c882091e64f0e48e3 100644
--- a/ecrire/inc/texte.php
+++ b/ecrire/inc/texte.php
@@ -257,10 +257,21 @@ $preg='') {
 function echappe_retour($letexte, $source='', $filtre = "") {
 	if (strpos($letexte,"base64$source")) {
 		# spip_log(htmlspecialchars($letexte));  ## pour les curieux
-		if (preg_match_all(',<(span|div) class=[\'"]base64'.$source.'[\'"]\s.*>\s*</\1>,UmsS',
+		if (preg_match_all(',<(span|div) class=[\'"]base64'.$source.'[\'"]\s(.*)>\s*</\1>,UmsS',
 		$letexte, $regs, PREG_SET_ORDER)) {
 			foreach ($regs as $reg) {
 				$rempl = base64_decode(extraire_attribut($reg[0], 'title'));
+				// recherche d'attributs supplementaires
+				$at = array();
+				foreach(array('lang', 'dir') as $attr) {
+					if ($a = extraire_attribut($reg[0], $attr))
+						$at[$attr] = $a;
+				}
+				if ($at) {
+					$rempl = '<'.$reg[1].'>'.$rempl.'</'.$reg[1].'>';
+					foreach($at as $attr => $a)
+						$rempl = inserer_attribut($rempl, $attr, $a);
+				}
 				if ($filtre) $rempl = $filtre($rempl);
 				$letexte = str_replace($reg[0], $rempl, $letexte);
 			}
@@ -527,10 +538,6 @@ function typo($letexte, $echapper=true, $connect=null) {
 }
 
 // Correcteur typographique
-// avec reperage des blocs multi dans le texte 
-
-define('_EXTRAIRE_MULTI', "@<multi>(.*?)</multi>@sS");
-
 define('_TYPO_PROTEGER', "!':;?~%-");
 define('_TYPO_PROTECTEUR', "\x1\x2\x3\x4\x5\x6\x7\x8");
 
@@ -547,14 +554,8 @@ function corriger_typo($letexte, $lang='') {
 	// Caracteres de controle "illegaux"
 	$letexte = corriger_caracteres($letexte);
 
-	// Charger & appliquer les fonctions de typographie
-
-	if (!$lang) $lang = lang_typo();
-	$typo2 = '';
-	$typographie = charger_fonction($lang, 'typographie');
-
 	// Proteger les caracteres typographiques a l'interieur des tags html
-	if ($typographie AND preg_match_all(_TYPO_BALISE, $letexte, $regs, PREG_SET_ORDER)) {
+	if (preg_match_all(_TYPO_BALISE, $letexte, $regs, PREG_SET_ORDER)) {
 		foreach ($regs as $reg) {
 			$insert = $reg[0];
 			// hack: on transforme les caracteres a proteger en les remplacant
@@ -564,44 +565,21 @@ function corriger_typo($letexte, $lang='') {
 		}
 	}
 
-	// simplifier les blocs multi,
-	// et si la selection est differente de la langue de l'objet, 
-	// (langue de l'objet absente du multi ou langue imposee par forcer_lang)
-	// la typographier selon les regles de celle trouvee si definies
+	// trouver les blocs multi et les traiter a part
+	$letexte = extraire_multi($e = $letexte, $lang);
+	$e = ($e === $letexte);
 
-	if (preg_match_all(_EXTRAIRE_MULTI, $letexte, $regs, PREG_SET_ORDER)) {
-		foreach ($regs as $reg) {
-			// chercher la version de la langue du contexte
-			// (= lang_typo() sauf parfois avec forcer_lang = true)
-			$trads = extraire_trads($reg[1]);
-			$l = approcher_langue($trads, $GLOBALS['spip_lang']);
-			if ($l) {
-				$trad = $trads[$l];
-				if ($lang != $GLOBALS['spip_lang']
-				AND $typo2 = charger_fonction($GLOBALS['spip_lang'], 'typographie', true)) {
-					$trad = $typo2($trad);
-					$trad = code_echappement($trad, 'multi');
-				}  
-			} else {
-				// langue absente, prendre la premiere dispo
-				$l = key($trads);
-				$trad = $trads[$l];
-				if ($typo2 = charger_fonction($l, 'typographie', true)) {
-					$trad = $typo2($trad);
-					$trad = code_echappement($trad, 'multi');
-				}
-			}
-			$letexte = str_replace($reg[0], $trad, $letexte);
-		}
-	}
+	// Charger & appliquer les fonctions de typographie
+	$typographie = charger_fonction(lang_typo($lang), 'typographie');
+	$letexte = $typographie($letexte);
 
-	if ($typographie) $letexte = $typographie($letexte);
+	// Les citations en une autre langue, s'il y a lieu
+	if (!$e) $letexte = echappe_retour($letexte, 'multi');
 
 	// Retablir les caracteres proteges
 	$letexte = strtr($letexte, _TYPO_PROTECTEUR, _TYPO_PROTEGER);
-	// et les citations en d'autres langues
-	if ($typo2!=='') $letexte = echappe_retour($letexte, 'multi');
 
+	// pipeline
 	$letexte = pipeline('post_typo', $letexte);
 
 	# un message pour abs_url - on est passe en mode texte