i18next-http-middleware 3.1.5 → 3.2.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/README.md CHANGED
@@ -5,11 +5,14 @@
5
5
  [![Travis](https://img.shields.io/travis/i18next/i18next-http-middleware/master.svg?style=flat-square)](https://travis-ci.org/i18next/i18next-http-middleware)
6
6
  [![npm version](https://img.shields.io/npm/v/i18next-http-middleware.svg?style=flat-square)](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
- *It's not bound to a specific http framework anymore.*
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 "https://deno.land/x/dotenv/dotenv.ts";
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
- handle(c.request, c.response, () => {})
118
- return next(c)
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 "https://deno.land/x/dotenv/dotenv.ts";
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
  }
@@ -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') return Object.fromEntries(req.query);
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') return req.ctx.body.bind(req.ctx);
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
- if (res.responseHeaders && typeof res.responseHeaders.set === 'function') return res.responseHeaders.set(name, value);
118
- if (res.headers && typeof res.headers.set === 'function') return res.headers.set(name, value);
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
@@ -10,6 +10,7 @@ exports.addRoute = addRoute;
10
10
  exports.default = void 0;
11
11
  exports.getResourcesHandler = getResourcesHandler;
12
12
  exports.handle = handle;
13
+ exports.hapiPlugin = void 0;
13
14
  exports.missingKeyHandler = missingKeyHandler;
14
15
  exports.plugin = plugin;
15
16
 
@@ -25,6 +26,12 @@ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "functio
25
26
 
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; }
27
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; }
30
+
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; }
34
+
28
35
  var LanguageDetector = _LanguageDetector.default;
29
36
  exports.LanguageDetector = LanguageDetector;
30
37
 
@@ -92,7 +99,11 @@ function handle(i18next) {
92
99
  }
93
100
  });
94
101
  var lng = req.lng;
95
- if (!lng && i18next.services.languageDetector) lng = i18next.services.languageDetector.detect(req, res);
102
+
103
+ if (!lng && i18next.services.languageDetector) {
104
+ lng = i18next.services.languageDetector.detect(req, res);
105
+ }
106
+
96
107
  req.language = req.locale = req.lng = lng;
97
108
 
98
109
  if (lng && options.getHeader(res, 'Content-Language') !== lng) {
@@ -120,7 +131,10 @@ function handle(i18next) {
120
131
  res.locals.languageDir = i18next.dir(lng);
121
132
  }
122
133
 
123
- if (i18next.services.languageDetector) i18next.services.languageDetector.cacheUserLanguage(req, res, lng);
134
+ if (i18next.services.languageDetector) {
135
+ i18next.services.languageDetector.cacheUserLanguage(req, res, lng);
136
+ }
137
+
124
138
  if (!req.lng) return next();
125
139
  i18next.loadLanguages(req.lng, function () {
126
140
  return next();
@@ -137,6 +151,21 @@ function plugin(instance, options, next) {
137
151
  return next();
138
152
  }
139
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('onPreAuth', 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;
140
169
  plugin[Symbol.for('skip-override')] = true;
141
170
 
142
171
  function getResourcesHandler(i18next) {
@@ -167,7 +196,9 @@ function getResourcesHandler(i18next) {
167
196
  var languages = options.getQuery(req)[options.lngParam || 'lng'] ? options.getQuery(req)[options.lngParam || 'lng'].split(' ') : [];
168
197
  var namespaces = options.getQuery(req)[options.nsParam || 'ns'] ? options.getQuery(req)[options.nsParam || 'ns'].split(' ') : [];
169
198
  namespaces.forEach(function (ns) {
170
- if (i18next.options.ns && i18next.options.ns.indexOf(ns) < 0) i18next.options.ns.push(ns);
199
+ if (i18next.options.ns && i18next.options.ns.indexOf(ns) < 0) {
200
+ i18next.options.ns.push(ns);
201
+ }
171
202
  });
172
203
  i18next.services.backendConnector.load(languages, namespaces, function () {
173
204
  languages.forEach(function (lng) {
@@ -255,6 +286,7 @@ function addRoute(i18next, route, lngs, app, verb, fc) {
255
286
 
256
287
  var _default = {
257
288
  plugin: plugin,
289
+ hapiPlugin: hapiPlugin,
258
290
  handle: handle,
259
291
  getResourcesHandler: getResourcesHandler,
260
292
  missingKeyHandler: missingKeyHandler,
@@ -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') return Object.fromEntries(req.query);
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') return req.ctx.body.bind(req.ctx);
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
- if (res.responseHeaders && typeof res.responseHeaders.set === 'function') return res.responseHeaders.set(name, value);
81
- if (res.headers && typeof res.headers.set === 'function') return res.headers.set(name, value);
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';
@@ -67,7 +73,11 @@ export function handle(i18next) {
67
73
  }
68
74
  });
69
75
  var lng = req.lng;
70
- if (!lng && i18next.services.languageDetector) lng = i18next.services.languageDetector.detect(req, res);
76
+
77
+ if (!lng && i18next.services.languageDetector) {
78
+ lng = i18next.services.languageDetector.detect(req, res);
79
+ }
80
+
71
81
  req.language = req.locale = req.lng = lng;
72
82
 
73
83
  if (lng && options.getHeader(res, 'Content-Language') !== lng) {
@@ -95,7 +105,10 @@ export function handle(i18next) {
95
105
  res.locals.languageDir = i18next.dir(lng);
96
106
  }
97
107
 
98
- if (i18next.services.languageDetector) i18next.services.languageDetector.cacheUserLanguage(req, res, lng);
108
+ if (i18next.services.languageDetector) {
109
+ i18next.services.languageDetector.cacheUserLanguage(req, res, lng);
110
+ }
111
+
99
112
  if (!req.lng) return next();
100
113
  i18next.loadLanguages(req.lng, function () {
101
114
  return next();
@@ -110,6 +123,20 @@ export function plugin(instance, options, next) {
110
123
  });
111
124
  return next();
112
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('onPreAuth', 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
+ };
113
140
  plugin[Symbol.for('skip-override')] = true;
114
141
  export function getResourcesHandler(i18next) {
115
142
  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
@@ -139,7 +166,9 @@ export function getResourcesHandler(i18next) {
139
166
  var languages = options.getQuery(req)[options.lngParam || 'lng'] ? options.getQuery(req)[options.lngParam || 'lng'].split(' ') : [];
140
167
  var namespaces = options.getQuery(req)[options.nsParam || 'ns'] ? options.getQuery(req)[options.nsParam || 'ns'].split(' ') : [];
141
168
  namespaces.forEach(function (ns) {
142
- if (i18next.options.ns && i18next.options.ns.indexOf(ns) < 0) i18next.options.ns.push(ns);
169
+ if (i18next.options.ns && i18next.options.ns.indexOf(ns) < 0) {
170
+ i18next.options.ns.push(ns);
171
+ }
143
172
  });
144
173
  i18next.services.backendConnector.load(languages, namespaces, function () {
145
174
  languages.forEach(function (lng) {
@@ -224,6 +253,7 @@ export function addRoute(i18next, route, lngs, app, verb, fc) {
224
253
  }
225
254
  export default {
226
255
  plugin: plugin,
256
+ hapiPlugin: hapiPlugin,
227
257
  handle: handle,
228
258
  getResourcesHandler: getResourcesHandler,
229
259
  missingKeyHandler: missingKeyHandler,
package/index.d.ts CHANGED
@@ -27,6 +27,10 @@ declare global {
27
27
  }
28
28
  }
29
29
 
30
+ declare module 'fastify' {
31
+ interface FastifyRequest extends I18NextRequest {}
32
+ }
33
+
30
34
  interface ExtendedOptions extends Object {
31
35
  getPath?: (req: Request) => string;
32
36
  getOriginalUrl?: (req: Request) => string;
@@ -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 (req.query && typeof req.query.entries === 'function' && typeof Object.fromEntries === 'function' && typeof req.query[Symbol.iterator] === 'function') return Object.fromEntries(req.query)
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 && rc.split(';').forEach((cookie) => {
51
- const parts = cookie.split('=')
52
- list[parts.shift().trim()] = decodeURI(encodeURI(parts.join('=')))
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') return req.ctx.body.bind(req.ctx)
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') return res.responseHeaders.set(name, value)
78
- if (res.headers && typeof res.headers.set === 'function') return res.headers.set(name, value)
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,14 +30,16 @@ export function handle (i18next, options = {}) {
30
30
  return next()
31
31
  }
32
32
  } else {
33
- const ignores = (options.ignoreRoutes instanceof Array && options.ignoreRoutes) || []
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', (lng) => { // Keep language in sync
41
+ i18n.on('languageChanged', lng => {
42
+ // Keep language in sync
41
43
  req.language = req.locale = req.lng = lng
42
44
 
43
45
  if (options.attachLocals) res.locals = res.locals || {}
@@ -58,7 +60,9 @@ export function handle (i18next, options = {}) {
58
60
  })
59
61
 
60
62
  let lng = req.lng
61
- if (!lng && i18next.services.languageDetector) lng = i18next.services.languageDetector.detect(req, res)
63
+ if (!lng && i18next.services.languageDetector) {
64
+ lng = i18next.services.languageDetector.detect(req, res)
65
+ }
62
66
 
63
67
  // set locale
64
68
  req.language = req.locale = req.lng = lng
@@ -71,7 +75,13 @@ export function handle (i18next, options = {}) {
71
75
  i18n.changeLanguage(lng || i18next.options.fallbackLng[0])
72
76
 
73
77
  if (req.i18nextLookupName === 'path' && options.removeLngFromUrl) {
74
- options.setUrl(req, utils.removeLngFromUrl(options.getUrl(req), i18next.services.languageDetector.options.lookupFromPathIndex))
78
+ options.setUrl(
79
+ req,
80
+ utils.removeLngFromUrl(
81
+ options.getUrl(req),
82
+ i18next.services.languageDetector.options.lookupFromPathIndex
83
+ )
84
+ )
75
85
  }
76
86
 
77
87
  const t = i18n.t.bind(i18n)
@@ -91,7 +101,9 @@ export function handle (i18next, options = {}) {
91
101
  res.locals.languageDir = i18next.dir(lng)
92
102
  }
93
103
 
94
- if (i18next.services.languageDetector) i18next.services.languageDetector.cacheUserLanguage(req, res, lng)
104
+ if (i18next.services.languageDetector) {
105
+ i18next.services.languageDetector.cacheUserLanguage(req, res, lng)
106
+ }
95
107
  // load resources
96
108
  if (!req.lng) return next()
97
109
  i18next.loadLanguages(req.lng, () => next())
@@ -101,9 +113,31 @@ export function handle (i18next, options = {}) {
101
113
  export function plugin (instance, options, next) {
102
114
  options.attachLocals = true
103
115
  const middleware = handle(options.i18next, options)
104
- instance.addHook('preHandler', (request, reply, next) => middleware(request, reply, next))
116
+ instance.addHook('preHandler', (request, reply, next) =>
117
+ middleware(request, reply, next)
118
+ )
105
119
  return next()
106
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('onPreAuth', (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
+
107
141
  plugin[Symbol.for('skip-override')] = true
108
142
 
109
143
  export function getResourcesHandler (i18next, options = {}) {
@@ -115,32 +149,55 @@ export function getResourcesHandler (i18next, options = {}) {
115
149
 
116
150
  if (!i18next.services.backendConnector) {
117
151
  options.setStatus(res, 404)
118
- return options.send(res, 'i18next-express-middleware:: no backend configured')
152
+ return options.send(
153
+ res,
154
+ 'i18next-express-middleware:: no backend configured'
155
+ )
119
156
  }
120
157
 
121
158
  const resources = {}
122
159
 
123
160
  options.setContentType(res, 'application/json')
124
- if (options.cache !== undefined ? options.cache : typeof process !== 'undefined' && process.env && process.env.NODE_ENV === 'production') {
161
+ if (
162
+ options.cache !== undefined
163
+ ? options.cache
164
+ : typeof process !== 'undefined' &&
165
+ process.env &&
166
+ process.env.NODE_ENV === 'production'
167
+ ) {
125
168
  options.setHeader(res, 'Cache-Control', 'public, max-age=' + maxAge)
126
- options.setHeader(res, 'Expires', (new Date(new Date().getTime() + maxAge * 1000)).toUTCString())
169
+ options.setHeader(
170
+ res,
171
+ 'Expires',
172
+ new Date(new Date().getTime() + maxAge * 1000).toUTCString()
173
+ )
127
174
  } else {
128
175
  options.setHeader(res, 'Pragma', 'no-cache')
129
176
  options.setHeader(res, 'Cache-Control', 'no-cache')
130
177
  }
131
178
 
132
- const languages = options.getQuery(req)[options.lngParam || 'lng'] ? options.getQuery(req)[options.lngParam || 'lng'].split(' ') : []
133
- const namespaces = options.getQuery(req)[options.nsParam || 'ns'] ? options.getQuery(req)[options.nsParam || 'ns'].split(' ') : []
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
+ : []
134
185
 
135
186
  // extend ns
136
187
  namespaces.forEach(ns => {
137
- if (i18next.options.ns && i18next.options.ns.indexOf(ns) < 0) i18next.options.ns.push(ns)
188
+ if (i18next.options.ns && i18next.options.ns.indexOf(ns) < 0) {
189
+ i18next.options.ns.push(ns)
190
+ }
138
191
  })
139
192
 
140
193
  i18next.services.backendConnector.load(languages, namespaces, function () {
141
194
  languages.forEach(lng => {
142
195
  namespaces.forEach(ns => {
143
- utils.setPath(resources, [lng, ns], i18next.getResourceBundle(lng, ns))
196
+ utils.setPath(
197
+ resources,
198
+ [lng, ns],
199
+ i18next.getResourceBundle(lng, ns)
200
+ )
144
201
  })
145
202
  })
146
203
  })
@@ -160,7 +217,10 @@ export function missingKeyHandler (i18next, options = {}) {
160
217
 
161
218
  if (!i18next.services.backendConnector) {
162
219
  options.setStatus(res, 404)
163
- return options.send(res, 'i18next-express-middleware:: no backend configured')
220
+ return options.send(
221
+ res,
222
+ 'i18next-express-middleware:: no backend configured'
223
+ )
164
224
  }
165
225
 
166
226
  const body = options.getBody(req)
@@ -168,8 +228,8 @@ export function missingKeyHandler (i18next, options = {}) {
168
228
  if (typeof body === 'function') {
169
229
  const promise = body()
170
230
  if (promise && typeof promise.then === 'function') {
171
- return new Promise((resolve) => {
172
- promise.then((b) => {
231
+ return new Promise(resolve => {
232
+ promise.then(b => {
173
233
  for (const m in b) {
174
234
  i18next.services.backendConnector.saveMissing([lng], ns, m, b[m])
175
235
  }
@@ -219,6 +279,7 @@ export function addRoute (i18next, route, lngs, app, verb, fc) {
219
279
 
220
280
  export default {
221
281
  plugin,
282
+ hapiPlugin,
222
283
  handle,
223
284
  getResourcesHandler,
224
285
  missingKeyHandler,
package/licence CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2021 i18next
1
+ Copyright (c) 2022 i18next
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to deal
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "i18next-http-middleware",
3
- "version": "3.1.5",
3
+ "version": "3.2.1",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./cjs/index.js",
@@ -24,6 +24,7 @@
24
24
  "@babel/cli": "7.16.0",
25
25
  "@babel/core": "7.16.5",
26
26
  "@babel/preset-env": "7.16.5",
27
+ "@hapi/hapi": "^20.2.1",
27
28
  "@types/express-serve-static-core": "^4.17.27",
28
29
  "babel-plugin-add-module-exports": "1.0.4",
29
30
  "eslint": "7.29.0",