i18next-http-middleware 3.0.4 → 3.1.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/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ## [v3.1.1](https://github.com/i18next/i18next-http-middleware/compare/v3.1.0...v3.1.1)
2
+ - make sure no undefined language is detected
3
+
4
+ ## [v3.1.0](https://github.com/i18next/i18next-http-middleware/compare/v3.0.6...v3.1.0)
5
+ - added types
6
+
7
+ ## [v3.0.6](https://github.com/i18next/i18next-http-middleware/compare/v3.0.5...v3.0.6)
8
+ - ignoreCase option true by default
9
+
10
+ ## [v3.0.5](https://github.com/i18next/i18next-http-middleware/compare/v3.0.4...v3.0.5)
11
+ - introduce ignoreCase option
12
+
1
13
  ## [v3.0.4](https://github.com/i18next/i18next-http-middleware/compare/v3.0.3...v3.0.4)
2
14
  - fix language detection algorithm to handle fallbackLng correctly
3
15
 
package/README.md CHANGED
@@ -296,6 +296,8 @@ As with all modules you can either pass the constructor function (class) to the
296
296
  // cache user language
297
297
  caches: false, // ['cookie']
298
298
 
299
+ ignoreCase: true, // ignore case of detected language
300
+
299
301
  // optional expire and domain for set cookie
300
302
  cookieExpirationDate: new Date(),
301
303
  cookieDomain: 'myDomain',
@@ -41,7 +41,8 @@ function getDefaults() {
41
41
  lookupSession: 'lng',
42
42
  lookupFromPathIndex: 0,
43
43
  caches: false,
44
- cookieSameSite: 'strict'
44
+ cookieSameSite: 'strict',
45
+ ignoreCase: true
45
46
  });
46
47
  }
47
48
 
@@ -91,10 +92,23 @@ var LanguageDetector = function () {
91
92
 
92
93
  if (!detections) return;
93
94
  if (!Array.isArray(detections)) detections = [detections];
95
+ detections = detections.filter(function (d) {
96
+ return d !== undefined && d !== null;
97
+ });
94
98
 
95
99
  if (_this.services.languageUtils.getBestMatchFromCodes) {
96
100
  found = _this.services.languageUtils.getBestMatchFromCodes(detections);
97
- if (found && detections.indexOf(found) < 0) found = undefined;
101
+
102
+ if (found) {
103
+ if (_this.options.ignoreCase) {
104
+ if (detections.map(function (d) {
105
+ return d.toLowerCase();
106
+ }).indexOf(found.toLowerCase()) < 0) found = undefined;
107
+ } else {
108
+ if (detections.indexOf(found) < 0) found = undefined;
109
+ }
110
+ }
111
+
98
112
  if (found) req.i18nextLookupName = detectorName;
99
113
  } else {
100
114
  found = detections.length > 0 ? detections[0] : null;
@@ -90,7 +90,8 @@ var getCookies = function getCookies(req) {
90
90
  exports.getCookies = getCookies;
91
91
 
92
92
  var getBody = function getBody(req) {
93
- if (req.ctx && req.ctx.body) return req.ctx.body.bind(req.ctx);
93
+ if (req.ctx && typeof req.ctx.body === 'function') return req.ctx.body.bind(req.ctx);
94
+ if (req.ctx && req.ctx.body) return req.ctx.body;
94
95
  if (req.json) return req.json;
95
96
  if (req.body) return req.body;
96
97
  console.log('no possibility found to get body');
@@ -80,7 +80,7 @@ var _default = {
80
80
 
81
81
  if (options.lookupCookie && typeof req !== 'undefined') {
82
82
  var cookies = options.getCookies(req);
83
- found = cookies[options.lookupCookie];
83
+ if (cookies) found = cookies[options.lookupCookie];
84
84
  }
85
85
 
86
86
  return found;
@@ -20,7 +20,8 @@ function getDefaults() {
20
20
  lookupSession: 'lng',
21
21
  lookupFromPathIndex: 0,
22
22
  caches: false,
23
- cookieSameSite: 'strict'
23
+ cookieSameSite: 'strict',
24
+ ignoreCase: true
24
25
  });
25
26
  }
26
27
 
@@ -70,10 +71,23 @@ var LanguageDetector = function () {
70
71
 
71
72
  if (!detections) return;
72
73
  if (!Array.isArray(detections)) detections = [detections];
74
+ detections = detections.filter(function (d) {
75
+ return d !== undefined && d !== null;
76
+ });
73
77
 
74
78
  if (_this.services.languageUtils.getBestMatchFromCodes) {
75
79
  found = _this.services.languageUtils.getBestMatchFromCodes(detections);
76
- if (found && detections.indexOf(found) < 0) found = undefined;
80
+
81
+ if (found) {
82
+ if (_this.options.ignoreCase) {
83
+ if (detections.map(function (d) {
84
+ return d.toLowerCase();
85
+ }).indexOf(found.toLowerCase()) < 0) found = undefined;
86
+ } else {
87
+ if (detections.indexOf(found) < 0) found = undefined;
88
+ }
89
+ }
90
+
77
91
  if (found) req.i18nextLookupName = detectorName;
78
92
  } else {
79
93
  found = detections.length > 0 ? detections[0] : null;
@@ -59,7 +59,8 @@ export var getCookies = function getCookies(req) {
59
59
  console.log('no possibility found to get cookies');
60
60
  };
61
61
  export var getBody = function getBody(req) {
62
- if (req.ctx && req.ctx.body) return req.ctx.body.bind(req.ctx);
62
+ if (req.ctx && typeof req.ctx.body === 'function') return req.ctx.body.bind(req.ctx);
63
+ if (req.ctx && req.ctx.body) return req.ctx.body;
63
64
  if (req.json) return req.json;
64
65
  if (req.body) return req.body;
65
66
  console.log('no possibility found to get body');
@@ -74,7 +74,7 @@ export default {
74
74
 
75
75
  if (options.lookupCookie && typeof req !== 'undefined') {
76
76
  var cookies = options.getCookies(req);
77
- found = cookies[options.lookupCookie];
77
+ if (cookies) found = cookies[options.lookupCookie];
78
78
  }
79
79
 
80
80
  return found;
package/index.d.ts ADDED
@@ -0,0 +1,175 @@
1
+ import {
2
+ Application,
3
+ Handler,
4
+ NextFunction,
5
+ Request,
6
+ RequestHandler,
7
+ Response,
8
+ Router,
9
+ } from "express-serve-static-core";
10
+ import * as i18next from "i18next";
11
+
12
+ /// <reference types="express-serve-static-core" />
13
+
14
+ type I18next = i18next.i18n;
15
+ type App = Application | Router;
16
+
17
+ type I18NextRequest = {
18
+ language: string;
19
+ languages: string[];
20
+ i18n: i18next.i18n;
21
+ t: i18next.TFunction;
22
+ };
23
+
24
+ declare global {
25
+ namespace Express {
26
+ interface Request extends I18NextRequest {}
27
+ }
28
+ }
29
+
30
+ interface ExtendedOptions extends Object {
31
+ getPath?: (req: Request) => string;
32
+ getOriginalUrl?: (req: Request) => string;
33
+ getUrl?: (req: Request) => string;
34
+ setUrl?: (req: Request, url: string) => void;
35
+ getParams?: (req: Request) => Object;
36
+ getSession?: (req: Request) => Object;
37
+ getQuery?: (req: Request) => Object;
38
+ getCookies?: (req: Request) => Object;
39
+ getBody?: (req: Request) => Object;
40
+ getHeaders?: (req: Request) => Object;
41
+ getHeader?: (res: Response, name: string) => Object;
42
+ setHeader?: (res: Response, name: string, value: string) => void;
43
+ setContentType?: (res: Response, type: string) => void;
44
+ setStatus?: (res: Response, code: number) => void;
45
+ send?: (res: Response, body: any) => void;
46
+ }
47
+
48
+ interface HandleOptions extends ExtendedOptions {
49
+ ignoreRoutes?: string[] | IgnoreRoutesFunction;
50
+ removeLngFromUrl?: boolean;
51
+ }
52
+
53
+ interface GetResourcesHandlerOptions extends ExtendedOptions {
54
+ maxAge?: number;
55
+ cache?: boolean;
56
+ lngParam?: string;
57
+ nsParam?: string;
58
+ }
59
+
60
+ interface MissingKeyHandlerOptions extends ExtendedOptions {
61
+ lngParam?: string;
62
+ nsParam?: string;
63
+ }
64
+
65
+ type IgnoreRoutesFunction = (
66
+ req: Request,
67
+ res: Response,
68
+ options: HandleOptions,
69
+ i18next: I18next
70
+ ) => boolean;
71
+
72
+ export function handle(i18next: I18next, options?: HandleOptions): Handler;
73
+
74
+ export function plugin(
75
+ instance: any,
76
+ options: HandleOptions & { i18next?: I18next },
77
+ next: NextFunction
78
+ ): Handler;
79
+
80
+ export function getResourcesHandler(
81
+ i18next: I18next,
82
+ options?: GetResourcesHandlerOptions
83
+ ): Handler;
84
+
85
+ export function missingKeyHandler(
86
+ i18next: I18next,
87
+ options?: MissingKeyHandlerOptions
88
+ ): Handler;
89
+
90
+ export function addRoute(
91
+ i18next: I18next,
92
+ route: string,
93
+ lngs: string[],
94
+ app: App,
95
+ verb: string,
96
+ fc: RequestHandler
97
+ ): void;
98
+
99
+ // LanguageDetector
100
+ type LanguageDetectorServices = any;
101
+ type LanguageDetectorOrder = string[];
102
+ type LanguageDetectorCaches = boolean | string[];
103
+ interface LanguageDetectorOptions {
104
+ order?: LanguageDetectorOrder;
105
+ lookupQuerystring?: string;
106
+ lookupCookie?: string;
107
+ lookupSession?: string;
108
+ lookupFromPathIndex?: number;
109
+ caches?: LanguageDetectorCaches;
110
+ cookieExpirationDate?: Date;
111
+ cookieDomain?: string;
112
+ }
113
+ interface LanguageDetectorAllOptions {
114
+ fallbackLng: boolean | string | string[];
115
+ }
116
+ interface LanguageDetectorInterfaceOptions {
117
+ [name: string]: any;
118
+ }
119
+ interface LanguageDetectorInterface {
120
+ name: string;
121
+
122
+ lookup: (
123
+ req: Request,
124
+ res: Response,
125
+ options?: LanguageDetectorInterfaceOptions
126
+ ) => string | string[];
127
+
128
+ cacheUserLanguage?: (
129
+ req: Request,
130
+ res: Response,
131
+ lng: string,
132
+ options?: Object
133
+ ) => void;
134
+ }
135
+
136
+ export class LanguageDetector implements i18next.Module {
137
+ type: "languageDetector";
138
+
139
+ constructor(
140
+ services: LanguageDetectorServices,
141
+ options?: LanguageDetectorOptions,
142
+ allOptions?: LanguageDetectorAllOptions
143
+ );
144
+
145
+ constructor(
146
+ options?: LanguageDetectorOptions,
147
+ allOptions?: LanguageDetectorAllOptions
148
+ );
149
+
150
+ init(
151
+ services: LanguageDetectorServices,
152
+ options?: LanguageDetectorOptions,
153
+ allOptions?: LanguageDetectorAllOptions
154
+ ): void;
155
+
156
+ init(
157
+ options?: LanguageDetectorOptions,
158
+ allOptions?: LanguageDetectorAllOptions
159
+ ): void;
160
+
161
+ addDetector(detector: LanguageDetectorInterface): void;
162
+
163
+ detect(
164
+ req: Request,
165
+ res: Response,
166
+ detectionOrder: LanguageDetectorOrder
167
+ ): void;
168
+
169
+ cacheUserLanguage(
170
+ req: Request,
171
+ res: Response,
172
+ lng: string,
173
+ caches: LanguageDetectorCaches
174
+ ): void;
175
+ }
package/index.js CHANGED
@@ -1,2 +1,3 @@
1
+ // // @deno-types='./index.d.ts'
1
2
  import mod from './lib/index.js'
2
3
  export default mod
@@ -19,7 +19,8 @@ function getDefaults () {
19
19
  // cookieExpirationDate: new Date(),
20
20
  // cookieDomain: 'myDomain'
21
21
  // cookiePath: '/my/path'
22
- cookieSameSite: 'strict'
22
+ cookieSameSite: 'strict',
23
+ ignoreCase: true
23
24
  })
24
25
  }
25
26
 
@@ -59,9 +60,17 @@ class LanguageDetector {
59
60
  if (!detections) return
60
61
  if (!Array.isArray(detections)) detections = [detections]
61
62
 
63
+ detections = detections.filter((d) => d !== undefined && d !== null)
64
+
62
65
  if (this.services.languageUtils.getBestMatchFromCodes) { // new i18next v19.5.0
63
66
  found = this.services.languageUtils.getBestMatchFromCodes(detections)
64
- if (found && detections.indexOf(found) < 0) found = undefined
67
+ if (found) {
68
+ if (this.options.ignoreCase) {
69
+ if (detections.map(d => d.toLowerCase()).indexOf(found.toLowerCase()) < 0) found = undefined
70
+ } else {
71
+ if (detections.indexOf(found) < 0) found = undefined
72
+ }
73
+ }
65
74
  if (found) req.i18nextLookupName = detectorName
66
75
  } else {
67
76
  found = detections.length > 0 ? detections[0] : null // a little backward compatibility
@@ -56,7 +56,8 @@ export const getCookies = (req) => {
56
56
  console.log('no possibility found to get cookies')
57
57
  }
58
58
  export const getBody = (req) => {
59
- if (req.ctx && req.ctx.body) return req.ctx.body.bind(req.ctx)
59
+ if (req.ctx && typeof req.ctx.body === 'function') return req.ctx.body.bind(req.ctx)
60
+ if (req.ctx && req.ctx.body) return req.ctx.body
60
61
  if (req.json) return req.json
61
62
  if (req.body) return req.body
62
63
  console.log('no possibility found to get body')
package/lib/index.js CHANGED
@@ -31,7 +31,7 @@ export function handle (i18next, options = {}) {
31
31
  }
32
32
  } else {
33
33
  const ignores = (options.ignoreRoutes instanceof Array && options.ignoreRoutes) || []
34
- for (var i = 0; i < ignores.length; i++) {
34
+ for (let i = 0; i < ignores.length; i++) {
35
35
  if (options.getPath(req).indexOf(ignores[i]) > -1) return next()
36
36
  }
37
37
  }
@@ -167,7 +167,7 @@ export function missingKeyHandler (i18next, options = {}) {
167
167
  if (promise && typeof promise.then === 'function') {
168
168
  return new Promise((resolve) => {
169
169
  promise.then((b) => {
170
- for (var m in b) {
170
+ for (const m in b) {
171
171
  i18next.services.backendConnector.saveMissing([lng], ns, m, b[m])
172
172
  }
173
173
  resolve(options.send(res, 'ok'))
@@ -176,7 +176,7 @@ export function missingKeyHandler (i18next, options = {}) {
176
176
  }
177
177
  }
178
178
 
179
- for (var m in body) {
179
+ for (const m in body) {
180
180
  i18next.services.backendConnector.saveMissing([lng], ns, m, body[m])
181
181
  }
182
182
 
@@ -61,7 +61,7 @@ export default {
61
61
 
62
62
  if (options.lookupCookie && typeof req !== 'undefined') {
63
63
  const cookies = options.getCookies(req)
64
- found = cookies[options.lookupCookie]
64
+ if (cookies) found = cookies[options.lookupCookie]
65
65
  }
66
66
 
67
67
  return found
package/lib/utils.js CHANGED
@@ -22,7 +22,7 @@ const slice = arr.slice
22
22
  export function defaults (obj) {
23
23
  each.call(slice.call(arguments, 1), function (source) {
24
24
  if (source) {
25
- for (var prop in source) {
25
+ for (const prop in source) {
26
26
  if (obj[prop] === undefined) obj[prop] = source[prop]
27
27
  }
28
28
  }
@@ -33,7 +33,7 @@ export function defaults (obj) {
33
33
  export function extend (obj) {
34
34
  each.call(slice.call(arguments, 1), function (source) {
35
35
  if (source) {
36
- for (var prop in source) {
36
+ for (const prop in source) {
37
37
  obj[prop] = source[prop]
38
38
  }
39
39
  }
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "i18next-http-middleware",
3
- "version": "3.0.4",
3
+ "version": "3.1.1",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./cjs/index.js",
7
+ "types": "./index.d.ts",
7
8
  "exports": {
8
9
  "./package.json": "./package.json",
9
10
  ".": {
@@ -20,24 +21,26 @@
20
21
  "module": "./esm/index.js",
21
22
  "dependencies": {},
22
23
  "devDependencies": {
23
- "@babel/cli": "7.10.5",
24
- "@babel/core": "7.11.4",
25
- "@babel/preset-env": "7.11.0",
26
- "babel-plugin-add-module-exports": "1.0.2",
27
- "eslint": "7.7.0",
28
- "eslint-config-standard": "14.1.1",
29
- "eslint-plugin-import": "2.22.0",
24
+ "@babel/cli": "7.12.10",
25
+ "@babel/core": "7.12.10",
26
+ "@babel/preset-env": "7.12.11",
27
+ "@types/express-serve-static-core": "^4.17.18",
28
+ "babel-plugin-add-module-exports": "1.0.4",
29
+ "eslint": "7.17.0",
30
+ "eslint-config-standard": "16.0.2",
31
+ "eslint-plugin-import": "2.22.1",
30
32
  "eslint-plugin-node": "11.1.0",
31
33
  "eslint-plugin-promise": "4.2.1",
32
34
  "eslint-plugin-require-path-exists": "1.1.9",
33
- "eslint-plugin-standard": "4.0.1",
35
+ "eslint-plugin-standard": "5.0.0",
34
36
  "expect.js": "0.3.1",
35
37
  "express": "4.17.1",
36
- "fastify": "3.3.0",
37
- "i18next": "19.7.0",
38
- "mocha": "8.1.3",
39
- "supertest": "4.0.2",
40
- "uglify-js": "3.10.3"
38
+ "fastify": "3.9.2",
39
+ "i18next": "19.8.4",
40
+ "mocha": "8.2.1",
41
+ "supertest": "6.0.1",
42
+ "tsd": "0.14.0",
43
+ "uglify-js": "3.12.4"
41
44
  },
42
45
  "description": "i18next-http-middleware is a middleware to be used with Node.js web frameworks like express or Fastify and also for Deno.",
43
46
  "keywords": [
@@ -66,9 +69,13 @@
66
69
  "compile:cjs": "rm -rf cjs && mkdir cjs && BABEL_ENV=cjs babel lib -d cjs && echo '{\"type\":\"commonjs\"}' > cjs/package.json",
67
70
  "compile": "npm run compile:esm && npm run compile:cjs",
68
71
  "build": "npm run compile",
69
- "test": "npm run lint && npm run build && mocha test -R spec --exit --experimental-modules",
70
- "test:deno": "deno test test/deno/*.js --allow-net --no-check",
72
+ "test": "npm run lint && npm run build && mocha test -R spec --exit --experimental-modules && npm run test:types",
73
+ "test:deno": "deno test --allow-net test/deno/*.js",
74
+ "test:types": "tsd",
71
75
  "preversion": "npm run test && npm run build && git push",
72
76
  "postversion": "git push && git push --tags"
77
+ },
78
+ "tsd": {
79
+ "directory": "test/types"
73
80
  }
74
81
  }