i18next-http-middleware 3.1.3 → 3.2.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/README.md +63 -16
- package/cjs/LanguageDetector.js +5 -4
- package/cjs/httpFunctions.js +21 -5
- package/cjs/index.js +46 -10
- package/cjs/languageLookups/session.js +1 -1
- package/cjs/utils.js +1 -1
- package/esm/LanguageDetector.js +2 -1
- package/esm/httpFunctions.js +20 -4
- package/esm/index.js +36 -3
- package/esm/languageLookups/session.js +1 -1
- package/index.d.ts +4 -0
- package/lib/LanguageDetector.js +1 -1
- package/lib/httpFunctions.js +26 -9
- package/lib/index.js +80 -16
- package/licence +1 -1
- package/package.json +18 -22
- package/CHANGELOG.md +0 -45
package/README.md
CHANGED
|
@@ -5,11 +5,14 @@
|
|
|
5
5
|
[](https://travis-ci.org/i18next/i18next-http-middleware)
|
|
6
6
|
[](https://www.npmjs.com/package/i18next-http-middleware)
|
|
7
7
|
|
|
8
|
-
|
|
9
8
|
This is a middleware to be used with Node.js web frameworks like express or Fastify and also for Deno.
|
|
10
9
|
|
|
11
10
|
It's based on the deprecated [i18next-express-middleware](https://github.com/i18next/i18next-express-middleware) and can be used as a drop-in replacement.
|
|
12
|
-
|
|
11
|
+
_It's not bound to a specific http framework anymore._
|
|
12
|
+
|
|
13
|
+
## Advice:
|
|
14
|
+
|
|
15
|
+
To get started with server side internationalization, you may also have a look at [this blog post](https://dev.to/adrai/how-does-server-side-internationalization-i18n-look-like-5f4c) also using [using i18next-http-middleware](https://dev.to/adrai/how-does-server-side-internationalization-i18n-look-like-5f4c#ssr).
|
|
13
16
|
|
|
14
17
|
# Getting started
|
|
15
18
|
|
|
@@ -52,6 +55,7 @@ div = t('myKey')
|
|
|
52
55
|
```
|
|
53
56
|
|
|
54
57
|
### Fastify usage
|
|
58
|
+
|
|
55
59
|
```js
|
|
56
60
|
var i18next = require('i18next')
|
|
57
61
|
var middleware = require('i18next-http-middleware')
|
|
@@ -83,6 +87,46 @@ app.get('myRoute', (request, reply) => {
|
|
|
83
87
|
})
|
|
84
88
|
```
|
|
85
89
|
|
|
90
|
+
### Hapi usage
|
|
91
|
+
|
|
92
|
+
```js
|
|
93
|
+
const i18next = require('i18next')
|
|
94
|
+
const middleware = require('i18next-http-middleware')
|
|
95
|
+
const Hapi = require('@hapi/hapi')
|
|
96
|
+
|
|
97
|
+
i18next.use(middleware.LanguageDetector).init({
|
|
98
|
+
preload: ['en', 'de', 'it'],
|
|
99
|
+
...otherOptions
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
const server = Hapi.server({
|
|
103
|
+
port: port,
|
|
104
|
+
host: '0.0.0.0',
|
|
105
|
+
|
|
106
|
+
await server.register({
|
|
107
|
+
plugin: i18nextMiddleware.hapiPlugin,
|
|
108
|
+
options: {
|
|
109
|
+
i18next,
|
|
110
|
+
ignoreRoutes: ['/foo'] // or function(req, res, options, i18next) { /* return true to ignore
|
|
111
|
+
}
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
// in your request handler
|
|
115
|
+
server.route({
|
|
116
|
+
method: 'GET',
|
|
117
|
+
path: '/myRoute',
|
|
118
|
+
handler: (request, h) => {
|
|
119
|
+
var lng = request.language // 'de-CH'
|
|
120
|
+
var lngs = v.languages // ['de-CH', 'de', 'en']
|
|
121
|
+
request.i18n.changeLanguage('en') // will not load that!!! assert it was preloaded
|
|
122
|
+
|
|
123
|
+
var exists = request.i18n.exists('myKey')
|
|
124
|
+
var translation = request.t('myKey')
|
|
125
|
+
}
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
|
|
86
130
|
### Deno usage
|
|
87
131
|
|
|
88
132
|
#### abc
|
|
@@ -92,7 +136,7 @@ import i18next from 'https://deno.land/x/i18next/index.js'
|
|
|
92
136
|
import Backend from 'https://cdn.jsdelivr.net/gh/i18next/i18next-fs-backend/index.js'
|
|
93
137
|
import i18nextMiddleware from 'https://deno.land/x/i18next_http_middleware/index.js'
|
|
94
138
|
import { Application } from 'https://deno.land/x/abc/mod.ts'
|
|
95
|
-
import { config } from
|
|
139
|
+
import { config } from 'https://deno.land/x/dotenv/dotenv.ts'
|
|
96
140
|
|
|
97
141
|
i18next
|
|
98
142
|
.use(Backend)
|
|
@@ -112,12 +156,10 @@ i18next
|
|
|
112
156
|
const port = config.PORT || 8080
|
|
113
157
|
const app = new Application()
|
|
114
158
|
const handle = i18nextMiddleware.handle(i18next)
|
|
115
|
-
app.use((next) =>
|
|
116
|
-
(c) => {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
120
|
-
)
|
|
159
|
+
app.use((next) => (c) => {
|
|
160
|
+
handle(c.request, c.response, () => {})
|
|
161
|
+
return next(c)
|
|
162
|
+
})
|
|
121
163
|
app.get('/', (c) => c.request.t('home.title'))
|
|
122
164
|
await app.start({ port })
|
|
123
165
|
```
|
|
@@ -129,7 +171,7 @@ import i18next from 'https://deno.land/x/i18next/index.js'
|
|
|
129
171
|
import Backend from 'https://cdn.jsdelivr.net/gh/i18next/i18next-fs-backend/index.js'
|
|
130
172
|
import i18nextMiddleware from 'https://deno.land/x/i18next_http_middleware/index.js'
|
|
131
173
|
import { createApp } from 'https://servestjs.org/@v1.0.0-rc2/mod.ts'
|
|
132
|
-
import { config } from
|
|
174
|
+
import { config } from 'https://deno.land/x/dotenv/dotenv.ts'
|
|
133
175
|
|
|
134
176
|
i18next
|
|
135
177
|
.use(Backend)
|
|
@@ -153,7 +195,7 @@ app.get('/', async (req) => {
|
|
|
153
195
|
await req.respond({
|
|
154
196
|
status: 200,
|
|
155
197
|
headers: new Headers({
|
|
156
|
-
'content-type': 'text/plain'
|
|
198
|
+
'content-type': 'text/plain'
|
|
157
199
|
}),
|
|
158
200
|
body: req.t('home.title')
|
|
159
201
|
})
|
|
@@ -169,6 +211,10 @@ app.post('/locales/add/:lng/:ns', middleware.missingKeyHandler(i18next))
|
|
|
169
211
|
|
|
170
212
|
// multiload backend route
|
|
171
213
|
app.get('/locales/resources.json', middleware.getResourcesHandler(i18next))
|
|
214
|
+
// can be used like:
|
|
215
|
+
// GET /locales/resources.json
|
|
216
|
+
// GET /locales/resources.json?lng=en
|
|
217
|
+
// GET /locales/resources.json?lng=en&ns=translation
|
|
172
218
|
```
|
|
173
219
|
|
|
174
220
|
## add localized routes
|
|
@@ -245,7 +291,7 @@ Define your own functions to handle your custom request or response
|
|
|
245
291
|
middleware.handle(i18next, {
|
|
246
292
|
getPath: (req) => req.path,
|
|
247
293
|
getUrl: (req) => req.url,
|
|
248
|
-
setUrl: (req, url) => req.url = url,
|
|
294
|
+
setUrl: (req, url) => (req.url = url),
|
|
249
295
|
getQuery: (req) => req.query,
|
|
250
296
|
getParams: (req) => req.params,
|
|
251
297
|
getBody: (req) => req.body,
|
|
@@ -266,6 +312,8 @@ Detects user language from current request. Comes with support for:
|
|
|
266
312
|
- querystring
|
|
267
313
|
- session
|
|
268
314
|
|
|
315
|
+
Based on the i18next language detection handling: https://www.i18next.com/misc/creating-own-plugins#languagedetector
|
|
316
|
+
|
|
269
317
|
Wiring up:
|
|
270
318
|
|
|
271
319
|
```js
|
|
@@ -293,7 +341,7 @@ As with all modules you can either pass the constructor function (class) to the
|
|
|
293
341
|
lookupPath: 'lng',
|
|
294
342
|
lookupFromPathIndex: 0,
|
|
295
343
|
|
|
296
|
-
// cache user language
|
|
344
|
+
// cache user language, you can define if an how the detected language should be "saved" => 'cookie' and/or 'session'
|
|
297
345
|
caches: false, // ['cookie']
|
|
298
346
|
|
|
299
347
|
ignoreCase: true, // ignore case of detected language
|
|
@@ -344,15 +392,14 @@ lngDetector.init(options)
|
|
|
344
392
|
module.exports = {
|
|
345
393
|
name: 'myDetectorsName',
|
|
346
394
|
|
|
347
|
-
lookup: function(req, res, options) {
|
|
395
|
+
lookup: function (req, res, options) {
|
|
348
396
|
// options -> are passed in options
|
|
349
397
|
return 'en'
|
|
350
398
|
},
|
|
351
399
|
|
|
352
|
-
cacheUserLanguage: function(req, res, lng, options) {
|
|
400
|
+
cacheUserLanguage: function (req, res, lng, options) {
|
|
353
401
|
// options -> are passed in options
|
|
354
402
|
// lng -> current language, will be called after init and on changeLanguage
|
|
355
|
-
|
|
356
403
|
// store it
|
|
357
404
|
}
|
|
358
405
|
}
|
package/cjs/LanguageDetector.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
function _typeof(obj) { "@babel/helpers - typeof";
|
|
3
|
+
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
|
|
4
4
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", {
|
|
6
6
|
value: true
|
|
@@ -23,15 +23,15 @@ var _httpFunctions = require("./httpFunctions.js");
|
|
|
23
23
|
|
|
24
24
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
25
25
|
|
|
26
|
-
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var
|
|
26
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
27
27
|
|
|
28
|
-
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
28
|
+
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
29
29
|
|
|
30
30
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
31
31
|
|
|
32
32
|
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
|
33
33
|
|
|
34
|
-
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
|
|
34
|
+
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
|
35
35
|
|
|
36
36
|
function getDefaults() {
|
|
37
37
|
return (0, _httpFunctions.extendOptionsWithDefaults)({
|
|
@@ -117,6 +117,7 @@ var LanguageDetector = function () {
|
|
|
117
117
|
|
|
118
118
|
if (!found) {
|
|
119
119
|
var fallbacks = this.allOptions.fallbackLng;
|
|
120
|
+
if (typeof fallbacks === 'function') fallbacks = fallbacks();
|
|
120
121
|
if (typeof fallbacks === 'string') fallbacks = [fallbacks];
|
|
121
122
|
if (!fallbacks) fallbacks = [];
|
|
122
123
|
|
package/cjs/httpFunctions.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.
|
|
6
|
+
exports.setUrl = exports.setStatus = exports.setHeader = exports.setContentType = exports.send = exports.getUrl = exports.getSession = exports.getQuery = exports.getPath = exports.getParams = exports.getOriginalUrl = exports.getHeaders = exports.getHeader = exports.getCookies = exports.getBody = exports.extendOptionsWithDefaults = void 0;
|
|
7
7
|
|
|
8
8
|
var getPath = function getPath(req) {
|
|
9
9
|
if (req.path) return req.path;
|
|
@@ -15,6 +15,7 @@ var getPath = function getPath(req) {
|
|
|
15
15
|
exports.getPath = getPath;
|
|
16
16
|
|
|
17
17
|
var getUrl = function getUrl(req) {
|
|
18
|
+
if (req.url && req.url.href) return req.url.href;
|
|
18
19
|
if (req.url) return req.url;
|
|
19
20
|
if (req.raw && req.raw.url) return req.raw.url;
|
|
20
21
|
console.log('no possibility found to get url');
|
|
@@ -42,8 +43,12 @@ var getOriginalUrl = function getOriginalUrl(req) {
|
|
|
42
43
|
exports.getOriginalUrl = getOriginalUrl;
|
|
43
44
|
|
|
44
45
|
var getQuery = function getQuery(req) {
|
|
45
|
-
if (req.query && typeof req.query.entries === 'function' && typeof Object.fromEntries === 'function' && typeof req.query[Symbol.iterator] === 'function')
|
|
46
|
+
if (req.query && typeof req.query.entries === 'function' && typeof Object.fromEntries === 'function' && typeof req.query[Symbol.iterator] === 'function') {
|
|
47
|
+
return Object.fromEntries(req.query);
|
|
48
|
+
}
|
|
49
|
+
|
|
46
50
|
if (req.query) return req.query;
|
|
51
|
+
if (req.searchParams) return req.searchParams;
|
|
47
52
|
if (req.raw && req.raw.query) return req.raw.query;
|
|
48
53
|
if (req.ctx && req.ctx.queryParams) return req.ctx.queryParams;
|
|
49
54
|
var url = req.url || req.raw && req.raw.url;
|
|
@@ -90,10 +95,14 @@ var getCookies = function getCookies(req) {
|
|
|
90
95
|
exports.getCookies = getCookies;
|
|
91
96
|
|
|
92
97
|
var getBody = function getBody(req) {
|
|
93
|
-
if (req.ctx && typeof req.ctx.body === 'function')
|
|
98
|
+
if (req.ctx && typeof req.ctx.body === 'function') {
|
|
99
|
+
return req.ctx.body.bind(req.ctx);
|
|
100
|
+
}
|
|
101
|
+
|
|
94
102
|
if (req.ctx && req.ctx.body) return req.ctx.body;
|
|
95
103
|
if (req.json) return req.json;
|
|
96
104
|
if (req.body) return req.body;
|
|
105
|
+
if (req.payload) return req.payload;
|
|
97
106
|
console.log('no possibility found to get body');
|
|
98
107
|
return {};
|
|
99
108
|
};
|
|
@@ -114,8 +123,15 @@ var setHeader = function setHeader(res, name, value) {
|
|
|
114
123
|
if (res._headerSent || res.headersSent) return;
|
|
115
124
|
if (typeof res.setHeader === 'function') return res.setHeader(name, value);
|
|
116
125
|
if (typeof res.header === 'function') return res.header(name, value);
|
|
117
|
-
|
|
118
|
-
if (res.
|
|
126
|
+
|
|
127
|
+
if (res.responseHeaders && typeof res.responseHeaders.set === 'function') {
|
|
128
|
+
return res.responseHeaders.set(name, value);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (res.headers && typeof res.headers.set === 'function') {
|
|
132
|
+
return res.headers.set(name, value);
|
|
133
|
+
}
|
|
134
|
+
|
|
119
135
|
console.log('no possibility found to set header');
|
|
120
136
|
};
|
|
121
137
|
|
package/cjs/index.js
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
function _typeof(obj) { "@babel/helpers - typeof";
|
|
3
|
+
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
|
|
4
4
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", {
|
|
6
6
|
value: true
|
|
7
7
|
});
|
|
8
|
-
exports.
|
|
9
|
-
exports.
|
|
8
|
+
exports.LanguageDetector = void 0;
|
|
9
|
+
exports.addRoute = addRoute;
|
|
10
|
+
exports.default = void 0;
|
|
10
11
|
exports.getResourcesHandler = getResourcesHandler;
|
|
12
|
+
exports.handle = handle;
|
|
13
|
+
exports.hapiPlugin = void 0;
|
|
11
14
|
exports.missingKeyHandler = missingKeyHandler;
|
|
12
|
-
exports.
|
|
13
|
-
exports.default = exports.LanguageDetector = void 0;
|
|
15
|
+
exports.plugin = plugin;
|
|
14
16
|
|
|
15
17
|
var utils = _interopRequireWildcard(require("./utils.js"));
|
|
16
18
|
|
|
@@ -20,9 +22,15 @@ var _httpFunctions = require("./httpFunctions.js");
|
|
|
20
22
|
|
|
21
23
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
22
24
|
|
|
23
|
-
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var
|
|
25
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
26
|
+
|
|
27
|
+
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
28
|
+
|
|
29
|
+
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
24
30
|
|
|
25
|
-
function
|
|
31
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
32
|
+
|
|
33
|
+
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
26
34
|
|
|
27
35
|
var LanguageDetector = _LanguageDetector.default;
|
|
28
36
|
exports.LanguageDetector = LanguageDetector;
|
|
@@ -73,6 +81,7 @@ function handle(i18next) {
|
|
|
73
81
|
});
|
|
74
82
|
i18n.on('languageChanged', function (lng) {
|
|
75
83
|
req.language = req.locale = req.lng = lng;
|
|
84
|
+
if (options.attachLocals) res.locals = res.locals || {};
|
|
76
85
|
|
|
77
86
|
if (res.locals) {
|
|
78
87
|
res.locals.language = lng;
|
|
@@ -90,7 +99,11 @@ function handle(i18next) {
|
|
|
90
99
|
}
|
|
91
100
|
});
|
|
92
101
|
var lng = req.lng;
|
|
93
|
-
|
|
102
|
+
|
|
103
|
+
if (!lng && i18next.services.languageDetector) {
|
|
104
|
+
lng = i18next.services.languageDetector.detect(req, res);
|
|
105
|
+
}
|
|
106
|
+
|
|
94
107
|
req.language = req.locale = req.lng = lng;
|
|
95
108
|
|
|
96
109
|
if (lng && options.getHeader(res, 'Content-Language') !== lng) {
|
|
@@ -108,6 +121,7 @@ function handle(i18next) {
|
|
|
108
121
|
var exists = i18n.exists.bind(i18n);
|
|
109
122
|
req.i18n = i18n;
|
|
110
123
|
req.t = t;
|
|
124
|
+
if (options.attachLocals) res.locals = res.locals || {};
|
|
111
125
|
|
|
112
126
|
if (res.locals) {
|
|
113
127
|
res.locals.t = t;
|
|
@@ -117,7 +131,10 @@ function handle(i18next) {
|
|
|
117
131
|
res.locals.languageDir = i18next.dir(lng);
|
|
118
132
|
}
|
|
119
133
|
|
|
120
|
-
if (i18next.services.languageDetector)
|
|
134
|
+
if (i18next.services.languageDetector) {
|
|
135
|
+
i18next.services.languageDetector.cacheUserLanguage(req, res, lng);
|
|
136
|
+
}
|
|
137
|
+
|
|
121
138
|
if (!req.lng) return next();
|
|
122
139
|
i18next.loadLanguages(req.lng, function () {
|
|
123
140
|
return next();
|
|
@@ -126,6 +143,7 @@ function handle(i18next) {
|
|
|
126
143
|
}
|
|
127
144
|
|
|
128
145
|
function plugin(instance, options, next) {
|
|
146
|
+
options.attachLocals = true;
|
|
129
147
|
var middleware = handle(options.i18next, options);
|
|
130
148
|
instance.addHook('preHandler', function (request, reply, next) {
|
|
131
149
|
return middleware(request, reply, next);
|
|
@@ -133,6 +151,21 @@ function plugin(instance, options, next) {
|
|
|
133
151
|
return next();
|
|
134
152
|
}
|
|
135
153
|
|
|
154
|
+
var hapiPlugin = {
|
|
155
|
+
name: 'i18next-http-middleware',
|
|
156
|
+
version: '1',
|
|
157
|
+
register: function register(server, options) {
|
|
158
|
+
options.attachLocals = true;
|
|
159
|
+
var middleware = handle(options.i18next, _objectSpread({}, options));
|
|
160
|
+
server.ext('onPreHandler', function (request, h) {
|
|
161
|
+
middleware(request, request.raw.res || h.response() || request.Response, function () {
|
|
162
|
+
return h.continue;
|
|
163
|
+
});
|
|
164
|
+
return h.continue;
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
exports.hapiPlugin = hapiPlugin;
|
|
136
169
|
plugin[Symbol.for('skip-override')] = true;
|
|
137
170
|
|
|
138
171
|
function getResourcesHandler(i18next) {
|
|
@@ -163,7 +196,9 @@ function getResourcesHandler(i18next) {
|
|
|
163
196
|
var languages = options.getQuery(req)[options.lngParam || 'lng'] ? options.getQuery(req)[options.lngParam || 'lng'].split(' ') : [];
|
|
164
197
|
var namespaces = options.getQuery(req)[options.nsParam || 'ns'] ? options.getQuery(req)[options.nsParam || 'ns'].split(' ') : [];
|
|
165
198
|
namespaces.forEach(function (ns) {
|
|
166
|
-
if (i18next.options.ns && i18next.options.ns.indexOf(ns) < 0)
|
|
199
|
+
if (i18next.options.ns && i18next.options.ns.indexOf(ns) < 0) {
|
|
200
|
+
i18next.options.ns.push(ns);
|
|
201
|
+
}
|
|
167
202
|
});
|
|
168
203
|
i18next.services.backendConnector.load(languages, namespaces, function () {
|
|
169
204
|
languages.forEach(function (lng) {
|
|
@@ -251,6 +286,7 @@ function addRoute(i18next, route, lngs, app, verb, fc) {
|
|
|
251
286
|
|
|
252
287
|
var _default = {
|
|
253
288
|
plugin: plugin,
|
|
289
|
+
hapiPlugin: hapiPlugin,
|
|
254
290
|
handle: handle,
|
|
255
291
|
getResourcesHandler: getResourcesHandler,
|
|
256
292
|
missingKeyHandler: missingKeyHandler,
|
|
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
|
|
8
|
-
function _typeof(obj) { "@babel/helpers - typeof";
|
|
8
|
+
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
|
|
9
9
|
|
|
10
10
|
var _default = {
|
|
11
11
|
name: 'session',
|
package/cjs/utils.js
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.setPath = setPath;
|
|
7
6
|
exports.defaults = defaults;
|
|
8
7
|
exports.extend = extend;
|
|
9
8
|
exports.removeLngFromUrl = removeLngFromUrl;
|
|
9
|
+
exports.setPath = setPath;
|
|
10
10
|
|
|
11
11
|
function setPath(object, path, newValue) {
|
|
12
12
|
var stack;
|
package/esm/LanguageDetector.js
CHANGED
|
@@ -2,7 +2,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
|
|
|
2
2
|
|
|
3
3
|
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
|
4
4
|
|
|
5
|
-
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
|
|
5
|
+
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
|
6
6
|
|
|
7
7
|
import * as utils from './utils.js';
|
|
8
8
|
import cookieLookup from './languageLookups/cookie.js';
|
|
@@ -96,6 +96,7 @@ var LanguageDetector = function () {
|
|
|
96
96
|
|
|
97
97
|
if (!found) {
|
|
98
98
|
var fallbacks = this.allOptions.fallbackLng;
|
|
99
|
+
if (typeof fallbacks === 'function') fallbacks = fallbacks();
|
|
99
100
|
if (typeof fallbacks === 'string') fallbacks = [fallbacks];
|
|
100
101
|
if (!fallbacks) fallbacks = [];
|
|
101
102
|
|
package/esm/httpFunctions.js
CHANGED
|
@@ -5,6 +5,7 @@ export var getPath = function getPath(req) {
|
|
|
5
5
|
console.log('no possibility found to get path');
|
|
6
6
|
};
|
|
7
7
|
export var getUrl = function getUrl(req) {
|
|
8
|
+
if (req.url && req.url.href) return req.url.href;
|
|
8
9
|
if (req.url) return req.url;
|
|
9
10
|
if (req.raw && req.raw.url) return req.raw.url;
|
|
10
11
|
console.log('no possibility found to get url');
|
|
@@ -23,8 +24,12 @@ export var getOriginalUrl = function getOriginalUrl(req) {
|
|
|
23
24
|
return getUrl(req);
|
|
24
25
|
};
|
|
25
26
|
export var getQuery = function getQuery(req) {
|
|
26
|
-
if (req.query && typeof req.query.entries === 'function' && typeof Object.fromEntries === 'function' && typeof req.query[Symbol.iterator] === 'function')
|
|
27
|
+
if (req.query && typeof req.query.entries === 'function' && typeof Object.fromEntries === 'function' && typeof req.query[Symbol.iterator] === 'function') {
|
|
28
|
+
return Object.fromEntries(req.query);
|
|
29
|
+
}
|
|
30
|
+
|
|
27
31
|
if (req.query) return req.query;
|
|
32
|
+
if (req.searchParams) return req.searchParams;
|
|
28
33
|
if (req.raw && req.raw.query) return req.raw.query;
|
|
29
34
|
if (req.ctx && req.ctx.queryParams) return req.ctx.queryParams;
|
|
30
35
|
var url = req.url || req.raw && req.raw.url;
|
|
@@ -59,10 +64,14 @@ export var getCookies = function getCookies(req) {
|
|
|
59
64
|
console.log('no possibility found to get cookies');
|
|
60
65
|
};
|
|
61
66
|
export var getBody = function getBody(req) {
|
|
62
|
-
if (req.ctx && typeof req.ctx.body === 'function')
|
|
67
|
+
if (req.ctx && typeof req.ctx.body === 'function') {
|
|
68
|
+
return req.ctx.body.bind(req.ctx);
|
|
69
|
+
}
|
|
70
|
+
|
|
63
71
|
if (req.ctx && req.ctx.body) return req.ctx.body;
|
|
64
72
|
if (req.json) return req.json;
|
|
65
73
|
if (req.body) return req.body;
|
|
74
|
+
if (req.payload) return req.payload;
|
|
66
75
|
console.log('no possibility found to get body');
|
|
67
76
|
return {};
|
|
68
77
|
};
|
|
@@ -77,8 +86,15 @@ export var setHeader = function setHeader(res, name, value) {
|
|
|
77
86
|
if (res._headerSent || res.headersSent) return;
|
|
78
87
|
if (typeof res.setHeader === 'function') return res.setHeader(name, value);
|
|
79
88
|
if (typeof res.header === 'function') return res.header(name, value);
|
|
80
|
-
|
|
81
|
-
if (res.
|
|
89
|
+
|
|
90
|
+
if (res.responseHeaders && typeof res.responseHeaders.set === 'function') {
|
|
91
|
+
return res.responseHeaders.set(name, value);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (res.headers && typeof res.headers.set === 'function') {
|
|
95
|
+
return res.headers.set(name, value);
|
|
96
|
+
}
|
|
97
|
+
|
|
82
98
|
console.log('no possibility found to set header');
|
|
83
99
|
};
|
|
84
100
|
export var setContentType = function setContentType(res, type) {
|
package/esm/index.js
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
2
|
+
|
|
3
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
4
|
+
|
|
5
|
+
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
6
|
+
|
|
1
7
|
import * as utils from './utils.js';
|
|
2
8
|
import LD from './LanguageDetector.js';
|
|
3
9
|
import { extendOptionsWithDefaults } from './httpFunctions.js';
|
|
@@ -49,6 +55,7 @@ export function handle(i18next) {
|
|
|
49
55
|
});
|
|
50
56
|
i18n.on('languageChanged', function (lng) {
|
|
51
57
|
req.language = req.locale = req.lng = lng;
|
|
58
|
+
if (options.attachLocals) res.locals = res.locals || {};
|
|
52
59
|
|
|
53
60
|
if (res.locals) {
|
|
54
61
|
res.locals.language = lng;
|
|
@@ -66,7 +73,11 @@ export function handle(i18next) {
|
|
|
66
73
|
}
|
|
67
74
|
});
|
|
68
75
|
var lng = req.lng;
|
|
69
|
-
|
|
76
|
+
|
|
77
|
+
if (!lng && i18next.services.languageDetector) {
|
|
78
|
+
lng = i18next.services.languageDetector.detect(req, res);
|
|
79
|
+
}
|
|
80
|
+
|
|
70
81
|
req.language = req.locale = req.lng = lng;
|
|
71
82
|
|
|
72
83
|
if (lng && options.getHeader(res, 'Content-Language') !== lng) {
|
|
@@ -84,6 +95,7 @@ export function handle(i18next) {
|
|
|
84
95
|
var exists = i18n.exists.bind(i18n);
|
|
85
96
|
req.i18n = i18n;
|
|
86
97
|
req.t = t;
|
|
98
|
+
if (options.attachLocals) res.locals = res.locals || {};
|
|
87
99
|
|
|
88
100
|
if (res.locals) {
|
|
89
101
|
res.locals.t = t;
|
|
@@ -93,7 +105,10 @@ export function handle(i18next) {
|
|
|
93
105
|
res.locals.languageDir = i18next.dir(lng);
|
|
94
106
|
}
|
|
95
107
|
|
|
96
|
-
if (i18next.services.languageDetector)
|
|
108
|
+
if (i18next.services.languageDetector) {
|
|
109
|
+
i18next.services.languageDetector.cacheUserLanguage(req, res, lng);
|
|
110
|
+
}
|
|
111
|
+
|
|
97
112
|
if (!req.lng) return next();
|
|
98
113
|
i18next.loadLanguages(req.lng, function () {
|
|
99
114
|
return next();
|
|
@@ -101,12 +116,27 @@ export function handle(i18next) {
|
|
|
101
116
|
};
|
|
102
117
|
}
|
|
103
118
|
export function plugin(instance, options, next) {
|
|
119
|
+
options.attachLocals = true;
|
|
104
120
|
var middleware = handle(options.i18next, options);
|
|
105
121
|
instance.addHook('preHandler', function (request, reply, next) {
|
|
106
122
|
return middleware(request, reply, next);
|
|
107
123
|
});
|
|
108
124
|
return next();
|
|
109
125
|
}
|
|
126
|
+
export var hapiPlugin = {
|
|
127
|
+
name: 'i18next-http-middleware',
|
|
128
|
+
version: '1',
|
|
129
|
+
register: function register(server, options) {
|
|
130
|
+
options.attachLocals = true;
|
|
131
|
+
var middleware = handle(options.i18next, _objectSpread({}, options));
|
|
132
|
+
server.ext('onPreHandler', function (request, h) {
|
|
133
|
+
middleware(request, request.raw.res || h.response() || request.Response, function () {
|
|
134
|
+
return h.continue;
|
|
135
|
+
});
|
|
136
|
+
return h.continue;
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
};
|
|
110
140
|
plugin[Symbol.for('skip-override')] = true;
|
|
111
141
|
export function getResourcesHandler(i18next) {
|
|
112
142
|
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
@@ -136,7 +166,9 @@ export function getResourcesHandler(i18next) {
|
|
|
136
166
|
var languages = options.getQuery(req)[options.lngParam || 'lng'] ? options.getQuery(req)[options.lngParam || 'lng'].split(' ') : [];
|
|
137
167
|
var namespaces = options.getQuery(req)[options.nsParam || 'ns'] ? options.getQuery(req)[options.nsParam || 'ns'].split(' ') : [];
|
|
138
168
|
namespaces.forEach(function (ns) {
|
|
139
|
-
if (i18next.options.ns && i18next.options.ns.indexOf(ns) < 0)
|
|
169
|
+
if (i18next.options.ns && i18next.options.ns.indexOf(ns) < 0) {
|
|
170
|
+
i18next.options.ns.push(ns);
|
|
171
|
+
}
|
|
140
172
|
});
|
|
141
173
|
i18next.services.backendConnector.load(languages, namespaces, function () {
|
|
142
174
|
languages.forEach(function (lng) {
|
|
@@ -221,6 +253,7 @@ export function addRoute(i18next, route, lngs, app, verb, fc) {
|
|
|
221
253
|
}
|
|
222
254
|
export default {
|
|
223
255
|
plugin: plugin,
|
|
256
|
+
hapiPlugin: hapiPlugin,
|
|
224
257
|
handle: handle,
|
|
225
258
|
getResourcesHandler: getResourcesHandler,
|
|
226
259
|
missingKeyHandler: missingKeyHandler,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
function _typeof(obj) { "@babel/helpers - typeof";
|
|
1
|
+
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
|
|
2
2
|
|
|
3
3
|
export default {
|
|
4
4
|
name: 'session',
|
package/index.d.ts
CHANGED
package/lib/LanguageDetector.js
CHANGED
|
@@ -79,9 +79,9 @@ class LanguageDetector {
|
|
|
79
79
|
|
|
80
80
|
if (!found) {
|
|
81
81
|
let fallbacks = this.allOptions.fallbackLng
|
|
82
|
+
if (typeof fallbacks === 'function') fallbacks = fallbacks()
|
|
82
83
|
if (typeof fallbacks === 'string') fallbacks = [fallbacks]
|
|
83
84
|
if (!fallbacks) fallbacks = []
|
|
84
|
-
|
|
85
85
|
if (Object.prototype.toString.apply(fallbacks) === '[object Array]') {
|
|
86
86
|
found = fallbacks[0]
|
|
87
87
|
} else {
|
package/lib/httpFunctions.js
CHANGED
|
@@ -5,6 +5,7 @@ export const getPath = (req) => {
|
|
|
5
5
|
console.log('no possibility found to get path')
|
|
6
6
|
}
|
|
7
7
|
export const getUrl = (req) => {
|
|
8
|
+
if (req.url && req.url.href) return req.url.href
|
|
8
9
|
if (req.url) return req.url
|
|
9
10
|
if (req.raw && req.raw.url) return req.raw.url
|
|
10
11
|
console.log('no possibility found to get url')
|
|
@@ -22,8 +23,16 @@ export const getOriginalUrl = (req) => {
|
|
|
22
23
|
return getUrl(req)
|
|
23
24
|
}
|
|
24
25
|
export const getQuery = (req) => {
|
|
25
|
-
if (
|
|
26
|
+
if (
|
|
27
|
+
req.query &&
|
|
28
|
+
typeof req.query.entries === 'function' &&
|
|
29
|
+
typeof Object.fromEntries === 'function' &&
|
|
30
|
+
typeof req.query[Symbol.iterator] === 'function'
|
|
31
|
+
) {
|
|
32
|
+
return Object.fromEntries(req.query)
|
|
33
|
+
}
|
|
26
34
|
if (req.query) return req.query
|
|
35
|
+
if (req.searchParams) return req.searchParams
|
|
27
36
|
if (req.raw && req.raw.query) return req.raw.query
|
|
28
37
|
if (req.ctx && req.ctx.queryParams) return req.ctx.queryParams
|
|
29
38
|
const url = req.url || (req.raw && req.raw.url)
|
|
@@ -47,19 +56,23 @@ export const getCookies = (req) => {
|
|
|
47
56
|
if (getHeaders(req)) {
|
|
48
57
|
const list = {}
|
|
49
58
|
const rc = getHeaders(req).cookie
|
|
50
|
-
rc &&
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
59
|
+
rc &&
|
|
60
|
+
rc.split(';').forEach((cookie) => {
|
|
61
|
+
const parts = cookie.split('=')
|
|
62
|
+
list[parts.shift().trim()] = decodeURI(encodeURI(parts.join('=')))
|
|
63
|
+
})
|
|
54
64
|
return list
|
|
55
65
|
}
|
|
56
66
|
console.log('no possibility found to get cookies')
|
|
57
67
|
}
|
|
58
68
|
export const getBody = (req) => {
|
|
59
|
-
if (req.ctx && typeof req.ctx.body === 'function')
|
|
69
|
+
if (req.ctx && typeof req.ctx.body === 'function') {
|
|
70
|
+
return req.ctx.body.bind(req.ctx)
|
|
71
|
+
}
|
|
60
72
|
if (req.ctx && req.ctx.body) return req.ctx.body
|
|
61
73
|
if (req.json) return req.json
|
|
62
74
|
if (req.body) return req.body
|
|
75
|
+
if (req.payload) return req.payload
|
|
63
76
|
console.log('no possibility found to get body')
|
|
64
77
|
return {}
|
|
65
78
|
}
|
|
@@ -74,8 +87,12 @@ export const setHeader = (res, name, value) => {
|
|
|
74
87
|
if (res._headerSent || res.headersSent) return
|
|
75
88
|
if (typeof res.setHeader === 'function') return res.setHeader(name, value)
|
|
76
89
|
if (typeof res.header === 'function') return res.header(name, value)
|
|
77
|
-
if (res.responseHeaders && typeof res.responseHeaders.set === 'function')
|
|
78
|
-
|
|
90
|
+
if (res.responseHeaders && typeof res.responseHeaders.set === 'function') {
|
|
91
|
+
return res.responseHeaders.set(name, value)
|
|
92
|
+
}
|
|
93
|
+
if (res.headers && typeof res.headers.set === 'function') {
|
|
94
|
+
return res.headers.set(name, value)
|
|
95
|
+
}
|
|
79
96
|
console.log('no possibility found to set header')
|
|
80
97
|
}
|
|
81
98
|
export const setContentType = (res, type) => {
|
|
@@ -86,7 +103,7 @@ export const setContentType = (res, type) => {
|
|
|
86
103
|
export const setStatus = (res, code) => {
|
|
87
104
|
if (typeof res.status === 'function') return res.status(code)
|
|
88
105
|
// eslint-disable-next-line no-return-assign
|
|
89
|
-
if (res.status) return res.status = code
|
|
106
|
+
if (res.status) return (res.status = code)
|
|
90
107
|
console.log('no possibility found to set status')
|
|
91
108
|
}
|
|
92
109
|
export const send = (res, body) => {
|
package/lib/index.js
CHANGED
|
@@ -30,16 +30,19 @@ export function handle (i18next, options = {}) {
|
|
|
30
30
|
return next()
|
|
31
31
|
}
|
|
32
32
|
} else {
|
|
33
|
-
const ignores =
|
|
33
|
+
const ignores =
|
|
34
|
+
(options.ignoreRoutes instanceof Array && options.ignoreRoutes) || []
|
|
34
35
|
for (let i = 0; i < ignores.length; i++) {
|
|
35
36
|
if (options.getPath(req).indexOf(ignores[i]) > -1) return next()
|
|
36
37
|
}
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
const i18n = i18next.cloneInstance({ initImmediate: false })
|
|
40
|
-
i18n.on('languageChanged',
|
|
41
|
+
i18n.on('languageChanged', lng => {
|
|
42
|
+
// Keep language in sync
|
|
41
43
|
req.language = req.locale = req.lng = lng
|
|
42
44
|
|
|
45
|
+
if (options.attachLocals) res.locals = res.locals || {}
|
|
43
46
|
if (res.locals) {
|
|
44
47
|
res.locals.language = lng
|
|
45
48
|
res.locals.languageDir = i18next.dir(lng)
|
|
@@ -57,7 +60,9 @@ export function handle (i18next, options = {}) {
|
|
|
57
60
|
})
|
|
58
61
|
|
|
59
62
|
let lng = req.lng
|
|
60
|
-
if (!lng && i18next.services.languageDetector)
|
|
63
|
+
if (!lng && i18next.services.languageDetector) {
|
|
64
|
+
lng = i18next.services.languageDetector.detect(req, res)
|
|
65
|
+
}
|
|
61
66
|
|
|
62
67
|
// set locale
|
|
63
68
|
req.language = req.locale = req.lng = lng
|
|
@@ -70,7 +75,13 @@ export function handle (i18next, options = {}) {
|
|
|
70
75
|
i18n.changeLanguage(lng || i18next.options.fallbackLng[0])
|
|
71
76
|
|
|
72
77
|
if (req.i18nextLookupName === 'path' && options.removeLngFromUrl) {
|
|
73
|
-
options.setUrl(
|
|
78
|
+
options.setUrl(
|
|
79
|
+
req,
|
|
80
|
+
utils.removeLngFromUrl(
|
|
81
|
+
options.getUrl(req),
|
|
82
|
+
i18next.services.languageDetector.options.lookupFromPathIndex
|
|
83
|
+
)
|
|
84
|
+
)
|
|
74
85
|
}
|
|
75
86
|
|
|
76
87
|
const t = i18n.t.bind(i18n)
|
|
@@ -81,6 +92,7 @@ export function handle (i18next, options = {}) {
|
|
|
81
92
|
req.t = t
|
|
82
93
|
|
|
83
94
|
// assert for res -> template
|
|
95
|
+
if (options.attachLocals) res.locals = res.locals || {}
|
|
84
96
|
if (res.locals) {
|
|
85
97
|
res.locals.t = t
|
|
86
98
|
res.locals.exists = exists
|
|
@@ -89,7 +101,9 @@ export function handle (i18next, options = {}) {
|
|
|
89
101
|
res.locals.languageDir = i18next.dir(lng)
|
|
90
102
|
}
|
|
91
103
|
|
|
92
|
-
if (i18next.services.languageDetector)
|
|
104
|
+
if (i18next.services.languageDetector) {
|
|
105
|
+
i18next.services.languageDetector.cacheUserLanguage(req, res, lng)
|
|
106
|
+
}
|
|
93
107
|
// load resources
|
|
94
108
|
if (!req.lng) return next()
|
|
95
109
|
i18next.loadLanguages(req.lng, () => next())
|
|
@@ -97,10 +111,33 @@ export function handle (i18next, options = {}) {
|
|
|
97
111
|
}
|
|
98
112
|
|
|
99
113
|
export function plugin (instance, options, next) {
|
|
114
|
+
options.attachLocals = true
|
|
100
115
|
const middleware = handle(options.i18next, options)
|
|
101
|
-
instance.addHook('preHandler', (request, reply, next) =>
|
|
116
|
+
instance.addHook('preHandler', (request, reply, next) =>
|
|
117
|
+
middleware(request, reply, next)
|
|
118
|
+
)
|
|
102
119
|
return next()
|
|
103
120
|
}
|
|
121
|
+
|
|
122
|
+
export const hapiPlugin = {
|
|
123
|
+
name: 'i18next-http-middleware',
|
|
124
|
+
version: '1',
|
|
125
|
+
register: (server, options) => {
|
|
126
|
+
options.attachLocals = true
|
|
127
|
+
const middleware = handle(options.i18next, {
|
|
128
|
+
...options
|
|
129
|
+
})
|
|
130
|
+
server.ext('onPreHandler', (request, h) => {
|
|
131
|
+
middleware(
|
|
132
|
+
request,
|
|
133
|
+
request.raw.res || h.response() || request.Response,
|
|
134
|
+
() => h.continue
|
|
135
|
+
)
|
|
136
|
+
return h.continue
|
|
137
|
+
})
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
104
141
|
plugin[Symbol.for('skip-override')] = true
|
|
105
142
|
|
|
106
143
|
export function getResourcesHandler (i18next, options = {}) {
|
|
@@ -112,32 +149,55 @@ export function getResourcesHandler (i18next, options = {}) {
|
|
|
112
149
|
|
|
113
150
|
if (!i18next.services.backendConnector) {
|
|
114
151
|
options.setStatus(res, 404)
|
|
115
|
-
return options.send(
|
|
152
|
+
return options.send(
|
|
153
|
+
res,
|
|
154
|
+
'i18next-express-middleware:: no backend configured'
|
|
155
|
+
)
|
|
116
156
|
}
|
|
117
157
|
|
|
118
158
|
const resources = {}
|
|
119
159
|
|
|
120
160
|
options.setContentType(res, 'application/json')
|
|
121
|
-
if (
|
|
161
|
+
if (
|
|
162
|
+
options.cache !== undefined
|
|
163
|
+
? options.cache
|
|
164
|
+
: typeof process !== 'undefined' &&
|
|
165
|
+
process.env &&
|
|
166
|
+
process.env.NODE_ENV === 'production'
|
|
167
|
+
) {
|
|
122
168
|
options.setHeader(res, 'Cache-Control', 'public, max-age=' + maxAge)
|
|
123
|
-
options.setHeader(
|
|
169
|
+
options.setHeader(
|
|
170
|
+
res,
|
|
171
|
+
'Expires',
|
|
172
|
+
new Date(new Date().getTime() + maxAge * 1000).toUTCString()
|
|
173
|
+
)
|
|
124
174
|
} else {
|
|
125
175
|
options.setHeader(res, 'Pragma', 'no-cache')
|
|
126
176
|
options.setHeader(res, 'Cache-Control', 'no-cache')
|
|
127
177
|
}
|
|
128
178
|
|
|
129
|
-
const languages = options.getQuery(req)[options.lngParam || 'lng']
|
|
130
|
-
|
|
179
|
+
const languages = options.getQuery(req)[options.lngParam || 'lng']
|
|
180
|
+
? options.getQuery(req)[options.lngParam || 'lng'].split(' ')
|
|
181
|
+
: []
|
|
182
|
+
const namespaces = options.getQuery(req)[options.nsParam || 'ns']
|
|
183
|
+
? options.getQuery(req)[options.nsParam || 'ns'].split(' ')
|
|
184
|
+
: []
|
|
131
185
|
|
|
132
186
|
// extend ns
|
|
133
187
|
namespaces.forEach(ns => {
|
|
134
|
-
if (i18next.options.ns && i18next.options.ns.indexOf(ns) < 0)
|
|
188
|
+
if (i18next.options.ns && i18next.options.ns.indexOf(ns) < 0) {
|
|
189
|
+
i18next.options.ns.push(ns)
|
|
190
|
+
}
|
|
135
191
|
})
|
|
136
192
|
|
|
137
193
|
i18next.services.backendConnector.load(languages, namespaces, function () {
|
|
138
194
|
languages.forEach(lng => {
|
|
139
195
|
namespaces.forEach(ns => {
|
|
140
|
-
utils.setPath(
|
|
196
|
+
utils.setPath(
|
|
197
|
+
resources,
|
|
198
|
+
[lng, ns],
|
|
199
|
+
i18next.getResourceBundle(lng, ns)
|
|
200
|
+
)
|
|
141
201
|
})
|
|
142
202
|
})
|
|
143
203
|
})
|
|
@@ -157,7 +217,10 @@ export function missingKeyHandler (i18next, options = {}) {
|
|
|
157
217
|
|
|
158
218
|
if (!i18next.services.backendConnector) {
|
|
159
219
|
options.setStatus(res, 404)
|
|
160
|
-
return options.send(
|
|
220
|
+
return options.send(
|
|
221
|
+
res,
|
|
222
|
+
'i18next-express-middleware:: no backend configured'
|
|
223
|
+
)
|
|
161
224
|
}
|
|
162
225
|
|
|
163
226
|
const body = options.getBody(req)
|
|
@@ -165,8 +228,8 @@ export function missingKeyHandler (i18next, options = {}) {
|
|
|
165
228
|
if (typeof body === 'function') {
|
|
166
229
|
const promise = body()
|
|
167
230
|
if (promise && typeof promise.then === 'function') {
|
|
168
|
-
return new Promise(
|
|
169
|
-
promise.then(
|
|
231
|
+
return new Promise(resolve => {
|
|
232
|
+
promise.then(b => {
|
|
170
233
|
for (const m in b) {
|
|
171
234
|
i18next.services.backendConnector.saveMissing([lng], ns, m, b[m])
|
|
172
235
|
}
|
|
@@ -216,6 +279,7 @@ export function addRoute (i18next, route, lngs, app, verb, fc) {
|
|
|
216
279
|
|
|
217
280
|
export default {
|
|
218
281
|
plugin,
|
|
282
|
+
hapiPlugin,
|
|
219
283
|
handle,
|
|
220
284
|
getResourcesHandler,
|
|
221
285
|
missingKeyHandler,
|
package/licence
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "i18next-http-middleware",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./cjs/index.js",
|
|
@@ -21,26 +21,27 @@
|
|
|
21
21
|
"module": "./esm/index.js",
|
|
22
22
|
"dependencies": {},
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@babel/cli": "7.
|
|
25
|
-
"@babel/core": "7.
|
|
26
|
-
"@babel/preset-env": "7.
|
|
27
|
-
"@
|
|
24
|
+
"@babel/cli": "7.16.0",
|
|
25
|
+
"@babel/core": "7.16.5",
|
|
26
|
+
"@babel/preset-env": "7.16.5",
|
|
27
|
+
"@hapi/hapi": "^20.2.1",
|
|
28
|
+
"@types/express-serve-static-core": "^4.17.27",
|
|
28
29
|
"babel-plugin-add-module-exports": "1.0.4",
|
|
29
|
-
"eslint": "7.
|
|
30
|
-
"eslint-config-standard": "16.0.
|
|
31
|
-
"eslint-plugin-import": "2.
|
|
30
|
+
"eslint": "7.29.0",
|
|
31
|
+
"eslint-config-standard": "16.0.3",
|
|
32
|
+
"eslint-plugin-import": "2.25.3",
|
|
32
33
|
"eslint-plugin-node": "11.1.0",
|
|
33
|
-
"eslint-plugin-promise": "
|
|
34
|
+
"eslint-plugin-promise": "5.1.0",
|
|
34
35
|
"eslint-plugin-require-path-exists": "1.1.9",
|
|
35
36
|
"eslint-plugin-standard": "5.0.0",
|
|
36
37
|
"expect.js": "0.3.1",
|
|
37
|
-
"express": "4.17.
|
|
38
|
-
"fastify": "3.
|
|
39
|
-
"i18next": "
|
|
40
|
-
"mocha": "
|
|
41
|
-
"supertest": "6.
|
|
42
|
-
"tsd": "0.
|
|
43
|
-
"uglify-js": "3.
|
|
38
|
+
"express": "4.17.2",
|
|
39
|
+
"fastify": "3.25.2",
|
|
40
|
+
"i18next": "21.6.3",
|
|
41
|
+
"mocha": "9.1.3",
|
|
42
|
+
"supertest": "6.1.6",
|
|
43
|
+
"tsd": "0.19.0",
|
|
44
|
+
"uglify-js": "3.14.5"
|
|
44
45
|
},
|
|
45
46
|
"description": "i18next-http-middleware is a middleware to be used with Node.js web frameworks like express or Fastify and also for Deno.",
|
|
46
47
|
"keywords": [
|
|
@@ -57,12 +58,7 @@
|
|
|
57
58
|
"bugs": {
|
|
58
59
|
"url": "https://github.com/i18next/i18next-http-middleware/issues"
|
|
59
60
|
},
|
|
60
|
-
"
|
|
61
|
-
{
|
|
62
|
-
"type": "MIT",
|
|
63
|
-
"url": "https://raw.github.com/i18next/i18next-http-middleware/master/licence"
|
|
64
|
-
}
|
|
65
|
-
],
|
|
61
|
+
"license": "MIT",
|
|
66
62
|
"scripts": {
|
|
67
63
|
"lint": "eslint .",
|
|
68
64
|
"compile:esm": "rm -rf esm && mkdir esm && BABEL_ENV=esm babel lib -d esm",
|
package/CHANGELOG.md
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
## [v3.1.3](https://github.com/i18next/i18next-http-middleware/compare/v3.1.2...v3.1.3)
|
|
2
|
-
- optimize getQuery() function to check if req.query is iterable
|
|
3
|
-
|
|
4
|
-
## [v3.1.2](https://github.com/i18next/i18next-http-middleware/compare/v3.1.1...v3.1.2)
|
|
5
|
-
- fix the type of the lookup method [#37](https://github.com/i18next/i18next-http-middleware/pull/37)
|
|
6
|
-
|
|
7
|
-
## [v3.1.1](https://github.com/i18next/i18next-http-middleware/compare/v3.1.0...v3.1.1)
|
|
8
|
-
- make sure no undefined language is detected
|
|
9
|
-
|
|
10
|
-
## [v3.1.0](https://github.com/i18next/i18next-http-middleware/compare/v3.0.6...v3.1.0)
|
|
11
|
-
- added types
|
|
12
|
-
|
|
13
|
-
## [v3.0.6](https://github.com/i18next/i18next-http-middleware/compare/v3.0.5...v3.0.6)
|
|
14
|
-
- ignoreCase option true by default
|
|
15
|
-
|
|
16
|
-
## [v3.0.5](https://github.com/i18next/i18next-http-middleware/compare/v3.0.4...v3.0.5)
|
|
17
|
-
- introduce ignoreCase option
|
|
18
|
-
|
|
19
|
-
## [v3.0.4](https://github.com/i18next/i18next-http-middleware/compare/v3.0.3...v3.0.4)
|
|
20
|
-
- fix language detection algorithm to handle fallbackLng correctly
|
|
21
|
-
|
|
22
|
-
## [v3.0.3](https://github.com/i18next/i18next-http-middleware/compare/v3.0.2...v3.0.3)
|
|
23
|
-
- prevent URIError with cookie language detector
|
|
24
|
-
|
|
25
|
-
## [v3.0.2](https://github.com/i18next/i18next-http-middleware/compare/v3.0.1...v3.0.2)
|
|
26
|
-
- transpile also esm
|
|
27
|
-
|
|
28
|
-
## [v3.0.1](https://github.com/i18next/i18next-http-middleware/compare/v3.0.0...v3.0.1)
|
|
29
|
-
- introduce lookupHeaderRegex option
|
|
30
|
-
|
|
31
|
-
## [v3.0.0](https://github.com/i18next/i18next-http-middleware/compare/v2.1.2...v3.0.0)
|
|
32
|
-
- **BREAKING** needs i18next >= 19.5.0
|
|
33
|
-
- let i18next figure out which detected lng is best match
|
|
34
|
-
|
|
35
|
-
## [v2.1.2](https://github.com/i18next/i18next-http-middleware/compare/v2.1.1...v2.1.2)
|
|
36
|
-
- fix: get whitelist from correct property
|
|
37
|
-
|
|
38
|
-
## [v2.1.1](https://github.com/i18next/i18next-http-middleware/compare/v2.1.0...v2.1.1)
|
|
39
|
-
- extend httpFunctions getQuery to handle some edge cases
|
|
40
|
-
|
|
41
|
-
## [v2.1.0](https://github.com/i18next/i18next-http-middleware/compare/v2.0.0...v2.1.0)
|
|
42
|
-
- LanguageDetector: cookie, new option: cookiePath
|
|
43
|
-
|
|
44
|
-
## [v2.0.0](https://github.com/i18next/i18next-http-middleware/compare/v1.3.1...v2.0.0)
|
|
45
|
-
- potentially BREAKING: change cookie defaults: cookieSameSite: 'strict'
|