zmdms-utils 0.0.72 → 0.0.74
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/dist/es/crypto.d.ts +3 -0
- package/dist/es/crypto.js +4 -0
- package/dist/es/locales/i18n.d.ts +15 -0
- package/dist/es/locales/t-in-non-react.d.ts +17 -0
- package/dist/es/locales/t-options.d.ts +7 -0
- package/dist/es/locales/use-translation.d.ts +42 -0
- package/dist/es/microAppCreator.d.ts +25 -2
- package/dist/es/microAppCreator.js +28 -6
- package/dist/es/node_modules/html-parse-stringify/dist/html-parse-stringify.module.js +5 -0
- package/dist/es/node_modules/i18next/dist/esm/i18next.js +2242 -0
- package/dist/es/node_modules/js-base64/base64.js +273 -0
- package/dist/es/node_modules/react-i18next/dist/es/Trans.js +47 -0
- package/dist/es/node_modules/react-i18next/dist/es/TransWithoutContext.js +312 -0
- package/dist/es/node_modules/react-i18next/dist/es/context.js +18 -0
- package/dist/es/node_modules/react-i18next/dist/es/defaults.js +21 -0
- package/dist/es/node_modules/react-i18next/dist/es/i18nInstance.js +7 -0
- package/dist/es/node_modules/react-i18next/dist/es/initReactI18next.js +12 -0
- package/dist/es/node_modules/react-i18next/dist/es/unescape.js +27 -0
- package/dist/es/node_modules/react-i18next/dist/es/useTranslation.js +112 -0
- package/dist/es/node_modules/react-i18next/dist/es/utils.js +63 -0
- package/dist/es/node_modules/void-elements/index.js +23 -0
- package/dist/es/request.d.ts +1 -1
- package/dist/es/request.js +4 -3
- package/dist/es/src/locales/i18n.js +16 -0
- package/dist/es/src/locales/t-in-non-react.js +54 -0
- package/dist/es/src/locales/t-options.js +20 -0
- package/dist/es/src/locales/use-translation.js +60 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/package.json +4 -1
- package/src/crypto.ts +6 -0
- package/src/index.ts +4 -1
- package/src/locales/i18n.ts +18 -0
- package/src/locales/index.ts +8 -0
- package/src/locales/t-in-non-react.ts +65 -0
- package/src/locales/t-options.ts +24 -0
- package/src/locales/use-translation.ts +76 -0
- package/src/locales//345/244/232/350/257/255/350/250/200.md +1 -0
- package/src/microAppCreator.ts +47 -8
- package/src/request.ts +5 -4
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* base64.ts
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the BSD 3-Clause License.
|
|
5
|
+
* http://opensource.org/licenses/BSD-3-Clause
|
|
6
|
+
*
|
|
7
|
+
* References:
|
|
8
|
+
* http://en.wikipedia.org/wiki/Base64
|
|
9
|
+
*
|
|
10
|
+
* @author Dan Kogai (https://github.com/dankogai)
|
|
11
|
+
*/
|
|
12
|
+
const version = '3.7.7';
|
|
13
|
+
/**
|
|
14
|
+
* @deprecated use lowercase `version`.
|
|
15
|
+
*/
|
|
16
|
+
const VERSION = version;
|
|
17
|
+
const _hasBuffer = typeof Buffer === 'function';
|
|
18
|
+
const _TD = typeof TextDecoder === 'function' ? new TextDecoder() : undefined;
|
|
19
|
+
const _TE = typeof TextEncoder === 'function' ? new TextEncoder() : undefined;
|
|
20
|
+
const b64ch = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
|
21
|
+
const b64chs = Array.prototype.slice.call(b64ch);
|
|
22
|
+
const b64tab = ((a) => {
|
|
23
|
+
let tab = {};
|
|
24
|
+
a.forEach((c, i) => tab[c] = i);
|
|
25
|
+
return tab;
|
|
26
|
+
})(b64chs);
|
|
27
|
+
const b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/;
|
|
28
|
+
const _fromCC = String.fromCharCode.bind(String);
|
|
29
|
+
const _U8Afrom = typeof Uint8Array.from === 'function'
|
|
30
|
+
? Uint8Array.from.bind(Uint8Array)
|
|
31
|
+
: (it) => new Uint8Array(Array.prototype.slice.call(it, 0));
|
|
32
|
+
const _mkUriSafe = (src) => src
|
|
33
|
+
.replace(/=/g, '').replace(/[+\/]/g, (m0) => m0 == '+' ? '-' : '_');
|
|
34
|
+
const _tidyB64 = (s) => s.replace(/[^A-Za-z0-9\+\/]/g, '');
|
|
35
|
+
/**
|
|
36
|
+
* polyfill version of `btoa`
|
|
37
|
+
*/
|
|
38
|
+
const btoaPolyfill = (bin) => {
|
|
39
|
+
// console.log('polyfilled');
|
|
40
|
+
let u32, c0, c1, c2, asc = '';
|
|
41
|
+
const pad = bin.length % 3;
|
|
42
|
+
for (let i = 0; i < bin.length;) {
|
|
43
|
+
if ((c0 = bin.charCodeAt(i++)) > 255 ||
|
|
44
|
+
(c1 = bin.charCodeAt(i++)) > 255 ||
|
|
45
|
+
(c2 = bin.charCodeAt(i++)) > 255)
|
|
46
|
+
throw new TypeError('invalid character found');
|
|
47
|
+
u32 = (c0 << 16) | (c1 << 8) | c2;
|
|
48
|
+
asc += b64chs[u32 >> 18 & 63]
|
|
49
|
+
+ b64chs[u32 >> 12 & 63]
|
|
50
|
+
+ b64chs[u32 >> 6 & 63]
|
|
51
|
+
+ b64chs[u32 & 63];
|
|
52
|
+
}
|
|
53
|
+
return pad ? asc.slice(0, pad - 3) + "===".substring(pad) : asc;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* does what `window.btoa` of web browsers do.
|
|
57
|
+
* @param {String} bin binary string
|
|
58
|
+
* @returns {string} Base64-encoded string
|
|
59
|
+
*/
|
|
60
|
+
const _btoa = typeof btoa === 'function' ? (bin) => btoa(bin)
|
|
61
|
+
: _hasBuffer ? (bin) => Buffer.from(bin, 'binary').toString('base64')
|
|
62
|
+
: btoaPolyfill;
|
|
63
|
+
const _fromUint8Array = _hasBuffer
|
|
64
|
+
? (u8a) => Buffer.from(u8a).toString('base64')
|
|
65
|
+
: (u8a) => {
|
|
66
|
+
// cf. https://stackoverflow.com/questions/12710001/how-to-convert-uint8-array-to-base64-encoded-string/12713326#12713326
|
|
67
|
+
const maxargs = 0x1000;
|
|
68
|
+
let strs = [];
|
|
69
|
+
for (let i = 0, l = u8a.length; i < l; i += maxargs) {
|
|
70
|
+
strs.push(_fromCC.apply(null, u8a.subarray(i, i + maxargs)));
|
|
71
|
+
}
|
|
72
|
+
return _btoa(strs.join(''));
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* converts a Uint8Array to a Base64 string.
|
|
76
|
+
* @param {boolean} [urlsafe] URL-and-filename-safe a la RFC4648 §5
|
|
77
|
+
* @returns {string} Base64 string
|
|
78
|
+
*/
|
|
79
|
+
const fromUint8Array = (u8a, urlsafe = false) => urlsafe ? _mkUriSafe(_fromUint8Array(u8a)) : _fromUint8Array(u8a);
|
|
80
|
+
// This trick is found broken https://github.com/dankogai/js-base64/issues/130
|
|
81
|
+
// const utob = (src: string) => unescape(encodeURIComponent(src));
|
|
82
|
+
// reverting good old fationed regexp
|
|
83
|
+
const cb_utob = (c) => {
|
|
84
|
+
if (c.length < 2) {
|
|
85
|
+
var cc = c.charCodeAt(0);
|
|
86
|
+
return cc < 0x80 ? c
|
|
87
|
+
: cc < 0x800 ? (_fromCC(0xc0 | (cc >>> 6))
|
|
88
|
+
+ _fromCC(0x80 | (cc & 0x3f)))
|
|
89
|
+
: (_fromCC(0xe0 | ((cc >>> 12) & 0x0f))
|
|
90
|
+
+ _fromCC(0x80 | ((cc >>> 6) & 0x3f))
|
|
91
|
+
+ _fromCC(0x80 | (cc & 0x3f)));
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
var cc = 0x10000
|
|
95
|
+
+ (c.charCodeAt(0) - 0xD800) * 0x400
|
|
96
|
+
+ (c.charCodeAt(1) - 0xDC00);
|
|
97
|
+
return (_fromCC(0xf0 | ((cc >>> 18) & 0x07))
|
|
98
|
+
+ _fromCC(0x80 | ((cc >>> 12) & 0x3f))
|
|
99
|
+
+ _fromCC(0x80 | ((cc >>> 6) & 0x3f))
|
|
100
|
+
+ _fromCC(0x80 | (cc & 0x3f)));
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
const re_utob = /[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g;
|
|
104
|
+
/**
|
|
105
|
+
* @deprecated should have been internal use only.
|
|
106
|
+
* @param {string} src UTF-8 string
|
|
107
|
+
* @returns {string} UTF-16 string
|
|
108
|
+
*/
|
|
109
|
+
const utob = (u) => u.replace(re_utob, cb_utob);
|
|
110
|
+
//
|
|
111
|
+
const _encode = _hasBuffer
|
|
112
|
+
? (s) => Buffer.from(s, 'utf8').toString('base64')
|
|
113
|
+
: _TE
|
|
114
|
+
? (s) => _fromUint8Array(_TE.encode(s))
|
|
115
|
+
: (s) => _btoa(utob(s));
|
|
116
|
+
/**
|
|
117
|
+
* converts a UTF-8-encoded string to a Base64 string.
|
|
118
|
+
* @param {boolean} [urlsafe] if `true` make the result URL-safe
|
|
119
|
+
* @returns {string} Base64 string
|
|
120
|
+
*/
|
|
121
|
+
const encode = (src, urlsafe = false) => urlsafe
|
|
122
|
+
? _mkUriSafe(_encode(src))
|
|
123
|
+
: _encode(src);
|
|
124
|
+
/**
|
|
125
|
+
* converts a UTF-8-encoded string to URL-safe Base64 RFC4648 §5.
|
|
126
|
+
* @returns {string} Base64 string
|
|
127
|
+
*/
|
|
128
|
+
const encodeURI = (src) => encode(src, true);
|
|
129
|
+
// This trick is found broken https://github.com/dankogai/js-base64/issues/130
|
|
130
|
+
// const btou = (src: string) => decodeURIComponent(escape(src));
|
|
131
|
+
// reverting good old fationed regexp
|
|
132
|
+
const re_btou = /[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g;
|
|
133
|
+
const cb_btou = (cccc) => {
|
|
134
|
+
switch (cccc.length) {
|
|
135
|
+
case 4:
|
|
136
|
+
var cp = ((0x07 & cccc.charCodeAt(0)) << 18)
|
|
137
|
+
| ((0x3f & cccc.charCodeAt(1)) << 12)
|
|
138
|
+
| ((0x3f & cccc.charCodeAt(2)) << 6)
|
|
139
|
+
| (0x3f & cccc.charCodeAt(3)), offset = cp - 0x10000;
|
|
140
|
+
return (_fromCC((offset >>> 10) + 0xD800)
|
|
141
|
+
+ _fromCC((offset & 0x3FF) + 0xDC00));
|
|
142
|
+
case 3:
|
|
143
|
+
return _fromCC(((0x0f & cccc.charCodeAt(0)) << 12)
|
|
144
|
+
| ((0x3f & cccc.charCodeAt(1)) << 6)
|
|
145
|
+
| (0x3f & cccc.charCodeAt(2)));
|
|
146
|
+
default:
|
|
147
|
+
return _fromCC(((0x1f & cccc.charCodeAt(0)) << 6)
|
|
148
|
+
| (0x3f & cccc.charCodeAt(1)));
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
/**
|
|
152
|
+
* @deprecated should have been internal use only.
|
|
153
|
+
* @param {string} src UTF-16 string
|
|
154
|
+
* @returns {string} UTF-8 string
|
|
155
|
+
*/
|
|
156
|
+
const btou = (b) => b.replace(re_btou, cb_btou);
|
|
157
|
+
/**
|
|
158
|
+
* polyfill version of `atob`
|
|
159
|
+
*/
|
|
160
|
+
const atobPolyfill = (asc) => {
|
|
161
|
+
// console.log('polyfilled');
|
|
162
|
+
asc = asc.replace(/\s+/g, '');
|
|
163
|
+
if (!b64re.test(asc))
|
|
164
|
+
throw new TypeError('malformed base64.');
|
|
165
|
+
asc += '=='.slice(2 - (asc.length & 3));
|
|
166
|
+
let u24, bin = '', r1, r2;
|
|
167
|
+
for (let i = 0; i < asc.length;) {
|
|
168
|
+
u24 = b64tab[asc.charAt(i++)] << 18
|
|
169
|
+
| b64tab[asc.charAt(i++)] << 12
|
|
170
|
+
| (r1 = b64tab[asc.charAt(i++)]) << 6
|
|
171
|
+
| (r2 = b64tab[asc.charAt(i++)]);
|
|
172
|
+
bin += r1 === 64 ? _fromCC(u24 >> 16 & 255)
|
|
173
|
+
: r2 === 64 ? _fromCC(u24 >> 16 & 255, u24 >> 8 & 255)
|
|
174
|
+
: _fromCC(u24 >> 16 & 255, u24 >> 8 & 255, u24 & 255);
|
|
175
|
+
}
|
|
176
|
+
return bin;
|
|
177
|
+
};
|
|
178
|
+
/**
|
|
179
|
+
* does what `window.atob` of web browsers do.
|
|
180
|
+
* @param {String} asc Base64-encoded string
|
|
181
|
+
* @returns {string} binary string
|
|
182
|
+
*/
|
|
183
|
+
const _atob = typeof atob === 'function' ? (asc) => atob(_tidyB64(asc))
|
|
184
|
+
: _hasBuffer ? (asc) => Buffer.from(asc, 'base64').toString('binary')
|
|
185
|
+
: atobPolyfill;
|
|
186
|
+
//
|
|
187
|
+
const _toUint8Array = _hasBuffer
|
|
188
|
+
? (a) => _U8Afrom(Buffer.from(a, 'base64'))
|
|
189
|
+
: (a) => _U8Afrom(_atob(a).split('').map(c => c.charCodeAt(0)));
|
|
190
|
+
/**
|
|
191
|
+
* converts a Base64 string to a Uint8Array.
|
|
192
|
+
*/
|
|
193
|
+
const toUint8Array = (a) => _toUint8Array(_unURI(a));
|
|
194
|
+
//
|
|
195
|
+
const _decode = _hasBuffer
|
|
196
|
+
? (a) => Buffer.from(a, 'base64').toString('utf8')
|
|
197
|
+
: _TD
|
|
198
|
+
? (a) => _TD.decode(_toUint8Array(a))
|
|
199
|
+
: (a) => btou(_atob(a));
|
|
200
|
+
const _unURI = (a) => _tidyB64(a.replace(/[-_]/g, (m0) => m0 == '-' ? '+' : '/'));
|
|
201
|
+
/**
|
|
202
|
+
* converts a Base64 string to a UTF-8 string.
|
|
203
|
+
* @param {String} src Base64 string. Both normal and URL-safe are supported
|
|
204
|
+
* @returns {string} UTF-8 string
|
|
205
|
+
*/
|
|
206
|
+
const decode = (src) => _decode(_unURI(src));
|
|
207
|
+
/**
|
|
208
|
+
* check if a value is a valid Base64 string
|
|
209
|
+
* @param {String} src a value to check
|
|
210
|
+
*/
|
|
211
|
+
const isValid = (src) => {
|
|
212
|
+
if (typeof src !== 'string')
|
|
213
|
+
return false;
|
|
214
|
+
const s = src.replace(/\s+/g, '').replace(/={0,2}$/, '');
|
|
215
|
+
return !/[^\s0-9a-zA-Z\+/]/.test(s) || !/[^\s0-9a-zA-Z\-_]/.test(s);
|
|
216
|
+
};
|
|
217
|
+
//
|
|
218
|
+
const _noEnum = (v) => {
|
|
219
|
+
return {
|
|
220
|
+
value: v, enumerable: false, writable: true, configurable: true
|
|
221
|
+
};
|
|
222
|
+
};
|
|
223
|
+
/**
|
|
224
|
+
* extend String.prototype with relevant methods
|
|
225
|
+
*/
|
|
226
|
+
const extendString = function () {
|
|
227
|
+
const _add = (name, body) => Object.defineProperty(String.prototype, name, _noEnum(body));
|
|
228
|
+
_add('fromBase64', function () { return decode(this); });
|
|
229
|
+
_add('toBase64', function (urlsafe) { return encode(this, urlsafe); });
|
|
230
|
+
_add('toBase64URI', function () { return encode(this, true); });
|
|
231
|
+
_add('toBase64URL', function () { return encode(this, true); });
|
|
232
|
+
_add('toUint8Array', function () { return toUint8Array(this); });
|
|
233
|
+
};
|
|
234
|
+
/**
|
|
235
|
+
* extend Uint8Array.prototype with relevant methods
|
|
236
|
+
*/
|
|
237
|
+
const extendUint8Array = function () {
|
|
238
|
+
const _add = (name, body) => Object.defineProperty(Uint8Array.prototype, name, _noEnum(body));
|
|
239
|
+
_add('toBase64', function (urlsafe) { return fromUint8Array(this, urlsafe); });
|
|
240
|
+
_add('toBase64URI', function () { return fromUint8Array(this, true); });
|
|
241
|
+
_add('toBase64URL', function () { return fromUint8Array(this, true); });
|
|
242
|
+
};
|
|
243
|
+
/**
|
|
244
|
+
* extend Builtin prototypes with relevant methods
|
|
245
|
+
*/
|
|
246
|
+
const extendBuiltins = () => {
|
|
247
|
+
extendString();
|
|
248
|
+
extendUint8Array();
|
|
249
|
+
};
|
|
250
|
+
const gBase64 = {
|
|
251
|
+
version: version,
|
|
252
|
+
VERSION: VERSION,
|
|
253
|
+
atob: _atob,
|
|
254
|
+
atobPolyfill: atobPolyfill,
|
|
255
|
+
btoa: _btoa,
|
|
256
|
+
btoaPolyfill: btoaPolyfill,
|
|
257
|
+
fromBase64: decode,
|
|
258
|
+
toBase64: encode,
|
|
259
|
+
encode: encode,
|
|
260
|
+
encodeURI: encodeURI,
|
|
261
|
+
encodeURL: encodeURI,
|
|
262
|
+
utob: utob,
|
|
263
|
+
btou: btou,
|
|
264
|
+
decode: decode,
|
|
265
|
+
isValid: isValid,
|
|
266
|
+
fromUint8Array: fromUint8Array,
|
|
267
|
+
toUint8Array: toUint8Array,
|
|
268
|
+
extendString: extendString,
|
|
269
|
+
extendUint8Array: extendUint8Array,
|
|
270
|
+
extendBuiltins: extendBuiltins
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
export { gBase64 as Base64, VERSION, _atob as atob, atobPolyfill, _btoa as btoa, btoaPolyfill, btou, decode, encode, encodeURI, encodeURI as encodeURL, extendBuiltins, extendString, extendUint8Array, decode as fromBase64, fromUint8Array, isValid, encode as toBase64, toUint8Array, utob, version };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useContext } from 'react';
|
|
2
|
+
import { Trans as Trans$1 } from './TransWithoutContext.js';
|
|
3
|
+
export { nodesToString } from './TransWithoutContext.js';
|
|
4
|
+
import { I18nContext } from './context.js';
|
|
5
|
+
import { getI18n } from './i18nInstance.js';
|
|
6
|
+
|
|
7
|
+
function Trans({
|
|
8
|
+
children,
|
|
9
|
+
count,
|
|
10
|
+
parent,
|
|
11
|
+
i18nKey,
|
|
12
|
+
context,
|
|
13
|
+
tOptions = {},
|
|
14
|
+
values,
|
|
15
|
+
defaults,
|
|
16
|
+
components,
|
|
17
|
+
ns,
|
|
18
|
+
i18n: i18nFromProps,
|
|
19
|
+
t: tFromProps,
|
|
20
|
+
shouldUnescape,
|
|
21
|
+
...additionalProps
|
|
22
|
+
}) {
|
|
23
|
+
const {
|
|
24
|
+
i18n: i18nFromContext,
|
|
25
|
+
defaultNS: defaultNSFromContext
|
|
26
|
+
} = useContext(I18nContext) || {};
|
|
27
|
+
const i18n = i18nFromProps || i18nFromContext || getI18n();
|
|
28
|
+
const t = tFromProps || i18n?.t.bind(i18n);
|
|
29
|
+
return Trans$1({
|
|
30
|
+
children,
|
|
31
|
+
count,
|
|
32
|
+
parent,
|
|
33
|
+
i18nKey,
|
|
34
|
+
context,
|
|
35
|
+
tOptions,
|
|
36
|
+
values,
|
|
37
|
+
defaults,
|
|
38
|
+
components,
|
|
39
|
+
ns: ns || t?.ns || defaultNSFromContext || i18n?.options?.defaultNS,
|
|
40
|
+
i18n,
|
|
41
|
+
t: tFromProps,
|
|
42
|
+
shouldUnescape,
|
|
43
|
+
...additionalProps
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export { Trans };
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
import { createElement, isValidElement, cloneElement, Children, Fragment } from 'react';
|
|
2
|
+
import c from '../../../html-parse-stringify/dist/html-parse-stringify.module.js';
|
|
3
|
+
import { warnOnce, isString, warn, isObject } from './utils.js';
|
|
4
|
+
import { getDefaults } from './defaults.js';
|
|
5
|
+
import { getI18n } from './i18nInstance.js';
|
|
6
|
+
|
|
7
|
+
const hasChildren = (node, checkLength) => {
|
|
8
|
+
if (!node) return false;
|
|
9
|
+
const base = node.props?.children ?? node.children;
|
|
10
|
+
if (checkLength) return base.length > 0;
|
|
11
|
+
return !!base;
|
|
12
|
+
};
|
|
13
|
+
const getChildren = node => {
|
|
14
|
+
if (!node) return [];
|
|
15
|
+
const children = node.props?.children ?? node.children;
|
|
16
|
+
return node.props?.i18nIsDynamicList ? getAsArray(children) : children;
|
|
17
|
+
};
|
|
18
|
+
const hasValidReactChildren = children => Array.isArray(children) && children.every(isValidElement);
|
|
19
|
+
const getAsArray = data => Array.isArray(data) ? data : [data];
|
|
20
|
+
const mergeProps = (source, target) => {
|
|
21
|
+
const newTarget = {
|
|
22
|
+
...target
|
|
23
|
+
};
|
|
24
|
+
newTarget.props = Object.assign(source.props, target.props);
|
|
25
|
+
return newTarget;
|
|
26
|
+
};
|
|
27
|
+
const nodesToString = (children, i18nOptions, i18n, i18nKey) => {
|
|
28
|
+
if (!children) return '';
|
|
29
|
+
let stringNode = '';
|
|
30
|
+
const childrenArray = getAsArray(children);
|
|
31
|
+
const keepArray = i18nOptions?.transSupportBasicHtmlNodes ? i18nOptions.transKeepBasicHtmlNodesFor ?? [] : [];
|
|
32
|
+
childrenArray.forEach((child, childIndex) => {
|
|
33
|
+
if (isString(child)) {
|
|
34
|
+
stringNode += `${child}`;
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (isValidElement(child)) {
|
|
38
|
+
const {
|
|
39
|
+
props,
|
|
40
|
+
type
|
|
41
|
+
} = child;
|
|
42
|
+
const childPropsCount = Object.keys(props).length;
|
|
43
|
+
const shouldKeepChild = keepArray.indexOf(type) > -1;
|
|
44
|
+
const childChildren = props.children;
|
|
45
|
+
if (!childChildren && shouldKeepChild && !childPropsCount) {
|
|
46
|
+
stringNode += `<${type}/>`;
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (!childChildren && (!shouldKeepChild || childPropsCount) || props.i18nIsDynamicList) {
|
|
50
|
+
stringNode += `<${childIndex}></${childIndex}>`;
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (shouldKeepChild && childPropsCount === 1 && isString(childChildren)) {
|
|
54
|
+
stringNode += `<${type}>${childChildren}</${type}>`;
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const content = nodesToString(childChildren, i18nOptions, i18n, i18nKey);
|
|
58
|
+
stringNode += `<${childIndex}>${content}</${childIndex}>`;
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (child === null) {
|
|
62
|
+
warn(i18n, 'TRANS_NULL_VALUE', `Passed in a null value as child`, {
|
|
63
|
+
i18nKey
|
|
64
|
+
});
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (isObject(child)) {
|
|
68
|
+
const {
|
|
69
|
+
format,
|
|
70
|
+
...clone
|
|
71
|
+
} = child;
|
|
72
|
+
const keys = Object.keys(clone);
|
|
73
|
+
if (keys.length === 1) {
|
|
74
|
+
const value = format ? `${keys[0]}, ${format}` : keys[0];
|
|
75
|
+
stringNode += `{{${value}}}`;
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
warn(i18n, 'TRANS_INVALID_OBJ', `Invalid child - Object should only have keys {{ value, format }} (format is optional).`, {
|
|
79
|
+
i18nKey,
|
|
80
|
+
child
|
|
81
|
+
});
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
warn(i18n, 'TRANS_INVALID_VAR', `Passed in a variable like {number} - pass variables for interpolation as full objects like {{number}}.`, {
|
|
85
|
+
i18nKey,
|
|
86
|
+
child
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
return stringNode;
|
|
90
|
+
};
|
|
91
|
+
const renderNodes = (children, targetString, i18n, i18nOptions, combinedTOpts, shouldUnescape) => {
|
|
92
|
+
if (targetString === '') return [];
|
|
93
|
+
const keepArray = i18nOptions.transKeepBasicHtmlNodesFor || [];
|
|
94
|
+
const emptyChildrenButNeedsHandling = targetString && new RegExp(keepArray.map(keep => `<${keep}`).join('|')).test(targetString);
|
|
95
|
+
if (!children && !emptyChildrenButNeedsHandling && !shouldUnescape) return [targetString];
|
|
96
|
+
const data = {};
|
|
97
|
+
const getData = childs => {
|
|
98
|
+
const childrenArray = getAsArray(childs);
|
|
99
|
+
childrenArray.forEach(child => {
|
|
100
|
+
if (isString(child)) return;
|
|
101
|
+
if (hasChildren(child)) getData(getChildren(child));else if (isObject(child) && !isValidElement(child)) Object.assign(data, child);
|
|
102
|
+
});
|
|
103
|
+
};
|
|
104
|
+
getData(children);
|
|
105
|
+
const ast = c.parse(`<0>${targetString}</0>`);
|
|
106
|
+
const opts = {
|
|
107
|
+
...data,
|
|
108
|
+
...combinedTOpts
|
|
109
|
+
};
|
|
110
|
+
const renderInner = (child, node, rootReactNode) => {
|
|
111
|
+
const childs = getChildren(child);
|
|
112
|
+
const mappedChildren = mapAST(childs, node.children, rootReactNode);
|
|
113
|
+
return hasValidReactChildren(childs) && mappedChildren.length === 0 || child.props?.i18nIsDynamicList ? childs : mappedChildren;
|
|
114
|
+
};
|
|
115
|
+
const pushTranslatedJSX = (child, inner, mem, i, isVoid) => {
|
|
116
|
+
if (child.dummy) {
|
|
117
|
+
child.children = inner;
|
|
118
|
+
mem.push(cloneElement(child, {
|
|
119
|
+
key: i
|
|
120
|
+
}, isVoid ? undefined : inner));
|
|
121
|
+
} else {
|
|
122
|
+
mem.push(...Children.map([child], c => {
|
|
123
|
+
const props = {
|
|
124
|
+
...c.props
|
|
125
|
+
};
|
|
126
|
+
delete props.i18nIsDynamicList;
|
|
127
|
+
return createElement(c.type, {
|
|
128
|
+
...props,
|
|
129
|
+
key: i,
|
|
130
|
+
ref: c.ref
|
|
131
|
+
}, isVoid ? null : inner);
|
|
132
|
+
}));
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
const mapAST = (reactNode, astNode, rootReactNode) => {
|
|
136
|
+
const reactNodes = getAsArray(reactNode);
|
|
137
|
+
const astNodes = getAsArray(astNode);
|
|
138
|
+
return astNodes.reduce((mem, node, i) => {
|
|
139
|
+
const translationContent = node.children?.[0]?.content && i18n.services.interpolator.interpolate(node.children[0].content, opts, i18n.language);
|
|
140
|
+
if (node.type === 'tag') {
|
|
141
|
+
let tmp = reactNodes[parseInt(node.name, 10)];
|
|
142
|
+
if (rootReactNode.length === 1 && !tmp) tmp = rootReactNode[0][node.name];
|
|
143
|
+
if (!tmp) tmp = {};
|
|
144
|
+
const child = Object.keys(node.attrs).length !== 0 ? mergeProps({
|
|
145
|
+
props: node.attrs
|
|
146
|
+
}, tmp) : tmp;
|
|
147
|
+
const isElement = isValidElement(child);
|
|
148
|
+
const isValidTranslationWithChildren = isElement && hasChildren(node, true) && !node.voidElement;
|
|
149
|
+
const isEmptyTransWithHTML = emptyChildrenButNeedsHandling && isObject(child) && child.dummy && !isElement;
|
|
150
|
+
const isKnownComponent = isObject(children) && Object.hasOwnProperty.call(children, node.name);
|
|
151
|
+
if (isString(child)) {
|
|
152
|
+
const value = i18n.services.interpolator.interpolate(child, opts, i18n.language);
|
|
153
|
+
mem.push(value);
|
|
154
|
+
} else if (hasChildren(child) || isValidTranslationWithChildren) {
|
|
155
|
+
const inner = renderInner(child, node, rootReactNode);
|
|
156
|
+
pushTranslatedJSX(child, inner, mem, i);
|
|
157
|
+
} else if (isEmptyTransWithHTML) {
|
|
158
|
+
const inner = mapAST(reactNodes, node.children, rootReactNode);
|
|
159
|
+
pushTranslatedJSX(child, inner, mem, i);
|
|
160
|
+
} else if (Number.isNaN(parseFloat(node.name))) {
|
|
161
|
+
if (isKnownComponent) {
|
|
162
|
+
const inner = renderInner(child, node, rootReactNode);
|
|
163
|
+
pushTranslatedJSX(child, inner, mem, i, node.voidElement);
|
|
164
|
+
} else if (i18nOptions.transSupportBasicHtmlNodes && keepArray.indexOf(node.name) > -1) {
|
|
165
|
+
if (node.voidElement) {
|
|
166
|
+
mem.push(createElement(node.name, {
|
|
167
|
+
key: `${node.name}-${i}`
|
|
168
|
+
}));
|
|
169
|
+
} else {
|
|
170
|
+
const inner = mapAST(reactNodes, node.children, rootReactNode);
|
|
171
|
+
mem.push(createElement(node.name, {
|
|
172
|
+
key: `${node.name}-${i}`
|
|
173
|
+
}, inner));
|
|
174
|
+
}
|
|
175
|
+
} else if (node.voidElement) {
|
|
176
|
+
mem.push(`<${node.name} />`);
|
|
177
|
+
} else {
|
|
178
|
+
const inner = mapAST(reactNodes, node.children, rootReactNode);
|
|
179
|
+
mem.push(`<${node.name}>${inner}</${node.name}>`);
|
|
180
|
+
}
|
|
181
|
+
} else if (isObject(child) && !isElement) {
|
|
182
|
+
const content = node.children[0] ? translationContent : null;
|
|
183
|
+
if (content) mem.push(content);
|
|
184
|
+
} else {
|
|
185
|
+
pushTranslatedJSX(child, translationContent, mem, i, node.children.length !== 1 || !translationContent);
|
|
186
|
+
}
|
|
187
|
+
} else if (node.type === 'text') {
|
|
188
|
+
const wrapTextNodes = i18nOptions.transWrapTextNodes;
|
|
189
|
+
const content = shouldUnescape ? i18nOptions.unescape(i18n.services.interpolator.interpolate(node.content, opts, i18n.language)) : i18n.services.interpolator.interpolate(node.content, opts, i18n.language);
|
|
190
|
+
if (wrapTextNodes) {
|
|
191
|
+
mem.push(createElement(wrapTextNodes, {
|
|
192
|
+
key: `${node.name}-${i}`
|
|
193
|
+
}, content));
|
|
194
|
+
} else {
|
|
195
|
+
mem.push(content);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return mem;
|
|
199
|
+
}, []);
|
|
200
|
+
};
|
|
201
|
+
const result = mapAST([{
|
|
202
|
+
dummy: true,
|
|
203
|
+
children: children || []
|
|
204
|
+
}], ast, getAsArray(children || []));
|
|
205
|
+
return getChildren(result[0]);
|
|
206
|
+
};
|
|
207
|
+
const fixComponentProps = (component, index, translation) => {
|
|
208
|
+
const componentKey = component.key || index;
|
|
209
|
+
const comp = cloneElement(component, {
|
|
210
|
+
key: componentKey
|
|
211
|
+
});
|
|
212
|
+
if (!comp.props || !comp.props.children || translation.indexOf(`${index}/>`) < 0 && translation.indexOf(`${index} />`) < 0) {
|
|
213
|
+
return comp;
|
|
214
|
+
}
|
|
215
|
+
function Componentized() {
|
|
216
|
+
return createElement(Fragment, null, comp);
|
|
217
|
+
}
|
|
218
|
+
return createElement(Componentized, {
|
|
219
|
+
key: componentKey
|
|
220
|
+
});
|
|
221
|
+
};
|
|
222
|
+
const generateArrayComponents = (components, translation) => components.map((c, index) => fixComponentProps(c, index, translation));
|
|
223
|
+
const generateObjectComponents = (components, translation) => {
|
|
224
|
+
const componentMap = {};
|
|
225
|
+
Object.keys(components).forEach(c => {
|
|
226
|
+
Object.assign(componentMap, {
|
|
227
|
+
[c]: fixComponentProps(components[c], c, translation)
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
return componentMap;
|
|
231
|
+
};
|
|
232
|
+
const generateComponents = (components, translation, i18n, i18nKey) => {
|
|
233
|
+
if (!components) return null;
|
|
234
|
+
if (Array.isArray(components)) {
|
|
235
|
+
return generateArrayComponents(components, translation);
|
|
236
|
+
}
|
|
237
|
+
if (isObject(components)) {
|
|
238
|
+
return generateObjectComponents(components, translation);
|
|
239
|
+
}
|
|
240
|
+
warnOnce(i18n, 'TRANS_INVALID_COMPONENTS', `<Trans /> "components" prop expects an object or array`, {
|
|
241
|
+
i18nKey
|
|
242
|
+
});
|
|
243
|
+
return null;
|
|
244
|
+
};
|
|
245
|
+
function Trans({
|
|
246
|
+
children,
|
|
247
|
+
count,
|
|
248
|
+
parent,
|
|
249
|
+
i18nKey,
|
|
250
|
+
context,
|
|
251
|
+
tOptions = {},
|
|
252
|
+
values,
|
|
253
|
+
defaults,
|
|
254
|
+
components,
|
|
255
|
+
ns,
|
|
256
|
+
i18n: i18nFromProps,
|
|
257
|
+
t: tFromProps,
|
|
258
|
+
shouldUnescape,
|
|
259
|
+
...additionalProps
|
|
260
|
+
}) {
|
|
261
|
+
const i18n = i18nFromProps || getI18n();
|
|
262
|
+
if (!i18n) {
|
|
263
|
+
warnOnce(i18n, 'NO_I18NEXT_INSTANCE', `Trans: You need to pass in an i18next instance using i18nextReactModule`, {
|
|
264
|
+
i18nKey
|
|
265
|
+
});
|
|
266
|
+
return children;
|
|
267
|
+
}
|
|
268
|
+
const t = tFromProps || i18n.t.bind(i18n) || (k => k);
|
|
269
|
+
const reactI18nextOptions = {
|
|
270
|
+
...getDefaults(),
|
|
271
|
+
...i18n.options?.react
|
|
272
|
+
};
|
|
273
|
+
let namespaces = ns || t.ns || i18n.options?.defaultNS;
|
|
274
|
+
namespaces = isString(namespaces) ? [namespaces] : namespaces || ['translation'];
|
|
275
|
+
const nodeAsString = nodesToString(children, reactI18nextOptions, i18n, i18nKey);
|
|
276
|
+
const defaultValue = defaults || nodeAsString || reactI18nextOptions.transEmptyNodeValue || i18nKey;
|
|
277
|
+
const {
|
|
278
|
+
hashTransKey
|
|
279
|
+
} = reactI18nextOptions;
|
|
280
|
+
const key = i18nKey || (hashTransKey ? hashTransKey(nodeAsString || defaultValue) : nodeAsString || defaultValue);
|
|
281
|
+
if (i18n.options?.interpolation?.defaultVariables) {
|
|
282
|
+
values = values && Object.keys(values).length > 0 ? {
|
|
283
|
+
...values,
|
|
284
|
+
...i18n.options.interpolation.defaultVariables
|
|
285
|
+
} : {
|
|
286
|
+
...i18n.options.interpolation.defaultVariables
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
const interpolationOverride = values || count !== undefined && !i18n.options?.interpolation?.alwaysFormat || !children ? tOptions.interpolation : {
|
|
290
|
+
interpolation: {
|
|
291
|
+
...tOptions.interpolation,
|
|
292
|
+
prefix: '#$?',
|
|
293
|
+
suffix: '?$#'
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
const combinedTOpts = {
|
|
297
|
+
...tOptions,
|
|
298
|
+
context: context || tOptions.context,
|
|
299
|
+
count,
|
|
300
|
+
...values,
|
|
301
|
+
...interpolationOverride,
|
|
302
|
+
defaultValue,
|
|
303
|
+
ns: namespaces
|
|
304
|
+
};
|
|
305
|
+
const translation = key ? t(key, combinedTOpts) : defaultValue;
|
|
306
|
+
const generatedComponents = generateComponents(components, translation, i18n, i18nKey);
|
|
307
|
+
const content = renderNodes(generatedComponents || children, translation, i18n, reactI18nextOptions, combinedTOpts, shouldUnescape);
|
|
308
|
+
const useAsParent = parent ?? reactI18nextOptions.defaultTransParent;
|
|
309
|
+
return useAsParent ? createElement(useAsParent, additionalProps, content) : content;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
export { Trans, nodesToString };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { createContext } from 'react';
|
|
2
|
+
|
|
3
|
+
const I18nContext = createContext();
|
|
4
|
+
class ReportNamespaces {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.usedNamespaces = {};
|
|
7
|
+
}
|
|
8
|
+
addUsedNamespaces(namespaces) {
|
|
9
|
+
namespaces.forEach(ns => {
|
|
10
|
+
if (!this.usedNamespaces[ns]) this.usedNamespaces[ns] = true;
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
getUsedNamespaces() {
|
|
14
|
+
return Object.keys(this.usedNamespaces);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { I18nContext, ReportNamespaces };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { unescape } from './unescape.js';
|
|
2
|
+
|
|
3
|
+
let defaultOptions = {
|
|
4
|
+
bindI18n: 'languageChanged',
|
|
5
|
+
bindI18nStore: '',
|
|
6
|
+
transEmptyNodeValue: '',
|
|
7
|
+
transSupportBasicHtmlNodes: true,
|
|
8
|
+
transWrapTextNodes: '',
|
|
9
|
+
transKeepBasicHtmlNodesFor: ['br', 'strong', 'i', 'p'],
|
|
10
|
+
useSuspense: true,
|
|
11
|
+
unescape
|
|
12
|
+
};
|
|
13
|
+
const setDefaults = (options = {}) => {
|
|
14
|
+
defaultOptions = {
|
|
15
|
+
...defaultOptions,
|
|
16
|
+
...options
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
const getDefaults = () => defaultOptions;
|
|
20
|
+
|
|
21
|
+
export { getDefaults, setDefaults };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { setDefaults } from './defaults.js';
|
|
2
|
+
import { setI18n } from './i18nInstance.js';
|
|
3
|
+
|
|
4
|
+
const initReactI18next = {
|
|
5
|
+
type: '3rdParty',
|
|
6
|
+
init(instance) {
|
|
7
|
+
setDefaults(instance.options.react);
|
|
8
|
+
setI18n(instance);
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export { initReactI18next };
|