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