Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@hmcts/one-per-page

Package Overview
Dependencies
Maintainers
14
Versions
67
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@hmcts/one-per-page - npm Package Compare versions

Comparing version 3.0.0-2 to 3.0.0

docs/images/lang-switch.png

43

CHANGELOG.md

@@ -1,10 +0,20 @@

<a name="3.0.0-2"></a>
# 3.0.0-2 (2018-02-27)
<a name="3.0.0"></a>
# 3.0.0 (2018-03-06)
* Add a function to list the available languages ([ff32db7](https://github.com/hmcts/one-per-page/commit/ff32db7))
* Add debugging of step instance creation ([0105488](https://github.com/hmcts/one-per-page/commit/0105488))
* Add documentation for the language switcher ([dd8b775](https://github.com/hmcts/one-per-page/commit/dd8b775))
* Add logging to BaseStep ([f506cc4](https://github.com/hmcts/one-per-page/commit/f506cc4))
* Add logging to error pages ([013eecd](https://github.com/hmcts/one-per-page/commit/013eecd))
* Ensure refs aren't included in checking if an answer has been given ([c4f307d](https://github.com/hmcts/one-per-page/commit/c4f307d))
* Fix heroku deployments ([94bf3d6](https://github.com/hmcts/one-per-page/commit/94bf3d6))
* Fix heroku deployments ([e434590](https://github.com/hmcts/one-per-page/commit/e434590))
* Fix heroku deployments ([520243c](https://github.com/hmcts/one-per-page/commit/520243c))
* Fix heroku deployments ([4a0808b](https://github.com/hmcts/one-per-page/commit/4a0808b))
* Fix heroku deployments ([e143c28](https://github.com/hmcts/one-per-page/commit/e143c28))
* Ignore webpack built assets in example app ([b68cf0f](https://github.com/hmcts/one-per-page/commit/b68cf0f))
* Include the language switcher styles in example app ([4f3dde7](https://github.com/hmcts/one-per-page/commit/4f3dde7))
* Increase coverage over i18Next.js ([cbbe369](https://github.com/hmcts/one-per-page/commit/cbbe369))
* Make form capable of retrieving values from a temp storage ([7cea8f2](https://github.com/hmcts/one-per-page/commit/7cea8f2))
* Move currentLang / availableLangs to req.i18n ([fb2c82a](https://github.com/hmcts/one-per-page/commit/fb2c82a))
* Omit dist folders from eslint ([f489757](https://github.com/hmcts/one-per-page/commit/f489757))

@@ -14,14 +24,32 @@ * Prevent caching of questions ([8f357a4](https://github.com/hmcts/one-per-page/commit/8f357a4))

* Redirect to GET on errors ([0fa6733](https://github.com/hmcts/one-per-page/commit/0fa6733))
* Release 3.0.0-1 ([b75bfce](https://github.com/hmcts/one-per-page/commit/b75bfce))
* Release 2.6.0 ([302e691](https://github.com/hmcts/one-per-page/commit/302e691))
* Remove old field types and underlying classes ([2f384e6](https://github.com/hmcts/one-per-page/commit/2f384e6))
* Shim over @hmcts/nodejs-logging for logging ([9b3a483](https://github.com/hmcts/one-per-page/commit/9b3a483))
* Switch action logging to new module ([28c00de](https://github.com/hmcts/one-per-page/commit/28c00de))
* Switch language based on url params ([8e19bae](https://github.com/hmcts/one-per-page/commit/8e19bae))
* Switch logging in journey to use new logging module ([e6016b0](https://github.com/hmcts/one-per-page/commit/e6016b0))
* Update tech-docs and fix issue where it couldn't see css-loader in heroku ([b01e78c](https://github.com/hmcts/one-per-page/commit/b01e78c))
<a name="3.0.0-1"></a>
# 3.0.0-1 (2018-02-23)
<a name="2.6.0"></a>
# 2.6.0 (2018-03-06)
* Add a function to list the available languages ([ff32db7](https://github.com/hmcts/one-per-page/commit/ff32db7))
* Add debugging of step instance creation ([0105488](https://github.com/hmcts/one-per-page/commit/0105488))
* Add documentation for the language switcher ([dd8b775](https://github.com/hmcts/one-per-page/commit/dd8b775))
* Add logging to BaseStep ([f506cc4](https://github.com/hmcts/one-per-page/commit/f506cc4))
* Add logging to error pages ([013eecd](https://github.com/hmcts/one-per-page/commit/013eecd))
* Ensure refs aren't included in checking if an answer has been given ([c4f307d](https://github.com/hmcts/one-per-page/commit/c4f307d))
* Fix heroku deployments ([520243c](https://github.com/hmcts/one-per-page/commit/520243c))
* Fix heroku deployments ([94bf3d6](https://github.com/hmcts/one-per-page/commit/94bf3d6))
* Fix heroku deployments ([e434590](https://github.com/hmcts/one-per-page/commit/e434590))
* Fix heroku deployments ([4a0808b](https://github.com/hmcts/one-per-page/commit/4a0808b))
* Fix heroku deployments ([e143c28](https://github.com/hmcts/one-per-page/commit/e143c28))
* Ignore webpack built assets in example app ([b68cf0f](https://github.com/hmcts/one-per-page/commit/b68cf0f))
* Include the language switcher styles in example app ([4f3dde7](https://github.com/hmcts/one-per-page/commit/4f3dde7))
* Increase coverage over i18Next.js ([cbbe369](https://github.com/hmcts/one-per-page/commit/cbbe369))
* Make form capable of retrieving values from a temp storage ([7cea8f2](https://github.com/hmcts/one-per-page/commit/7cea8f2))
* Move currentLang / availableLangs to req.i18n ([fb2c82a](https://github.com/hmcts/one-per-page/commit/fb2c82a))
* Omit dist folders from eslint ([f489757](https://github.com/hmcts/one-per-page/commit/f489757))
* Prevent caching of questions ([8f357a4](https://github.com/hmcts/one-per-page/commit/8f357a4))

@@ -31,2 +59,7 @@ * Provide a way to temporarily store values ([b558a2f](https://github.com/hmcts/one-per-page/commit/b558a2f))

* Remove old field types and underlying classes ([2f384e6](https://github.com/hmcts/one-per-page/commit/2f384e6))
* Shim over @hmcts/nodejs-logging for logging ([9b3a483](https://github.com/hmcts/one-per-page/commit/9b3a483))
* Switch action logging to new module ([28c00de](https://github.com/hmcts/one-per-page/commit/28c00de))
* Switch language based on url params ([8e19bae](https://github.com/hmcts/one-per-page/commit/8e19bae))
* Switch logging in journey to use new logging module ([e6016b0](https://github.com/hmcts/one-per-page/commit/e6016b0))
* Update tech-docs and fix issue where it couldn't see css-loader in heroku ([b01e78c](https://github.com/hmcts/one-per-page/commit/b01e78c))

@@ -33,0 +66,0 @@

@@ -110,2 +110,37 @@ # Page

#### Switching languages in your pages
You can add a language switcher to your pages to allow the user to choose which
language to view the page in.
The [look-and-feel] package provides a handy macro for switching languages:
![Example of the language switcher](/docs/images/lang-switch.png)
To use this switcher you can import `languageSwitch` from [look-and-feel]:
_MyPage.template.html_
```djangohtml
{% extends "look-and-feel/layouts/two_thirds.html" %}
{% from "look-and-feel/components/i18n.njk" import languageSwitch %}
{% block breadcrumbs %}
{{ languageSwitch(i18n.availableLanguages, i18n.currentLanguage) }}
{% endblock %}
```
And add the following import to your sass file to ensure you get the correct
styling:
_main.scss_
```sass
@import 'look-and-feel/language-switch';
```
This switcher presents a link for each language that you have made available for
that particular page.
> The `question.html`, `check_your_answers.html` and `add_another.html` templates
> provide this language switcher by default
### Template locals

@@ -192,3 +227,4 @@

[i18Next]: https://www.i18next.com/
[look-and-feel]: https://github.com/hmcts/look-and-feel
[IETF language tag]: https://en.wikipedia.org/wiki/IETF_language_tag
[resolveTemplate]: /docs/middleware/resolveTemplate

8

package.json

@@ -5,3 +5,3 @@ {

"homepage": "https://github.com/hmcts/one-per-page#readme",
"version": "3.0.0-2",
"version": "3.0.0",
"main": "./src/main.js",

@@ -22,2 +22,3 @@ "repository": {

"connect-redis": "^3.3.2",
"cookie-parser": "^1.4.3",
"debug": "^3.1.0",

@@ -41,3 +42,3 @@ "deepmerge": "^2.0.1",

"@hmcts/eslint-config": "^1.3.0",
"@hmcts/tech-docs": "^0.3.0",
"@hmcts/tech-docs": "^0.4.0",
"chai": "^4.1.0",

@@ -64,4 +65,5 @@ "chai-as-promised": "^7.1.1",

"docs": "tech-docs --use-http --watch",
"heroku-postbuild": "yarn add @hmcts/tech-docs",
"heroku-postbuild": "yarn remove @hmcts/tech-docs; yarn add @hmcts/tech-docs",
"lint": "eslint .",
"serve-docs": "tech-docs -p $PORT -d $URL",
"test": "NODE_PATH=. NODE_ENV=testing nyc --reporter=text-summary mocha --exit 'test/**/*.test.js'"

@@ -68,0 +70,0 @@ },

@@ -9,2 +9,3 @@ const session = require('../session');

const log = require('../util/logging')('journey');
const cookieParser = require('cookie-parser');

@@ -69,2 +70,3 @@ const parseUrl = baseUrl => {

app.use(cookieParser());
app.use(setupMiddleware);

@@ -71,0 +73,0 @@ app.use(opts.session);

const i18Next = require('i18next');
const { defined } = require('../util/checks');
const defaultIfUndefined = require('../util/defaultIfUndefined');

@@ -7,9 +8,35 @@ const i18NextInstance = i18Next.init({ fallbackLng: 'en' });

const i18nMiddleware = (req, res, next) => {
if (defined(req.i18Next)) {
next();
return;
if (!defined(req.i18Next)) {
req.i18Next = i18NextInstance;
}
req.i18Next = i18NextInstance;
if (!defined(req.i18n)) {
req.i18n = {
t: i18NextInstance.t.bind(i18NextInstance),
get availableLanguages() {
const ns = req.currentStep.name;
const allLangs = Object.keys(req.i18Next.services.resourceStore.data);
return allLangs
.filter(lang => ns in req.i18Next.services.resourceStore.data[lang])
.map(lang => {
return { code: lang, name: req.i18Next.t(lang) };
});
},
get currentLanguage() {
return defaultIfUndefined(req.i18Next.language, 'en');
}
};
}
if (defined(req.query) && defined(req.query.lng)) {
req.i18Next.changeLanguage(req.query.lng);
} else if (defined(req.cookies) && defined(req.cookies.i18n)) {
req.i18Next.changeLanguage(req.cookies.i18n);
} else {
req.i18Next.changeLanguage('en');
}
res.cookie('i18n', defaultIfUndefined(req.i18Next.language, 'en'));
next();

@@ -16,0 +43,0 @@ };

@@ -69,2 +69,6 @@ const BaseStep = require('./BaseStep');

get i18n() {
return this.req.i18n;
}
handler(req, res) {

@@ -71,0 +75,0 @@ if (req.method === 'GET') {

@@ -1,2 +0,2 @@

const { expect } = require('../util/chai');
const { expect, sinon } = require('../util/chai');
const { i18NextInstance, i18nMiddleware } = require('../../src/i18n/i18Next');

@@ -12,4 +12,4 @@

const executeMiddleware = ({
req = {},
res = {}
req = { cookies: {} },
res = { cookie: sinon.stub() }
} = {}) => new Promise((resolve, reject) => {

@@ -27,3 +27,4 @@ const next = error => {

it('does nothing if req.i18Next exists', () => {
return executeMiddleware({ req: { i18Next: {} } })
const fakeI18Next = { changeLanguage: sinon.stub(), language: 'en' };
return executeMiddleware({ req: { i18Next: fakeI18Next } })
.then(({ req }) => expect(req.i18Next).to.not.eql(i18NextInstance));

@@ -36,2 +37,115 @@ });

});
it('attaches i18n to req', () => {
return executeMiddleware().then(({ req }) => {
expect(req.i18n).to.be.an('object');
expect(req.i18n.t).to.be.a('function');
});
});
it('defaults the current language to english', () => {
const req = {
i18Next: { changeLanguage: sinon.stub(), language: 'en' },
cookies: {}
};
const res = { cookie: sinon.stub() };
return executeMiddleware({ req, res }).then(() => {
expect(req.i18Next.changeLanguage).calledWith('en');
});
});
it('defaults the current language to english if i18n has no lang', () => {
const req = {
i18Next: { changeLanguage: sinon.stub() },
cookies: {}
};
const res = { cookie: sinon.stub() };
return executeMiddleware({ req, res }).then(() => {
expect(req.i18Next.changeLanguage).calledWith('en');
expect(res.cookie).calledWith('i18n', 'en');
});
});
it('sets the current language if req.param.lng is present', () => {
const req = {
i18Next: { changeLanguage: sinon.stub(), language: 'en' },
cookies: {},
query: { lng: 'cy' }
};
const res = { cookie: sinon.stub() };
return executeMiddleware({ req, res }).then(() => {
expect(req.i18Next.changeLanguage).calledWith('cy');
});
});
it('sets the current language i18n cookie is present', () => {
const req = {
i18Next: { changeLanguage: sinon.stub(), language: 'en' },
cookies: { i18n: 'cy' }
};
const res = { cookie: sinon.stub() };
return executeMiddleware({ req, res }).then(() => {
expect(req.i18Next.changeLanguage).calledWith('cy');
});
});
describe('req.i18n.availableLanguages', () => {
it('returns all langs that have content for the current step', () => {
const i18Next = {
t: sinon.stub(),
changeLanguage: sinon.stub(),
language: 'en',
services: {
resourceStore: {
// eslint-disable-next-line id-blacklist
data: {
en: { FooStep: {} },
cy: { FooStep: {} }
}
}
}
};
const currentStep = { name: 'FooStep' };
const expected = [
{ code: 'en', name: 'English' },
{ code: 'cy', name: 'Welsh' }
];
i18Next.t.withArgs('en').returns('English');
i18Next.t.withArgs('cy').returns('Welsh');
return executeMiddleware({ req: { i18Next, currentStep } })
.then(({ req }) =>
expect(req.i18n.availableLanguages).to.eql(expected)
);
});
});
describe('req.i18n.currentLanguage', () => {
it('returns the language currently used by i18Next', () => {
const i18Next = {
t: sinon.stub(),
changeLanguage: sinon.stub(),
language: 'cy'
};
const currentStep = { name: 'FooStep' };
return executeMiddleware({ req: { i18Next, currentStep } })
.then(({ req }) => {
expect(req.i18n.currentLanguage).to.eql('cy');
});
});
it('defaults to english if no i18Next has no chosen language', () => {
const i18Next = {
t: sinon.stub(),
changeLanguage: sinon.stub()
};
const currentStep = { name: 'FooStep' };
return executeMiddleware({ req: { i18Next, currentStep } })
.then(({ req }) => {
expect(req.i18n.currentLanguage).to.eql('en');
});
});
});
});

@@ -38,0 +152,0 @@

@@ -11,2 +11,3 @@ const express = require('express');

const { RequestBoundJourney } = require('../../src/flow');
const cookieParser = require('cookie-parser');

@@ -26,6 +27,3 @@ function testApp(views = []) {

const cookie = res => {
const setCookie = res.headers['set-cookie'];
return (setCookie && setCookie[0]) || undefined;
};
const cookies = res => res.headers['set-cookie'] || [];

@@ -50,2 +48,3 @@ const _supertest = Symbol('supertest');

app.use(session({ baseUrl: '127.0.0.1', secret: 'keyboard cat' }));
app.use(cookieParser());
app.use(i18nMiddleware);

@@ -79,6 +78,6 @@

return supertestObj.then(res => {
const sid = cookie(res);
// const sid = cookies(res);
return supertest(supertestObj.app)
.get('/supertest-check-session')
.set('Cookie', sid)
.set('Cookie', cookies(res))
.expect(200);

@@ -93,7 +92,7 @@ }).then(res => {

const shouldNotSetCookie = name => {
return res => Promise.all([
expect(Object.keys(res.headers)).to.not.include('set-cookie'),
expect(res.headers['set-cookie']).to.not.include.match(name)
]);
const shouldNotSetCookie = name => res => {
if (typeof res.headers['set-cookie'] !== 'undefined') {
return expect(res.headers['set-cookie']).to.not.include.match(name);
}
return expect(Object.keys(res.headers)).to.not.include('set-cookie');
};

@@ -100,0 +99,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc