diff --git a/application/example/i18n/providers/embed.mjs b/application/example/i18n/providers/embed.mjs new file mode 100644 index 0000000000000000000000000000000000000000..52912ff1a24444d0a8678586f078fcc0d0a0d899 --- /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 0000000000000000000000000000000000000000..d4d1f0b7f5c5ce404cc2b5c479a06dc75fdbeb1c --- /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 672db975ffa46ee9c1fe2215d5eab00ba41cc623..0ce8abe25a0302db18464a46321669ea18c40b8b 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 0000000000000000000000000000000000000000..686bec19ad082d0e848f1ab760f2c69cab8ed4a5 --- /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