diff --git a/src/actions/account.js b/src/actions/account.js index 7049337b8..98aed4eef 100644 --- a/src/actions/account.js +++ b/src/actions/account.js @@ -1,3 +1,4 @@ +import i18next from 'i18next'; import actionTypes from '../constants/actions'; import { setSecondPassphrase, send } from '../utils/api/account'; import { registerDelegate } from '../utils/api/delegate'; @@ -62,7 +63,7 @@ export const secondPassphraseRegistered = ({ activePeer, secondPassphrase, accou type: transactionTypes.setSecondPassphrase, })); }).catch((error) => { - const text = (error && error.message) ? error.message : 'An error occurred while registering your second passphrase. Please try again.'; + const text = (error && error.message) ? error.message : i18next.t('An error occurred while registering your second passphrase. Please try again.'); dispatch(errorAlertDialogDisplayed({ text })); }); dispatch(passphraseUsed(account.passphrase)); @@ -88,7 +89,7 @@ export const delegateRegistered = ({ })); }) .catch((error) => { - const text = error && error.message ? `${error.message}.` : 'An error occurred while registering as delegate.'; + const text = error && error.message ? `${error.message}.` : i18next.t('An error occurred while registering as delegate.'); const actionObj = errorAlertDialogDisplayed({ text }); dispatch(actionObj); }); @@ -113,7 +114,7 @@ export const sent = ({ activePeer, account, recipientId, amount, passphrase, sec })); }) .catch((error) => { - const text = error && error.message ? `${error.message}.` : 'An error occurred while creating the transaction.'; + const text = error && error.message ? `${error.message}.` : i18next.t('An error occurred while creating the transaction.'); dispatch(errorAlertDialogDisplayed({ text })); }); dispatch(passphraseUsed(passphrase)); diff --git a/src/components/passphraseInput/index.js b/src/components/passphraseInput/index.js index edbe19a1f..6c8c8c654 100644 --- a/src/components/passphraseInput/index.js +++ b/src/components/passphraseInput/index.js @@ -21,7 +21,7 @@ class PassphraseInput extends React.Component { let error; if (!value) { - error = 'Required'; + error = this.props.t('Required'); } else if (!isValidPassphrase(value)) { error = this.getPassphraseValidationError(value); } else if (this.hasExtraWhitespace(value)) { @@ -35,7 +35,7 @@ class PassphraseInput extends React.Component { getPassphraseValidationError(passphrase) { const mnemonic = passphrase.trim().split(' '); if (mnemonic.length < 12) { - return `Passphrase should have 12 words, entered passphrase has ${mnemonic.length}`; + return this.props.t('Passphrase should have 12 words, entered passphrase has {{length}}', { length: mnemonic.length }); } const invalidWord = mnemonic.find(word => !inDictionary(word.toLowerCase())); @@ -43,12 +43,12 @@ class PassphraseInput extends React.Component { if (invalidWord.length >= 2 && invalidWord.length <= 8) { const validWord = findSimilarWord(invalidWord); if (validWord) { - return `Word "${invalidWord}" is not on the passphrase Word List. Most similar word on the list is "${findSimilarWord(invalidWord)}"`; + return this.props.t('Word "{{invalidWord}}" is not on the passphrase Word List. Most similar word on the list is "{{similarWord}}"', { invalidWord, similarWord: findSimilarWord(invalidWord) }); } } - return `Word "${invalidWord}" is not on the passphrase Word List.`; + return this.props.t('Word "{{invalidWord}}" is not on the passphrase Word List.', { invalidWord }); } - return 'Passphrase is not valid'; + return this.props.t('Passphrase is not valid'); } // eslint-disable-next-line class-methods-use-this @@ -60,11 +60,11 @@ class PassphraseInput extends React.Component { // eslint-disable-next-line class-methods-use-this getPassphraseWhitespaceError(passphrase) { if (passphrase.replace(/^\s+/, '') !== passphrase) { - return 'Passphrase contains unnecessary whitespace at the beginning'; + return this.props.t('Passphrase contains unnecessary whitespace at the beginning'); } else if (passphrase.replace(/\s+$/, '') !== passphrase) { - return 'Passphrase contains unnecessary whitespace at the end'; + return this.props.t('Passphrase contains unnecessary whitespace at the end'); } else if (passphrase.replace(/\s+/g, ' ') !== passphrase) { - return 'Passphrase contains extra whitespace between words'; + return this.props.t('Passphrase contains extra whitespace between words'); } return null; diff --git a/src/components/proxyDialog/index.js b/src/components/proxyDialog/index.js index dbcc209ef..1406a8747 100644 --- a/src/components/proxyDialog/index.js +++ b/src/components/proxyDialog/index.js @@ -1,5 +1,6 @@ import { Input, Button } from 'react-toolbox'; import React from 'react'; +import { translate } from 'react-i18next'; class ProxyDialog extends React.Component { @@ -19,7 +20,7 @@ class ProxyDialog extends React.Component { this.setState({ [name]: { value, - error: value === '' ? 'Required' : '', + error: value === '' ? this.props.t('Required') : '', }, }); } @@ -39,12 +40,12 @@ class ProxyDialog extends React.Component { To connect to Lisk network, you need to enter a username and password for proxy {this.props.authInfo.host}

- - + label={this.props.t('Submit')} type='submit' /> ); } } -export default ProxyDialog; +export default translate()(ProxyDialog); + diff --git a/src/components/proxyDialog/index.test.js b/src/components/proxyDialog/index.test.js index 8c7cf18c4..1a227d9f2 100644 --- a/src/components/proxyDialog/index.test.js +++ b/src/components/proxyDialog/index.test.js @@ -2,7 +2,7 @@ import React from 'react'; import { expect } from 'chai'; import { mount } from 'enzyme'; import { spy, mock } from 'sinon'; - +import i18n from '../../i18n'; import ProxyDialog from './'; describe('ProxyDialog', () => { @@ -14,6 +14,7 @@ describe('ProxyDialog', () => { callback: spy(), closeDialog: spy(), authInfo: { host: 'someProxy.com' }, + i18n, }; wrapper = mount(); }); diff --git a/src/components/verifyMessage/index.js b/src/components/verifyMessage/index.js index d3c504d39..25ce0ceb5 100644 --- a/src/components/verifyMessage/index.js +++ b/src/components/verifyMessage/index.js @@ -64,7 +64,7 @@ class VerifyMessage extends React.Component { onChange={this.handleChange.bind(this, 'signature')} /> {this.state.result ? - : + : null } diff --git a/src/locales/en/common.json b/src/locales/en/common.json index 486ca6b6f..0d7c75145 100644 --- a/src/locales/en/common.json +++ b/src/locales/en/common.json @@ -1,9 +1,14 @@ { " Make sure that you are using the latest version of Lisk Nano.": " Make sure that you are using the latest version of Lisk Nano.", + "Account saved": "Account saved", + "Account was successfully forgotten.": "Account was successfully forgotten.", "Add vote to": "Add vote to", "Address": "Address", "Address copied to clipboard": "Address copied to clipboard", "Amount": "Amount", + "An error occurred while creating the transaction.": "An error occurred while creating the transaction.", + "An error occurred while registering as delegate.": "An error occurred while registering as delegate.", + "An error occurred while registering your second passphrase. Please try again.": "An error occurred while registering your second passphrase. Please try again.", "Approval": "Approval", "Back": "Back", "Balance": "Balance", @@ -61,13 +66,21 @@ "Note: After registration completes,": "Note: After registration completes,", "Note: Digital Signatures and signed messages are not encrypted!": "Note: Digital Signatures and signed messages are not encrypted!", "Ok": "Ok", + "Original Message": "Original Message", "Passphrase": "Passphrase", + "Passphrase contains extra whitespace between words": "Passphrase contains extra whitespace between words", + "Passphrase contains unnecessary whitespace at the beginning": "Passphrase contains unnecessary whitespace at the beginning", + "Passphrase contains unnecessary whitespace at the end": "Passphrase contains unnecessary whitespace at the end", + "Passphrase is not valid": "Passphrase is not valid", "Passphrase of the account is saved till the end of the session.": "Passphrase of the account is saved till the end of the session.", "Passphrase of the account will be required to perform any transaction.": "Passphrase of the account will be required to perform any transaction.", + "Passphrase should have 12 words, entered passphrase has {{length}}": "Passphrase should have 12 words, entered passphrase has {{length}}", + "Password": "Password", "Peer": "Peer", "Please click Next, then move around your mouse randomly to generate a random passphrase.": "Please click Next, then move around your mouse randomly to generate a random passphrase.", "Please keep it safe!": "Please keep it safe!", "Press #{key} to copy": "Press #{key} to copy", + "Proxy Authentication": "Proxy Authentication", "Public Key": "Public Key", "Rank": "Rank", "Receive LSK": "Receive LSK", @@ -102,8 +115,10 @@ "Sign message": "Sign message", "Signature": "Signature", "Signing a message with this tool indicates ownership of a privateKey (secret) and provides a level of proof that you are the owner of the key. Its important to bear in mind that this is not a 100% proof as computer systems can be compromised, but is still an effective tool for proving ownership of a particular publicKey/address pair.": "Signing a message with this tool indicates ownership of a privateKey (secret) and provides a level of proof that you are the owner of the key. Its important to bear in mind that this is not a 100% proof as computer systems can be compromised, but is still an effective tool for proving ownership of a particular publicKey/address pair.", + "Submit": "Submit", "Success": "Success", "Testnet": "Testnet", + "The URL was invalid": "The URL was invalid", "There are no transactions, yet.": "There are no transactions, yet.", "This account is protected by a second passphrase": "This account is protected by a second passphrase", "This passphrase is not recoverable and if you lose it, you will lose access to your account forever.": "This passphrase is not recoverable and if you lose it, you will lose access to your account forever.", @@ -116,14 +131,18 @@ "Transaction Amount": "Transaction Amount", "Transaction ID": "Transaction ID", "Transactions": "Transactions", + "URL is invalid": "URL is invalid", "Unable to connect to the node": "Unable to connect to the node", "Uptime": "Uptime", "Upvotes:": "Upvotes:", + "Username": "Username", "Verify message": "Verify message", "Vote": "Vote", "Vote for delegates": "Vote for delegates", "Voting": "Voting", "When you have the signature, you only need the publicKey of the signer in order to verify that the message came from the right private/publicKey pair. Be aware, everybody knowing the signature and the publicKey can verify the message. If ever there is a dispute, everybody can take the publicKey and signature to a judge and prove that the message is coming from the specific private/publicKey pair.": "When you have the signature, you only need the publicKey of the signer in order to verify that the message came from the right private/publicKey pair. Be aware, everybody knowing the signature and the publicKey can verify the message. If ever there is a dispute, everybody can take the publicKey and signature to a judge and prove that the message is coming from the specific private/publicKey pair.", + "Word \"{{invalidWord}}\" is not on the passphrase Word List.": "Word \"{{invalidWord}}\" is not on the passphrase Word List.", + "Word \"{{invalidWord}}\" is not on the passphrase Word List. Most similar word on the list is \"{{similarWord}}\"": "Word \"{{invalidWord}}\" is not on the passphrase Word List. Most similar word on the list is \"{{similarWord}}\"", "Yes! It's safe": "Yes! It's safe", "You can select up to {{count}} delegates in one voting turn.": "You can select up to {{count}} delegates in one voting turn.", "You can select up to {{count}} delegates in one voting turn._plural": "", diff --git a/src/store/middlewares/savedAccounts.js b/src/store/middlewares/savedAccounts.js index 23d94ecb8..5144136d9 100644 --- a/src/store/middlewares/savedAccounts.js +++ b/src/store/middlewares/savedAccounts.js @@ -1,3 +1,4 @@ +import i18next from 'i18next'; import actionTypes from '../../constants/actions'; import { successToastDisplayed } from '../../actions/toaster'; @@ -5,10 +6,10 @@ const savedAccountsMiddleware = store => next => (action) => { next(action); switch (action.type) { case actionTypes.accountSaved: - store.dispatch(successToastDisplayed({ label: 'Account saved' })); + store.dispatch(successToastDisplayed({ label: i18next.t('Account saved') })); break; case actionTypes.accountRemoved: - store.dispatch(successToastDisplayed({ label: 'Account was successfully forgotten.' })); + store.dispatch(successToastDisplayed({ label: i18next.t('Account was successfully forgotten.') })); break; default: break; diff --git a/src/utils/externalLinks.js b/src/utils/externalLinks.js index 57778eb32..430db59c0 100644 --- a/src/utils/externalLinks.js +++ b/src/utils/externalLinks.js @@ -1,3 +1,4 @@ +import i18next from 'i18next'; import history from '../history'; import routesReg from './routes'; import { errorToastDisplayed } from '../actions/toaster'; @@ -14,7 +15,7 @@ export default { if (route !== undefined) { history.push(normalizedUrl); } else { - store.dispatch(errorToastDisplayed({ label: 'The URL was invalid' })); + store.dispatch(errorToastDisplayed({ label: i18next.t('The URL was invalid') })); } }); } diff --git a/src/utils/login.js b/src/utils/login.js index 863a39029..eb409df9d 100644 --- a/src/utils/login.js +++ b/src/utils/login.js @@ -1,10 +1,12 @@ +import i18next from 'i18next'; + const validateUrl = (value) => { const addHttp = (url) => { const reg = /^(?:f|ht)tps?:\/\//i; return reg.test(url) ? url : `http://${url}`; }; - const errorMessage = 'URL is invalid'; + const errorMessage = i18next.t('URL is invalid'); const isValidLocalhost = url => url.hostname === 'localhost' && url.port.length > 1; const isValidRemote = url => /(([a-z\d]([a-z\d-]*[a-z\d])*)\.)+[a-z]{2,}|((\d{1,3}\.){3}\d{1,3})/.test(url.hostname); diff --git a/src/utils/proxyLogin.js b/src/utils/proxyLogin.js index 033676773..2ed3e22f6 100644 --- a/src/utils/proxyLogin.js +++ b/src/utils/proxyLogin.js @@ -1,3 +1,4 @@ +import i18next from 'i18next'; import { dialogDisplayed } from '../actions/dialog'; import ProxyDialog from '../components/proxyDialog'; import store from '../store'; @@ -9,7 +10,7 @@ export default { if (ipc) { ipc.on('proxyLogin', (action, authInfo) => { store.dispatch(dialogDisplayed({ - title: 'Proxy Authentication', + title: i18next.t('Proxy Authentication'), childComponent: ProxyDialog, childComponentProps: { authInfo,