diff --git a/salvatore/lecteur.php b/salvatore/lecteur.php
index 9bae4c55e99e8623643de141233feafabecfea1e..735167dc74bcc7b7625f902bf1d50fc7ca95a38f 100644
--- a/salvatore/lecteur.php
+++ b/salvatore/lecteur.php
@@ -83,6 +83,7 @@ function salvatore_lire($liste_sources, $force_reload = false, $dir_modules = nu
 		 * On regarde quelle est la date de dernière modification du fichier de langue principale
 		 */
 		$last_update = filemtime($fichier_lang_principal);
+		$type_export = salvatore_retrouver_type_export($fichier_lang_principal);
 
 		if ($row_module = salvatore_retrouver_tradlang_module($dir_module, $module)) {
 			$id_tradlang_module = (int) $row_module['id_tradlang_module'];
@@ -93,8 +94,17 @@ function salvatore_lire($liste_sources, $force_reload = false, $dir_modules = nu
 			if ($row_module['lang_mere'] !== $source['lang']) {
 				sql_updateq('spip_tradlang_modules', ['lang_mere' => $source['lang']], 'id_tradlang_module=' . (int) $id_tradlang_module);
 				salvatore_log('lang_mere mise a jour : ' . $row_module['lang_mere'] . ' => ' . $source['lang']);
+				$last_update = time();
 				$row_module['lang_mere'] = $source['lang'];
+			}
+			/**
+			 * Si le type d’export de fichier a changé, on le modifie
+			 */
+			if ($row_module['type_export'] !== $type_export) {
+				sql_updateq('spip_tradlang_modules', ['type_export' => $type_export], 'id_tradlang_module=' . (int) $id_tradlang_module);
+				salvatore_log('type_export mise a jour : ' . $row_module['type_export'] . ' => ' . $type_export);
 				$last_update = time();
+				$row_module['type_export'] = $type_export;
 			}
 			/**
 			 * Si le dir_module a change, on le met a jour
@@ -121,7 +131,6 @@ function salvatore_lire($liste_sources, $force_reload = false, $dir_modules = nu
 
 		if (!$row_module || $force_reload || $last_update > $refresh_time) {
 			$priorite = '';
-			$modifs = 0;
 			if (defined('_TRAD_PRIORITE_DEFAUT')) {
 				$priorite = _TRAD_PRIORITE_DEFAUT;
 			}
@@ -136,6 +145,7 @@ function salvatore_lire($liste_sources, $force_reload = false, $dir_modules = nu
 					'nom_mod' => calculer_nom_module($source['module'], $source['dir_module']),
 					'lang_prefix' => $source['module'],
 					'lang_mere' => $source['lang'],
+					'type_export' => $type_export,
 					'priorite' => $priorite,
 				];
 				$id_tradlang_module = sql_insertq('spip_tradlang_modules', $insert);
@@ -144,16 +154,14 @@ function salvatore_lire($liste_sources, $force_reload = false, $dir_modules = nu
 				 */
 				if (!(int) $id_tradlang_module) {
 					salvatore_fail("[Lecteur] Erreur sur $module", 'Echec insertion dans spip_tradlang_modules ' . json_encode($insert, JSON_THROW_ON_ERROR));
-				}
-				else {
+				} else {
 					salvatore_log("Insertion en base #$id_tradlang_module");
 				}
 				$new_module = true;
 			}
 			$force_reload = true;
-		}
-		// Pas de mise a jour recente du fichier maitre deja en base
-		else {
+		} else {
+			// Pas de mise a jour recente du fichier maitre deja en base
 			salvatore_log("On ne modifie rien : fichier original $fichier_lang_principal inchangé depuis " . date('Y-m-d H:i:s', $last_update));
 			$id_tradlang_module = (int) $row_module['id_tradlang_module'];
 
@@ -169,8 +177,7 @@ function salvatore_lire($liste_sources, $force_reload = false, $dir_modules = nu
 				$lang = salvatore_get_lang_from($module, $fichier_lang);
 				if (!in_array($lang, $langues_en_base)) {
 					$langues_a_ajouter[] = ['lang' => $lang, 'fichier' => $fichier_lang];
-				}
-				else {
+				} else {
 					// inutile de regarder ce fichier
 					$langues_a_jour[] = $lang;
 				}
@@ -198,8 +205,7 @@ function salvatore_lire($liste_sources, $force_reload = false, $dir_modules = nu
 					if ($tradlang_verifier_langue_base) {
 						$tradlang_verifier_langue_base($id_tradlang_module, $lang);
 						salvatore_log('|-- Synchro de la langue ' . $lang . ' pour le module ' . $source['module']);
-					}
-					else {
+					} else {
 						salvatore_log("<error>|-- Pas de Fonction de synchro inexistante pour synchroniser lang $lang</error>");
 					}
 				}
@@ -241,6 +247,41 @@ function salvatore_lire($liste_sources, $force_reload = false, $dir_modules = nu
 	}
 }
 
+/** @return array{commentaires: array<string,string>, chaines: array<string,string>} */
+function salvatore_importer_module_langue_chaines(string $fichier_lang): ?array {
+	// type spip ou spip5 ?
+	$type_export = salvatore_retrouver_type_export($fichier_lang);
+	// charger le fichier et ses commentaires
+	$chaines = null;
+	if ($type_export === 'spip') {
+		$commentaires = salvatore_charger_commentaires_fichier_langue_spip($fichier_lang);
+		$chaines = salvatore_importer_module_langue_chaines_spip($fichier_lang);
+	} elseif ($type_export === 'spip5') {
+		$commentaires = salvatore_charger_commentaires_fichier_langue_spip5($fichier_lang);
+		$chaines = salvatore_importer_module_langue_chaines_spip5($fichier_lang);
+	}
+	if ($chaines === null || !is_array($chaines)) {
+		return null;
+	}
+	return [
+		'commentaires' => $commentaires,
+		'chaines' => $chaines,
+	];
+}
+
+function salvatore_importer_module_langue_chaines_spip(string $fichier_lang): ?array {
+	$idx = $GLOBALS['idx_lang'] = 'i18n_' . crc32($fichier_lang) . '_tmp';
+	$GLOBALS[$idx] = null;
+	include $fichier_lang;
+	$chaines = $GLOBALS[$idx];  // on a vu certains fichiers faire des betises et modifier idx_lang
+	return $chaines;
+}
+
+function salvatore_importer_module_langue_chaines_spip5(string $fichier_lang): ?array {
+	$chaines = include $fichier_lang;
+	return is_array($chaines) ? $chaines : null;
+}
+
 /**
  * Import d'un fichier de langue dans la base
  *
@@ -254,28 +295,22 @@ function salvatore_lire($liste_sources, $force_reload = false, $dir_modules = nu
  * @param bool $new_module
  *   true signifie qu'on est en train d'importer un nouveau module
  * @param array $liste_md5_master
- * @return string
+ * @return string|false
  */
 function salvatore_importer_module_langue($id_tradlang_module, $source, $fichier_lang, $is_master, $new_module, &$liste_md5_master) {
 	salvatore_log("!\n+ Import de $fichier_lang\n");
-	$idx = $GLOBALS['idx_lang'] = 'i18n_' . crc32($fichier_lang) . '_tmp';
-
-	$lang = salvatore_get_lang_from($source['module'], $fichier_lang);
 	$module = $source['module'];
+	$lang = salvatore_get_lang_from($module, $fichier_lang);
+	$desc = salvatore_importer_module_langue_chaines($fichier_lang);
 
-	// charger le fichier et ses commentaires
-	$GLOBALS[$idx] = null;
-	$commentaires = salvatore_charger_commentaires_fichier_langue($fichier_lang);
-
-	include $fichier_lang;
-	$chaines = $GLOBALS[$idx];  // on a vu certains fichiers faire des betises et modifier idx_lang
-
-	if (is_null($chaines)) {
+	if ($desc === null) {
 		$erreur = "Erreur, fichier $fichier_lang mal forme";
 		salvatore_log("<error>$erreur</error>");
 		salvatore_envoyer_mail("[Lecteur] Erreur sur $module", $erreur);
 		return false;
 	}
+	$commentaires = $desc['commentaires'];
+	$chaines = $desc['chaines'];
 
 	/**
 	 * Nettoyer le contenu de ses <MODIF>,<NEW> et <PLUS_UTILISE>
@@ -405,8 +440,7 @@ function salvatore_importer_module_langue($id_tradlang_module, $source, $fichier
 									sql_updateq('spip_tradlangs', $maj, 'id_tradlang=' . (int) $trad['id_tradlang']);
 								}
 								$recuperees++;
-							}
-							else {
+							} else {
 								salvatore_fail('[Lecteur] Echec insertion', 'Echec insertion en base : ' . json_encode($set, JSON_THROW_ON_ERROR));
 							}
 						}
@@ -487,8 +521,7 @@ function salvatore_importer_module_langue($id_tradlang_module, $source, $fichier
 					$md5 = md5($chaines[$id]);
 					if ($md5 === $existant[$id]) {
 						$inchangees++;
-					}
-					else {
+					} else {
 						// * modifiee ? => UPDATE
 						salvatore_log("Chaine $id modifiee $md5 != " . $existant[$id]);
 
@@ -559,16 +592,76 @@ function salvatore_importer_module_langue($id_tradlang_module, $source, $fichier
 
 
 /**
- * Chargement des commentaires de fichier de langue
+ * Chargement des commentaires de fichier de langue SPIP >= 5
+ *
+ * Le fichier est chargé en mode texte pour récupérer les commentaires dans lesquels sont situés les statuts
+ *
+ * @param string $fichier_lang Le chemin du fichier de langue
+ * @return array $liste_trad Un tableau id/chaine
+ */
+function salvatore_charger_commentaires_fichier_langue_spip5($fichier_lang) {
+
+	$contenu = file_get_contents($fichier_lang);
+	$tokens = PhpToken::tokenize($contenu);
+
+	$comments = [];
+
+	// allons jusqu'au debut du tableau
+	while (count($tokens)) {
+		$token = array_shift($tokens);
+		if ($token->is(T_RETURN)) {
+			while ($token = array_shift($tokens)) {
+				if ($token->is(T_WHITESPACE)) {
+					continue;
+				} elseif ($token->is('[')) {
+					break 2;
+				}
+				break;
+			}
+		}
+	}
+
+	$last_tring = '';
+	$index = '';
+	while (count($tokens)) {
+		$token = array_shift($tokens);
+		switch ($token->id) {
+			case T_CONSTANT_ENCAPSED_STRING:
+				$last_tring = $token->text;
+				break;
+			case T_DOUBLE_ARROW:
+				$index = trim($last_tring, "'\"");
+				break;
+			case T_WHITESPACE:
+				// si c'est une nouvelle ligne, on est plus interesse par le commentaire
+				if (str_contains($token->text, "\n") || str_contains($token->text, "\r")) {
+					$index = '';
+				}
+				break;
+			case T_COMMENT:
+				if ($index && strpos($token->text, '#') === 0) {
+					$comments[$index] = trim(substr($token->text, 1));
+				}
+				break;
+		}
+	}
+
+	return $comments;
+}
+
+
+/**
+ * Chargement des commentaires de fichier de langue SPIP < 5
  * Le fichier est chargé en mode texte pour récupérer les commentaires dans lesquels sont situés les statuts
  *
  * @param string $fichier_lang Le chemin du fichier de langue
  * @return array $liste_trad Un tableau id/chaine
  */
-function salvatore_charger_commentaires_fichier_langue($fichier_lang) {
+function salvatore_charger_commentaires_fichier_langue_spip($fichier_lang) {
 
 	$contenu = file_get_contents($fichier_lang);
 	$tokens = token_get_all($contenu);
+
 	$comments = [];
 
 	// allons jusqu'au debut du tableau