hapi-locale-17
Advanced tools
Comparing version 1.0.2 to 2.0.0
{ | ||
"name": "hapi-locale-17", | ||
"version": "1.0.2", | ||
"version": "2.0.0", | ||
"description": "Locale and language detection for Hapi v17", | ||
@@ -16,3 +16,3 @@ "main": "src/index.js", | ||
"l10n", | ||
"langauge", | ||
"language", | ||
"locale" | ||
@@ -22,3 +22,3 @@ ], | ||
"lint": "eslint . --ignore-path ./.eslintignore", | ||
"test": "NODE_ENV=test istanbul cover _mocha -- --recursive --timeout 5000 test", | ||
"test": "NODE_ENV=test istanbul cover _mocha -- --recursive test", | ||
"preversion": "npm run lint && npm test" | ||
@@ -39,10 +39,8 @@ }, | ||
"istanbul": "^0.4.5", | ||
"mocha": "^4.0.1", | ||
"sinon": "^4.1.3", | ||
"sinon-chai": "^2.14.0" | ||
"mocha": "^4.0.1" | ||
}, | ||
"dependencies": { | ||
"accept-language-parser": "^1.4.1", | ||
"rind-locale": "0.0.3" | ||
"rind-locale": "~0.0.3" | ||
} | ||
} |
@@ -5,7 +5,13 @@ # hapi-locale-17 | ||
Evaluates locale information from `accept-language` header and query parameter and attaches locale to `request.locale` available in all Hapi route handlers. | ||
Evaluates locale information from `accept-language` header and query or path parameter. | ||
Decorates Hapi request object with `request.getLocale()` available in all route handlers. | ||
If a `locale` query parameter is provided, it has highest priority. Second priority is the `accept-language` http request header. Final priority is a fallback locale. | ||
Priority of evaluation: | ||
(1) `locale` query parameter (if provided), | ||
(2) `locale` path parameter (if provided), | ||
(3) `accept-language` http request header, | ||
(4) fallback locale (the first locale in `locales` list). | ||
Target attribute `request.locale` and query parameter `locale` can be renamed. | ||
Decorated method `request.getLocale()` can be renamed. | ||
Query and path parameters `locale` can be renamed or switched off. | ||
@@ -18,4 +24,6 @@ ## Install | ||
## Example | ||
## Usage | ||
Register the plugin with Hapi server like this: | ||
```js | ||
@@ -34,4 +42,2 @@ const Hapi = require('hapi'); | ||
locales: ['de', 'en'], // your supported locales | ||
query: 'lang', // name of query param, defaults to 'locale' | ||
attribute: 'lang', // name of target attribute, defaults to 'locale' | ||
} | ||
@@ -44,1 +50,25 @@ }); | ||
``` | ||
In your route handler, do something like this: | ||
```js | ||
server.route({ | ||
method: 'GET', | ||
path: '/test', | ||
handler: function (request, h) { | ||
const locale = request.getLocale(); | ||
// ... | ||
} | ||
}); | ||
``` | ||
## Options | ||
The plugin provides the following options: | ||
| Option | Default | Description | | ||
|-----------|-------------|-------------| | ||
| `locales` | `[]` | Your list of supported locales, e.g., `['de', 'en']` or `['en-US', 'es-ES']`. | | ||
| `query` | `locale` | Name of query parameter to evaluate. Set to `false` to switch off. | | ||
| `path` | `locale` | Name of path parameter to evaluate. Set to `false` to switch off. | | ||
| `method` | `getLocale` | Name of method for request decoration, i.e., `request.getLocale()`. | |
@@ -6,26 +6,27 @@ const parser = require('accept-language-parser'); | ||
const register = (server, { | ||
locales = [], fallback = locales[0], query = 'locale', attribute = 'locale', | ||
locales = [], | ||
fallback = locales[0], | ||
query = 'locale', | ||
path = 'locale', | ||
method = 'getLocale', | ||
}) => { | ||
server.ext({ | ||
type: 'onRequest', | ||
method: (request, h) => { | ||
const setLocale = (value) => { | ||
request[attribute] = value; | ||
}; | ||
// 1. query parameter | ||
const queryParam = request.query[query]; | ||
if (queryParam) { | ||
setLocale(matcher({ locales })(queryParam) || fallback); | ||
return h.continue; | ||
server.decorate('request', method, function f() { | ||
const request = this; | ||
try { | ||
const queryValue = query ? request.query[query] : false; | ||
if (queryValue) { | ||
return matcher({ locales })(queryValue) || fallback; | ||
} | ||
// 2. http header | ||
const acceptLanguage = request.headers['accept-language']; | ||
if (acceptLanguage) { | ||
setLocale(parser.pick(locales, acceptLanguage) || fallback); | ||
return h.continue; | ||
const pathValue = path ? request.params[path] : false; | ||
if (pathValue) { | ||
return matcher({ locales })(pathValue) || fallback; | ||
} | ||
// 3. fallback | ||
setLocale(fallback); | ||
return h.continue; | ||
}, | ||
const headerValue = request.headers['accept-language']; | ||
if (headerValue) { | ||
return parser.pick(locales, headerValue) || fallback; | ||
} | ||
} catch (err) { | ||
request.log(['err', 'error'], err); | ||
} | ||
return fallback; | ||
}); | ||
@@ -32,0 +33,0 @@ }; |
const Hapi = require('hapi'); | ||
const chai = require('chai'); | ||
const chaiAsPromised = require('chai-as-promised'); | ||
const sinon = require('sinon'); | ||
const sinonChai = require('sinon-chai'); | ||
const locale = require('../src/index'); | ||
chai.use(chaiAsPromised); | ||
chai.use(sinonChai); | ||
global.chai = chai; | ||
global.sinon = sinon; | ||
global.expect = chai.expect; | ||
@@ -20,3 +16,3 @@ global.should = chai.should(); | ||
}); | ||
const test = { | ||
const route1 = { | ||
method: 'GET', | ||
@@ -26,4 +22,16 @@ path: '/test', | ||
}; | ||
const route2 = { | ||
method: 'GET', | ||
path: '/media/{locale}', | ||
handler: () => 'ok', | ||
}; | ||
const route3 = { | ||
method: 'GET', | ||
path: '/media2/{lang}', | ||
handler: () => 'ok', | ||
}; | ||
await server.register({ plugin: locale, options }); | ||
await server.route(test); | ||
await server.route(route1); | ||
await server.route(route2); | ||
await server.route(route3); | ||
await server.start(); | ||
@@ -36,3 +44,3 @@ return server; | ||
before(async () => { | ||
beforeEach(async () => { | ||
server = await setup({ | ||
@@ -43,7 +51,7 @@ locales: ['es', 'de', 'en'], | ||
after(async () => { | ||
afterEach(async () => { | ||
server.stop(); | ||
}); | ||
it('should add `locale` to request with supported `de`', () => { | ||
it('should provide `request.getLocale()` with supported `de`', () => { | ||
return server | ||
@@ -57,7 +65,7 @@ .inject({ | ||
.should.be.fulfilled.then((response) => { | ||
expect(response.request.locale).to.be.equal('de'); | ||
expect(response.request.getLocale()).to.be.equal('de'); | ||
}); | ||
}); | ||
it('should add `locale` to request with supported `de` / query param', () => { | ||
it('should provide `request.getLocale()` with supported `de` / query param', () => { | ||
return server | ||
@@ -71,9 +79,22 @@ .inject({ | ||
.should.be.fulfilled.then((response) => { | ||
expect(response.request.locale).to.be.equal('de'); | ||
expect(response.request.getLocale()).to.be.equal('de'); | ||
}); | ||
}); | ||
it('should add `locale` to request with default `es` / query param with unsupported locale', () => { | ||
it('should provide `request.getLocale()` with supported `de` / path param', () => { | ||
return server | ||
.inject({ | ||
url: '/media/de', | ||
headers: { | ||
'Accept-Language': 'en-GB;q=0.8,en-US;q=0.7,en;q=0.6', | ||
}, | ||
}) | ||
.should.be.fulfilled.then((response) => { | ||
expect(response.request.getLocale()).to.be.equal('de'); | ||
}); | ||
}); | ||
it('should provide `request.getLocale()` with default `es` / query param with unsupported locale', () => { | ||
return server | ||
.inject({ | ||
url: '/test?locale=tr', | ||
@@ -85,8 +106,21 @@ headers: { | ||
.should.be.fulfilled.then((response) => { | ||
expect(response.request.locale).to.be.equal('es'); | ||
expect(response.request.getLocale()).to.be.equal('es'); | ||
}); | ||
}); | ||
it('should provide `request.getLocale()` with default `es` / path param with unsupported locale', () => { | ||
return server | ||
.inject({ | ||
url: '/media/tr', | ||
headers: { | ||
'Accept-Language': 'q=0.9,en-GB;q=0.8,en-US;q=0.7,en;q=0.6', | ||
}, | ||
}) | ||
.should.be.fulfilled.then((response) => { | ||
expect(response.request.getLocale()).to.be.equal('es'); | ||
}); | ||
}); | ||
}); | ||
describe('hapi-locale-17 with `attribute` option', async () => { | ||
describe('hapi-locale-17 with `method` option', async () => { | ||
let server; | ||
@@ -97,3 +131,3 @@ | ||
locales: ['de', 'en'], | ||
attribute: 'lang', | ||
method: 'getLang', | ||
}); | ||
@@ -106,3 +140,3 @@ }); | ||
it('should add user-defined attribute', () => { | ||
it('should provide user-defined `request.getLang()`', () => { | ||
return server | ||
@@ -116,4 +150,3 @@ .inject({ | ||
.should.be.fulfilled.then((response) => { | ||
expect(response.request.lang).to.be.equal('en'); | ||
expect(response.request.locale).to.be.undefined; | ||
expect(response.request.getLang()).to.be.equal('en'); | ||
}); | ||
@@ -130,3 +163,4 @@ }); | ||
query: 'lang', | ||
attribute: 'lang', | ||
path: false, | ||
method: 'getLang', | ||
}); | ||
@@ -139,3 +173,3 @@ }); | ||
it('should accept user-defined query param', () => { | ||
it('should accept user-defined query param `lang`', () => { | ||
return server | ||
@@ -149,5 +183,75 @@ .inject({ | ||
.should.be.fulfilled.then((response) => { | ||
expect(response.request.lang).to.be.equal('de'); | ||
expect(response.request.getLang()).to.be.equal('de'); | ||
}); | ||
}); | ||
}); | ||
describe('hapi-locale-17 with `path` option', async () => { | ||
let server; | ||
before(async () => { | ||
server = await setup({ | ||
locales: ['de', 'en'], | ||
query: false, | ||
path: 'lang', | ||
method: 'getLang', | ||
}); | ||
}); | ||
after(async () => { | ||
server.stop(); | ||
}); | ||
it('should accept user-defined path param `lang`', () => { | ||
return server | ||
.inject({ | ||
url: '/media2/de', | ||
headers: { | ||
'Accept-Language': 'en-GB;q=0.8,en-US;q=0.7,en;q=0.6', | ||
}, | ||
}) | ||
.should.be.fulfilled.then((response) => { | ||
expect(response.request.getLang()).to.be.equal('de'); | ||
}); | ||
}); | ||
}); | ||
describe('hapi-locale-17 with locale option `en-US`', async () => { | ||
let server; | ||
before(async () => { | ||
server = await setup({ | ||
locales: ['en-US', 'es'], | ||
}); | ||
}); | ||
after(async () => { | ||
server.stop(); | ||
}); | ||
it('should accept locale `en-US`', () => { | ||
return server | ||
.inject({ | ||
url: '/test', | ||
headers: { | ||
'Accept-Language': 'en-GB;q=0.8,en-US;q=0.7,en;q=0.6', | ||
}, | ||
}) | ||
.should.be.fulfilled.then((response) => { | ||
expect(response.request.getLocale()).to.be.equal('en-US'); | ||
}); | ||
}); | ||
it('should accept locale `en-US` / query param', () => { | ||
return server | ||
.inject({ | ||
url: '/test?locale=en', | ||
headers: { | ||
'Accept-Language': 'es-ES,es;q=0.9,en-GB;q=0.8,en-US;q=0.7,en;q=0.6', | ||
}, | ||
}) | ||
.should.be.fulfilled.then((response) => { | ||
expect(response.request.getLocale()).to.be.equal('en-US'); | ||
}); | ||
}); | ||
}); |
10599
10
248
71
Updatedrind-locale@~0.0.3