From d031f40095f6e480e0d545624c981c07fd4d2d33 Mon Sep 17 00:00:00 2001
From: Manuel Kocher <manuel.kocher@tugraz.at>
Date: Thu, 9 Jun 2022 07:47:04 +0200
Subject: [PATCH] Add session storage support to improve translation runtime

---
 packages/app-shell/src/app-shell.js |  7 ++++++-
 packages/app-shell/src/i18n.js      |  4 +++-
 packages/common/i18next.js          | 28 ++++++++++++++++++++++------
 packages/common/src/translation.js  | 12 ++++++------
 4 files changed, 37 insertions(+), 14 deletions(-)

diff --git a/packages/app-shell/src/app-shell.js b/packages/app-shell/src/app-shell.js
index 0c7d2a88..ecf3fd38 100644
--- a/packages/app-shell/src/app-shell.js
+++ b/packages/app-shell/src/app-shell.js
@@ -1,4 +1,4 @@
-import {createInstance} from './i18n.js';
+import {createInstance, fetchOverridestoSessionStorage} from './i18n.js';
 import {html, css} from 'lit';
 import {ScopedElementsMixin} from '@open-wc/scoped-elements';
 import {LanguageSelect} from '@dbp-toolkit/language-select';
@@ -168,6 +168,11 @@ export class AppShell extends ScopedElementsMixin(DBPLitElement) {
         this.metadata = metadata;
         this.routes = routes;
 
+        // fetch translations
+        for(let lng of this._i18n.languages) {
+          fetchOverridestoSessionStorage(this.langDir, lng);
+        }
+
         // Switch to the first route if none is selected
         if (!this.activeView) this.switchComponent(routes[0]);
         else this.switchComponent(this.activeView);
diff --git a/packages/app-shell/src/i18n.js b/packages/app-shell/src/i18n.js
index 0c6fedc8..090a555c 100644
--- a/packages/app-shell/src/i18n.js
+++ b/packages/app-shell/src/i18n.js
@@ -1,4 +1,4 @@
-import {createInstance as _createInstance} from '@dbp-toolkit/common/i18next.js';
+import {createInstance as _createInstance, fetchOverridestoSessionStorage} from '@dbp-toolkit/common/i18next.js';
 
 import de from './i18n/de/translation.json';
 import en from './i18n/en/translation.json';
@@ -6,3 +6,5 @@ import en from './i18n/en/translation.json';
 export function createInstance() {
     return _createInstance({en: en, de: de}, 'de', 'en');
 }
+
+export {fetchOverridestoSessionStorage}
diff --git a/packages/common/i18next.js b/packages/common/i18next.js
index 21544a46..74e8659d 100644
--- a/packages/common/i18next.js
+++ b/packages/common/i18next.js
@@ -134,6 +134,16 @@ async function fetchOverridesByLanguage(overrides, lng) {
   return json;
 }
 
+export async function fetchOverridestoSessionStorage(overridesFile, lng) {
+  // use local cache for translation file
+  if (sessionStorage.getItem("translation-overrides-" + lng) === null) {
+    // get translation.json for each lang
+    let response = await fetchOverridesByLanguage(overridesFile, lng);
+    sessionStorage.setItem("translation-overrides-" + lng, JSON.stringify(response));
+
+  }
+}
+
 /**
  * Sets translation overrides for the given i18next instance. Any previously
  * applied overrides will be removed first. So calling this with an empty overrides
@@ -143,7 +153,7 @@ async function fetchOverridesByLanguage(overrides, lng) {
  * @param {HTMLElement} element - The element at which the overrides are targeted
  * @param {string} overridesFile - Path to the translation file containing the overrides
  */
-export async function setOverridesByFile(i18n, element, overridesFile) {
+export async function setOverridesByFile(i18n, element, overridesFile, keyName) {
     // We add a special namespace which gets used with priority and falls back
     // to the original one. This way we an change the overrides at runtime
     // and can even remove them.
@@ -154,18 +164,24 @@ export async function setOverridesByFile(i18n, element, overridesFile) {
     let overrideNamespace = getOverrideNamespace(namespace);
     let hasOverrides = false;
     for (let lng of i18n.languages) {
-        // get translation.json for each lang
-        let response = await fetchOverridesByLanguage(overridesFile, lng);
+
+        await fetchOverridestoSessionStorage(overridesFile, lng);
+
+        let response = JSON.parse(sessionStorage.getItem("translation-overrides-" + lng));
+
         // remove old language
         i18n.removeResourceBundle(lng, overrideNamespace);
         // if no new translation is available, skip
         if (response === undefined || response[tagName] === undefined) return;
         // get new translation
-        let resources = response[tagName];
+        let resource = {};
+        resource[keyName] = response[tagName][keyName];
         hasOverrides = true;
+
         // set new translation
-        i18n.addResourceBundle(lng, overrideNamespace, resources);
-        i18n.setDefaultNamespace(hasOverrides ? overrideNamespace : namespace);
+        i18n.addResourceBundle(lng, overrideNamespace, resource);
     }
+
+    i18n.setDefaultNamespace(hasOverrides ? overrideNamespace : namespace);
     return i18n;
 }
diff --git a/packages/common/src/translation.js b/packages/common/src/translation.js
index fc0e4404..d0fd965c 100644
--- a/packages/common/src/translation.js
+++ b/packages/common/src/translation.js
@@ -35,7 +35,6 @@ export class Translation extends DBPLitElement {
 
     connectedCallback() {
       super.connectedCallback();
-
       // init objects with empty string as value for key
       const de = {};
       const en = {};
@@ -44,13 +43,14 @@ export class Translation extends DBPLitElement {
 
       // create i18n instance with given translations
       this._i18n = createInstanceGivenResources(en, de);
-
-      // after init of overrides re-render page
       let local = this;
       if (this.langDir) {
-        setOverridesByFile(this._i18n, this, this.langDir).then(function(response) {
+
+        // after init of overrides re-render page
+        setOverridesByFile(this._i18n, this, this.langDir, this.key).then(function(response) {
             local.requestUpdate();
         });
+
       }
     }
 
@@ -78,12 +78,12 @@ export class Translation extends DBPLitElement {
             return this._i18n.t(this.key);
         })();
 
-        // if translation == "", key was not found
+        // if translation == "" key was not found
         let key = "";
         if (translation != "") {
           key = unsafeHTML("<!-- key: " + this.key + "-->");
         } else {
-          key = unsafeHTML("<!-- key: " + this.key + " not found! -->");
+          key = unsafeHTML("<!-- key \"" + this.key + "\" not found! -->");
         }
 
         // load translation text
-- 
GitLab