diff --git a/packages/common/i18next.js b/packages/common/i18next.js index d72b9abcc272045f9d50fff1928d33f6eb8358fa..5f56097cfd5a5db5d726441879dabe86cc3c2195 100644 --- a/packages/common/i18next.js +++ b/packages/common/i18next.js @@ -1,5 +1,31 @@ import i18next from 'i18next'; +// global variable as cache for translations +const translationCache = {}; + +// fetches overrides for given language +async function fetchOverridesByLanguage(overrides, lng) { + let result = await + fetch(overrides + lng +'/translation.json', { + headers: {'Content-Type': 'application/json'}, + }); + let json = await result.json(); + return json; +} + +// handles translation cache promises +async function cacheOverrides(overridesFile, lng) { + // use global var as cache + if (translationCache[lng] === undefined) { + // get translation.json for each lang + let response = fetchOverridesByLanguage(overridesFile, lng); + translationCache[lng] = response; + return response; + } else { + return translationCache[lng]; + } +} + /** * Like Intl.DateTimeFormat().format() but uses the current language as locale. * @@ -133,23 +159,25 @@ export function setOverrides(i18n, element, overrides) { * * @param {i18next.i18n} i18n - The i18next instance * @param {HTMLElement} element - The element at which the overrides are targeted - * @param {object} overrides - The override data as promise */ -export async function setOverridesByPromise(i18n, element, overrides) { +export async function setOverridesByGlobalCache(i18n, element) { // 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. + + // The scoped mixin saves the real tag name under data-tag-name let tagName = ((element.dataset && element.dataset.tagName) || element.tagName).toLowerCase(); let namespace = i18n.options.fallbackNS; let overrideNamespace = getOverrideNamespace(namespace); let hasOverrides = false; for (let lng of i18n.languages) { - overrides[lng] = await overrides[lng]; + cacheOverrides(element.langDir, lng); + translationCache[lng] = await translationCache[lng]; i18n.removeResourceBundle(lng, overrideNamespace); - if (overrides[lng] === undefined || overrides[lng][tagName] === undefined) continue; - let resources = overrides[lng][tagName]; + if (translationCache[lng] === undefined || translationCache[lng][tagName] === undefined) continue; + let resources = translationCache[lng][tagName]; hasOverrides = true; i18n.addResourceBundle(lng, overrideNamespace, resources); } diff --git a/packages/common/src/i18n.js b/packages/common/src/i18n.js index 1db56149c8772428260cc630cbcd4559b37d2eba..ec940db5c5d14b8e2319bd69fc5c97407693c2d0 100644 --- a/packages/common/src/i18n.js +++ b/packages/common/src/i18n.js @@ -1,4 +1,4 @@ -import {createInstance as _createInstance, setOverridesByPromise} from '../i18next.js'; +import {createInstance as _createInstance, setOverridesByGlobalCache} from '../i18next.js'; import de from './i18n/de/translation.json'; import en from './i18n/en/translation.json'; @@ -11,4 +11,4 @@ export function createInstanceGivenResources(en, de) { return _createInstance({en: en, de: de}, 'de', 'en'); } -export {setOverridesByPromise}; +export {setOverridesByGlobalCache}; diff --git a/packages/common/src/translation.js b/packages/common/src/translation.js index 07bb756e091f3df29ceb010ade2caf7805de8ad5..ebf230a7eae1e3e3bb2b96968719478a27fb3bb0 100644 --- a/packages/common/src/translation.js +++ b/packages/common/src/translation.js @@ -1,33 +1,8 @@ import {css, html} from 'lit'; import {unsafeHTML} from 'lit/directives/unsafe-html.js'; import DBPLitElement from '../dbp-lit-element'; -import {createInstanceGivenResources, setOverridesByPromise} from './i18n.js'; - -// global variable as cache for translations -const translationCache = {}; - -// fetches overrides for given language -async function fetchOverridesByLanguage(overrides, lng) { - let result = await - fetch(overrides + lng +'/translation.json', { - headers: {'Content-Type': 'application/json'}, - }); - let json = await result.json(); - return json; -} - -// handles translation cache promises -async function cacheOverrides(overridesFile, lng) { - // use global var as cache - if (translationCache[lng] === undefined) { - // get translation.json for each lang - let response = fetchOverridesByLanguage(overridesFile, lng); - translationCache[lng] = response; - return response; - } else { - return translationCache[lng]; - } -} +import * as commonStyles from '../styles.js'; +import {createInstanceGivenResources, setOverridesByGlobalCache} from './i18n.js'; export class Translation extends DBPLitElement { constructor() { @@ -52,11 +27,25 @@ export class Translation extends DBPLitElement { static get styles() { // language=css - return css` - .hidden { - display: none; - } - `; + return [ + + commonStyles.getThemeCSS(), + commonStyles.getGeneralCSS(), + css` + .hidden { + display: none; + } + .links { + border-bottom: var(--dbp-border); + border-color: var(--dbp-content); + padding: 0; + transition: background-color 0.15s ease 0s, color 0.15s ease 0s; + color: var(--dbp-content); + cursor: pointer; + text-decoration: none; + } + `, + ]; } connectedCallback() { @@ -71,10 +60,7 @@ export class Translation extends DBPLitElement { this._i18n = createInstanceGivenResources(en, de); if (this.langDir) { - for(let lng of this._i18n.languages) { - cacheOverrides(this.langDir, lng); - setOverridesByPromise(this._i18n, this, translationCache); - } + setOverridesByGlobalCache(this._i18n, this); } } diff --git a/packages/theme-switcher/src/demo.js b/packages/theme-switcher/src/demo.js index 7f8725ea8baa5eb18dd3b1edf272124b88b5ef9c..3a9bc1ae709ec4c08a193e1bd943d0b4a039277a 100644 --- a/packages/theme-switcher/src/demo.js +++ b/packages/theme-switcher/src/demo.js @@ -1,4 +1,4 @@ -import {createInstance} from './i18n'; +import {createInstance, setOverridesByGlobalCache} from './i18n'; import {html, LitElement} from 'lit'; import {ScopedElementsMixin} from '@open-wc/scoped-elements'; import {ThemeSwitcher} from './theme-switcher'; @@ -12,6 +12,7 @@ export class ThemeSwitcherDemo extends ScopedElementsMixin(LitElement) { this.url = ''; this.selectedFiles = []; this.selectedFilesCount = 0; + this.langDir = ''; } static get scopedElements() { @@ -23,11 +24,15 @@ export class ThemeSwitcherDemo extends ScopedElementsMixin(LitElement) { static get properties() { return { lang: {type: String}, + langDir: {type: String, attribute: "lang-dir"}, }; } connectedCallback() { super.connectedCallback(); + if (this.langDir) { + setOverridesByGlobalCache(this._i18n, this); + } } update(changedProperties) { @@ -101,7 +106,7 @@ export class ThemeSwitcherDemo extends ScopedElementsMixin(LitElement) { <p>${i18n.t('intro')}</p> </div> <div class="content"> - <dbp-theme-switcher + <dbp-theme-switcher subscribe="lang, lang-dir" themes='[{"class": "light-theme", "icon": "sun", "name": "Light Mode"}, {"class": "dark-theme", "icon": "night", "name": "Dark Mode"}]'></dbp-theme-switcher> </div> </section> diff --git a/packages/theme-switcher/src/i18n.js b/packages/theme-switcher/src/i18n.js index 0c6fedc883e4f02965df30acfb47fa37e11a268c..96e808148afd698b71d85b15a12312ab7c0c3cc8 100644 --- a/packages/theme-switcher/src/i18n.js +++ b/packages/theme-switcher/src/i18n.js @@ -1,4 +1,4 @@ -import {createInstance as _createInstance} from '@dbp-toolkit/common/i18next.js'; +import {createInstance as _createInstance, setOverridesByGlobalCache} 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{setOverridesByGlobalCache}; diff --git a/packages/theme-switcher/src/i18n/en/translation.json b/packages/theme-switcher/src/i18n/en/translation.json index d8c90ce29156c2211cda6d6185b4f5563014d7f6..eb93e777e5e2337e5fbef8368e9c5737cecc834e 100644 --- a/packages/theme-switcher/src/i18n/en/translation.json +++ b/packages/theme-switcher/src/i18n/en/translation.json @@ -1,5 +1,5 @@ { - "color-mode": "Farbmodus ändern", + "color-mode": "Change color mode", "demo-title": "Theme Switcher Demo", "intro": "With the theme-switcher you can switch between multiple themes." } diff --git a/packages/theme-switcher/src/theme-switcher.js b/packages/theme-switcher/src/theme-switcher.js index cd13807736b7e6779a8ab283b2fa0bbbce48bafb..6a236f82bf33f0c9e92274891dc31540aee4a2ad 100644 --- a/packages/theme-switcher/src/theme-switcher.js +++ b/packages/theme-switcher/src/theme-switcher.js @@ -1,4 +1,4 @@ -import {createInstance} from './i18n.js'; +import {createInstance, setOverridesByGlobalCache} from './i18n.js'; import {html, css} from 'lit'; import {ScopedElementsMixin} from '@open-wc/scoped-elements'; import {AdapterLitElement, Icon} from '@dbp-toolkit/common'; @@ -15,6 +15,7 @@ export class ThemeSwitcher extends ScopedElementsMixin(AdapterLitElement) { this.boundCloseAdditionalMenuHandler = this.hideModeMenu.bind(this); this.detectBrowserDarkMode = false; this.darkModeClass = 'dark-theme'; + this.langDir = ''; } static get properties() { @@ -23,6 +24,7 @@ export class ThemeSwitcher extends ScopedElementsMixin(AdapterLitElement) { lang: {type: String}, themes: {type: Array, attribute: 'themes'}, darkModeThemeOverride: {type: String, attribute: 'dark-mode-theme-override'}, + langDir: {type: String, attribute: 'lang-dir'}, }; } @@ -55,6 +57,9 @@ export class ThemeSwitcher extends ScopedElementsMixin(AdapterLitElement) { this.loadTheme('light-theme'); this.detectInitialMode(); }); + if (this.langDir) { + setOverridesByGlobalCache(this._i18n, this); + } } detectInitialMode() { @@ -158,8 +163,8 @@ export class ThemeSwitcher extends ScopedElementsMixin(AdapterLitElement) { ${commonStyles.getThemeCSS()} ${commonStyles.getGeneralCSS()} ${commonStyles.getButtonCSS()} - - + + mode-button, button.button { border: none; } diff --git a/toolkit-showcase/assets/theme-switcher.metadata.json b/toolkit-showcase/assets/theme-switcher.metadata.json index 79d3bd989bf61fce3d9c681b3570b9ff734467d9..b7b1ea749863cd9db4d43e936af4324578e463db 100644 --- a/toolkit-showcase/assets/theme-switcher.metadata.json +++ b/toolkit-showcase/assets/theme-switcher.metadata.json @@ -14,5 +14,5 @@ "de": "Theme Switcher Web Komponente", "en": "Theme-Switcher web component" }, - "subscribe": "lang" + "subscribe": "lang, lang-dir" } diff --git a/toolkit-showcase/assets/translation-overrides/de/translation.json b/toolkit-showcase/assets/translation-overrides/de/translation.json index 27d226ddd06de5cf6471160a27d98a31f25a8f79..5a89e9d1d3a788c37f8c61658c74d8a3b0a1d0be 100644 --- a/toolkit-showcase/assets/translation-overrides/de/translation.json +++ b/toolkit-showcase/assets/translation-overrides/de/translation.json @@ -1,6 +1,15 @@ { "dbp-translation": { "toolkit-showcase": "Dieser Text wird mithilfe von i18n aus einer benutzerdefinierten Sprachdatei gelesen und ins Englische übersetzt wenn man die Sprache auf Englisch stellt.", - "toolkit-showcase-link": "Es können sogar links mittels <a href=\"{{- link1}}\">interpolation</a> und escaping dargestellt werden." + "toolkit-showcase-link": "Es können sogar links mittels <a href=\"{{- link1}}\" class=\"links\">interpolation</a> und escaping dargestellt werden.", + "color-mode": "Sollte nicht angezeigt werden. Dieser Text ist nur als test vorhanden.", + "intro": "Sollte nicht angezeigt werden. Dieser Text ist nur als test vorhanden." + }, + "dbp-theme-switcher": { + "color-mode": "Theme ändern", + "intro": "Sollte nicht angezeigt werden. Dieser Text ist nur als test vorhanden." + }, + "dbp-theme-switcher-demo": { + "intro": "Mit dem Theme-Switcher können Sie zwischen unterschiedlichen Farb-Themes umschalten, wie z.B. zwischen Light- und Dark Mode." } } diff --git a/toolkit-showcase/assets/translation-overrides/en/translation.json b/toolkit-showcase/assets/translation-overrides/en/translation.json index e3cd5c3858abaac1396241f2235a71fdb2f17d86..fa7eaaa94b6942af6030d3d765813b23f940942c 100644 --- a/toolkit-showcase/assets/translation-overrides/en/translation.json +++ b/toolkit-showcase/assets/translation-overrides/en/translation.json @@ -1,6 +1,15 @@ { "dbp-translation": { "toolkit-showcase": "This text will be translated to german using i18n with a user defined language file when the language is changed to german.", - "toolkit-showcase-link": "Furthermore its possible to display links through <a href=\"{{- link1}}\">interpolation</a> and escaping." + "toolkit-showcase-link": "Furthermore its possible to display links through <a href=\"{{- link1}}\" class=\"links\">interpolation</a> and escaping.", + "color-mode": "This text is not supposed to be displayed. It is only here for testing.", + "intro": "This text is not supposed to be displayed. It is only here for testing." + }, + "dbp-theme-switcher": { + "color-mode": "Change theme", + "intro": "This text is not supposed to be displayed. It is only here for testing." + }, + "dbp-theme-switcher-demo": { + "intro": "With the theme-switcher you can switch between multiple themes. For example, between Light Mode and Dark Mode." } } diff --git a/toolkit-showcase/src/dbp-theme-switcher-demo-activity.js b/toolkit-showcase/src/dbp-theme-switcher-demo-activity.js index ee698cfc2096e1e4c26511bcd0f6fa7f773caf74..bc4bbed350661129ee2787cd804e46e0e848d9fc 100644 --- a/toolkit-showcase/src/dbp-theme-switcher-demo-activity.js +++ b/toolkit-showcase/src/dbp-theme-switcher-demo-activity.js @@ -12,6 +12,7 @@ export class DbpThemeSwitcherDemoActivity extends ScopedElementsMixin(AdapterLit constructor() { super(); this.lang = 'en'; + this.langDir = ''; } static get scopedElements() { @@ -24,6 +25,7 @@ export class DbpThemeSwitcherDemoActivity extends ScopedElementsMixin(AdapterLit return { ...super.properties, lang: {type: String}, + langDir: {type: String, attribute: "lang-dir"}, }; } @@ -58,7 +60,7 @@ export class DbpThemeSwitcherDemoActivity extends ScopedElementsMixin(AdapterLit render() { return html` ${unsafeHTML(readme)} - <dbp-theme-switcher-demo id="demo" lang="${this.lang}"></dbp-theme-switcher-demo> + <dbp-theme-switcher-demo id="demo" lang="${this.lang}" lang-dir="${this.langDir}"></dbp-theme-switcher-demo> `; } }