@schukai/monster 3.4.2 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/example/i18n/providers/embed.mjs +5 -0
- package/package.json +1 -1
- package/source/data/datasource/server.mjs +1 -1
- package/source/dom/locale.mjs +35 -1
- package/source/i18n/providers/embed.mjs +125 -0
- package/source/i18n/providers/fetch.mjs +11 -10
- package/source/i18n/translations.mjs +9 -6
- package/source/types/version.mjs +1 -1
- package/test/cases/dom/locale.mjs +15 -0
- package/test/cases/i18n/providers/embed.mjs +72 -0
- package/test/cases/monster.mjs +1 -1
package/package.json
CHANGED
package/source/dom/locale.mjs
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import {parseLocale} from "../i18n/locale.mjs";
|
|
9
|
-
|
|
10
9
|
import {getDocument} from "./util.mjs";
|
|
10
|
+
import {getGlobalObject} from "../types/global.mjs";
|
|
11
11
|
|
|
12
12
|
export {getLocaleOfDocument}
|
|
13
13
|
|
|
@@ -46,6 +46,40 @@ function getLocaleOfDocument() {
|
|
|
46
46
|
return new parseLocale(locale)
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
+
|
|
50
|
+
let navigatorLanguage = getNavigatorLanguage();
|
|
51
|
+
if (navigatorLanguage) {
|
|
52
|
+
return parseLocale(navigatorLanguage);
|
|
53
|
+
}
|
|
49
54
|
|
|
50
55
|
return parseLocale(DEFAULT_LANGUAGE);
|
|
51
56
|
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @private
|
|
60
|
+
* @returns {string|undefined|*}
|
|
61
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/language
|
|
62
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/languages
|
|
63
|
+
*/
|
|
64
|
+
const getNavigatorLanguage = () => {
|
|
65
|
+
const navigator = getGlobalObject('navigator');
|
|
66
|
+
if (navigator === undefined) {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (navigator.hasOwnProperty('language')) {
|
|
71
|
+
const language = navigator.language;
|
|
72
|
+
if (typeof language === 'string' && language.length > 0) {
|
|
73
|
+
return language;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const languages = navigator?.languages;
|
|
79
|
+
if (Array.isArray(languages) && languages.length>0) {
|
|
80
|
+
return languages[0];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return undefined;
|
|
84
|
+
|
|
85
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright schukai GmbH and contributors 2022. All Rights Reserved.
|
|
3
|
+
* Node module: @schukai/monster
|
|
4
|
+
* This file is licensed under the AGPLv3 License.
|
|
5
|
+
* License text available at https://www.gnu.org/licenses/agpl-3.0.en.html
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {internalSymbol} from "../../constants.mjs";
|
|
9
|
+
import {extend} from "../../data/extend.mjs";
|
|
10
|
+
import { getGlobalObject} from "../../types/global.mjs";
|
|
11
|
+
import {isString} from "../../types/is.mjs";
|
|
12
|
+
import {validateObject, validateString} from "../../types/validate.mjs";
|
|
13
|
+
import {parseLocale} from "../locale.mjs";
|
|
14
|
+
import {Provider} from "../provider.mjs";
|
|
15
|
+
import {Translations} from "../translations.mjs";
|
|
16
|
+
|
|
17
|
+
export {Embed}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The Embed provider retrieves a JSON file from the given Script Tag.
|
|
21
|
+
*
|
|
22
|
+
* @externalExample ../../../example/i18n/providers/embed.mjs
|
|
23
|
+
* @license AGPLv3
|
|
24
|
+
* @since 1.13.0
|
|
25
|
+
* @copyright schukai GmbH
|
|
26
|
+
* @memberOf Monster.I18n.Providers
|
|
27
|
+
* @see {@link https://datatracker.ietf.org/doc/html/rfc3066}
|
|
28
|
+
* @tutorial i18n-locale-and-formatter
|
|
29
|
+
*/
|
|
30
|
+
class Embed extends Provider {
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* ```html
|
|
34
|
+
* <script id="translations" type="application/json">
|
|
35
|
+
* {
|
|
36
|
+
* "hello": "Hallo"
|
|
37
|
+
* }
|
|
38
|
+
* </script>
|
|
39
|
+
* ```
|
|
40
|
+
*
|
|
41
|
+
*
|
|
42
|
+
* ```javascript
|
|
43
|
+
* new Embed('translations')
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
46
|
+
* @param {string} id
|
|
47
|
+
* @param {Object} options
|
|
48
|
+
*/
|
|
49
|
+
constructor(id, options) {
|
|
50
|
+
super(options);
|
|
51
|
+
|
|
52
|
+
if (options === undefined) {
|
|
53
|
+
options = {};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
validateString(id);
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @property {string}
|
|
60
|
+
*/
|
|
61
|
+
this.textId = id;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @private
|
|
65
|
+
* @property {Object} options
|
|
66
|
+
*/
|
|
67
|
+
this[internalSymbol] = extend({}, super.defaults, this.defaults, validateObject(options));
|
|
68
|
+
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Defaults
|
|
73
|
+
*
|
|
74
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API}
|
|
75
|
+
*/
|
|
76
|
+
get defaults() {
|
|
77
|
+
return extend({}, super.defaults);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
*
|
|
82
|
+
* @param {Locale|string} locale
|
|
83
|
+
* @return {Promise}
|
|
84
|
+
*/
|
|
85
|
+
getTranslations(locale) {
|
|
86
|
+
|
|
87
|
+
if (isString(locale)) {
|
|
88
|
+
locale = parseLocale(locale);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return new Promise((resolve, reject) => {
|
|
92
|
+
|
|
93
|
+
let text = getGlobalObject('document').getElementById(this.textId);
|
|
94
|
+
|
|
95
|
+
if (text === null) {
|
|
96
|
+
reject(new Error('Text not found'));
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
let translations = null;
|
|
101
|
+
try {
|
|
102
|
+
translations = JSON.parse(text.innerHTML);
|
|
103
|
+
} catch (e) {
|
|
104
|
+
reject(e);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
if (translations === null) {
|
|
110
|
+
reject(new Error('Translations not found or invalid'));
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const t = new Translations(locale);
|
|
115
|
+
t.assignTranslations(translations)
|
|
116
|
+
|
|
117
|
+
resolve(t);
|
|
118
|
+
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
}
|
|
125
|
+
|
|
@@ -84,16 +84,17 @@ export {Fetch}
|
|
|
84
84
|
*/
|
|
85
85
|
get defaults() {
|
|
86
86
|
|
|
87
|
-
return
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
87
|
+
return extend(
|
|
88
|
+
{
|
|
89
|
+
fetch: {
|
|
90
|
+
method: 'GET', // *GET, POST, PUT, DELETE, etc.
|
|
91
|
+
mode: 'cors', // no-cors, *cors, same-origin
|
|
92
|
+
cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
|
|
93
|
+
credentials: 'omit', // include, *same-origin, omit
|
|
94
|
+
redirect: 'follow', // manual, *follow, error
|
|
95
|
+
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
|
|
96
|
+
}
|
|
97
|
+
}, super.defaults);
|
|
97
98
|
|
|
98
99
|
}
|
|
99
100
|
|
|
@@ -142,13 +142,16 @@ class Translations extends Base {
|
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
/**
|
|
145
|
-
* This method can be used to transfer overlays from an object. The keys are transferred and the values are entered
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
145
|
+
* This method can be used to transfer overlays from an object. The keys are transferred, and the values are entered
|
|
146
|
+
* as text.
|
|
147
|
+
*
|
|
148
|
+
* The values can either be character strings or, in the case of texts with plural forms, objects. The plural forms
|
|
149
|
+
* must be stored as text via a standard key "zero", "one", "two", "few", "many" and "other".
|
|
150
|
+
*
|
|
149
151
|
* Additionally, the key default can be specified, which will be used if no other key fits.
|
|
150
|
-
*
|
|
151
|
-
* In some languages, like for example in
|
|
152
|
+
*
|
|
153
|
+
* In some languages, like for example in German, there is no own more number at the value 0. In these languages,
|
|
154
|
+
* the function applies additionally zero.
|
|
152
155
|
*
|
|
153
156
|
* ```
|
|
154
157
|
* translations.assignTranslations({
|
package/source/types/version.mjs
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import {expect} from "chai"
|
|
4
4
|
|
|
5
|
+
import {Locale} from "../../../../application/source/i18n/locale.mjs";
|
|
5
6
|
import {getLocaleOfDocument} from "../../../../application/source/dom/locale.mjs";
|
|
6
7
|
import {initJSDOM} from "../../util/jsdom.mjs";
|
|
7
8
|
|
|
@@ -32,10 +33,24 @@ describe('Attributes', function () {
|
|
|
32
33
|
node.setAttribute('lang', a);
|
|
33
34
|
expect(getLocaleOfDocument().toString()).to.be.equal(a);
|
|
34
35
|
})
|
|
36
|
+
|
|
37
|
+
|
|
35
38
|
|
|
36
39
|
});
|
|
37
40
|
|
|
38
41
|
|
|
39
42
|
});
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
it('return language en', function () {
|
|
46
|
+
let html = document.getElementsByTagName('html');
|
|
47
|
+
let node = html.item(0);
|
|
48
|
+
|
|
49
|
+
node.removeAttribute('lang');
|
|
50
|
+
const locale = getLocaleOfDocument();
|
|
51
|
+
expect(locale).to.be.instanceOf(Locale);
|
|
52
|
+
expect(locale.localeString).to.be.equal('en-US');
|
|
53
|
+
})
|
|
54
|
+
|
|
40
55
|
|
|
41
56
|
})
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import {expect} from "chai"
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import {Embed} from "../../../../../application/source/i18n/providers/embed.mjs";
|
|
5
|
+
import {Translations} from "../../../../../application/source/i18n/translations.mjs";
|
|
6
|
+
import {getGlobal} from "../../../../../application/source/types/global.mjs";
|
|
7
|
+
import {initJSDOM} from "../../../util/jsdom.mjs";
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
const global = getGlobal();
|
|
11
|
+
|
|
12
|
+
const html1 = `
|
|
13
|
+
<script id="templocale" type="application/json">
|
|
14
|
+
{
|
|
15
|
+
"key": "translation"
|
|
16
|
+
}
|
|
17
|
+
</script>
|
|
18
|
+
`;
|
|
19
|
+
|
|
20
|
+
describe('Translation Provider Embed', function () {
|
|
21
|
+
|
|
22
|
+
before(function (done) {
|
|
23
|
+
initJSDOM().then(() => {
|
|
24
|
+
done()
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
afterEach(() => {
|
|
30
|
+
let mocks = document.getElementById('mocks');
|
|
31
|
+
mocks.innerHTML = "";
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
beforeEach(() => {
|
|
35
|
+
let mocks = document.getElementById('mocks');
|
|
36
|
+
mocks.innerHTML = html1;
|
|
37
|
+
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
describe('get mock data and create translation', function () {
|
|
41
|
+
|
|
42
|
+
it('embed', function (done) {
|
|
43
|
+
|
|
44
|
+
const e = new Embed('templocale');
|
|
45
|
+
let p = e.getTranslations('en');
|
|
46
|
+
expect(p).is.instanceof(Promise);
|
|
47
|
+
|
|
48
|
+
p.then(r => {
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
expect(r).is.instanceof(Translations);
|
|
52
|
+
|
|
53
|
+
let t = r.getText('key')
|
|
54
|
+
expect(t).is.equal('translation');
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
done();
|
|
58
|
+
} catch (e) {
|
|
59
|
+
done(e);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
}).catch(e => {
|
|
64
|
+
done(e);
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
});
|
package/test/cases/monster.mjs
CHANGED