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

Add support of translation overrides to dbp-translation

parent 4dbce52e
No related branches found
No related tags found
No related merge requests found
Pipeline #176850 failed
......@@ -75,6 +75,7 @@ export class AppShell extends ScopedElementsMixin(DBPLitElement) {
this.auth = {};
this.langFiles = '';
this.overrideFiles = '';
}
static get scopedElements() {
......@@ -273,6 +274,7 @@ export class AppShell extends ScopedElementsMixin(DBPLitElement) {
env: {type: String},
auth: {type: Object},
langFiles: {type: String, attribute: 'lang-files'},
overrideFiles: {type: String, attribute: 'override-files'},
};
}
......
......@@ -15,13 +15,14 @@ import {
Translation,
} from './index.js';
export class DbpCommonDemo extends ScopedElementsMixin(LitElement) {
constructor() {
super();
this._i18n = createInstance();
this.lang = this._i18n.language;
this.noAuth = false;
this.langFiles = '';
}
static get scopedElements() {
......@@ -47,7 +48,6 @@ export class DbpCommonDemo extends ScopedElementsMixin(LitElement) {
return {
lang: {type: String},
noAuth: {type: Boolean, attribute: 'no-auth'},
langFiles: {type: String, attribute: 'lang-files'},
};
}
......@@ -302,8 +302,10 @@ html {
</dbp-translated>
</div>
<div class="control" id="dbp-translation-demo">
<dbp-translation key="toolkit-showcase" subscribe="lang, lang-files"></dbp-translation>
<dbp-translation key="toolkit-showcase-link" var='{"link1": "https://www.i18next.com/translation-function/interpolation"}' subscribe="lang, lang-files" unsafe></dbp-translation>
<p><dbp-translation key="toolkit-showcase" subscribe="lang, lang-files"></dbp-translation></p>
<p><dbp-translation key="toolkit-showcase" subscribe="lang, lang-files, override-files"></dbp-translation></p>
<p><dbp-translation key="toolkit-showcase-link" var='{"link1": "https://www.i18next.com/translation-function/interpolation"}' subscribe="lang, lang-files" unsafe></dbp-translation></p>
<p><dbp-translation key="toolkit-showcase-link" var='{"link1": "https://dbp-demo.tugraz.at/"}' subscribe="lang, lang-files, override-files" unsafe></dbp-translation></p>
</div>
</div>
</section>
......
......@@ -124,3 +124,48 @@ export function setOverrides(i18n, element, overrides) {
}
i18n.setDefaultNamespace(hasOverrides ? overrideNamespace : namespace);
}
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;
}
/**
* Sets translation overrides for the given i18next instance. Any previously
* applied overrides will be removed first. So calling this with an empty overrides
* object is equal to removing all overrides.
*
* @param {i18next.i18n} i18n - The i18next instance
* @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) {
// 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) {
// get translation.json for each lang
let response = await fetchOverridesByLanguage(overridesFile, 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];
hasOverrides = true;
// set new translation
i18n.addResourceBundle(lng, overrideNamespace, resources);
i18n.setDefaultNamespace(hasOverrides ? overrideNamespace : namespace);
}
return i18n;
}
import {createInstance as _createInstance} from '../i18next.js';
import {createInstance as _createInstance, setOverridesByFile} from '../i18next.js';
import de from './i18n/de/translation.json';
import en from './i18n/en/translation.json';
......@@ -12,6 +12,7 @@ export async function createInstanceAsync(langFile, namespace) {
namespace = 'translation'
// check if a path to language files is given
if(langFile) {
// request german lang file asynchronously
let result = await
fetch(langFile + 'de/' + namespace +'.json', {
......@@ -31,3 +32,5 @@ export async function createInstanceAsync(langFile, namespace) {
return _createInstance({en: en, de: de}, 'de', 'en', namespace);
}
export {setOverridesByFile};
......@@ -7,6 +7,5 @@
"api-documentation-server": "Verbindung zum apiDocumentation API Server {{apiDocUrl}} fehlgeschlagen!",
"error-api-server": "Verbindung zum API Server {{apiUrl}} fehlgeschlagen!",
"error-hydra-documentation-url-not-set": "Hydra apiDocumentation URL wurden für server {{apiUrl}} nicht gesetzt!"
},
"toolkit-showcase": "Dieser Text wird mithilfe von i18n Englisch wenn man die Sprache auf Englisch stellt."
}
}
......@@ -7,6 +7,5 @@
"api-documentation-server": "Connection to apiDocumentation server {{apiDocUrl}} failed!",
"error-api-server": "Connection to api server {{apiUrl}} failed!",
"error-hydra-documentation-url-not-set": "Hydra apiDocumentation url was not set for server {{apiUrl}}!"
},
"toolkit-showcase": "This text will be translated to german using i18n when the user changes the language to german."
}
}
......@@ -2,7 +2,20 @@ import {css, html} from 'lit';
import {until} from 'lit/directives/until.js';
import {unsafeHTML} from 'lit/directives/unsafe-html.js';
import DBPLitElement from '../dbp-lit-element';
import {createInstanceAsync} from './i18n.js';
import {createInstanceAsync, setOverridesByFile} from './i18n.js';
let OVERRIDE = {
'de': {
'dbp-translation': {
'toolkit-showcase': 'testText'
}
},
'en': {
'dbp-translation': {
'toolkit-showcase': 'testText2'
}
}
}
export class Translation extends DBPLitElement {
constructor() {
......@@ -12,6 +25,7 @@ export class Translation extends DBPLitElement {
this.langFiles = '';
this.interpolation = '';
this.namespace = '';
this.overrideFiles = '';
}
static get properties() {
......@@ -23,6 +37,7 @@ export class Translation extends DBPLitElement {
interpolation: {type: Object, attribute: 'var'},
unsafe: {type: Boolean, attribute: 'unsafe'},
namespace: {type: String, attribute: 'ns'},
overrideFiles: {type: String, attribute: 'override-files'},
};
}
......@@ -37,11 +52,24 @@ export class Translation extends DBPLitElement {
connectedCallback() {
super.connectedCallback();
if (this.namespace == '')
if (this.namespace == '') {
this._i18n = createInstanceAsync(this.langFiles);
}
else {
this._i18n = createInstanceAsync(this.langFiles, this.namespace);
}
let local = this;
let overrideFiles = this.overrideFiles;
if (this.overrideFiles) {
this._i18n.then(function(response) {
setOverridesByFile(response, local, overrideFiles).then(function(response) {
local._i18n = response;
local.requestUpdate();
});
})
}
}
update(changedProperties) {
......@@ -49,7 +77,7 @@ export class Translation extends DBPLitElement {
changedProperties.forEach((oldValue, propName) => {
switch (propName) {
case 'lang':
this._i18n.then(function(response) {
Promise.resolve(this._i18n).then(function(response) {
response.changeLanguage(lang);
});
break;
......@@ -66,7 +94,7 @@ export class Translation extends DBPLitElement {
let unsafe = this.unsafe;
// async request to i18n translation
const translation = this._i18n.then(function(response){
const translation = Promise.resolve(this._i18n).then(function(response){
if (interpolation && unsafe)
return unsafeHTML(response.t(key, interpolation));
else if (interpolation)
......
......@@ -114,6 +114,7 @@
provider-root
lang="de"
lang-files="<%= getPrivateUrl('i18n/') %>"
override-files="<%= getPrivateUrl('i18n/overrides/') %>"
entry-point-url="<%= entryPointURL %>"
nextcloud-auth-url="<%= nextcloudWebAppPasswordURL %>"
nextcloud-web-dav-url="<%= nextcloudWebDavURL %>"
......
{
"dbp-translation": {
"toolkit-showcase": "Überschriebener i18n toolkit-showcase Text",
"toolkit-showcase-link": "Überschriebener i18n toolkit-showcase-link Text mit <a href=\"{{- link1}}\">TestLink</a>"
}
}
{
"dbp-translation": {
"toolkit-showcase": "Overriden i18n toolkit-showcase text",
"toolkit-showcase-link": "Overriden i18n toolkit-showcase-link text with a <a href=\"{{- link1}}\">test link</a>"
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment