diff --git a/scripts/check-translations.js b/scripts/check-translations.js
index 8beb57298f50ac1f30cdf6457f35778a309d6f6d..4143d689e4546a86d78ec4fdd665c8e9e915eb91 100644
--- a/scripts/check-translations.js
+++ b/scripts/check-translations.js
@@ -1,7 +1,24 @@
 'use strict';
 
+/**
+ * 1) Reads Message enum in jalhyd, and for every message code in it, checks
+ * that there is a translation in each nghyd's locale/*.json file (ie. for
+ * every language)
+ * 
+ * 2) For every nghyd calculator, checks that the translated keys are the same
+ * in all language files
+ */
+
 const fs = require('fs');
 
+/* IMPORTANT: during step 2, will look for those languages codes only */
+const expectedLanguages = [ "fr", "en" ];
+
+// total errors
+let nbErr = 0;
+
+// ---- 1. JaLHyd messages ----
+
 // read and transform JaLHyd message file
 const jalhydMessagesPath = "../jalhyd/src/util/message.ts";
 let jm = fs.readFileSync(jalhydMessagesPath, "utf-8");
@@ -17,10 +34,12 @@ jm = jm.replace(/\/\/.+/g, "");
 jm = jm.replace(/[ \t]+/g, "");
 // remove line breaks
 jm = jm.replace(/\n/g, "");
+
 // split on ";"
 const messages = jm.split(",");
 
-// console.log(messages);
+// remove import on 1st line (wtf) @clodo
+messages[0] = messages[0].substring(24);
 
 // read every language file
 const localePath = "src/locale";
@@ -30,15 +49,76 @@ for (let i = 0; i < localeDir.length; i++) {
     const res = localeFile.match(/^messages\.([a-z]{2})\.json$/);
     if (res) {
         const lang = res[1];
-        console.log("Loading translations for language [" + lang + "]");
+        console.log("Loading global translations for language [" + lang + "]");
         const langFilePath = localePath + '/' + localeFile;
-        let translations = Object.keys(JSON.parse(fs.readFileSync(langFilePath, "utf-8")));
+        const translations = Object.keys(JSON.parse(fs.readFileSync(langFilePath, "utf-8")));
         // console.log(translations);
         // check against JaLHyd messages list
         for (const mess of messages) {
             if (! translations.includes(mess)) {
                 console.log("  missing message in [" + lang + "] translation: " + mess);
+                nbErr++;
             }
         }
     }
 }
+
+// ---- 2. calculators localisation ----
+
+// find every calculator folder
+const calculatorsPath = "src/app/calculators";
+const calculatorsDir = fs.readdirSync(calculatorsPath);
+console.log("Checking all calculators translations for languages [" + expectedLanguages.join(", ") + "]");
+for (let i = 0; i < calculatorsDir.length; i++) {
+    const calcPath = calculatorsPath + "/" + calculatorsDir[i];
+    const stats = {};
+    // console.log(" checking calculator [" + calculatorsDir[i] + "]");
+    // find all language files for this calculator, and store translation keys
+    for (let j = 0; j < expectedLanguages.length; j++) {
+        const exLang = expectedLanguages[j];
+        const langFilePath = calcPath + "/" + exLang + ".json";
+        if (fs.existsSync(langFilePath)) {
+            const translations = Object.keys(JSON.parse(fs.readFileSync(langFilePath, "utf-8")));
+            // console.log(translations);
+            stats[exLang] = translations;
+        } else {
+            console.log(" missing language file [" + exLang + ".json] for calculator [" + calculatorsDir[i] + "]");
+            nbErr++;
+        }
+    }
+    // console.log(stats);
+    // compare number of translations per file
+    let sameNumber = true;
+    // compare keys names (order-dependent) per file
+    let sameKeys = true;
+    let prevKeys = null;
+    const sKeys = Object.keys(stats);
+    for (let k = 0; k < sKeys.length; k++) {
+        const key = sKeys[k];
+        if (k > 0) {
+            sameNumber = sameNumber && (stats[key].length === prevKeys.length);
+            sameKeys = sameKeys && (JSON.stringify(stats[key]) === JSON.stringify(prevKeys)); // compare arrays
+        }
+        prevKeys = stats[key];
+    }
+    // difference found ?
+    if (! sameNumber) {
+        console.log(" [" + calculatorsDir[i] + "]: different number of keys found", sKeys.map((s) => {
+            return s + ": " + stats[s].length;
+        }));
+        nbErr++;
+    } else if (! sameKeys) {
+        console.log(" [" + calculatorsDir[i] + "]: different keys found", stats);
+        nbErr++;
+    }
+}
+
+
+// ---- 3. JaLHyd messages ----
+
+if (nbErr === 0) {
+    console.log("Everything OK !");
+    process.exit(0);
+} else {
+    process.exit(1);
+}
diff --git a/src/app/calculators/bief/en.json b/src/app/calculators/bief/en.json
index 30465b07a001799b439f37cbd77f79b5c55a469c..83ef6c03f737582786d59d38359f40974a6e617a 100644
--- a/src/app/calculators/bief/en.json
+++ b/src/app/calculators/bief/en.json
@@ -26,8 +26,8 @@
     "fs_condlim": "Boundary conditions",
     "Q": "Upstream flow",
     "S": "Wet surface",
-    "fs_param_calc": "Calculation parameters",
     "Dx": "Discretisation step",
+    "fs_param_calc": "Calculation parameters",
     "Z1": "Upstream water elevation",
     "Z2": "Downstream water elevation",
     "ZF1": "Upstream bottom elevation",
diff --git a/src/app/calculators/cloisons/en.json b/src/app/calculators/cloisons/en.json
index 22a43f9ac81c48230975b81008a4f426f8b607bc..af443e0f84fa4abc8864354ad601a33c380e2747 100644
--- a/src/app/calculators/cloisons/en.json
+++ b/src/app/calculators/cloisons/en.json
@@ -2,9 +2,6 @@
     "Q": "Total discharge",
     "P": "Sill",
     "W": "Gate opening",
-    "ZR": "Upstream bed elevation",
-    "PB": "Pool mean depth",
-    "h1": "Head",
 
 	"UNIT_Q": "m³/s",
     "UNIT_YMOY": "m",
diff --git a/src/app/calculators/lechaptcalmon/en.json b/src/app/calculators/lechaptcalmon/en.json
index 0e0b0798c73c0110466290d20c5656645b20d698..729994b0eefa9009092b821d43e3410b05358419 100644
--- a/src/app/calculators/lechaptcalmon/en.json
+++ b/src/app/calculators/lechaptcalmon/en.json
@@ -14,7 +14,6 @@
     "M": "M",
     "N": "N",
     "fs_hydraulique": "Hydraulic features",
-    "Q": "Flow",
     "D": "Pipe diameter",
     "J": "Total head loss",
     "Ks": "Singular head loss coefficient",
@@ -22,5 +21,8 @@
     "fs_param_calc": "Calculation parameters",
     "Jl": "Linear head loss",
     "Kl": "Linear head loss coefficient",
-    "fD": "Darcy friction factor"
+    "fD": "Darcy friction factor",
+
+    "UNIT_JL": "m",
+    "UNIT_V": "m/s"
 }
\ No newline at end of file
diff --git a/src/app/calculators/lechaptcalmon/fr.json b/src/app/calculators/lechaptcalmon/fr.json
index 0ce375bc6bfb74389554e1b65d75ed100e5daa0a..89884cabd4634f566ed4d86d2a419de79000447f 100644
--- a/src/app/calculators/lechaptcalmon/fr.json
+++ b/src/app/calculators/lechaptcalmon/fr.json
@@ -20,8 +20,9 @@
     "Lg": "Longueur du tuyau",
     "fs_param_calc": "Paramètres de calcul",
     "Jl": "Perte de charge linéaire",
-    "UNIT_JL": "m",
-    "UNIT_V": "m/s",
     "Kl": "Coefficient de perte de charge linéaire",
-    "fD": "Coefficient de perte de charge de Darcy"
+    "fD": "Coefficient de perte de charge de Darcy",
+
+    "UNIT_JL": "m",
+    "UNIT_V": "m/s"
 }
\ No newline at end of file
diff --git a/src/app/calculators/pabpuissance/en.json b/src/app/calculators/pabpuissance/en.json
index 582ca3f4574a5bd17f16a445ef6cec2836294260..5872528a56724df3749e24cf9ec1727c0b6b8bdd 100644
--- a/src/app/calculators/pabpuissance/en.json
+++ b/src/app/calculators/pabpuissance/en.json
@@ -1,7 +1,6 @@
 {
     "fs_puissance": "Basin dimensions",
     "DH": "Drop",
-    "Q": "Discharge",
     "V": "Volume",
     "PV": "Dissipated power"
 }
\ No newline at end of file
diff --git a/src/app/calculators/par/en.json b/src/app/calculators/par/en.json
index fc7eddd2d9cb266adb86fd8381b7d51e3e416c4a..f1d88aa176d3fee207ac7bba0b07b84095c489ac 100644
--- a/src/app/calculators/par/en.json
+++ b/src/app/calculators/par/en.json
@@ -1,10 +1,6 @@
 {
     "fs_param_hydro": "Hydraulic parameters",
 
-    "Q": "Flow",
-    "Z1": "Upstream water elevation",
-    "Z2": "Downstream water elevation",
-
     "fs_geometry": "Pass geometry",
 
     "ha": "Upstream head",
diff --git a/src/app/calculators/parsimulation/en.json b/src/app/calculators/parsimulation/en.json
index a5b752e2162fc757f4d38fbc1b111fb28ea86ffa..36c46b4b1706938004c1e6724b95665ca8c78524 100644
--- a/src/app/calculators/parsimulation/en.json
+++ b/src/app/calculators/parsimulation/en.json
@@ -1,10 +1,6 @@
 {
     "fs_param_hydro": "Hydraulic parameters",
 
-    "Q": "Flow",
-    "Z1": "Upstream water elevation",
-    "Z2": "Downstream water elevation",
-
     "fs_geometry": "Pass geometry",
 
     "ZD1": "Upstream spilling elevation",
diff --git a/src/app/calculators/sectionparametree/en.json b/src/app/calculators/sectionparametree/en.json
index 943320f64a4b42fcb06d8da12e7f3886dc790295..92a0479a837ab8d6a34e523b10719826aee6a5cc 100644
--- a/src/app/calculators/sectionparametree/en.json
+++ b/src/app/calculators/sectionparametree/en.json
@@ -17,7 +17,6 @@
     "If": "Bottom slope",
     "YB": "Embankment elevation",
     "fs_hydraulique": "Hydraulic features",
-    "Q": "Flow",
     "Y": "Draft",
     "fs_param_calc": "Calculation parameters",
     "Hs": "Specific head",
diff --git a/src/locale/messages.en.json b/src/locale/messages.en.json
index 073d7138d12380cb0023801844110803907ef295..acbc4c1501bac560a985122e6d8a3223e51bb0e3 100644
--- a/src/locale/messages.en.json
+++ b/src/locale/messages.en.json
@@ -57,15 +57,20 @@
     "ERROR_REMOUS_PAS_CALCUL": "No possible calculation, neither from upstream nor from downstream",
     "ERROR_REMOUS_PENTE_FORTE": "The water line slope is too steep at abscissa %x% m (the discretisation step should be reduced)",
     "ERROR_RU_CIRC_LEVEL_TOO_HIGH": "Uniform flow cannot be calculated with a pipe under load",
+    "ERROR_NEWTON_NON_CONVERGENCE": "Non-convergence (Newton's method)",
     "ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCONJUG": "Non-convergence of the calculation of the combined depth (Newton's method)",
     "ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCRITIQUE": "Non-convergence of the calculation of the critical depth (Newton's method)",
     "ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCOR": "Non convergence of the calculation of the corresponding elevation (Newton's method)",
     "ERROR_SECTION_NON_CONVERGENCE_NEWTON_HNORMALE": "Non convergence of the calculation of the normal depth (Newton's method)",
     "ERROR_SECTION_PENTE_NEG_NULLE_HNORMALE_INF": "The slope is negative or zero, the normal depth is infinite",
+    "ERROR_SECTION_PERIMETRE_NUL": "Section: calculation is impossible when perimeter is null",
+    "ERROR_SECTION_RAYON_NUL": "Section: calculation is impossible when radius is null",
     "ERROR_SECTION_SURFACE_NULLE": "Section: calculation is impossible when surface is null",
     "ERROR_SOMETHING_FAILED_IN_CHILD": "Calculation of child module #%number% failed",
     "ERROR_SOLVEUR_NO_VARIATED_PARAMS_ALLOWED": "Solver cannot be used with a modules chain containing variated parameters",
     "ERROR_STRUCTURE_Q_TROP_ELEVE": "The flow passing through the other devices is too high: the requested parameter is not calculable.",
+    "ERROR_STRUCTURE_ZDV_PAS_CALCULABLE": "Parameter \"Crest elevation\" cannot be calculated with this discharge law",
+    "ERROR_STRUCTURE_Z_EGAUX_Q_NON_NUL": "Upstream and downstream elevations are equal but flow is not null",
     "INFO_CALCULATOR_CALC_NAME": "Calculator name",
     "INFO_CALCULATOR_CALCULER": "Compute",
     "INFO_CALCULATOR_CLONE": "Duplicate",
@@ -604,6 +609,7 @@
     "INFO_VERIF_OK": "Crossing criteria are met for all species",
     "INFO_VERIF_VARYING_OK": "Crossing criteria are met for all species and all pass modalities",
     "WARNING_VERIF_OK_BUT": "Crossing criteria are met for all species, but there are warnings",
+    "WARNING_VERIF_VARYING_OK_BUT": "Only certain modalities of the pass are crossable",
     "INFO_VERIFICATEUR_CUSTOM_SPECIES": "Custom species: %s",
     "INFO_VERIFICATEUR_SPECIES_GROUP": "Species group",
     "INFO_VERIFICATEUR_TITRE": "Fish pass verification",
@@ -626,6 +632,7 @@
     "WARNING_GRILLE_ALPHA_GREATER_THAN_45": "Recommendation for fish guiding: α ≤ 45°",
     "WARNING_GRILLE_BETA_GREATER_THAN_26": "Recommendation for fish guiding: β ≤ 26°",
     "WARNING_GRILLE_VN_GREATER_THAN_05": "Recommendation to prevent fish getting stuck on grid plan (physical barrier) or prematurely passing through the grid (behavioural barrier): VN ≤ 0.5 m/s.<br>Above average value calculated here, refer to the recommendations taken from experimental caracterisation of effective speed values.",
+    "WARNING_GRILLE_O_LOWER_THAN_OB": "Total obstruction (entered) is lower than obstruction due to bars only (calculated)",
     "WARNING_LECHAPT_CALMON_SPEED_OUTSIDE_04_2": "This formula is discouraged for a speed that is not between 0.4 and 2 m/s",
     "WARNING_UPSTREAM_BOTTOM_HIGHER_THAN_WATER": "Upstream water elevation is lower or equal to bottom elevation",
     "WARNING_DOWNSTREAM_BOTTOM_HIGHER_THAN_WATER": "Downstream water elevation is lower or equal to bottom elevation",
@@ -656,6 +663,7 @@
     "INFO_PARENT_PREFIX": "%name% #%position%: ",
     "INFO_PARENT_PREFIX_DOWNWALL": "downwall: ",
     "ERROR_VERIF_ERRORS_IN_PASS": "Pass to verify contains errors",
+    "ERROR_VERIF_VARYING_ERRORS_IN_PASS": "Pass to verify contains error at iteration %i%",
     "ERROR_VERIF_MISSING_CRITERION": "Criterion %var_criterion% must be defined",
     "ERROR_VERIF_MR_VMAX": "Maximum speed %V% too high (maximum: %maxV%)",
     "ERROR_VERIF_MR_PVMAX": "Dissipated power %PV% too high (maximum: %maxPV%)",
diff --git a/src/locale/messages.fr.json b/src/locale/messages.fr.json
index 58d8ec44e8d920398dc794ef354654bf8970ce2d..2fe2697aaa909d0f891524bba0fede5a4fbe4684 100644
--- a/src/locale/messages.fr.json
+++ b/src/locale/messages.fr.json
@@ -57,15 +57,20 @@
     "ERROR_REMOUS_PAS_CALCUL": "Aucun calcul possible ni depuis l'amont ni depuis l'aval",
     "ERROR_REMOUS_PENTE_FORTE": "La pente de la ligne d'eau est trop forte à l'abscisse %x% m (il faudrait réduire le pas de discrétisation)",
     "ERROR_RU_CIRC_LEVEL_TOO_HIGH": "Le régime uniforme ne peut pas être calculé avec une conduite en charge",
+    "ERROR_NEWTON_NON_CONVERGENCE": "Non convergence (Méthode de Newton)",
     "ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCONJUG": "Non convergence du calcul de la hauteur conjuguée (Méthode de Newton)",
     "ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCRITIQUE": "Non convergence du calcul de la hauteur critique (Méthode de Newton)",
     "ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCOR": "Non convergence du calcul de la hauteur correspondante (Méthode de Newton)",
     "ERROR_SECTION_NON_CONVERGENCE_NEWTON_HNORMALE": "Non convergence du calcul de la hauteur normale (Méthode de Newton)",
     "ERROR_SECTION_PENTE_NEG_NULLE_HNORMALE_INF": "La pente est négative ou nulle, la hauteur normale est infinie",
+    "ERROR_SECTION_PERIMETRE_NUL": "Section&nbsp;: calcul impossible à cause d'un périmètre nul",
+    "ERROR_SECTION_RAYON_NUL": "Section&nbsp;: calcul impossible à cause d'un rayon nul",
     "ERROR_SECTION_SURFACE_NULLE": "Section&nbsp;: calcul impossible à cause d'une surface nulle",
     "ERROR_SOMETHING_FAILED_IN_CHILD": "Le calcul du module enfant n°%number% a échoué",
     "ERROR_SOLVEUR_NO_VARIATED_PARAMS_ALLOWED": "Le solveur ne peut pas être utilisé avec une chaîne de modules contenant des paramètres variés",
     "ERROR_STRUCTURE_Q_TROP_ELEVE": "Le débit passant par les autres ouvrages est trop élevé&nbsp;: le paramètre demandé n'est pas calculable.",
+    "ERROR_STRUCTURE_ZDV_PAS_CALCULABLE": "Le paramètre \"Cote de radier\" ne peut pas être calculé avec cette loi de débit",
+    "ERROR_STRUCTURE_Z_EGAUX_Q_NON_NUL": "Les cotes amont aval sont égales et le débit n'est pas nul",
     "INFO_CALCULATOR_CALC_NAME": "Nom du module de calcul",
     "INFO_CALCULATOR_CALCULER": "Calculer",
     "INFO_CALCULATOR_CLONE": "Dupliquer",
@@ -628,6 +633,7 @@
     "WARNING_GRILLE_ALPHA_GREATER_THAN_45": "Préconisation pour le guidage des poissons&nbsp;: α ≤ 45°",
     "WARNING_GRILLE_BETA_GREATER_THAN_26": "Préconisation pour le guidage des poissons&nbsp;: β ≤ 26°",
     "WARNING_GRILLE_VN_GREATER_THAN_05": "Préconisation pour éviter le placage des poissons sur le plan de grille (barrière physique) ou leur passage prématuré au travers (barrière comportementale)&nbsp;: VN ≤ 0.5 m/s.<br>Au-delà de la valeur moyenne calculée ici, se reporter aux préconisations tirées de la caractérisation expérimentale des valeurs effectives de vitesses.",
+    "WARNING_GRILLE_O_LOWER_THAN_OB": "L'obstruction totale (saisie) est inférieure à l'obstruction due aux barreaux seulement (calculée)",
     "WARNING_LECHAPT_CALMON_SPEED_OUTSIDE_04_2": "Cette formule n'est pas conseillée pour une vitesse non comprise entre 0.4 et 2 m/s",
     "WARNING_UPSTREAM_BOTTOM_HIGHER_THAN_WATER": "La cote de l'eau à l'amont est plus basse ou égale à la cote de fond",
     "WARNING_DOWNSTREAM_BOTTOM_HIGHER_THAN_WATER": "La cote de l'eau à l'aval est plus basse ou égale à la cote de fond",