diff --git a/package.json b/package.json
index 55f78b485..e7d75b97c 100644
--- a/package.json
+++ b/package.json
@@ -32,6 +32,9 @@
"bitcore-mnemonic": "=1.1.1",
"copy-to-clipboard": "=3.0.6",
"flexboxgrid": "=6.3.1",
+ "i18next": "^9.0.0",
+ "i18next-localstorage-cache": "^1.1.1",
+ "i18next-xhr-backend": "^1.4.2",
"lisk-js": "=0.4.5",
"moment": "=2.15.1",
"postcss": "=6.0.2",
@@ -42,6 +45,7 @@
"react-circular-progressbar": "=0.1.5",
"react-css-themr": "=2.1.2",
"react-dom": "=15.6.x",
+ "react-i18next": "^5.2.0",
"react-redux": "=5.0.5",
"react-router": "=4.1.2",
"react-router-dom": "=4.1.2",
diff --git a/src/components/app/index.test.js b/src/components/app/index.test.js
index ab864a635..b249a7275 100644
--- a/src/components/app/index.test.js
+++ b/src/components/app/index.test.js
@@ -4,6 +4,8 @@ import { MemoryRouter } from 'react-router';
import { Provider } from 'react-redux';
import { expect } from 'chai';
import configureStore from 'redux-mock-store';
+import { I18nextProvider } from 'react-i18next';
+import i18n from '../../i18n'; // initialized i18next instance
import App from './';
import Login from '../login';
import Transactions from '../transactions';
@@ -16,7 +18,9 @@ const addRouter = Component => (props, path) =>
mount(
+
+
,
);
diff --git a/src/components/header/header.js b/src/components/header/header.js
index 61d57ee3a..bac432ad0 100644
--- a/src/components/header/header.js
+++ b/src/components/header/header.js
@@ -54,13 +54,13 @@ const Header = props => (
})}
/>
-
+
+ })}>{props.t('send')}
);
diff --git a/src/components/header/header.test.js b/src/components/header/header.test.js
index 3b5058f1b..3adf251a3 100644
--- a/src/components/header/header.test.js
+++ b/src/components/header/header.test.js
@@ -15,6 +15,7 @@ describe('Header', () => {
const mockInputProps = {
setActiveDialog: () => { },
account: {},
+ t: t => t,
};
propsMock = sinon.mock(mockInputProps);
wrapper = shallow();
diff --git a/src/components/header/index.js b/src/components/header/index.js
index bb858ad9d..cee76574c 100644
--- a/src/components/header/index.js
+++ b/src/components/header/index.js
@@ -1,4 +1,5 @@
import { connect } from 'react-redux';
+import { translate } from 'react-i18next';
import { dialogDisplayed } from '../../actions/dialog';
import { accountLoggedOut } from '../../actions/account';
import Header from './header';
@@ -11,8 +12,7 @@ const mapDispatchToProps = dispatch => ({
setActiveDialog: data => dispatch(dialogDisplayed(data)),
logOut: () => dispatch(accountLoggedOut()),
});
-
export default connect(
mapStateToProps,
mapDispatchToProps,
-)(Header);
+)(translate()(Header));
diff --git a/src/components/header/index.test.js b/src/components/header/index.test.js
index 196225312..9f7894f33 100644
--- a/src/components/header/index.test.js
+++ b/src/components/header/index.test.js
@@ -3,6 +3,8 @@ import { expect } from 'chai';
import { mount } from 'enzyme';
import { Provider } from 'react-redux';
import sinon from 'sinon';
+import { I18nextProvider } from 'react-i18next';
+import i18n from '../../i18n'; // initialized i18next instance
import * as accountActions from '../../actions/account';
import * as dialogActions from '../../actions/dialog';
import Header from './header';
@@ -14,7 +16,11 @@ describe('HeaderHOC', () => {
let wrapper;
beforeEach(() => {
- wrapper = mount();
+ wrapper = mount(
+
+
+
+ );
});
it('should render Header', () => {
diff --git a/src/i18n.js b/src/i18n.js
new file mode 100755
index 000000000..ea7622042
--- /dev/null
+++ b/src/i18n.js
@@ -0,0 +1,37 @@
+import i18n from 'i18next';
+import XHR from 'i18next-xhr-backend';
+// import Cache from 'i18next-localstorage-cache';
+
+i18n
+ .use(XHR)
+ // .use(Cache)
+ .init({
+ fallbackLng: 'en',
+ lng: 'en',
+ react: {
+ // wait: true, // globally set to wait for loaded translations in translate hoc
+ // exposeNamespace: true // exposes namespace on data-i18next-options to be used in eg.
+ },
+
+ // have a common namespace used around the full app
+ ns: ['common'],
+ defaultNS: 'common',
+
+ debug: true,
+
+ // cache: {
+ // enabled: true,
+ // },
+
+ interpolation: {
+ escapeValue: false, // not needed for react!!
+ formatSeparator: ',',
+ format: (value, format) => {
+ if (format === 'uppercase') return value.toUpperCase();
+ return value;
+ },
+ },
+ });
+
+
+export default i18n;
diff --git a/src/locales/de/common.json b/src/locales/de/common.json
new file mode 100644
index 000000000..26873f929
--- /dev/null
+++ b/src/locales/de/common.json
@@ -0,0 +1,4 @@
+{
+ "send": "senden",
+ "logout": "Ausloggen"
+}
diff --git a/src/locales/en/common.json b/src/locales/en/common.json
new file mode 100644
index 000000000..3d74db400
--- /dev/null
+++ b/src/locales/en/common.json
@@ -0,0 +1,4 @@
+{
+ "send": "send",
+ "logout": "logout"
+}
diff --git a/src/main.js b/src/main.js
index acf338c8c..3ac36ddbc 100644
--- a/src/main.js
+++ b/src/main.js
@@ -2,15 +2,19 @@ import React from 'react';
import ReactDOM from 'react-dom';
import { HashRouter as Router } from 'react-router-dom';
import { Provider } from 'react-redux';
+import { I18nextProvider } from 'react-i18next';
import App from './components/app';
import store from './store';
+import i18n from './i18n'; // initialized i18next instance
const rootElement = document.getElementById('app');
const renderWithRouter = Component =>
-
+
+
+
;