From cfaf56405fb753e30f80fd6b42d2140a63ac5148 Mon Sep 17 00:00:00 2001
From: "mathias.chouet" <mathias.chouet@irstea.fr>
Date: Tue, 1 Sep 2020 11:17:00 +0200
Subject: [PATCH] Fix #223 - enhance translation system

---
 .../calculator.component.ts                   |  2 +
 .../formulaire/elements/formulaire-element.ts | 14 ++---
 src/app/formulaire/elements/select-field.ts   | 11 ++--
 src/app/services/formulaire.service.ts        | 52 +++++++++++++++++--
 .../services/internationalisation.service.ts  | 13 ++---
 5 files changed, 66 insertions(+), 26 deletions(-)

diff --git a/src/app/components/generic-calculator/calculator.component.ts b/src/app/components/generic-calculator/calculator.component.ts
index f1cd53d10..d16af2522 100644
--- a/src/app/components/generic-calculator/calculator.component.ts
+++ b/src/app/components/generic-calculator/calculator.component.ts
@@ -433,6 +433,8 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
                     this.setForm(this.formulaireService.getFormulaireFromId(uid));
                     this.resultsComponent.formulaire = this._formulaire;
                     this._calculatorNameComponent.model = this._formulaire;
+                    // reload localisation in all cases (it does not eat bread)
+                    this.formulaireService.updateFormulaireLocalisation(this._formulaire);
                     // call Form init hook
                     this._formulaire.onCalculatorInit();
                     break;
diff --git a/src/app/formulaire/elements/formulaire-element.ts b/src/app/formulaire/elements/formulaire-element.ts
index 79a4899ea..579b62648 100644
--- a/src/app/formulaire/elements/formulaire-element.ts
+++ b/src/app/formulaire/elements/formulaire-element.ts
@@ -1,8 +1,7 @@
 import { FormulaireNode } from "./formulaire-node";
-import { StringMap } from "../../stringmap";
-import { I18nService } from "../../services/internationalisation.service";
 import { ServiceFactory } from "../../services/service-factory";
 import { FormulaireDefinition } from "../definition/form-definition";
+import { FormulaireService } from "../../services/formulaire.service";
 
 /**
  * élément (enfant) du formulaire : fieldset, input, container, ...
@@ -18,7 +17,7 @@ export abstract class FormulaireElement extends FormulaireNode {
      */
     protected _label: string;
 
-    private intlService: I18nService;
+    private formulaireService: FormulaireService;
 
     public static removePrefix(s: string, prefix: string): string {
         if (s.startsWith(prefix)) {
@@ -30,7 +29,7 @@ export abstract class FormulaireElement extends FormulaireNode {
     constructor(parent: FormulaireNode) {
         super(parent);
         this._isDisplayed = true;
-        this.intlService = ServiceFactory.i18nService;
+        this.formulaireService = ServiceFactory.formulaireService;
     }
 
     get isDisplayed(): boolean {
@@ -71,11 +70,8 @@ export abstract class FormulaireElement extends FormulaireNode {
      * @param loc calculator-specific localised messages map
      * @param key Element label key
      */
-    public updateLocalisation(key?: string) {
-        if (!key) {
-            key = this._confId;
-        }
-        this._label = this.intlService.localizeText(key);
+    public updateLocalisation() {
+        this._label = this.formulaireService.localizeText(this._confId, this.parentForm.currentNub.calcType);
         for (const f of this.getKids()) {
             f.updateLocalisation();
         }
diff --git a/src/app/formulaire/elements/select-field.ts b/src/app/formulaire/elements/select-field.ts
index 4f7196cf6..680cab630 100644
--- a/src/app/formulaire/elements/select-field.ts
+++ b/src/app/formulaire/elements/select-field.ts
@@ -10,7 +10,6 @@ import {
 
 import { Field } from "./field";
 import { SelectEntry } from "./select-entry";
-import { StringMap } from "../../stringmap";
 import { FormulaireNode } from "./formulaire-node";
 import { FormulaireDefinition } from "../definition/form-definition";
 import { ServiceFactory } from "../../services/service-factory";
@@ -114,10 +113,12 @@ export class SelectField extends Field {
         super.updateLocalisation();
         for (const e of this._entries) {
             // some Select fields already have a translated label at this time; translate others
-            if (e.label === undefined) {
-                const aId = e.id.split("_");
-                e.label = ServiceFactory.i18nService.localizeText(`${aId[1].toUpperCase()}_${aId[2]}`);
-            }
+            const aId = e.id.split("_");
+            const trad = ServiceFactory.formulaireService.localizeText(
+                `${aId[1].toUpperCase()}_${aId[2]}`,
+                this.parentForm.currentNub.calcType
+            );
+            e.label = trad;
         }
     }
 
diff --git a/src/app/services/formulaire.service.ts b/src/app/services/formulaire.service.ts
index 72818b95e..0a2f94e14 100644
--- a/src/app/services/formulaire.service.ts
+++ b/src/app/services/formulaire.service.ts
@@ -91,6 +91,51 @@ export class FormulaireService extends Observable {
         return this.intlService.localizeText(`INFO_${sCalculator}_TITRE_COURT`);
     }
 
+    /**
+     * Forces update of all form strings in given Formulaire, with current language
+     */
+    public updateFormulaireLocalisation(f: FormulaireDefinition) {
+        const requiredLang = this.intlService.currentLanguage;
+        f.updateLocalisation(requiredLang);
+    }
+
+
+    /**
+     * Tente de trouver une traduction pour textKey dans les fichiers de langues
+     * spécifiques du module de calcul en cours, dans la langue en cours, puis
+     * dans la langue par défaut; si aucune traduction n'est trouvée, demande au
+     * service i18n de rechercher dans les fichiers de langues globaux
+     * @param textKey la clé du texte à traduire
+     */
+    public localizeText(textKey: string, ct: CalculatorType): string {
+        const calcType = /* this.currentForm?.currentNub?.calcType || */ ct;
+        if (calcType !== undefined) {
+            // throw new Error("FormulaireService.localizeText(): cannot find CalculatorType for current form's Nub");
+            let langCache = this.i18nService.languageCache;
+            if (langCache && langCache[calcType]) {
+                langCache = langCache[calcType]; // …for target Nub type
+            }
+            // try current language
+            if (
+                langCache
+                && langCache[this.intlService.currentLanguage]
+                && langCache[this.intlService.currentLanguage][textKey] !== undefined
+            ) {
+                return langCache[this.intlService.currentLanguage][textKey];
+
+            } else if ( // try calculator type specific translation, but for default language
+                langCache
+                && langCache[this.appSetupService.fallbackLanguage]
+                && langCache[this.appSetupService.fallbackLanguage][textKey] !== undefined
+            ) {
+                return langCache[this.appSetupService.fallbackLanguage][textKey];
+
+            }
+        }
+        // fallback to global (not calculator type specific) translation system
+        return this.i18nService.localizeText(textKey);
+    }
+
     /**
      * Returns variable name from symbol
      * @param calcType
@@ -107,7 +152,7 @@ export class FormulaireService extends Observable {
             langCache = langCache[this.intlService.currentLanguage]; // … for current language
         }
         if (langCache && langCache[symbol] !== undefined) {
-            s = this.intlService.localizeText(symbol, langCache);
+            s = this.localizeText(symbol, calcType);
         } else {
             // is symbol of the form ouvrages[i]… ?
             const re = /([A-Z,a-z]+)\[(\d+)\]\.(.+)/;
@@ -161,7 +206,7 @@ export class FormulaireService extends Observable {
             } else {
                 const unitKey = "UNIT_" + symbolBase;
                 if (langCache && langCache[unitKey] !== undefined) {
-                    unit = this.intlService.localizeText(unitKey, langCache);
+                    unit = this.localizeText(unitKey, calcType);
                 }
             }
         }
@@ -287,8 +332,7 @@ export class FormulaireService extends Observable {
         const f: FormulaireDefinition = this.newFormulaire(ct);
         this._formulaires.push(f);
         // Charge la configuration dépendamment du type
-        const prom: Promise<any> = this.loadConfig(ct);
-        return prom.then(s => {
+        return this.loadConfig(ct).then(s => {
             f.preparseConfig(s);
 
             // Associe le Nub fourni (chargement de session / duplication de module), sinon en crée un nouveau
diff --git a/src/app/services/internationalisation.service.ts b/src/app/services/internationalisation.service.ts
index 26d2cecce..ed8011d09 100644
--- a/src/app/services/internationalisation.service.ts
+++ b/src/app/services/internationalisation.service.ts
@@ -79,7 +79,6 @@ export class I18nService extends Observable implements Observer {
             this._Messages = undefined;
             // reload all messages: global lang files, plus lang files for all calculators !
             const that = this;
-            console.log("> promise.all !");
             const promisesList: Promise<any>[] = [];
             for (const ct in CalculatorType) {
                 const calcType = Number(ct);
@@ -88,7 +87,6 @@ export class I18nService extends Observable implements Observer {
                 }
             }
             Promise.all(promisesList).then(() => {
-                console.log(">> get global messages !");
                 this.httpGetMessages(code).then((res: any) => {
                     that._Messages = res;
                     // propagate language change to all application
@@ -174,16 +172,15 @@ export class I18nService extends Observable implements Observer {
      *
      * @param textKey id du texte (ex: "ERROR_PARAM_NULL")
      */
-    public localizeText(textKey: string, msg?: StringMap) {
-        const messages = msg || this._Messages;
-        if (! messages) {
+    public localizeText(textKey: string) {
+        if (! this._Messages) {
             return `*** messages not loaded: ${this._currentLanguage} ***`;
         }
-        if (messages[textKey] !== undefined) {
-            return decodeHtml(messages[textKey]);
+        if (this._Messages[textKey] !== undefined) {
+            return decodeHtml(this._Messages[textKey]);
         } else {
             // try general message
-            if (msg !== undefined && this._Messages["INFO_LIB_" + textKey.toUpperCase()] !== undefined) {
+            if (this._Messages !== undefined && this._Messages["INFO_LIB_" + textKey.toUpperCase()] !== undefined) {
                 return decodeHtml(this._Messages["INFO_LIB_" + textKey.toUpperCase()]);
             }
             if (!isDevMode()) {
-- 
GitLab