diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 7b79d655a874978c0a8cb90a26c8206cd958ac86..3b4ad89a8004509b36ead8b50cc085a7e5e2f474 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -823,6 +823,139 @@ export class AppComponent implements OnInit, OnDestroy, Observer {
             if (itemId) {
                 this.scrollToQuicknav(itemId, "auto");
             }
+        this.loadSessionFile(result.file, result.calculators);
+      }
+    }
+
+  public async loadSessionFile(f: File, info?: any) {
+    // notes merge detection: was there already some notes ?
+    const existingNotes = Session.getInstance().documentation;
+    // load
+    try {
+      const data = await this.formulaireService.loadSession(f, info)
+      if (data.hasErrors) {
+        this.notificationsService.notify(this.intlService.localizeText("ERROR_PROBLEM_LOADING_SESSION"), 3500);
+      } else {
+        if (data.loaded && data.loaded.length > 0) {
+          if (! isDevMode()) {
+            this.matomoTracker.trackEvent("userAction", "loadSession");
+          }
+          // notes merge detection: was there already some notes ?
+          const currentNotes = Session.getInstance().documentation;
+          if (existingNotes !== "" && currentNotes !== existingNotes) {
+            this.notificationsService.notify(this.intlService.localizeText("WARNING_SESSION_LOAD_NOTES_MERGED"), 3500);
+          }
+          // go to calc or diagram depending on what was loaded
+          if (data.loaded.length > 1) {
+            this.toDiagram();
+          } else {
+            this.toCalc(data.loaded[0]);
+          }
+        }
+      }
+    } catch(err) {
+      this.notificationsService.notify(this.intlService.localizeText("ERROR_LOADING_SESSION"), 3500);
+      console.error("error loading session - ", err);
+      // rollback to ensure session is clean
+      this.doEmptySession();
+    }
+  }
+
+  /**
+   * Demande au client d'envoyer un email (génère un lien mailto:), pré-rempli
+   * avec un texte standard, et le contenu de la session au format JSON
+   */
+  public reportBug() {
+    const recipient = "bug@cassiopee.g-eau.fr";
+    const subject = "[ISSUE] " + this.intlService.localizeText("INFO_REPORT_BUG_SUBJECT");
+    let body = this.intlService.localizeText("INFO_REPORT_BUG_BODY");
+
+    // add session description
+
+    // get all forms
+    const list = [];
+    for (const c of this._calculators) {
+      list.push({
+        title: c.title,
+        uid: c.uid,
+        selected: true
+      });
+    }
+    let session = this.buildSessionFile(list);
+
+    // compress
+    session = pako.deflate(session, { to: "string" }); // gzip (zlib)
+    session = btoa(session); // base64
+
+    body += session + "\n";
+    body = encodeURIComponent(body);
+
+    const mailtoURL = `mailto:${recipient}?subject=${subject}&body=${body}`;
+
+    // temporarily disable tab closing alert, as tab won't be closed for real
+    this.appSetupService.warnBeforeTabClose = false;
+    window.location.href = mailtoURL;
+    this.appSetupService.warnBeforeTabClose = true;
+  }
+
+  public get revisionInfo(): any {
+    return {
+      jalhyd: {
+        date: jalhydDateRev,
+        version: jalhydVersion,
+      },
+      nghyd: {
+        date: nghydDateRev,
+        version: nghydVersion
+      }
+    };
+  }
+
+  /**
+   * sauvegarde du/des formulaires
+   * @param form formulaire à sélectionner par défaut dans la liste
+   */
+  public saveForm(form?: FormulaireDefinition) {
+    // liste des formulaires
+    const list = [];
+    for (const c of this._calculators) {
+      const uid = c["uid"];
+      const nub = Session.getInstance().findNubByUid(uid);
+      let required = nub.getTargettedNubs().map((req) => {
+        return req.uid;
+      });
+      required = required.filter(
+        (item, index) => required.indexOf(item) === index // deduplicate
+      );
+      list.push({
+        "children": nub.getChildren().map((child) => {
+          return child.uid;
+        }),
+        "requires": required,
+        "selected": form ? (uid === form.uid) : true,
+        "title": c["title"],
+        "uid": uid
+      });
+    }
+    // dialogue de sélection des formulaires à sauver
+    const dialogRef = this.saveSessionDialog.open(
+      DialogSaveSessionComponent,
+      {
+        data: {
+          calculators: list
+        },
+        disableClose: false
+      }
+    );
+    dialogRef.afterClosed().subscribe(result => {
+      if (result) {
+        let name = result.filename;
+
+        // ajout extension ".json"
+        const re = /.+\.json/;
+        const match = re.exec(name.toLowerCase());
+        if (match === null) {
+          name = name + ".json";
         }
     }
 
diff --git a/src/app/components/app-setup/app-setup.component.ts b/src/app/components/app-setup/app-setup.component.ts
index 66b9df46216df020241301b28f5f222a0584c024..1b3c52d158c498cf992ed9ee31e0fe88dca086c5 100644
--- a/src/app/components/app-setup/app-setup.component.ts
+++ b/src/app/components/app-setup/app-setup.component.ts
@@ -135,12 +135,11 @@ export class ApplicationSetupComponent implements Observer, OnInit {
         });
     }
 
-    public restoreDefaultValues() {
+    public async restoreDefaultValues() {
         const text = this.intlService.localizeText("INFO_SNACKBAR_DEFAULT_SETTINGS_RESTORED");
-        this.appSetupService.restoreDefaultValues().then(() => {
-            this.snackBar.open(text, "OK", {
-                duration: 2500
-            });
+        await this.appSetupService.restoreDefaultValues();
+        this.snackBar.open(text, "OK", {
+            duration: 2500
         });
     }
 
diff --git a/src/app/components/calculator-list/calculator-list.component.ts b/src/app/components/calculator-list/calculator-list.component.ts
index e4c9a47b2c6d4134cea74527eb6d4fc095ca5f97..f850cdd39bb87414df77674a52ab37b0dbffcc72 100644
--- a/src/app/components/calculator-list/calculator-list.component.ts
+++ b/src/app/components/calculator-list/calculator-list.component.ts
@@ -142,53 +142,49 @@ export class CalculatorListComponent implements OnInit {
         this.filterItems();
     }
 
-    public create(t: CalculatorType) {
-        const p: Promise<FormulaireDefinition> = ServiceFactory.formulaireService.createFormulaire(t);
-        p.then(f => {
-            this.router.navigate(["/calculator", f.uid]);
-            return f;
-        }).then(f => {
-            // on ajoute un ouvrage après l'ouverture du module de calcul "ouvrages parallèles"
-            if (f instanceof FormulaireParallelStructure) {
-                for (const e of f.allFormElements) {
-                    if (e instanceof FieldsetContainer) {
-                        e.addFromTemplate(0);
-                        break;
-                    }
+    public async create(t: CalculatorType) {
+        const f: FormulaireDefinition = await ServiceFactory.instance.formulaireService.createFormulaire(t);
+        await this.router.navigate(["/calculator", f.uid]);
+        // on ajoute un ouvrage après l'ouverture du module de calcul "ouvrages parallèles"
+        if (f instanceof FormulaireParallelStructure) {
+            for (const e of f.allFormElements) {
+                if (e instanceof FieldsetContainer) {
+                    e.addFromTemplate(0);
+                    break;
                 }
             }
-            // on ajoute un ouvrage après l'ouverture du module de calcul "passe à bassins"
-            if (f instanceof FormulairePab) {
-                for (const e of f.allFormElements) {
-                    if (e instanceof FieldsetContainer) {
-                        e.addFromTemplate(0);
-                        break;
-                    }
+        }
+        // on ajoute un ouvrage après l'ouverture du module de calcul "passe à bassins"
+        if (f instanceof FormulairePab) {
+            for (const e of f.allFormElements) {
+                if (e instanceof FieldsetContainer) {
+                    e.addFromTemplate(0);
+                    break;
                 }
             }
-            // adding GUI for default apron, in MacroRugoCompound
-            if (f instanceof FormulaireMacrorugoCompound) {
-                for (const e of f.allFormElements) {
-                    if (e instanceof FieldsetContainer) {
-                        e.addFromTemplate(0, 0, f.currentNub.getChildren()[0]);
-                        break;
-                    }
+        }
+        // adding GUI for default apron, in MacroRugoCompound
+        if (f instanceof FormulaireMacrorugoCompound) {
+            for (const e of f.allFormElements) {
+                if (e instanceof FieldsetContainer) {
+                    e.addFromTemplate(0, 0, f.currentNub.getChildren()[0]);
+                    break;
                 }
             }
-            // on ajoute un YAXN après l'ouverture du module de calcul "somme / produit de puissances"
-            if (f instanceof FormulaireSPP) {
-                for (const e of f.allFormElements) {
-                    if (e instanceof FieldsetContainer) {
-                        e.addFromTemplate(0);
-                        break;
-                    }
+        }
+        // on ajoute un YAXN après l'ouverture du module de calcul "somme / produit de puissances"
+        if (f instanceof FormulaireSPP) {
+            for (const e of f.allFormElements) {
+                if (e instanceof FieldsetContainer) {
+                    e.addFromTemplate(0);
+                    break;
                 }
             }
+        }
 
-            if (this.appSetupService.enableEmptyFieldsOnFormInit) {
-                f.emptyFields();
-            }
-        });
+        if (this.appSetupService.enableEmptyFieldsOnFormInit) {
+            f.emptyFields();
+        }
     }
 
     public get nbOpenCalculators() {
@@ -276,14 +272,15 @@ export class CalculatorListComponent implements OnInit {
         ];
     }
 
-    public loadExample(path: string) {
+    public async loadExample(path: string) {
         const realPath = "app/examples/" + path;
-        this.httpService.httpGetBlobRequestPromise(realPath).then((d) => {
+        try {
+            const d = await this.httpService.httpGetBlobRequestPromise(realPath);
             const f: any = new Blob([d], { type: "application/json" });
             this.appComponent.loadSessionFile(f);
-        }).catch((e) => {
+        } catch(e) {
             console.error("could not load session file", e);
-        });
+        }
     }
 
     public get uitextWelcomeTitle() {
diff --git a/src/app/components/dialog-load-session/dialog-load-session.component.ts b/src/app/components/dialog-load-session/dialog-load-session.component.ts
index 653cf5ff55a9376e8ccdce2a7072cb90fa274801..02473fe41ccec8feb2ea36bbc47cdeb77bb3f111 100644
--- a/src/app/components/dialog-load-session/dialog-load-session.component.ts
+++ b/src/app/components/dialog-load-session/dialog-load-session.component.ts
@@ -138,35 +138,34 @@ export class DialogLoadSessionComponent {
         this.checkLinkedParamsAndModelsDependencies();
     }
 
-    public onFileSelected(event: any) {
-        if (event.target.files && event.target.files.length) {
-            this.file = event.target.files[0];
-            // reinit file infos
-            this.calculators = [];
-            this.fileFormatVersion = "";
-            // reinit flags
-            this.loadingError = false;
-            this.loadingComplete = false;
-
-            const formService = ServiceFactory.formulaireService;
-            formService.calculatorInfosFromSessionFile(this.file).then(
-                calcInfos => {
-                    this.fileFormatVersion = calcInfos.formatVersion;
-                    this.calculators = calcInfos.nubs;
-                    for (const n of this.calculators) {
-                        n.selected = true;
-                        // if no title was given, generate a default one
-                        if (!n.title) {
-                            n.title = decode(formService.getLocalisedShortTitleFromCalculatorType(n.type));
-                        }
-                    }
-                    this.loadingComplete = true;
-                }
-            ).catch((err) => {
-                console.error(err);
-                this.loadingError = true;
-            });
+    public async onFileSelected(event: any) {
+      if (event.target.files && event.target.files.length) {
+        this.file = event.target.files[0];
+        // reinit file infos
+        this.calculators = [];
+        this.fileFormatVersion = "";
+        // reinit flags
+        this.loadingError = false;
+        this.loadingComplete = false;
+
+        const formService = ServiceFactory.instance.formulaireService;
+        try {
+          const calcInfos: any = await formService.calculatorInfosFromSessionFile(this.file);
+          this.fileFormatVersion = calcInfos.formatVersion;
+          this.calculators = calcInfos.nubs;
+          for (const n of this.calculators) {
+            n.selected = true;
+            // if no title was given, generate a default one
+            if (! n.title) {
+              n.title = decode(formService.getLocalisedShortTitleFromCalculatorType(n.type));
+            }
+          }
+          this.loadingComplete = true;
+        } catch(err) {
+          console.error(err);
+          this.loadingError = true;
         }
+      }
     }
 
     public loadSession() {
diff --git a/src/app/components/fixedvar-results/results.component.ts b/src/app/components/fixedvar-results/results.component.ts
index 8ba53061af029d00787e37c77061108fd1f87830..00d4f84e3e27ab3fd871333b581661144e7c2041 100644
--- a/src/app/components/fixedvar-results/results.component.ts
+++ b/src/app/components/fixedvar-results/results.component.ts
@@ -23,21 +23,19 @@ export class ResultsComponentDirective {
         }
     }
 
-    public setFullscreen(element): Promise<void> {
+    public async setFullscreen(element): Promise<void> {
         const sf = <Screenfull>screenfull;
         if (sf.isEnabled) {
-            return sf.request(element).then(() => {
-                this.fullscreenChange(true);
-            });
+            await sf.request(element);
+            this.fullscreenChange(true);
         }
     }
 
-    public exitFullscreen(): Promise<void> {
+    public async exitFullscreen(): Promise<void> {
         const sf = <Screenfull>screenfull;
         if (sf.isEnabled) {
-            return sf.exit().then(() => {
-                this.fullscreenChange(false);
-            });
+            await sf.exit();
+            this.fullscreenChange(false);
         }
     }
 
diff --git a/src/app/components/generic-calculator/calculator.component.ts b/src/app/components/generic-calculator/calculator.component.ts
index 404e789b906370cd1fbcf8d79c0b2e9b7bf1d686..ca5675539fe6d42dea02f759b7ed330f1ef5a669 100644
--- a/src/app/components/generic-calculator/calculator.component.ts
+++ b/src/app/components/generic-calculator/calculator.component.ts
@@ -716,10 +716,10 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
             disableClose: false
           }
         );
-        dialogRef.afterClosed().subscribe(result => {
+        dialogRef.afterClosed().subscribe(async result => {
           if (result) {
             if (result.generate) {
-              this.formulaireService.createFormulaire(CalculatorType.Pab).then((f: FormulaireDefinition) => {
+                const f: FormulaireDefinition = await this.formulaireService.createFormulaire(CalculatorType.Pab);
                 const pab = (f.currentNub as Pab);
                 const params = pab.prms;
                 // paramètres hydrauliques
@@ -731,7 +731,6 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
                 pab.addCloisonsFromModel(this._formulaire.currentNub as Cloisons, result.nbBassins);
                 // go to new PAB
                 this.router.navigate(["/calculator", f.uid]);
-              });
             }
           }
         });
@@ -836,7 +835,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
      * @param Ys tirant(s) d'eau
      * @param Ifs pente(s)
      */
-    private generateBiefSP(Ys: number | number[], Ifs: number | number[]) {
+    private async generateBiefSP(Ys: number | number[], Ifs: number | number[]) {
         const bief = (this._formulaire.currentNub as Bief);
         const serialisedSection = bief.section.serialise();
         const sectionCopy = Session.getInstance().unserialiseSingleNub(serialisedSection, false).nub;
@@ -859,18 +858,15 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
             }
         }
 
-        this.formulaireService.createFormulaire(CalculatorType.SectionParametree, secParam)
-            .then((f: FormulaireDefinition) => {
+        const f: FormulaireDefinition = await this.formulaireService.createFormulaire(CalculatorType.SectionParametree, secParam);
                 const sp = (f.currentNub as SectionParametree);
                 sp.section.prms.Y.setValues(Ys);
                 sp.section.prms.If.setValues(Ifs);
                 // calculate
                 f.doCompute();
                 // go to new SP
-                this.router.navigate(["/calculator", f.uid]).then();
+        this.router.navigate(["/calculator", f.uid]);
             }
-        );
-    }
 
     public get generateRuSpEnabled(): boolean {
         return this.hasResults && ! this._formulaire.currentNub.result.hasErrorMessages();
@@ -887,7 +883,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
     /**
      * Génère une SectionParametree à partir du module RegimeUniforme en cours
      */
-    public generateRuSp() {
+    public async generateRuSp() {
         const ru = (this._formulaire.currentNub as RegimeUniforme);
         // copy section
         const serialisedSection = ru.section.serialise();
@@ -903,14 +899,11 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
         }
         Session.getInstance().registerNub(secParam);
 
-        this.formulaireService.createFormulaire(CalculatorType.SectionParametree, secParam)
-            .then((f: FormulaireDefinition) => {
+        const f: FormulaireDefinition = await this.formulaireService.createFormulaire(CalculatorType.SectionParametree, secParam);
                 // calculate
                 f.doCompute();
                 // go to new SP
             }
-        );
-    }
 
     public get generatePARSimulationEnabled(): boolean {
         const parCalage = (this._formulaire.currentNub as Par);
@@ -1008,7 +1001,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
      * Creates a new Formulaire with a ParSimulation Nub, using given
      * values as parameters
      */
-    protected doGenerateParSimWithValues(v: any) {
+    protected async doGenerateParSimWithValues(v: any) {
         const parCalage = (this._formulaire.currentNub as Par);
         const psim = new ParSimulationParams(
             round(v.Q, 3),      round(v.Z1, 3),     round(v.Z2, 3),
@@ -1021,14 +1014,11 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
         parSimulation.parType = parCalage.parType;
         Session.getInstance().registerNub(parSimulation);
 
-        this.formulaireService.createFormulaire(CalculatorType.ParSimulation, parSimulation)
-            .then((f: FormulaireDefinition) => {
+        const f: FormulaireDefinition = await this.formulaireService.createFormulaire(CalculatorType.ParSimulation, parSimulation);
                 // calculate
                 f.doCompute();
                 // go to new ParSimulation
-                this.router.navigate(["/calculator", f.uid]).then();
-            }
-        );
+        this.router.navigate(["/calculator", f.uid]);
     }
 
     /**
@@ -1078,11 +1068,10 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
     /**
      * Duplicates the current calculator form
      */
-    public cloneCalculator() {
+    public async cloneCalculator() {
         const serialisedNub: string = this._formulaire.currentNub.serialise({ title: this._formulaire.calculatorName });
         const nubPointer = Session.getInstance().unserialiseSingleNub(serialisedNub);
-        this.formulaireService.createFormulaire(nubPointer.nub.calcType, nubPointer.nub, nubPointer.meta.title).then((f) => {
+        const f = await this.formulaireService.createFormulaire(nubPointer.nub.calcType, nubPointer.nub, nubPointer.meta.title);
             this.router.navigate(["/calculator", f.uid]);
-        });
     }
 }
diff --git a/src/app/services/app-setup.service.ts b/src/app/services/app-setup.service.ts
index 22db10b3c856b50d69b21d3cc3fc069a2672af8c..e0aab36d07930a801b1fd9570d38e5cc4ce466bd 100644
--- a/src/app/services/app-setup.service.ts
+++ b/src/app/services/app-setup.service.ts
@@ -115,13 +115,12 @@ export class ApplicationSetupService extends Observable {
     /**
      * Restore configuration values
      */
-    public restoreDefaultValues(): Promise<any> {
-        return this.readValuesFromConfig().then(() => {
-            // notify I18nService
-            this.notifyObservers({
-                action: "languagePreferenceChanged",
-                languages: [ this.language ]
-            });
+    public async restoreDefaultValues(): Promise<any> {
+        await this.readValuesFromConfig()
+        // notify I18nService
+        this.notifyObservers({
+            action: "languagePreferenceChanged",
+            languages: [ this.language ]
         });
     }
 
@@ -172,18 +171,17 @@ export class ApplicationSetupService extends Observable {
     /**
      * Read configuration values from config (async)
      */
-    private readValuesFromConfig(): Promise<any> {
-        return this.httpService.httpGetRequestPromise(this.CONFIG_FILE_PATH).then((data: any) => {
-            // get all config values (volontarily non-generic to prevent side-effects)
-            this.displayPrecision = data.params.displayPrecision;
-            this.computePrecision = data.params.computePrecision;
-            this.maxIterations = data.params.maxIterations;
-            this.enableNotifications = data.params.enableNotifications;
-            this.enableHotkeys = data.params.enableHotkeys;
-            this.enableEmptyFieldsOnFormInit = data.params.enableEmptyFieldsOnFormInit;
-            this.language = data.params.language;
-            // load themes for calculators list page
-            this.themes = data.themes;
-        });
+    private async readValuesFromConfig(): Promise<any> {
+        const data: any = await this.httpService.httpGetRequestPromise(this.CONFIG_FILE_PATH);
+        // get all config values (volontarily non-generic to prevent side-effects)
+        this.displayPrecision = data.params.displayPrecision;
+        this.computePrecision = data.params.computePrecision;
+        this.maxIterations = data.params.maxIterations;
+        this.enableNotifications = data.params.enableNotifications;
+        this.enableHotkeys = data.params.enableHotkeys;
+        this.enableEmptyFieldsOnFormInit = data.params.enableEmptyFieldsOnFormInit;
+        this.language = data.params.language;
+        // load themes for calculators list page
+        this.themes = data.themes;
     }
 }
diff --git a/src/app/services/formulaire.service.ts b/src/app/services/formulaire.service.ts
index a9a6a716006c62da7d8fcc34ab5d9202c713408f..c7fa7a3fb9527d5f16a5870046c575b4904386e6 100644
--- a/src/app/services/formulaire.service.ts
+++ b/src/app/services/formulaire.service.ts
@@ -332,12 +332,12 @@ export class FormulaireService extends Observable {
      * @param nub nub existant à associer au formulaire (chargement de session / duplication de module)
      * @param calculatorName nom du module, à afficher dans l'interface
      */
-    public createFormulaire(ct: CalculatorType, nub?: Nub, calculatorName?: string): Promise<FormulaireDefinition> {
+    public async createFormulaire(ct: CalculatorType, nub?: Nub, calculatorName?: string): Promise<FormulaireDefinition> {
         // Crée un formulaire du bon type
         const f: FormulaireDefinition = this.newFormulaire(ct);
         this._formulaires.push(f);
         // Charge la configuration dépendamment du type
-        return this.loadConfig(ct).then(s => {
+        const s: any = await this.loadConfig(ct);
             f.preparseConfig(s);
 
             // Associe le Nub fourni (chargement de session / duplication de module), sinon en crée un nouveau
@@ -422,16 +422,11 @@ export class FormulaireService extends Observable {
                 newDownWall.addChild(newDownwallDevice);
                 f.pabNub.downWall = newDownWall;
             }
-
-            return f;
-
-        }).then(fi => {
             this.notifyObservers({
                 "action": "createForm",
-                "form": fi
-            });
-            return fi;
+            "form": f
         });
+        return f;
     }
 
     /**
@@ -642,10 +637,13 @@ export class FormulaireService extends Observable {
      * obtient des infos (nom, uid des modules de calcul, dépendances) d'un fichier session
      * @param f fichier session
      */
-    public calculatorInfosFromSessionFile(f: File): Promise<{ nubs: any[], formatVersion: string }> {
-        return this.readSingleFile(f).then(s => {
+    public async calculatorInfosFromSessionFile(f: File): Promise<{ nubs: any[], formatVersion: string }> {
+        const s = await this.readSingleFile(f);
             // return value
-            const res: { nubs: any[], formatVersion: string } = {
+        const res: {
+            nubs: any[];
+            formatVersion: string;
+        } = {
                 nubs: [],
                 formatVersion: ""
             };
@@ -663,7 +661,7 @@ export class FormulaireService extends Observable {
                     // list linked params dependencies for each Nub
                     if (e.parameters) {
                         e.parameters.forEach((p) => {
-                            if (p.targetNub && ! nubInfo.requires.includes(p.targetNub)) {
+                        if (p.targetNub && !nubInfo.requires.includes(p.targetNub)) {
                                 nubInfo.requires.push(p.targetNub);
                             }
                         });
@@ -682,7 +680,6 @@ export class FormulaireService extends Observable {
                 res.formatVersion = data.header.format_version;
             }
             return res;
-        });
     }
 
     public saveForm(f: FormulaireDefinition) {
diff --git a/src/app/services/internationalisation.service.ts b/src/app/services/internationalisation.service.ts
index 451931f1b508a6d8104470a5b855a174053676ae..4d1dabf05ef7342c3c295d0a8ec84f19a03c2b59 100644
--- a/src/app/services/internationalisation.service.ts
+++ b/src/app/services/internationalisation.service.ts
@@ -59,7 +59,7 @@ export class I18nService extends Observable implements Observer {
      *
      * @param code ISO 639-1 language code
      */
-    public setLanguage(code: string) {
+    public async setLanguage(code: string) {
         // ensure 2-letter language code
         code = code.substring(0, 2);
         // is language supported ?
@@ -79,7 +79,7 @@ export class I18nService extends Observable implements Observer {
                     promisesList.push(this.loadLocalisation(calcType).catch((err) => { /* silent fail */ }));
                 }
             }
-            Promise.all(promisesList).then(() => {
+            await Promise.all(promisesList).then(() => {
                 this.httpGetMessages(code).then((res: any) => {
                     that._Messages = res;
                     // propagate language change to all application
@@ -128,12 +128,10 @@ export class I18nService extends Observable implements Observer {
      * Loads localized messages from JSON files for the given language
      * (general messages files, not calculator-specific ones)
      */
-    private httpGetMessages(lang: string): Promise<void> {
+    private async httpGetMessages(lang: string): Promise<any> {
         const fileName = "messages." + lang + ".json";
         const filePath = "locale/" + fileName;
-        return this.httpService.httpGetRequestPromise(filePath).then((res: any) => {
-            return res;
-        });
+        return await this.httpService.httpGetRequestPromise(filePath);
     }
 
     private getMessageFromCode(c: MessageCode): string {