i18next-http-middleware 3.9.11 → 3.10.1
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/cjs/index.js +9 -8
- package/cjs/utils.js +1 -2
- package/esm/index.js +9 -8
- package/esm/utils.js +1 -2
- package/lib/index.js +17 -15
- package/lib/utils.js +8 -6
- package/package.json +1 -1
package/cjs/index.js
CHANGED
|
@@ -132,7 +132,7 @@ function handle(i18next) {
|
|
|
132
132
|
i18next.services.languageDetector.cacheUserLanguage(req, res, lng);
|
|
133
133
|
}
|
|
134
134
|
if (!req.lng) return next();
|
|
135
|
-
|
|
135
|
+
i18n.loadLanguages(req.lng, function () {
|
|
136
136
|
return next();
|
|
137
137
|
});
|
|
138
138
|
};
|
|
@@ -253,17 +253,16 @@ function getResourcesHandler(i18next) {
|
|
|
253
253
|
}
|
|
254
254
|
languages = languages.filter(utils.isSafeLangIdentifier);
|
|
255
255
|
namespaces = namespaces.filter(utils.isSafeNsIdentifier);
|
|
256
|
-
namespaces.forEach(function (ns) {
|
|
257
|
-
if (i18next.options.ns && i18next.options.ns.indexOf(ns) < 0) {
|
|
258
|
-
i18next.options.ns.push(ns);
|
|
259
|
-
}
|
|
260
|
-
});
|
|
261
256
|
var loaded = false;
|
|
262
257
|
var onLoaded;
|
|
263
258
|
i18next.services.backendConnector.load(languages, namespaces, function () {
|
|
264
259
|
languages.forEach(function (lng) {
|
|
265
260
|
namespaces.forEach(function (ns) {
|
|
266
|
-
|
|
261
|
+
var bundle = i18next.getResourceBundle(lng, ns);
|
|
262
|
+
if (bundle && i18next.options.ns && i18next.options.ns.indexOf(ns) < 0) {
|
|
263
|
+
i18next.options.ns.push(ns);
|
|
264
|
+
}
|
|
265
|
+
utils.setPath(resources, [lng, ns], bundle);
|
|
267
266
|
});
|
|
268
267
|
});
|
|
269
268
|
loaded = true;
|
|
@@ -300,12 +299,14 @@ function missingKeyHandler(i18next) {
|
|
|
300
299
|
}
|
|
301
300
|
var body = options.getBody(req);
|
|
302
301
|
var keySeparator = i18next.options && i18next.options.keySeparator;
|
|
302
|
+
var utilsOfRequest = req.i18n && req.i18n.services && req.i18n.services.utils;
|
|
303
|
+
var hasLoadedNamespace = utilsOfRequest && utilsOfRequest.hasLoadedNamespace;
|
|
303
304
|
var saveMissingKeys = function saveMissingKeys(src) {
|
|
304
305
|
if (!src || _typeof(src) !== 'object') return;
|
|
305
306
|
for (var _i = 0, _Object$keys = Object.keys(src); _i < _Object$keys.length; _i++) {
|
|
306
307
|
var m = _Object$keys[_i];
|
|
307
308
|
if (utils.hasUnsafeKeySegment(m, keySeparator)) continue;
|
|
308
|
-
i18next.services.backendConnector.saveMissing([lng], ns, m, src[m]);
|
|
309
|
+
i18next.services.backendConnector.saveMissing([lng], ns, m, src[m], undefined, undefined, undefined, hasLoadedNamespace);
|
|
309
310
|
}
|
|
310
311
|
};
|
|
311
312
|
if (typeof body === 'function') {
|
package/cjs/utils.js
CHANGED
|
@@ -30,8 +30,7 @@ function isSafeIdentifierBase(v) {
|
|
|
30
30
|
}
|
|
31
31
|
function isSafeLangIdentifier(v) {
|
|
32
32
|
if (!isSafeIdentifierBase(v)) return false;
|
|
33
|
-
|
|
34
|
-
return true;
|
|
33
|
+
return /^[A-Za-z0-9_@.-]+$/.test(v);
|
|
35
34
|
}
|
|
36
35
|
function isSafeNsIdentifier(v) {
|
|
37
36
|
return isSafeIdentifierBase(v);
|
package/esm/index.js
CHANGED
|
@@ -115,7 +115,7 @@ export function handle(i18next) {
|
|
|
115
115
|
i18next.services.languageDetector.cacheUserLanguage(req, res, lng);
|
|
116
116
|
}
|
|
117
117
|
if (!req.lng) return next();
|
|
118
|
-
|
|
118
|
+
i18n.loadLanguages(req.lng, function () {
|
|
119
119
|
return next();
|
|
120
120
|
});
|
|
121
121
|
};
|
|
@@ -236,17 +236,16 @@ export function getResourcesHandler(i18next) {
|
|
|
236
236
|
}
|
|
237
237
|
languages = languages.filter(utils.isSafeLangIdentifier);
|
|
238
238
|
namespaces = namespaces.filter(utils.isSafeNsIdentifier);
|
|
239
|
-
namespaces.forEach(function (ns) {
|
|
240
|
-
if (i18next.options.ns && i18next.options.ns.indexOf(ns) < 0) {
|
|
241
|
-
i18next.options.ns.push(ns);
|
|
242
|
-
}
|
|
243
|
-
});
|
|
244
239
|
var loaded = false;
|
|
245
240
|
var onLoaded;
|
|
246
241
|
i18next.services.backendConnector.load(languages, namespaces, function () {
|
|
247
242
|
languages.forEach(function (lng) {
|
|
248
243
|
namespaces.forEach(function (ns) {
|
|
249
|
-
|
|
244
|
+
var bundle = i18next.getResourceBundle(lng, ns);
|
|
245
|
+
if (bundle && i18next.options.ns && i18next.options.ns.indexOf(ns) < 0) {
|
|
246
|
+
i18next.options.ns.push(ns);
|
|
247
|
+
}
|
|
248
|
+
utils.setPath(resources, [lng, ns], bundle);
|
|
250
249
|
});
|
|
251
250
|
});
|
|
252
251
|
loaded = true;
|
|
@@ -283,12 +282,14 @@ export function missingKeyHandler(i18next) {
|
|
|
283
282
|
}
|
|
284
283
|
var body = options.getBody(req);
|
|
285
284
|
var keySeparator = i18next.options && i18next.options.keySeparator;
|
|
285
|
+
var utilsOfRequest = req.i18n && req.i18n.services && req.i18n.services.utils;
|
|
286
|
+
var hasLoadedNamespace = utilsOfRequest && utilsOfRequest.hasLoadedNamespace;
|
|
286
287
|
var saveMissingKeys = function saveMissingKeys(src) {
|
|
287
288
|
if (!src || _typeof(src) !== 'object') return;
|
|
288
289
|
for (var _i = 0, _Object$keys = Object.keys(src); _i < _Object$keys.length; _i++) {
|
|
289
290
|
var m = _Object$keys[_i];
|
|
290
291
|
if (utils.hasUnsafeKeySegment(m, keySeparator)) continue;
|
|
291
|
-
i18next.services.backendConnector.saveMissing([lng], ns, m, src[m]);
|
|
292
|
+
i18next.services.backendConnector.saveMissing([lng], ns, m, src[m], undefined, undefined, undefined, hasLoadedNamespace);
|
|
292
293
|
}
|
|
293
294
|
};
|
|
294
295
|
if (typeof body === 'function') {
|
package/esm/utils.js
CHANGED
|
@@ -13,8 +13,7 @@ function isSafeIdentifierBase(v) {
|
|
|
13
13
|
}
|
|
14
14
|
export function isSafeLangIdentifier(v) {
|
|
15
15
|
if (!isSafeIdentifierBase(v)) return false;
|
|
16
|
-
|
|
17
|
-
return true;
|
|
16
|
+
return /^[A-Za-z0-9_@.-]+$/.test(v);
|
|
18
17
|
}
|
|
19
18
|
export function isSafeNsIdentifier(v) {
|
|
20
19
|
return isSafeIdentifierBase(v);
|
package/lib/index.js
CHANGED
|
@@ -127,9 +127,11 @@ export function handle (i18next, options = {}) {
|
|
|
127
127
|
if (i18next.services.languageDetector) {
|
|
128
128
|
i18next.services.languageDetector.cacheUserLanguage(req, res, lng)
|
|
129
129
|
}
|
|
130
|
-
// load resources
|
|
130
|
+
// load resources: through the request's clone, as loadLanguages() adds
|
|
131
|
+
// the language to options.preload, and every request on the shared
|
|
132
|
+
// instance pays for the length of that list until the process restarts
|
|
131
133
|
if (!req.lng) return next()
|
|
132
|
-
|
|
134
|
+
i18n.loadLanguages(req.lng, () => next())
|
|
133
135
|
}
|
|
134
136
|
}
|
|
135
137
|
|
|
@@ -265,23 +267,19 @@ export function getResourcesHandler (i18next, options = {}) {
|
|
|
265
267
|
languages = languages.filter(utils.isSafeLangIdentifier)
|
|
266
268
|
namespaces = namespaces.filter(utils.isSafeNsIdentifier)
|
|
267
269
|
|
|
268
|
-
// extend ns
|
|
269
|
-
namespaces.forEach(ns => {
|
|
270
|
-
if (i18next.options.ns && i18next.options.ns.indexOf(ns) < 0) {
|
|
271
|
-
i18next.options.ns.push(ns)
|
|
272
|
-
}
|
|
273
|
-
})
|
|
274
|
-
|
|
275
270
|
let loaded = false
|
|
276
271
|
let onLoaded
|
|
277
272
|
i18next.services.backendConnector.load(languages, namespaces, function () {
|
|
278
273
|
languages.forEach(lng => {
|
|
279
274
|
namespaces.forEach(ns => {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
)
|
|
275
|
+
const bundle = i18next.getResourceBundle(lng, ns)
|
|
276
|
+
// extend ns only with a namespace the backend has: every request
|
|
277
|
+
// pays for the length of this shared list, and a made-up ns from
|
|
278
|
+
// the request would stay in it until the process restarts
|
|
279
|
+
if (bundle && i18next.options.ns && i18next.options.ns.indexOf(ns) < 0) {
|
|
280
|
+
i18next.options.ns.push(ns)
|
|
281
|
+
}
|
|
282
|
+
utils.setPath(resources, [lng, ns], bundle)
|
|
285
283
|
})
|
|
286
284
|
})
|
|
287
285
|
loaded = true
|
|
@@ -335,6 +333,8 @@ export function missingKeyHandler (i18next, options = {}) {
|
|
|
335
333
|
|
|
336
334
|
const body = options.getBody(req)
|
|
337
335
|
const keySeparator = i18next.options && i18next.options.keySeparator
|
|
336
|
+
const utilsOfRequest = req.i18n && req.i18n.services && req.i18n.services.utils
|
|
337
|
+
const hasLoadedNamespace = utilsOfRequest && utilsOfRequest.hasLoadedNamespace
|
|
338
338
|
|
|
339
339
|
// iterate only over own, non-prototype-polluting keys. The check also
|
|
340
340
|
// rejects dotted variants like `__proto__.polluted` whose segments under
|
|
@@ -343,7 +343,9 @@ export function missingKeyHandler (i18next, options = {}) {
|
|
|
343
343
|
if (!src || typeof src !== 'object') return
|
|
344
344
|
for (const m of Object.keys(src)) {
|
|
345
345
|
if (utils.hasUnsafeKeySegment(m, keySeparator)) continue
|
|
346
|
-
i18next.
|
|
346
|
+
// i18next >= 26.7 takes the check of this request's instance (one clone per
|
|
347
|
+
// request) as the 8th argument; without it, it checks the newest clone
|
|
348
|
+
i18next.services.backendConnector.saveMissing([lng], ns, m, src[m], undefined, undefined, undefined, hasLoadedNamespace)
|
|
347
349
|
}
|
|
348
350
|
}
|
|
349
351
|
|
package/lib/utils.js
CHANGED
|
@@ -17,14 +17,16 @@ function isSafeIdentifierBase (v) {
|
|
|
17
17
|
return true
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
// Strict
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
//
|
|
20
|
+
// Strict, applied to `lng`: on top of the base checks, the shape i18next accepts
|
|
21
|
+
// for a language code from outside since 26.7 (the rule of its exported
|
|
22
|
+
// `isSafeLanguageCode`): letters, digits, `-`, `_`, `@` and `.`. It is not a
|
|
23
|
+
// BCP-47 check (https://www.i18next.com/how-to/faq#how-should-the-language-codes-be-formatted),
|
|
24
|
+
// so `en_US`, `zh_Hant_TW` and `sr@latin` pass. `/`, quotes, spaces and `=` do
|
|
25
|
+
// not: a detected language ends up in `<html lang="...">`, and a value like
|
|
26
|
+
// `" onmouseover="x()` passed the base checks and the XSS patterns.
|
|
24
27
|
export function isSafeLangIdentifier (v) {
|
|
25
28
|
if (!isSafeIdentifierBase(v)) return false
|
|
26
|
-
|
|
27
|
-
return true
|
|
29
|
+
return /^[A-Za-z0-9_@.-]+$/.test(v)
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
// Loose — allows `/`. Applied to `ns`:
|