From b881ddc4a0e264237996064b36433b6ba85646f0 Mon Sep 17 00:00:00 2001 From: Volker Schukai <volker.schukai@schukai.com> Date: Mon, 23 Jan 2023 14:40:54 +0100 Subject: [PATCH] feat: new embed i18n provider --- application/example/i18n/providers/embed.mjs | 5 + application/source/i18n/providers/embed.mjs | 125 ++++++++++++++++++ application/source/i18n/providers/fetch.mjs | 21 +-- .../test/cases/i18n/providers/embed.mjs | 72 ++++++++++ 4 files changed, 213 insertions(+), 10 deletions(-) create mode 100644 application/example/i18n/providers/embed.mjs create mode 100644 application/source/i18n/providers/embed.mjs create mode 100644 development/test/cases/i18n/providers/embed.mjs diff --git a/application/example/i18n/providers/embed.mjs b/application/example/i18n/providers/embed.mjs new file mode 100644 index 000000000..52912ff1a --- /dev/null +++ b/application/example/i18n/providers/embed.mjs @@ -0,0 +1,5 @@ +import {Embed} from '@schukai/monster/source/i18n/providers/embed.mjs'; + +// read from scritp tag with id i18n +const translation = new Embed('i18n'); + diff --git a/application/source/i18n/providers/embed.mjs b/application/source/i18n/providers/embed.mjs new file mode 100644 index 000000000..d4d1f0b7f --- /dev/null +++ b/application/source/i18n/providers/embed.mjs @@ -0,0 +1,125 @@ +/** + * Copyright schukai GmbH and contributors 2022. All Rights Reserved. + * Node module: @schukai/monster + * This file is licensed under the AGPLv3 License. + * License text available at https://www.gnu.org/licenses/agpl-3.0.en.html + */ + +import {internalSymbol} from "../../constants.mjs"; +import {extend} from "../../data/extend.mjs"; +import { getGlobalObject} from "../../types/global.mjs"; +import {isString} from "../../types/is.mjs"; +import {validateObject, validateString} from "../../types/validate.mjs"; +import {parseLocale} from "../locale.mjs"; +import {Provider} from "../provider.mjs"; +import {Translations} from "../translations.mjs"; + +export {Embed} + +/** + * The Embed provider retrieves a JSON file from the given Script Tag. + * + * @externalExample ../../../example/i18n/providers/embed.mjs + * @license AGPLv3 + * @since 1.13.0 + * @copyright schukai GmbH + * @memberOf Monster.I18n.Providers + * @see {@link https://datatracker.ietf.org/doc/html/rfc3066} + * @tutorial i18n-locale-and-formatter + */ +class Embed extends Provider { + + /** + * ```html + * <script id="translations" type="application/json"> + * { + * "hello": "Hallo" + * } + * </script> + * ``` + * + * + * ```javascript + * new Embed('translations') + * ``` + * + * @param {string} id + * @param {Object} options + */ + constructor(id, options) { + super(options); + + if (options === undefined) { + options = {}; + } + + validateString(id); + + /** + * @property {string} + */ + this.textId = id; + + /** + * @private + * @property {Object} options + */ + this[internalSymbol] = extend({}, super.defaults, this.defaults, validateObject(options)); + + } + + /** + * Defaults + * + * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API} + */ + get defaults() { + return extend({}, super.defaults); + } + + /** + * + * @param {Locale|string} locale + * @return {Promise} + */ + getTranslations(locale) { + + if (isString(locale)) { + locale = parseLocale(locale); + } + + return new Promise((resolve, reject) => { + + let text = getGlobalObject('document').getElementById(this.textId); + + if (text === null) { + reject(new Error('Text not found')); + return; + } + + let translations = null; + try { + translations = JSON.parse(text.innerHTML); + } catch (e) { + reject(e); + return; + } + + + if (translations === null) { + reject(new Error('Translations not found or invalid')); + return; + } + + const t = new Translations(locale); + t.assignTranslations(translations) + + resolve(t); + + }); + + } + + +} + diff --git a/application/source/i18n/providers/fetch.mjs b/application/source/i18n/providers/fetch.mjs index 672db975f..0ce8abe25 100644 --- a/application/source/i18n/providers/fetch.mjs +++ b/application/source/i18n/providers/fetch.mjs @@ -84,16 +84,17 @@ export {Fetch} */ get defaults() { - return { - fetch: { - method: 'GET', // *GET, POST, PUT, DELETE, etc. - mode: 'cors', // no-cors, *cors, same-origin - cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached - credentials: 'omit', // include, *same-origin, omit - redirect: 'follow', // manual, *follow, error - referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url - } - } + return extend( + { + fetch: { + method: 'GET', // *GET, POST, PUT, DELETE, etc. + mode: 'cors', // no-cors, *cors, same-origin + cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached + credentials: 'omit', // include, *same-origin, omit + redirect: 'follow', // manual, *follow, error + referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url + } + }, super.defaults); } diff --git a/development/test/cases/i18n/providers/embed.mjs b/development/test/cases/i18n/providers/embed.mjs new file mode 100644 index 000000000..686bec19a --- /dev/null +++ b/development/test/cases/i18n/providers/embed.mjs @@ -0,0 +1,72 @@ +import {expect} from "chai" + + +import {Embed} from "../../../../../application/source/i18n/providers/embed.mjs"; +import {Translations} from "../../../../../application/source/i18n/translations.mjs"; +import {getGlobal} from "../../../../../application/source/types/global.mjs"; +import {initJSDOM} from "../../../util/jsdom.mjs"; + + +const global = getGlobal(); + +const html1 = ` +<script id="templocale" type="application/json"> +{ + "key": "translation" +} +</script> +`; + +describe('Translation Provider Embed', function () { + + before(function (done) { + initJSDOM().then(() => { + done() + }); + }); + + + afterEach(() => { + let mocks = document.getElementById('mocks'); + mocks.innerHTML = ""; + }); + + beforeEach(() => { + let mocks = document.getElementById('mocks'); + mocks.innerHTML = html1; + + }) + + describe('get mock data and create translation', function () { + + it('embed', function (done) { + + const e = new Embed('templocale'); + let p = e.getTranslations('en'); + expect(p).is.instanceof(Promise); + + p.then(r => { + + try { + expect(r).is.instanceof(Translations); + + let t = r.getText('key') + expect(t).is.equal('translation'); + + + done(); + } catch (e) { + done(e); + } + + + }).catch(e => { + done(e); + }) + + }); + + }); + + +}); \ No newline at end of file -- GitLab