Skip to content
Snippets Groups Projects
Commit 1c965cb8 authored by Kocher, Manuel's avatar Kocher, Manuel
Browse files

Merge branch 'dbp-translation-component' into 'master'

parents 2c8de070 438a329c
No related branches found
No related tags found
No related merge requests found
Pipeline #187959 passed
import i18next from 'i18next'; 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. * Like Intl.DateTimeFormat().format() but uses the current language as locale.
* *
...@@ -133,23 +159,25 @@ export function setOverrides(i18n, element, overrides) { ...@@ -133,23 +159,25 @@ export function setOverrides(i18n, element, overrides) {
* *
* @param {i18next.i18n} i18n - The i18next instance * @param {i18next.i18n} i18n - The i18next instance
* @param {HTMLElement} element - The element at which the overrides are targeted * @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 // 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 // to the original one. This way we an change the overrides at runtime
// and can even remove them. // and can even remove them.
// The scoped mixin saves the real tag name under data-tag-name // The scoped mixin saves the real tag name under data-tag-name
let tagName = ((element.dataset && element.dataset.tagName) || element.tagName).toLowerCase(); let tagName = ((element.dataset && element.dataset.tagName) || element.tagName).toLowerCase();
let namespace = i18n.options.fallbackNS; let namespace = i18n.options.fallbackNS;
let overrideNamespace = getOverrideNamespace(namespace); let overrideNamespace = getOverrideNamespace(namespace);
let hasOverrides = false; let hasOverrides = false;
for (let lng of i18n.languages) { for (let lng of i18n.languages) {
overrides[lng] = await overrides[lng]; cacheOverrides(element.langDir, lng);
translationCache[lng] = await translationCache[lng];
i18n.removeResourceBundle(lng, overrideNamespace); i18n.removeResourceBundle(lng, overrideNamespace);
if (overrides[lng] === undefined || overrides[lng][tagName] === undefined) continue; if (translationCache[lng] === undefined || translationCache[lng][tagName] === undefined) continue;
let resources = overrides[lng][tagName]; let resources = translationCache[lng][tagName];
hasOverrides = true; hasOverrides = true;
i18n.addResourceBundle(lng, overrideNamespace, resources); i18n.addResourceBundle(lng, overrideNamespace, resources);
} }
......
import {createInstance as _createInstance, setOverridesByPromise} from '../i18next.js'; import {createInstance as _createInstance, setOverridesByGlobalCache} from '../i18next.js';
import de from './i18n/de/translation.json'; import de from './i18n/de/translation.json';
import en from './i18n/en/translation.json'; import en from './i18n/en/translation.json';
...@@ -11,4 +11,4 @@ export function createInstanceGivenResources(en, de) { ...@@ -11,4 +11,4 @@ export function createInstanceGivenResources(en, de) {
return _createInstance({en: en, de: de}, 'de', 'en'); return _createInstance({en: en, de: de}, 'de', 'en');
} }
export {setOverridesByPromise}; export {setOverridesByGlobalCache};
import {css, html} from 'lit'; import {css, html} from 'lit';
import {unsafeHTML} from 'lit/directives/unsafe-html.js'; import {unsafeHTML} from 'lit/directives/unsafe-html.js';
import DBPLitElement from '../dbp-lit-element'; import DBPLitElement from '../dbp-lit-element';
import {createInstanceGivenResources, setOverridesByPromise} from './i18n.js'; import * as commonStyles from '../styles.js';
import {createInstanceGivenResources, setOverridesByGlobalCache} 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];
}
}
export class Translation extends DBPLitElement { export class Translation extends DBPLitElement {
constructor() { constructor() {
...@@ -52,11 +27,25 @@ export class Translation extends DBPLitElement { ...@@ -52,11 +27,25 @@ export class Translation extends DBPLitElement {
static get styles() { static get styles() {
// language=css // language=css
return css` return [
commonStyles.getThemeCSS(),
commonStyles.getGeneralCSS(),
css`
.hidden { .hidden {
display: none; 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() { connectedCallback() {
...@@ -71,10 +60,7 @@ export class Translation extends DBPLitElement { ...@@ -71,10 +60,7 @@ export class Translation extends DBPLitElement {
this._i18n = createInstanceGivenResources(en, de); this._i18n = createInstanceGivenResources(en, de);
if (this.langDir) { if (this.langDir) {
for(let lng of this._i18n.languages) { setOverridesByGlobalCache(this._i18n, this);
cacheOverrides(this.langDir, lng);
setOverridesByPromise(this._i18n, this, translationCache);
}
} }
} }
......
import {createInstance} from './i18n'; import {createInstance, setOverridesByGlobalCache} from './i18n';
import {html, LitElement} from 'lit'; import {html, LitElement} from 'lit';
import {ScopedElementsMixin} from '@open-wc/scoped-elements'; import {ScopedElementsMixin} from '@open-wc/scoped-elements';
import {ThemeSwitcher} from './theme-switcher'; import {ThemeSwitcher} from './theme-switcher';
...@@ -12,6 +12,7 @@ export class ThemeSwitcherDemo extends ScopedElementsMixin(LitElement) { ...@@ -12,6 +12,7 @@ export class ThemeSwitcherDemo extends ScopedElementsMixin(LitElement) {
this.url = ''; this.url = '';
this.selectedFiles = []; this.selectedFiles = [];
this.selectedFilesCount = 0; this.selectedFilesCount = 0;
this.langDir = '';
} }
static get scopedElements() { static get scopedElements() {
...@@ -23,11 +24,15 @@ export class ThemeSwitcherDemo extends ScopedElementsMixin(LitElement) { ...@@ -23,11 +24,15 @@ export class ThemeSwitcherDemo extends ScopedElementsMixin(LitElement) {
static get properties() { static get properties() {
return { return {
lang: {type: String}, lang: {type: String},
langDir: {type: String, attribute: "lang-dir"},
}; };
} }
connectedCallback() { connectedCallback() {
super.connectedCallback(); super.connectedCallback();
if (this.langDir) {
setOverridesByGlobalCache(this._i18n, this);
}
} }
update(changedProperties) { update(changedProperties) {
...@@ -101,7 +106,7 @@ export class ThemeSwitcherDemo extends ScopedElementsMixin(LitElement) { ...@@ -101,7 +106,7 @@ export class ThemeSwitcherDemo extends ScopedElementsMixin(LitElement) {
<p>${i18n.t('intro')}</p> <p>${i18n.t('intro')}</p>
</div> </div>
<div class="content"> <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> themes='[{"class": "light-theme", "icon": "sun", "name": "Light Mode"}, {"class": "dark-theme", "icon": "night", "name": "Dark Mode"}]'></dbp-theme-switcher>
</div> </div>
</section> </section>
......
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 de from './i18n/de/translation.json';
import en from './i18n/en/translation.json'; import en from './i18n/en/translation.json';
...@@ -6,3 +6,5 @@ import en from './i18n/en/translation.json'; ...@@ -6,3 +6,5 @@ import en from './i18n/en/translation.json';
export function createInstance() { export function createInstance() {
return _createInstance({en: en, de: de}, 'de', 'en'); return _createInstance({en: en, de: de}, 'de', 'en');
} }
export{setOverridesByGlobalCache};
{ {
"color-mode": "Farbmodus ändern", "color-mode": "Change color mode",
"demo-title": "Theme Switcher Demo", "demo-title": "Theme Switcher Demo",
"intro": "With the theme-switcher you can switch between multiple themes." "intro": "With the theme-switcher you can switch between multiple themes."
} }
import {createInstance} from './i18n.js'; import {createInstance, setOverridesByGlobalCache} from './i18n.js';
import {html, css} from 'lit'; import {html, css} from 'lit';
import {ScopedElementsMixin} from '@open-wc/scoped-elements'; import {ScopedElementsMixin} from '@open-wc/scoped-elements';
import {AdapterLitElement, Icon} from '@dbp-toolkit/common'; import {AdapterLitElement, Icon} from '@dbp-toolkit/common';
...@@ -15,6 +15,7 @@ export class ThemeSwitcher extends ScopedElementsMixin(AdapterLitElement) { ...@@ -15,6 +15,7 @@ export class ThemeSwitcher extends ScopedElementsMixin(AdapterLitElement) {
this.boundCloseAdditionalMenuHandler = this.hideModeMenu.bind(this); this.boundCloseAdditionalMenuHandler = this.hideModeMenu.bind(this);
this.detectBrowserDarkMode = false; this.detectBrowserDarkMode = false;
this.darkModeClass = 'dark-theme'; this.darkModeClass = 'dark-theme';
this.langDir = '';
} }
static get properties() { static get properties() {
...@@ -23,6 +24,7 @@ export class ThemeSwitcher extends ScopedElementsMixin(AdapterLitElement) { ...@@ -23,6 +24,7 @@ export class ThemeSwitcher extends ScopedElementsMixin(AdapterLitElement) {
lang: {type: String}, lang: {type: String},
themes: {type: Array, attribute: 'themes'}, themes: {type: Array, attribute: 'themes'},
darkModeThemeOverride: {type: String, attribute: 'dark-mode-theme-override'}, darkModeThemeOverride: {type: String, attribute: 'dark-mode-theme-override'},
langDir: {type: String, attribute: 'lang-dir'},
}; };
} }
...@@ -55,6 +57,9 @@ export class ThemeSwitcher extends ScopedElementsMixin(AdapterLitElement) { ...@@ -55,6 +57,9 @@ export class ThemeSwitcher extends ScopedElementsMixin(AdapterLitElement) {
this.loadTheme('light-theme'); this.loadTheme('light-theme');
this.detectInitialMode(); this.detectInitialMode();
}); });
if (this.langDir) {
setOverridesByGlobalCache(this._i18n, this);
}
} }
detectInitialMode() { detectInitialMode() {
......
...@@ -14,5 +14,5 @@ ...@@ -14,5 +14,5 @@
"de": "Theme Switcher Web Komponente", "de": "Theme Switcher Web Komponente",
"en": "Theme-Switcher web component" "en": "Theme-Switcher web component"
}, },
"subscribe": "lang" "subscribe": "lang, lang-dir"
} }
{ {
"dbp-translation": { "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": "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."
} }
} }
{ {
"dbp-translation": { "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": "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."
} }
} }
...@@ -12,6 +12,7 @@ export class DbpThemeSwitcherDemoActivity extends ScopedElementsMixin(AdapterLit ...@@ -12,6 +12,7 @@ export class DbpThemeSwitcherDemoActivity extends ScopedElementsMixin(AdapterLit
constructor() { constructor() {
super(); super();
this.lang = 'en'; this.lang = 'en';
this.langDir = '';
} }
static get scopedElements() { static get scopedElements() {
...@@ -24,6 +25,7 @@ export class DbpThemeSwitcherDemoActivity extends ScopedElementsMixin(AdapterLit ...@@ -24,6 +25,7 @@ export class DbpThemeSwitcherDemoActivity extends ScopedElementsMixin(AdapterLit
return { return {
...super.properties, ...super.properties,
lang: {type: String}, lang: {type: String},
langDir: {type: String, attribute: "lang-dir"},
}; };
} }
...@@ -58,7 +60,7 @@ export class DbpThemeSwitcherDemoActivity extends ScopedElementsMixin(AdapterLit ...@@ -58,7 +60,7 @@ export class DbpThemeSwitcherDemoActivity extends ScopedElementsMixin(AdapterLit
render() { render() {
return html` return html`
${unsafeHTML(readme)} ${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>
`; `;
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment