Adding i18next integration

This commit is contained in:
Jeff Avallone
2019-01-06 12:24:47 -05:00
parent 7d7916baf0
commit e1c4cb9068
15 changed files with 715 additions and 3 deletions
@@ -56,6 +56,9 @@ ShallowWrapper {
Privacy Policy
</mockConstructor>
</li>
<li>
<LoadNamespace(LocaleSwitcherImpl) />
</li>
</ul>,
],
"className": "header",
@@ -115,6 +118,9 @@ ShallowWrapper {
Privacy Policy
</mockConstructor>
</li>,
<li>
<LoadNamespace(LocaleSwitcherImpl) />
</li>,
],
"className": "list",
},
@@ -200,6 +206,25 @@ ShallowWrapper {
},
"type": "li",
},
Object {
"instance": null,
"key": undefined,
"nodeType": "host",
"props": Object {
"children": <LoadNamespace(LocaleSwitcherImpl) />,
},
"ref": null,
"rendered": Object {
"instance": null,
"key": undefined,
"nodeType": "class",
"props": Object {},
"ref": null,
"rendered": null,
"type": [Function],
},
"type": "li",
},
],
"type": "ul",
},
@@ -243,6 +268,9 @@ ShallowWrapper {
Privacy Policy
</mockConstructor>
</li>
<li>
<LoadNamespace(LocaleSwitcherImpl) />
</li>
</ul>,
],
"className": "header",
@@ -302,6 +330,9 @@ ShallowWrapper {
Privacy Policy
</mockConstructor>
</li>,
<li>
<LoadNamespace(LocaleSwitcherImpl) />
</li>,
],
"className": "list",
},
@@ -387,6 +418,25 @@ ShallowWrapper {
},
"type": "li",
},
Object {
"instance": null,
"key": undefined,
"nodeType": "host",
"props": Object {
"children": <LoadNamespace(LocaleSwitcherImpl) />,
},
"ref": null,
"rendered": Object {
"instance": null,
"key": undefined,
"nodeType": "class",
"props": Object {},
"ref": null,
"rendered": null,
"type": [Function],
},
"type": "li",
},
],
"type": "ul",
},
@@ -470,6 +520,9 @@ ShallowWrapper {
Privacy Policy
</mockConstructor>
</li>
<li>
<LoadNamespace(LocaleSwitcherImpl) />
</li>
</ul>,
],
"className": "header",
@@ -529,6 +582,9 @@ ShallowWrapper {
Privacy Policy
</mockConstructor>
</li>,
<li>
<LoadNamespace(LocaleSwitcherImpl) />
</li>,
],
"className": "list",
},
@@ -614,6 +670,25 @@ ShallowWrapper {
},
"type": "li",
},
Object {
"instance": null,
"key": undefined,
"nodeType": "host",
"props": Object {
"children": <LoadNamespace(LocaleSwitcherImpl) />,
},
"ref": null,
"rendered": Object {
"instance": null,
"key": undefined,
"nodeType": "class",
"props": Object {},
"ref": null,
"rendered": null,
"type": [Function],
},
"type": "li",
},
],
"type": "ul",
},
@@ -657,6 +732,9 @@ ShallowWrapper {
Privacy Policy
</mockConstructor>
</li>
<li>
<LoadNamespace(LocaleSwitcherImpl) />
</li>
</ul>,
],
"className": "header",
@@ -716,6 +794,9 @@ ShallowWrapper {
Privacy Policy
</mockConstructor>
</li>,
<li>
<LoadNamespace(LocaleSwitcherImpl) />
</li>,
],
"className": "list",
},
@@ -801,6 +882,25 @@ ShallowWrapper {
},
"type": "li",
},
Object {
"instance": null,
"key": undefined,
"nodeType": "host",
"props": Object {
"children": <LoadNamespace(LocaleSwitcherImpl) />,
},
"ref": null,
"rendered": Object {
"instance": null,
"key": undefined,
"nodeType": "class",
"props": Object {},
"ref": null,
"rendered": null,
"type": [Function],
},
"type": "li",
},
],
"type": "ul",
},
+5
View File
@@ -4,6 +4,8 @@ import { Link, StaticQuery, graphql } from 'gatsby';
import GitlabIcon from 'react-feather/dist/icons/gitlab';
import LocaleSwitcher from 'components/LocaleSwitcher';
import style from './style.module.css';
const query = graphql`
@@ -36,6 +38,9 @@ export const HeaderImpl = ({ site: { siteMetadata } }) => (
<li>
<Link to="/privacy">Privacy Policy</Link>
</li>
<li>
<LocaleSwitcher />
</li>
</ul>
</header>
);
@@ -0,0 +1,323 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`LocaleSwitcher rendering 1`] = `
ShallowWrapper {
Symbol(enzyme.__root__): [Circular],
Symbol(enzyme.__unrendered__): <LocaleSwitcherImpl />,
Symbol(enzyme.__renderer__): Object {
"batchedUpdates": [Function],
"getNode": [Function],
"render": [Function],
"simulateError": [Function],
"simulateEvent": [Function],
"unmount": [Function],
},
Symbol(enzyme.__node__): Object {
"instance": null,
"key": undefined,
"nodeType": "host",
"props": Object {
"children": Array [
<WithMergedOptions(TransComponent)>
Language
</WithMergedOptions(TransComponent)>,
<div
className="switcher"
>
<select
onChange={[Function]}
value="en"
>
<option
value="en"
>
English
</option>
<option
value="other"
>
Other
</option>
</select>
<ChevronsDown
color="currentColor"
size="24"
/>
</div>,
],
},
"ref": null,
"rendered": Array [
Object {
"instance": null,
"key": undefined,
"nodeType": "class",
"props": Object {
"children": "Language",
},
"ref": null,
"rendered": "Language",
"type": [Function],
},
Object {
"instance": null,
"key": undefined,
"nodeType": "host",
"props": Object {
"children": Array [
<select
onChange={[Function]}
value="en"
>
<option
value="en"
>
English
</option>
<option
value="other"
>
Other
</option>
</select>,
<ChevronsDown
color="currentColor"
size="24"
/>,
],
"className": "switcher",
},
"ref": null,
"rendered": Array [
Object {
"instance": null,
"key": undefined,
"nodeType": "host",
"props": Object {
"children": Array [
<option
value="en"
>
English
</option>,
<option
value="other"
>
Other
</option>,
],
"onChange": [Function],
"value": "en",
},
"ref": null,
"rendered": Array [
Object {
"instance": null,
"key": "en",
"nodeType": "host",
"props": Object {
"children": "English",
"value": "en",
},
"ref": null,
"rendered": "English",
"type": "option",
},
Object {
"instance": null,
"key": "other",
"nodeType": "host",
"props": Object {
"children": "Other",
"value": "other",
},
"ref": null,
"rendered": "Other",
"type": "option",
},
],
"type": "select",
},
Object {
"instance": null,
"key": undefined,
"nodeType": "function",
"props": Object {
"color": "currentColor",
"size": "24",
},
"ref": null,
"rendered": null,
"type": [Function],
},
],
"type": "div",
},
],
"type": "label",
},
Symbol(enzyme.__nodes__): Array [
Object {
"instance": null,
"key": undefined,
"nodeType": "host",
"props": Object {
"children": Array [
<WithMergedOptions(TransComponent)>
Language
</WithMergedOptions(TransComponent)>,
<div
className="switcher"
>
<select
onChange={[Function]}
value="en"
>
<option
value="en"
>
English
</option>
<option
value="other"
>
Other
</option>
</select>
<ChevronsDown
color="currentColor"
size="24"
/>
</div>,
],
},
"ref": null,
"rendered": Array [
Object {
"instance": null,
"key": undefined,
"nodeType": "class",
"props": Object {
"children": "Language",
},
"ref": null,
"rendered": "Language",
"type": [Function],
},
Object {
"instance": null,
"key": undefined,
"nodeType": "host",
"props": Object {
"children": Array [
<select
onChange={[Function]}
value="en"
>
<option
value="en"
>
English
</option>
<option
value="other"
>
Other
</option>
</select>,
<ChevronsDown
color="currentColor"
size="24"
/>,
],
"className": "switcher",
},
"ref": null,
"rendered": Array [
Object {
"instance": null,
"key": undefined,
"nodeType": "host",
"props": Object {
"children": Array [
<option
value="en"
>
English
</option>,
<option
value="other"
>
Other
</option>,
],
"onChange": [Function],
"value": "en",
},
"ref": null,
"rendered": Array [
Object {
"instance": null,
"key": "en",
"nodeType": "host",
"props": Object {
"children": "English",
"value": "en",
},
"ref": null,
"rendered": "English",
"type": "option",
},
Object {
"instance": null,
"key": "other",
"nodeType": "host",
"props": Object {
"children": "Other",
"value": "other",
},
"ref": null,
"rendered": "Other",
"type": "option",
},
],
"type": "select",
},
Object {
"instance": null,
"key": undefined,
"nodeType": "function",
"props": Object {
"color": "currentColor",
"size": "24",
},
"ref": null,
"rendered": null,
"type": [Function],
},
],
"type": "div",
},
],
"type": "label",
},
],
Symbol(enzyme.__options__): Object {
"adapter": ReactSixteenAdapter {
"options": Object {
"enableComponentDidUpdateOnSetState": true,
"lifecycles": Object {
"componentDidUpdate": Object {
"onSetState": true,
},
"getDerivedStateFromProps": true,
"getSnapshotBeforeUpdate": true,
"setState": Object {
"skipsComponentDidUpdateOnNullish": true,
},
},
},
},
},
}
`;
+67
View File
@@ -0,0 +1,67 @@
import React from 'react';
import { withNamespaces, Trans } from 'react-i18next';
import ExpandIcon from 'react-feather/dist/icons/chevrons-down';
import i18n, { locales } from 'i18n';
import style from './style.module.css';
const localeToAvailable = (locale, available, defaultLocale) => {
if (available.includes(locale)) {
return locale;
}
const parts = locale.split('-');
if (parts.length > 0 && available.includes(parts[0])) {
return parts[0];
}
return defaultLocale;
};
export class LocaleSwitcherImpl extends React.PureComponent {
state = {
current: localeToAvailable(
i18n.language || '',
locales.map(l => l.code),
'en')
}
componentDidMount() {
i18n.on('languageChanged', this.handleLanguageChange);
}
componentWillUnmount() {
i18n.off('languageChanged', this.handleLanguageChange);
}
handleSelectChange = ({ target }) => {
i18n.changeLanguage(target.value);
}
handleLanguageChange = lang => {
this.setState({ current: lang });
}
render() {
const { current } = this.state;
return <label>
<Trans>Language</Trans>
<div className={ style.switcher }>
<select value={ current } onChange={ this.handleSelectChange }>
{ locales.map(locale => (
<option value={ locale.code } key={ locale.code }>
{ locale.name }
</option>
)) }
</select>
<ExpandIcon />
</div>
</label>;
}
}
export default withNamespaces()(LocaleSwitcherImpl);
@@ -0,0 +1,11 @@
@import url('../../globals.module.css');
:root {
--control-gradient: var(--color-tan) var(--gradient-tan);
--select-height: 2.4rem;
--select-width: 10rem;
}
.switcher {
composes: fancy-select;
}
+27
View File
@@ -0,0 +1,27 @@
import React from 'react';
import { shallow } from 'enzyme';
import i18n from 'i18n';
import { LocaleSwitcherImpl } from 'components/LocaleSwitcher';
describe('LocaleSwitcher', () => {
test('rendering', () => {
const component = shallow(
<LocaleSwitcherImpl />
);
expect(component).toMatchSnapshot();
});
test('changing language', () => {
jest.spyOn(i18n, 'changeLanguage');
const component = shallow(
<LocaleSwitcherImpl />
);
const selectInput = component.find('select');
selectInput.value = 'other';
selectInput.simulate('change', { target: { value: 'other' } });
expect(i18n.changeLanguage).toHaveBeenCalledWith('other');
});
});