From 48a470714bc30cb09a30c6503161a6ffff4b2b6b Mon Sep 17 00:00:00 2001
From: "mathias.chouet" <mathias.chouet@irstea.fr>
Date: Thu, 7 Mar 2019 17:11:13 +0100
Subject: [PATCH] Traduction: en mode "prod", gestion d'une langue de secours

---
 .../internationalisation.service.ts           | 84 ++++++++++++++-----
 1 file changed, 63 insertions(+), 21 deletions(-)

diff --git a/src/app/services/internationalisation/internationalisation.service.ts b/src/app/services/internationalisation/internationalisation.service.ts
index 9700324ca..fe7c6dc3e 100644
--- a/src/app/services/internationalisation/internationalisation.service.ts
+++ b/src/app/services/internationalisation/internationalisation.service.ts
@@ -1,4 +1,4 @@
-import { Injectable } from "@angular/core";
+import { Injectable, isDevMode } from "@angular/core";
 
 import { Message, MessageCode, Observable, Observer } from "jalhyd";
 
@@ -18,6 +18,9 @@ export class I18nService extends Observable implements Observer {
     /** localized messages */
     private _Messages: StringMap;
 
+    /** localized messages in fallback language (the one in the config file) */
+    private _fallbackMessages: StringMap;
+
     constructor(
         private applicationSetupService: ApplicationSetupService,
         private httpService: HttpService
@@ -27,6 +30,10 @@ export class I18nService extends Observable implements Observer {
             fr: "Français",
             en: "English"
         };
+        // load fallback language messages once for all
+        this.httpGetMessages(this.applicationSetupService.fallbackLanguage).then((res: any) => {
+            this._fallbackMessages = res;
+        });
         // add language preferences observer
         this.applicationSetupService.addObserver(this);
     }
@@ -53,7 +60,7 @@ export class I18nService extends Observable implements Observer {
     public setLanguage(code: string) {
         // is language supported ?
         if (! Object.keys(this._availableLanguages).includes(code)) {
-            throw new Error(`ERROR_LANGUAGE_UNSUPPORTED "${code}"`);
+            throw new Error(`LANGUAGE_UNSUPPORTED "${code}"`);
         }
         // did language change ?
         if (this._currentLanguage !== code) {
@@ -62,7 +69,8 @@ export class I18nService extends Observable implements Observer {
             this._Messages = undefined;
             // reload all messages
             const that = this;
-            this.httpGetMessages().then((res) => {
+            this.httpGetMessages(code).then((res: any) => {
+                that._Messages = res;
                 // propagate language change to all application
                 that.notifyObservers(undefined);
             });
@@ -70,39 +78,73 @@ export class I18nService extends Observable implements Observer {
     }
 
     /**
-     * Loads localized messages from JSON files, for the current language
-     * (general message file, not calculator-specific ones)
+     * Loads localized messages from JSON files for the given language
+     * (general messages files, not calculator-specific ones)
      */
-    private httpGetMessages(): Promise<void> {
-        const that = this;
-        const fileName = "messages." + this._currentLanguage + ".json";
-        return this.httpService.httpGetRequestPromise("locale/" + fileName).then(
-            (res: any) => { that._Messages = res; }
-        );
+    private httpGetMessages(lang: string): Promise<void> {
+        const fileName = "messages." + lang + ".json";
+        const filePath = "locale/" + fileName;
+        return this.httpService.httpGetRequestPromise(filePath).then((res: any) => {
+            return res;
+        });
     }
 
     private getMessageFromCode(c: MessageCode): string {
         if (! this._Messages) {
-            return `*** Messages not loaded yet ***`;
+            return `*** messages not loaded yet ***`;
         }
         if (this._Messages[MessageCode[c]] === undefined) {
-            return `*** Message ${MessageCode[c]} non traduit ***`;
+            return `*** message not found ${MessageCode[c]} ***`;
         }
         return this._Messages[MessageCode[c]];
     }
 
     /**
-     * Traduit un texte défini dans un fichier de langue, à partir de sa clé
+     * Translates a text from its key.
+     *
+     * In production mode, looks in different messages collections :
+     *  1. ${msg} if provided
+     *  2. messages for current language
+     *  3. messages for fallback language
+     *
+     * In dev mode, looks only in 1. if provided, else only in 2. which makes missing
+     * translations easier to detect
+     *
      * @param textKey id du texte (ex: "ERROR_PARAM_NULL")
      */
-    public localizeText(textKey: string, messages = this._Messages) {
-        if (messages === undefined) {
-            return `*** messages not loaded: ${this._currentLanguage} ***`;
-        }
-        if (messages[textKey] === undefined) {
-            return `*** message not found: ${textKey} ***`;
+    public localizeText(textKey: string, msg?: StringMap) {
+        if (isDevMode()) {
+            // expose missing translations
+            if (msg) {
+                if (msg[textKey] === undefined) {
+                    return `*** message not found: ${textKey} ***`;
+                }
+                return msg[textKey];
+            } else {
+                if (! this._Messages) {
+                    return `*** messages not loaded: ${this._currentLanguage} ***`;
+                }
+                if (this._Messages[textKey] === undefined) {
+                    return `*** message not found: ${textKey} ***`;
+                }
+                return this._Messages[textKey];
+            }
+        } else {
+            const messages = msg || this._Messages;
+            if (! messages) {
+                return `*** messages not loaded: ${this._currentLanguage} ***`;
+            }
+            if (messages[textKey] === undefined) {
+                // try fallback language before giving up
+                if (this._fallbackMessages[textKey] === undefined) {
+                    return `*** message not found: ${textKey} ***`;
+                } else {
+                    return this._fallbackMessages[textKey];
+                }
+            } else {
+                return messages[textKey];
+            }
         }
-        return messages[textKey];
     }
 
     /**
-- 
GitLab