diff --git a/src/app/formulaire/elements/select-field-custom.ts b/src/app/formulaire/elements/select-field-custom.ts
index 86d32757d98dfc801571b02eee508929ad71a685..3320cf8b8cd89af1dcfcd692f13a1a95f24f7cd8 100644
--- a/src/app/formulaire/elements/select-field-custom.ts
+++ b/src/app/formulaire/elements/select-field-custom.ts
@@ -146,7 +146,7 @@ export class SelectFieldCustom extends SelectField {
                         new SelectEntry(
                             this._entriesBaseId + spgId,
                             FishSpecies[j],
-                            ServiceFactory.instance.i18nService.localizeText("INFO_ENUM_" + FishSpecies[j]) + " (" + spgId + ")"
+                            ServiceFactory.instance.i18nService.localizeText("INFO_ENUM_" + FishSpecies[j])
                         )
                     );
                 }
diff --git a/src/app/services/internationalisation.service.ts b/src/app/services/internationalisation.service.ts
index 5ba795217ef322500f4534d302e5c58b8a3241fa..45fbe17cd3985c0fc37649d6b6d8cda2316c18ed 100644
--- a/src/app/services/internationalisation.service.ts
+++ b/src/app/services/internationalisation.service.ts
@@ -143,7 +143,7 @@ export class I18nService extends Observable implements Observer {
     public localizeMessage(r: Message, nDigits: number = 3): string {
         let text: string;
         let m: string = this.getMessageFromCode(r.code);
-
+        // replace %X% by formatted value of extraVar.X
         for (const k in r.extraVar) {
             if (r.extraVar.hasOwnProperty(k)) {
                 const v: any = r.extraVar[k];
@@ -167,6 +167,21 @@ export class I18nService extends Observable implements Observer {
                 m = this.replaceAll(m, "%" + k + "%", s);
             }
         }
+        // replace "ENUM_X_Y" by translated enum value;
+        // example for lang "fr" : "ENUM_SPECIES_6" => "INFO_ENUM_SPECIES_6" => "Ombre commun"
+        m = m.replace(/(ENUM_[^ ,;\.]+)/g, (match, p1) => {
+            return this.localizeText("INFO_" + p1);
+        });
+
+        // replace "FORM_ID_X" by form name in current session, if any
+        m = m.replace(/FORM_ID_(\w{6})/g, (match, p1) => {
+            const form = ServiceFactory.instance.formulaireService.getFormulaireFromNubId(p1); // cannot inject FormulaireService => cyclic dependency :/
+            let formName = "**UNKNOWN_FORM**";
+            if (form !== undefined) {
+                formName = form.calculatorName;
+            }
+            return formName;
+        });
 
         // replace "ENUM_X_Y" by translated enum value;
         // example for lang "fr" : "ENUM_SPECIES_6" => "INFO_ENUM_SPECIES_6" => "Ombre commun"
@@ -239,6 +254,7 @@ export class I18nService extends Observable implements Observer {
     /**
      * Met en forme un result en fonction du libellé qui l'accompagne
      * Les result avec le terme "ENUM_" sont traduit avec le message INFO_ENUM_[Nom de la variable après ENUM_]
+     * Exemple pour la langue "fr" : "ENUM_STRUCTUREFLOWREGIME_1" => "INFO_ENUM_STRUCTUREFLOWREGIME_1" => "Partiellement noyé"
      */
     public formatResult(label: string, value: number): string {
         if (value === undefined) {
diff --git a/src/locale/messages.en.json b/src/locale/messages.en.json
index 96f93168e4eef8bc25f8b6fd0104dda56cc90b5f..132e2b4f100a7d5c08d372a67555de24c206d4ba 100644
--- a/src/locale/messages.en.json
+++ b/src/locale/messages.en.json
@@ -139,26 +139,26 @@
     "INFO_ENUM_OUVRAGE_Q_REGIME_3": "Zero flow",
     "INFO_ENUM_PARFLOWREGIME_0": "Free",
     "INFO_ENUM_PARFLOWREGIME_1": "Submerged",
-    "INFO_ENUM_SPECIES_1": "Salmon, trout [50-100]",
-    "INFO_ENUM_SPECIES_2": "Mules",
-    "INFO_ENUM_SPECIES_3a": "Great Shad",
-    "INFO_ENUM_SPECIES_3b": "Shad shad",
-    "INFO_ENUM_SPECIES_3c": "Sea lamprey",
-    "INFO_ENUM_SPECIES_4a": "Trout [25-55]",
-    "INFO_ENUM_SPECIES_4b": "River trout [15-30]",
-    "INFO_ENUM_SPECIES_5": "Aspe, pike",
-    "INFO_ENUM_SPECIES_6": "Common Shadow",
-    "INFO_ENUM_SPECIES_7a": "Barbeau, chevaine, hotu",
-    "INFO_ENUM_SPECIES_7b": "River Lamprey",
-    "INFO_ENUM_SPECIES_8a": "Common Carp",
-    "INFO_ENUM_SPECIES_8b": "Common bream, pike-perch",
-    "INFO_ENUM_SPECIES_8c": "Brim bream, ide, monkfish, perch, tench",
-    "INFO_ENUM_SPECIES_8d": "Vandoises",
-    "INFO_ENUM_SPECIES_9a": "Ablette, cockle, carrassin, roach...",
-    "INFO_ENUM_SPECIES_9b": "Apron, sculpins, bolts, loche...",
-    "INFO_ENUM_SPECIES_10": "Able, cowherd, stickleback, minnows",
-    "INFO_ENUM_SPECIES_11a": "European eel [yellow]",
-    "INFO_ENUM_SPECIES_11b": "European Eel [glass eel]",
+    "INFO_ENUM_SPECIES_1": "Salmon, trout [50-100] (1)",
+    "INFO_ENUM_SPECIES_2": "Mules (2)",
+    "INFO_ENUM_SPECIES_3a": "Great Shad (3a)",
+    "INFO_ENUM_SPECIES_3b": "Shad shad (3b)",
+    "INFO_ENUM_SPECIES_3c": "Sea lamprey (3c)",
+    "INFO_ENUM_SPECIES_4a": "Trout [25-55] (4a)",
+    "INFO_ENUM_SPECIES_4b": "River trout [15-30] (4b)",
+    "INFO_ENUM_SPECIES_5": "Aspe, pike (5)",
+    "INFO_ENUM_SPECIES_6": "Common Shadow (6)",
+    "INFO_ENUM_SPECIES_7a": "Barbeau, chevaine, hotu (7a)",
+    "INFO_ENUM_SPECIES_7b": "River Lamprey (7b)",
+    "INFO_ENUM_SPECIES_8a": "Common Carp (8a)",
+    "INFO_ENUM_SPECIES_8b": "Common bream, pike-perch (8b)",
+    "INFO_ENUM_SPECIES_8c": "Brim bream, ide, monkfish, perch, tench (8c)",
+    "INFO_ENUM_SPECIES_8d": "Vandoises (8d)",
+    "INFO_ENUM_SPECIES_9a": "Ablette, cockle, carrassin, roach... (9a)",
+    "INFO_ENUM_SPECIES_9b": "Apron, sculpins, bolts, loche... (9b)",
+    "INFO_ENUM_SPECIES_10": "Able, cowherd, stickleback, minnows (10)",
+    "INFO_ENUM_SPECIES_11a": "European eel [yellow] (11a)",
+    "INFO_ENUM_SPECIES_11b": "European Eel [glass eel] (11b)",
     "INFO_ENUM_STRUCTUREFLOWMODE_0": "Weir",
     "INFO_ENUM_STRUCTUREFLOWMODE_1": "Orifice",
     "INFO_ENUM_STRUCTUREFLOWMODE_2": "Zero flow",
@@ -633,8 +633,10 @@
     "ERROR_VERIF_PAR_DH": "Downstream pass fall prevents crossability",
     "ERROR_VERIF_PAR_YMIN": "Water level %h% too low (minimum: %minY%)",
     "ERROR_VERIF_KO": "Crossability criteria are not met for at least one species group",
-    "ERROR_VERIF_SPECIES_KO": "Crossability criteria are not met for species group %speciesGroup%",
-    "INFO_VERIF_SPECIES_OK": "Crossability criteria are met for species group %speciesGroup%",
+    "ERROR_VERIF_SPECIES_GROUP_KO": "Crossability criteria are not met for species group ENUM_%speciesGroup%",
+    "INFO_VERIF_SPECIES_GROUP_OK": "Crossability criteria are met for species group ENUM_%speciesGroup%",
+    "ERROR_VERIF_SPECIES_NUB_KO": "Crossability criteria are not met for custom species FORM_ID_%uid%",
+    "INFO_VERIF_SPECIES_NUB_OK": "Crossability criteria are met for custom species FORM_ID_%uid%",
     "ERROR_VERIF_PAB_WALL_NOT_CROSSABLE": "Wall #%N% is not crossable",
     "ERROR_VERIF_PAB_DW_NOT_CROSSABLE": "Downwall is not crossable",
     "WARNING_VERIF_PAR_SPECIES_GROUP": "Species groups 3a, 3b et 7b are discouraged for this pass type"
diff --git a/src/locale/messages.fr.json b/src/locale/messages.fr.json
index fe6856a2eb13abe25283e1642bf6766938cf8188..d2d4687f2ef049be3a85913adfcd20f3ce8e6160 100644
--- a/src/locale/messages.fr.json
+++ b/src/locale/messages.fr.json
@@ -139,26 +139,26 @@
     "INFO_ENUM_OUVRAGE_Q_REGIME_3": "Débit nul",
     "INFO_ENUM_PARFLOWREGIME_0": "Dénoyé",
     "INFO_ENUM_PARFLOWREGIME_1": "Noyé",
-    "INFO_ENUM_SPECIES_1": "Saumon, truite [50-100]",
-    "INFO_ENUM_SPECIES_2": "Mulets",
-    "INFO_ENUM_SPECIES_3a": "Grande Alose",
-    "INFO_ENUM_SPECIES_3b": "Alose feinte",
-    "INFO_ENUM_SPECIES_3c": "Lamproie marine",
-    "INFO_ENUM_SPECIES_4a": "Truite [25-55]",
-    "INFO_ENUM_SPECIES_4b": "Truite de rivière [15-30]",
-    "INFO_ENUM_SPECIES_5": "Aspe, brochet",
-    "INFO_ENUM_SPECIES_6": "Ombre commun",
-    "INFO_ENUM_SPECIES_7a": "Barbeau, chevaine, hotu",
-    "INFO_ENUM_SPECIES_7b": "Lamproie fluviatile",
-    "INFO_ENUM_SPECIES_8a": "Carpe commune",
-    "INFO_ENUM_SPECIES_8b": "Brème commune, sandre",
-    "INFO_ENUM_SPECIES_8c": "Brème bordelière, ide, lotte, perche, tanche",
-    "INFO_ENUM_SPECIES_8d": "Vandoises",
-    "INFO_ENUM_SPECIES_9a": "Ablette, blageon, carrassin, gardon...",
-    "INFO_ENUM_SPECIES_9b": "Apron, chabots, goujons, loche...",
-    "INFO_ENUM_SPECIES_10": "Able, bouvière, épinoche(tte), vairons",
-    "INFO_ENUM_SPECIES_11a": "Anguille européenne [jaune]",
-    "INFO_ENUM_SPECIES_11b": "Anguille européenne [civelle]",
+    "INFO_ENUM_SPECIES_1": "Saumon, truite [50-100] (1)",
+    "INFO_ENUM_SPECIES_2": "Mulets (2)",
+    "INFO_ENUM_SPECIES_3a": "Grande Alose (3a)",
+    "INFO_ENUM_SPECIES_3b": "Alose feinte (3b)",
+    "INFO_ENUM_SPECIES_3c": "Lamproie marine (3c)",
+    "INFO_ENUM_SPECIES_4a": "Truite [25-55] (4a)",
+    "INFO_ENUM_SPECIES_4b": "Truite de rivière [15-30] (4b)",
+    "INFO_ENUM_SPECIES_5": "Aspe, brochet (5)",
+    "INFO_ENUM_SPECIES_6": "Ombre commun (6)",
+    "INFO_ENUM_SPECIES_7a": "Barbeau, chevaine, hotu (7a)",
+    "INFO_ENUM_SPECIES_7b": "Lamproie fluviatile (7b)",
+    "INFO_ENUM_SPECIES_8a": "Carpe commune (8a)",
+    "INFO_ENUM_SPECIES_8b": "Brème commune, sandre (8b)",
+    "INFO_ENUM_SPECIES_8c": "Brème bordelière, ide, lotte, perche, tanche (8c)",
+    "INFO_ENUM_SPECIES_8d": "Vandoises (8d)",
+    "INFO_ENUM_SPECIES_9a": "Ablette, blageon, carrassin, gardon... (9a)",
+    "INFO_ENUM_SPECIES_9b": "Apron, chabots, goujons, loche... (9b)",
+    "INFO_ENUM_SPECIES_10": "Able, bouvière, épinoche(tte), vairons (10)",
+    "INFO_ENUM_SPECIES_11a": "Anguille européenne [jaune] (11a)",
+    "INFO_ENUM_SPECIES_11b": "Anguille européenne [civelle] (11b)",
     "INFO_ENUM_STRUCTUREFLOWMODE_0": "Surface libre",
     "INFO_ENUM_STRUCTUREFLOWMODE_1": "En charge",
     "INFO_ENUM_STRUCTUREFLOWMODE_2": "Débit nul",
@@ -634,8 +634,10 @@
     "ERROR_VERIF_PAR_DH": "La chute en pied de passe empêche le franchissement",
     "ERROR_VERIF_PAR_YMIN": "Tirant d'eau %h% insuffisant (minimum : %minY%)",
     "ERROR_VERIF_KO": "Le franchissement est impossible pour au moins un groupe d'espèces",
-    "ERROR_VERIF_SPECIES_KO": "Le franchissement est impossible pour le groupe d'espèces %speciesGroup%",
-    "INFO_VERIF_SPECIES_OK": "Le franchissement est possible pour le groupe d'espèces %speciesGroup%",
+    "ERROR_VERIF_SPECIES_GROUP_KO": "Le franchissement est impossible pour le groupe d'espèces ENUM_%speciesGroup%",
+    "INFO_VERIF_SPECIES_GROUP_OK": "Le franchissement est possible pour le groupe d'espèces ENUM_%speciesGroup%",
+    "ERROR_VERIF_SPECIES_NUB_KO": "Le franchissement est impossible pour l'espèce personnalisée FORM_ID_%uid%",
+    "INFO_VERIF_SPECIES_NUB_OK": "Le franchissement est possible pour l'espèce personnalisée FORM_ID_%uid%",
     "ERROR_VERIF_PAB_WALLS_NOT_CROSSABLE": "La cloison n°%N% n'est pas franchissable",
     "ERROR_VERIF_PAB_DW_NOT_CROSSABLE": "La cloison aval n'est pas franchissable",
     "WARNING_VERIF_PAR_SPECIES_GROUP": "Les groupes d'espèces 3a, 3b et 7b sont déconseillés pour ce type de passe"