diff options
Merge branch 'master' into retry-tx-refractor
Diffstat (limited to 'ui/app')
69 files changed, 855 insertions, 597 deletions
diff --git a/ui/app/accounts/import/index.js b/ui/app/accounts/import/index.js index adb52db74..c1b190e3d 100644 --- a/ui/app/accounts/import/index.js +++ b/ui/app/accounts/import/index.js @@ -2,6 +2,7 @@ const inherits = require('util').inherits const Component = require('react').Component const h = require('react-hyperscript') const connect = require('react-redux').connect +const t = require('../../../i18n') import Select from 'react-select' // Subviews @@ -9,8 +10,8 @@ const JsonImportView = require('./json.js') const PrivateKeyImportView = require('./private-key.js') const menuItems = [ - 'Private Key', - 'JSON File', + t('privateKey'), + t('jsonFile'), ] module.exports = connect(mapStateToProps)(AccountImportSubview) @@ -85,9 +86,9 @@ AccountImportSubview.prototype.renderImportView = function () { const current = type || menuItems[0] switch (current) { - case 'Private Key': + case t('privateKey'): return h(PrivateKeyImportView) - case 'JSON File': + case t('jsonFile'): return h(JsonImportView) default: return h(JsonImportView) diff --git a/ui/app/accounts/import/json.js b/ui/app/accounts/import/json.js index dd5dfad22..1b5e485d7 100644 --- a/ui/app/accounts/import/json.js +++ b/ui/app/accounts/import/json.js @@ -1,106 +1,131 @@ -const inherits = require('util').inherits const Component = require('react').Component +const PropTypes = require('prop-types') const h = require('react-hyperscript') const connect = require('react-redux').connect const actions = require('../../actions') const FileInput = require('react-simple-file-input').default +const t = require('../../../i18n') const HELP_LINK = 'https://support.metamask.io/kb/article/7-importing-accounts' -module.exports = connect(mapStateToProps)(JsonImportSubview) +class JsonImportSubview extends Component { + constructor (props) { + super(props) -function mapStateToProps (state) { - return { - error: state.appState.warning, + this.state = { + file: null, + fileContents: '', + } } -} -inherits(JsonImportSubview, Component) -function JsonImportSubview () { - Component.call(this) -} + render () { + const { error } = this.props + + return ( + h('div.new-account-import-form__json', [ + + h('p', t('usedByClients')), + h('a.warning', { + href: HELP_LINK, + target: '_blank', + }, t('fileImportFail')), + + h(FileInput, { + readAs: 'text', + onLoad: this.onLoad.bind(this), + style: { + margin: '20px 0px 12px 34%', + fontSize: '15px', + display: 'flex', + justifyContent: 'center', + }, + }), + + h('input.new-account-import-form__input-password', { + type: 'password', + placeholder: t('enterPassword'), + id: 'json-password-box', + onKeyPress: this.createKeyringOnEnter.bind(this), + }), + + h('div.new-account-create-form__buttons', {}, [ + + h('button.new-account-create-form__button-cancel', { + onClick: () => this.props.goHome(), + }, [ + t('cancel'), + ]), + + h('button.new-account-create-form__button-create', { + onClick: () => this.createNewKeychain(), + }, [ + t('import'), + ]), -JsonImportSubview.prototype.render = function () { - const { error } = this.props - - return ( - h('div.new-account-import-form__json', [ - - h('p', 'Used by a variety of different clients'), - h('a.warning', { href: HELP_LINK, target: '_blank' }, 'File import not working? Click here!'), - - h(FileInput, { - readAs: 'text', - onLoad: this.onLoad.bind(this), - style: { - margin: '20px 0px 12px 34%', - fontSize: '15px', - display: 'flex', - justifyContent: 'center', - }, - }), - - h('input.new-account-import-form__input-password', { - type: 'password', - placeholder: 'Enter password', - id: 'json-password-box', - onKeyPress: this.createKeyringOnEnter.bind(this), - }), - - h('div.new-account-create-form__buttons', {}, [ - - h('button.new-account-create-form__button-cancel', { - onClick: () => this.props.goHome(), - }, [ - 'CANCEL', ]), - h('button.new-account-create-form__button-create', { - onClick: () => this.createNewKeychain.bind(this), - }, [ - 'IMPORT', - ]), + error ? h('span.error', error) : null, + ]) + ) + } - ]), + onLoad (event, file) { + this.setState({file: file, fileContents: event.target.result}) + } - error ? h('span.error', error) : null, - ]) - ) -} + createKeyringOnEnter (event) { + if (event.key === 'Enter') { + event.preventDefault() + this.createNewKeychain() + } + } -JsonImportSubview.prototype.onLoad = function (event, file) { - this.setState({file: file, fileContents: event.target.result}) -} + createNewKeychain () { + const state = this.state -JsonImportSubview.prototype.createKeyringOnEnter = function (event) { - if (event.key === 'Enter') { - event.preventDefault() - this.createNewKeychain() - } -} + if (!state) { + const message = 'You must select a valid file to import.' + return this.props.displayWarning(message) + } -JsonImportSubview.prototype.createNewKeychain = function () { - const state = this.state + const { fileContents } = state - if (!state) { - const message = 'You must select a valid file to import.' - return this.props.dispatch(actions.displayWarning(message)) - } + if (!fileContents) { + const message = t('needImportFile') + return this.props.displayWarning(message) + } - const { fileContents } = state + const passwordInput = document.getElementById('json-password-box') + const password = passwordInput.value - if (!fileContents) { - const message = 'You must select a file to import.' - return this.props.dispatch(actions.displayWarning(message)) + if (!password) { + const message = t('needImportPassword') + return this.props.displayWarning(message) + } + + this.props.importNewJsonAccount([ fileContents, password ]) } +} - const passwordInput = document.getElementById('json-password-box') - const password = passwordInput.value +JsonImportSubview.propTypes = { + error: PropTypes.string, + goHome: PropTypes.func, + displayWarning: PropTypes.func, + importNewJsonAccount: PropTypes.func, +} - if (!password) { - const message = 'You must enter a password for the selected file.' - return this.props.dispatch(actions.displayWarning(message)) +const mapStateToProps = state => { + return { + error: state.appState.warning, } +} - this.props.dispatch(actions.importNewAccount('JSON File', [ fileContents, password ])) +const mapDispatchToProps = dispatch => { + return { + goHome: () => dispatch(actions.goHome()), + displayWarning: warning => dispatch(actions.displayWarning(warning)), + importNewJsonAccount: options => dispatch(actions.importNewAccount('JSON File', options)), + } } + +module.exports = connect(mapStateToProps, mapDispatchToProps)(JsonImportSubview) diff --git a/ui/app/accounts/import/private-key.js b/ui/app/accounts/import/private-key.js index 12f3a6430..bc9e9384e 100644 --- a/ui/app/accounts/import/private-key.js +++ b/ui/app/accounts/import/private-key.js @@ -3,6 +3,7 @@ const Component = require('react').Component const h = require('react-hyperscript') const connect = require('react-redux').connect const actions = require('../../actions') +const t = require('../../../i18n') module.exports = connect(mapStateToProps, mapDispatchToProps)(PrivateKeyImportView) @@ -33,9 +34,9 @@ PrivateKeyImportView.prototype.render = function () { return ( h('div.new-account-import-form__private-key', [ - h('div.new-account-import-form__private-key-password-container', [ + h('span.new-account-create-form__instruction', t('pastePrivateKey')), - h('span.new-account-import-form__instruction', 'Paste your private key string here:'), + h('div.new-account-import-form__private-key-password-container', [ h('input.new-account-import-form__input-password', { type: 'password', @@ -47,16 +48,16 @@ PrivateKeyImportView.prototype.render = function () { h('div.new-account-import-form__buttons', {}, [ - h('button.new-account-create-form__button-cancel', { + h('button.new-account-create-form__button-cancel.allcaps', { onClick: () => goHome(), }, [ - 'CANCEL', + t('cancel'), ]), - h('button.new-account-create-form__button-create', { + h('button.new-account-create-form__button-create.allcaps', { onClick: () => this.createNewKeychain(), }, [ - 'IMPORT', + t('import'), ]), ]), diff --git a/ui/app/accounts/import/seed.js b/ui/app/accounts/import/seed.js index b4a7c0afa..9ffc669a2 100644 --- a/ui/app/accounts/import/seed.js +++ b/ui/app/accounts/import/seed.js @@ -2,6 +2,7 @@ const inherits = require('util').inherits const Component = require('react').Component const h = require('react-hyperscript') const connect = require('react-redux').connect +const t = require('../../../i18n') module.exports = connect(mapStateToProps)(SeedImportSubview) @@ -20,11 +21,10 @@ SeedImportSubview.prototype.render = function () { style: { }, }, [ - `Paste your seed phrase here!`, + t('pasteSeed'), h('textarea'), h('br'), - h('button', 'Submit'), + h('button', t('submit')), ]) ) } - diff --git a/ui/app/accounts/new-account/create-form.js b/ui/app/accounts/new-account/create-form.js index a6b3bba4b..eb34f7a2f 100644 --- a/ui/app/accounts/new-account/create-form.js +++ b/ui/app/accounts/new-account/create-form.js @@ -3,6 +3,7 @@ const PropTypes = require('prop-types') const h = require('react-hyperscript') const { connect } = require('react-redux') const actions = require('../../actions') +const t = require('../../../i18n') class NewAccountCreateForm extends Component { constructor (props) { @@ -13,7 +14,7 @@ class NewAccountCreateForm extends Component { this.state = { newAccountName: '', - defaultAccountName: `Account ${newAccountNumber}`, + defaultAccountName: t('newAccountNumberName', newAccountNumber), } } @@ -24,7 +25,7 @@ class NewAccountCreateForm extends Component { return h('div.new-account-create-form', [ h('div.new-account-create-form__input-label', {}, [ - 'Account Name', + t('accountName'), ]), h('div.new-account-create-form__input-wrapper', {}, [ @@ -37,16 +38,16 @@ class NewAccountCreateForm extends Component { h('div.new-account-create-form__buttons', {}, [ - h('button.new-account-create-form__button-cancel', { + h('button.new-account-create-form__button-cancel.allcaps', { onClick: () => this.props.goHome(), }, [ - 'CANCEL', + t('cancel'), ]), - h('button.new-account-create-form__button-create', { + h('button.new-account-create-form__button-create.allcaps', { onClick: () => this.props.createAccount(newAccountName || defaultAccountName), }, [ - 'CREATE', + t('create'), ]), ]), diff --git a/ui/app/accounts/new-account/index.js b/ui/app/accounts/new-account/index.js index acf0dc6e4..854568c77 100644 --- a/ui/app/accounts/new-account/index.js +++ b/ui/app/accounts/new-account/index.js @@ -3,6 +3,7 @@ const h = require('react-hyperscript') const inherits = require('util').inherits const connect = require('react-redux').connect const actions = require('../../actions') +const t = require('../../../i18n') const { getCurrentViewContext } = require('../../selectors') const classnames = require('classnames') @@ -42,10 +43,10 @@ AccountDetailsModal.prototype.render = function () { const { displayedForm, displayForm } = this.props return h('div.new-account', {}, [ - + h('div.new-account__header', [ - h('div.new-account__title', 'New Account'), + h('div.new-account__title', t('newAccount')), h('div.new-account__tabs', [ @@ -55,7 +56,7 @@ AccountDetailsModal.prototype.render = function () { 'new-account__tabs__unselected cursor-pointer': displayedForm !== 'CREATE', }), onClick: () => displayForm('CREATE'), - }, 'Create'), + }, t('createDen')), h('div.new-account__tabs__tab', { className: classnames('new-account__tabs__tab', { @@ -63,7 +64,7 @@ AccountDetailsModal.prototype.render = function () { 'new-account__tabs__unselected cursor-pointer': displayedForm !== 'IMPORT', }), onClick: () => displayForm('IMPORT'), - }, 'Import'), + }, t('import')), ]), diff --git a/ui/app/actions.js b/ui/app/actions.js index d6f509590..bc7ee3d07 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -75,6 +75,8 @@ var actions = { resetAccount, showNewVaultSeed: showNewVaultSeed, showInfoPage: showInfoPage, + CLOSE_WELCOME_SCREEN: 'CLOSE_WELCOME_SCREEN', + closeWelcomeScreen, // seed recovery actions REVEAL_SEED_CONFIRMATION: 'REVEAL_SEED_CONFIRMATION', revealSeedConfirmation: revealSeedConfirmation, @@ -788,7 +790,7 @@ function updateTransaction (txData) { function updateAndApproveTx (txData) { log.info('actions: updateAndApproveTx: ' + JSON.stringify(txData)) return (dispatch) => { - log.debug(`actions calling background.updateAndApproveTx`) + log.debug(`actions calling background.updateAndApproveTx.`) background.updateAndApproveTransaction(txData, (err) => { dispatch(actions.hideLoadingIndication()) dispatch(actions.updateTransactionParams(txData.id, txData.txParams)) @@ -947,6 +949,12 @@ function showNewVaultSeed (seed) { } } +function closeWelcomeScreen () { + return { + type: actions.CLOSE_WELCOME_SCREEN, + } +} + function backToUnlockView () { return { type: actions.BACK_TO_UNLOCK_VIEW, diff --git a/ui/app/add-token.js b/ui/app/add-token.js index 51c577987..b8878b772 100644 --- a/ui/app/add-token.js +++ b/ui/app/add-token.js @@ -71,13 +71,17 @@ AddTokenScreen.prototype.componentWillMount = function () { } AddTokenScreen.prototype.toggleToken = function (address, token) { - const { selectedTokens, errors } = this.state - const { [address]: selectedToken } = selectedTokens + const { selectedTokens = {}, errors } = this.state + const selectedTokensCopy = { ...selectedTokens } + + if (address in selectedTokensCopy) { + delete selectedTokensCopy[address] + } else { + selectedTokensCopy[address] = token + } + this.setState({ - selectedTokens: { - ...selectedTokens, - [address]: selectedToken ? null : token, - }, + selectedTokens: selectedTokensCopy, errors: { ...errors, tokenSelector: null, diff --git a/ui/app/app.js b/ui/app/app.js index 4e6da24c3..9708a2485 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -4,6 +4,7 @@ const connect = require('react-redux').connect const h = require('react-hyperscript') const actions = require('./actions') const classnames = require('classnames') +const t = require('../i18n') // mascara const MascaraFirstTime = require('../../mascara/src/app/first-time').default @@ -12,6 +13,8 @@ const MascaraBuyEtherScreen = require('../../mascara/src/app/first-time/buy-ethe const OldUIInitializeMenuScreen = require('./first-time/init-menu') const InitializeMenuScreen = MascaraFirstTime const NewKeyChainScreen = require('./new-keychain') +const WelcomeScreen = require('./welcome-screen').default + // accounts const MainContainer = require('./main-container') const SendTransactionScreen2 = require('./components/send/send-v2-container') @@ -91,6 +94,7 @@ function mapStateToProps (state) { betaUI: state.metamask.featureFlags.betaUI, isRevealingSeedWords: state.metamask.isRevealingSeedWords, Qr: state.appState.Qr, + welcomeScreenSeen: state.metamask.welcomeScreenSeen, // state needed to get account dropdown temporarily rendering from app bar identities, @@ -244,6 +248,7 @@ App.prototype.renderAppBar = function () { isInitialized, betaUI, isPopup, + welcomeScreenSeen, } = this.props if (window.METAMASK_UI_TYPE === 'notification') { @@ -269,7 +274,7 @@ App.prototype.renderAppBar = function () { style: {}, }, [ - h('.app-header.flex-row.flex-space-between', { + (isInitialized || welcomeScreenSeen || isPopup || !betaUI) && h('.app-header.flex-row.flex-space-between', { className: classnames({ 'app-header--initialized': !isOnboarding, }), @@ -289,12 +294,12 @@ App.prototype.renderAppBar = function () { // metamask name h('.flex-row', [ - h('h1', 'MetaMask'), - h('div.beta-label', 'BETA'), + h('h1', t('appName')), + h('div.beta-label', t('beta')), ]), ]), - h('div.header__right-actions', [ + betaUI && isInitialized && h('div.header__right-actions', [ h('div.network-component-wrapper', { style: {}, }, [ @@ -324,8 +329,12 @@ App.prototype.renderAppBar = function () { ]), ]), - !isInitialized && !isPopup && betaUI && h('h2.alpha-warning', - 'Please be aware that this version is still under development'), + !isInitialized && !isPopup && betaUI && h('h2', { + className: classnames({ + 'alpha-warning': welcomeScreenSeen, + 'alpha-warning-welcome-screen': !welcomeScreenSeen, + }), + }, 'Please be aware that this version is still under development'), ]) ) @@ -369,11 +378,18 @@ App.prototype.renderPrimary = function () { isOnboarding, betaUI, isRevealingSeedWords, + welcomeScreenSeen, Qr, + isInitialized, + isUnlocked, } = props const isMascaraOnboarding = isMascara && isOnboarding const isBetaUIOnboarding = betaUI && isOnboarding && !props.isPopup && !isRevealingSeedWords + if (!welcomeScreenSeen && betaUI && !isInitialized && !isUnlocked) { + return h(WelcomeScreen) + } + if (isMascaraOnboarding || isBetaUIOnboarding) { return h(MascaraFirstTime) } diff --git a/ui/app/components/account-dropdowns.js b/ui/app/components/account-dropdowns.js index 1cd7a0847..1612d7b6a 100644 --- a/ui/app/components/account-dropdowns.js +++ b/ui/app/components/account-dropdowns.js @@ -9,6 +9,7 @@ const DropdownMenuItem = require('./dropdown').DropdownMenuItem const Identicon = require('./identicon') const ethUtil = require('ethereumjs-util') const copyToClipboard = require('copy-to-clipboard') +const t = require('../../i18n') class AccountDropdowns extends Component { constructor (props) { @@ -79,7 +80,7 @@ class AccountDropdowns extends Component { try { // Sometimes keyrings aren't loaded yet: const type = keyring.type const isLoose = type !== 'HD Key Tree' - return isLoose ? h('.keyring-label', 'LOOSE') : null + return isLoose ? h('.keyring-label.allcaps', t('loose')) : null } catch (e) { return } } @@ -129,7 +130,7 @@ class AccountDropdowns extends Component { diameter: 32, }, ), - h('span', { style: { marginLeft: '20px', fontSize: '24px' } }, 'Create Account'), + h('span', { style: { marginLeft: '20px', fontSize: '24px' } }, t('createAccount')), ], ), h( @@ -154,7 +155,7 @@ class AccountDropdowns extends Component { fontSize: '24px', marginBottom: '5px', }, - }, 'Import Account'), + }, t('importAccount')), ] ), ] @@ -192,7 +193,7 @@ class AccountDropdowns extends Component { global.platform.openWindow({ url }) }, }, - 'View account on Etherscan', + t('etherscanView'), ), h( DropdownMenuItem, @@ -204,7 +205,7 @@ class AccountDropdowns extends Component { actions.showQrView(selected, identity ? identity.name : '') }, }, - 'Show QR Code', + t('showQRCode'), ), h( DropdownMenuItem, @@ -216,7 +217,7 @@ class AccountDropdowns extends Component { copyToClipboard(checkSumAddress) }, }, - 'Copy Address to clipboard', + t('copyAddress'), ), h( DropdownMenuItem, @@ -226,7 +227,7 @@ class AccountDropdowns extends Component { actions.requestAccountExport() }, }, - 'Export Private Key', + t('exportPrivateKey'), ), ] ) diff --git a/ui/app/components/account-export.js b/ui/app/components/account-export.js index 32b103c86..5637bc8d0 100644 --- a/ui/app/components/account-export.js +++ b/ui/app/components/account-export.js @@ -6,6 +6,7 @@ const copyToClipboard = require('copy-to-clipboard') const actions = require('../actions') const ethUtil = require('ethereumjs-util') const connect = require('react-redux').connect +const t = require('../../i18n') module.exports = connect(mapStateToProps)(ExportAccountView) @@ -35,7 +36,7 @@ ExportAccountView.prototype.render = function () { if (notExporting) return h('div') if (exportRequested) { - const warning = `Export private keys at your own risk.` + const warning = t('exportPrivateKeyWarning') return ( h('div', { style: { @@ -53,7 +54,7 @@ ExportAccountView.prototype.render = function () { h('p.error', warning), h('input#exportAccount.sizing-input', { type: 'password', - placeholder: 'confirm password', + placeholder: t('confirmPassword').toLowerCase(), onKeyPress: this.onExportKeyPress.bind(this), style: { position: 'relative', @@ -74,10 +75,10 @@ ExportAccountView.prototype.render = function () { style: { marginRight: '10px', }, - }, 'Submit'), + }, t('submit')), h('button', { onClick: () => this.props.dispatch(actions.backToAccountDetail(this.props.address)), - }, 'Cancel'), + }, t('cancel')), ]), (this.props.warning) && ( h('span.error', { @@ -98,7 +99,7 @@ ExportAccountView.prototype.render = function () { margin: '0 20px', }, }, [ - h('label', 'Your private key (click to copy):'), + h('label', t('copyPrivateKey') + ':'), h('p.error.cursor-pointer', { style: { textOverflow: 'ellipsis', @@ -112,13 +113,13 @@ ExportAccountView.prototype.render = function () { }, plainKey), h('button', { onClick: () => this.props.dispatch(actions.backToAccountDetail(this.props.address)), - }, 'Done'), + }, t('done')), h('button', { style: { marginLeft: '10px', }, onClick: () => exportAsFile(`MetaMask ${nickname} Private Key`, plainKey), - }, 'Save as File'), + }, t('saveAsFile')), ]) } } diff --git a/ui/app/components/account-menu/index.js b/ui/app/components/account-menu/index.js index 1a0103d4f..e838e8916 100644 --- a/ui/app/components/account-menu/index.js +++ b/ui/app/components/account-menu/index.js @@ -6,6 +6,7 @@ const actions = require('../../actions') const { Menu, Item, Divider, CloseArea } = require('../dropdowns/components/menu') const Identicon = require('../identicon') const { formatBalance } = require('../../util') +const t = require('../../../i18n') module.exports = connect(mapStateToProps, mapDispatchToProps)(AccountMenu) @@ -70,10 +71,10 @@ AccountMenu.prototype.render = function () { h(Item, { className: 'account-menu__header', }, [ - 'My Accounts', + t('myAccounts'), h('button.account-menu__logout-button', { onClick: lockMetamask, - }, 'Log out'), + }, t('logout')), ]), h(Divider), h('div.account-menu__accounts', this.renderAccounts()), @@ -81,23 +82,23 @@ AccountMenu.prototype.render = function () { h(Item, { onClick: () => showNewAccountPage('CREATE'), icon: h('img.account-menu__item-icon', { src: 'images/plus-btn-white.svg' }), - text: 'Create Account', + text: t('createAccount'), }), h(Item, { onClick: () => showNewAccountPage('IMPORT'), icon: h('img.account-menu__item-icon', { src: 'images/import-account.svg' }), - text: 'Import Account', + text: t('importAccount'), }), h(Divider), h(Item, { onClick: showInfoPage, - icon: h('img.account-menu__item-icon', { src: 'images/mm-info-icon.svg' }), - text: 'Info & Help', + icon: h('img', { src: 'images/mm-info-icon.svg' }), + text: t('infoHelp'), }), h(Item, { onClick: showConfigPage, icon: h('img.account-menu__item-icon', { src: 'images/settings.svg' }), - text: 'Settings', + text: t('settings'), }), ]) } @@ -155,6 +156,6 @@ AccountMenu.prototype.indicateIfLoose = function (keyring) { try { // Sometimes keyrings aren't loaded yet: const type = keyring.type const isLoose = type !== 'HD Key Tree' - return isLoose ? h('.keyring-label', 'IMPORTED') : null + return isLoose ? h('.keyring-label.allcaps', t('imported')) : null } catch (e) { return } } diff --git a/ui/app/components/bn-as-decimal-input.js b/ui/app/components/bn-as-decimal-input.js index 22e37602e..70701b039 100644 --- a/ui/app/components/bn-as-decimal-input.js +++ b/ui/app/components/bn-as-decimal-input.js @@ -4,6 +4,7 @@ const inherits = require('util').inherits const ethUtil = require('ethereumjs-util') const BN = ethUtil.BN const extend = require('xtend') +const t = require('../../i18n') module.exports = BnAsDecimalInput @@ -136,13 +137,13 @@ BnAsDecimalInput.prototype.constructWarning = function () { let message = name ? name + ' ' : '' if (min && max) { - message += `must be greater than or equal to ${newMin} ${suffix} and less than or equal to ${newMax} ${suffix}.` + message += t('betweenMinAndMax', [`${newMin} ${suffix}`, `${newMax} ${suffix}`]) } else if (min) { - message += `must be greater than or equal to ${newMin} ${suffix}.` + message += t('greaterThanMin', [`${newMin} ${suffix}`]) } else if (max) { - message += `must be less than or equal to ${newMax} ${suffix}.` + message += t('lessThanMax', [`${newMax} ${suffix}`]) } else { - message += 'Invalid input.' + message += t('invalidInput') } return message diff --git a/ui/app/components/buy-button-subview.js b/ui/app/components/buy-button-subview.js index d5958787b..1e277a94b 100644 --- a/ui/app/components/buy-button-subview.js +++ b/ui/app/components/buy-button-subview.js @@ -9,6 +9,7 @@ const Loading = require('./loading') const AccountPanel = require('./account-panel') const RadioList = require('./custom-radio-list') const networkNames = require('../../../app/scripts/config.js').networkNames +const t = require('../../i18n') module.exports = connect(mapStateToProps)(BuyButtonSubview) @@ -76,7 +77,7 @@ BuyButtonSubview.prototype.headerSubview = function () { paddingTop: '4px', paddingBottom: '4px', }, - }, 'Deposit Eth'), + }, t('depositEth')), ]), // loading indication @@ -118,7 +119,7 @@ BuyButtonSubview.prototype.headerSubview = function () { paddingTop: '4px', paddingBottom: '4px', }, - }, 'Select Service'), + }, t('selectService')), ]), ]) @@ -143,7 +144,7 @@ BuyButtonSubview.prototype.primarySubview = function () { case '4': case '42': const networkName = networkNames[network] - const label = `${networkName} Test Faucet` + const label = `${networkName} ${t('testFaucet')}` return ( h('div.flex-column', { style: { @@ -164,14 +165,14 @@ BuyButtonSubview.prototype.primarySubview = function () { style: { marginTop: '15px', }, - }, 'Borrow With Dharma (Beta)') + }, t('borrowDharma')) ) : null, ]) ) default: return ( - h('h2.error', 'Unknown network ID') + h('h2.error', t('unknownNetworkId')) ) } @@ -203,8 +204,8 @@ BuyButtonSubview.prototype.mainnetSubview = function () { 'ShapeShift', ], subtext: { - 'Coinbase': 'Crypto/FIAT (USA only)', - 'ShapeShift': 'Crypto', + 'Coinbase': `${t('crypto')}/${t('fiat')} (${t('usaOnly')})`, + 'ShapeShift': t('crypto'), }, onClick: this.radioHandler.bind(this), }), diff --git a/ui/app/components/coinbase-form.js b/ui/app/components/coinbase-form.js index f70208625..e442b43d5 100644 --- a/ui/app/components/coinbase-form.js +++ b/ui/app/components/coinbase-form.js @@ -3,6 +3,7 @@ const h = require('react-hyperscript') const inherits = require('util').inherits const connect = require('react-redux').connect const actions = require('../actions') +const t = require('../../i18n') module.exports = connect(mapStateToProps)(CoinbaseForm) @@ -37,11 +38,11 @@ CoinbaseForm.prototype.render = function () { }, [ h('button.btn-green', { onClick: this.toCoinbase.bind(this), - }, 'Continue to Coinbase'), + }, t('continueToCoinbase')), h('button.btn-red', { onClick: () => props.dispatch(actions.goHome()), - }, 'Cancel'), + }, t('cancel')), ]), ]) } diff --git a/ui/app/components/copyButton.js b/ui/app/components/copyButton.js index a25d0719c..355f78d45 100644 --- a/ui/app/components/copyButton.js +++ b/ui/app/components/copyButton.js @@ -2,6 +2,7 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits const copyToClipboard = require('copy-to-clipboard') +const t = require('../../i18n') const Tooltip = require('./tooltip') @@ -22,7 +23,7 @@ CopyButton.prototype.render = function () { const value = props.value const copied = state.copied - const message = copied ? 'Copied' : props.title || ' Copy ' + const message = copied ? t('copiedButton') : props.title || t('copyButton') return h('.copy-button', { style: { diff --git a/ui/app/components/copyable.js b/ui/app/components/copyable.js index a4f6f4bc6..fca7d3863 100644 --- a/ui/app/components/copyable.js +++ b/ui/app/components/copyable.js @@ -4,6 +4,7 @@ const inherits = require('util').inherits const Tooltip = require('./tooltip') const copyToClipboard = require('copy-to-clipboard') +const t = require('../../i18n') module.exports = Copyable @@ -22,7 +23,7 @@ Copyable.prototype.render = function () { const { copied } = state return h(Tooltip, { - title: copied ? 'Copied!' : 'Copy', + title: copied ? t('copiedExclamation') : t('copy'), position: 'bottom', }, h('span', { style: { diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js index 2bac57253..291447bb4 100644 --- a/ui/app/components/customize-gas-modal/index.js +++ b/ui/app/components/customize-gas-modal/index.js @@ -3,6 +3,7 @@ const h = require('react-hyperscript') const inherits = require('util').inherits const connect = require('react-redux').connect const actions = require('../../actions') +const t = require('../../../i18n') const GasModalCard = require('./gas-modal-card') const ethUtil = require('ethereumjs-util') @@ -149,7 +150,7 @@ CustomizeGasModal.prototype.validate = function ({ gasTotal, gasLimit }) { }) if (!balanceIsSufficient) { - error = 'Insufficient balance for current gas total' + error = t('balanceIsInsufficientGas') } const gasLimitTooLow = gasLimit && conversionGreaterThan( @@ -165,7 +166,7 @@ CustomizeGasModal.prototype.validate = function ({ gasTotal, gasLimit }) { ) if (gasLimitTooLow) { - error = 'Gas limit must be at least 21000' + error = t('gasLimitTooLow') } this.setState({ error }) @@ -253,7 +254,7 @@ CustomizeGasModal.prototype.render = function () { }, [ h('div.send-v2__customize-gas__header', {}, [ - h('div.send-v2__customize-gas__title', 'Customize Gas'), + h('div.send-v2__customize-gas__title', t('customGas')), h('div.send-v2__customize-gas__close', { onClick: hideModal, @@ -269,8 +270,8 @@ CustomizeGasModal.prototype.render = function () { // max: 1000, step: multiplyCurrencies(MIN_GAS_PRICE_GWEI, 10), onChange: value => this.convertAndSetGasPrice(value), - title: 'Gas Price (GWEI)', - copy: 'We calculate the suggested gas prices based on network success rates.', + title: t('gasPrice'), + copy: t('gasPriceCalculation'), }), h(GasModalCard, { @@ -279,8 +280,8 @@ CustomizeGasModal.prototype.render = function () { // max: 100000, step: 1, onChange: value => this.convertAndSetGasLimit(value), - title: 'Gas Limit', - copy: 'We calculate the suggested gas limit based on network success rates.', + title: t('gasLimit'), + copy: t('gasLimitCalculation'), }), ]), @@ -293,16 +294,16 @@ CustomizeGasModal.prototype.render = function () { h('div.send-v2__customize-gas__revert', { onClick: () => this.revert(), - }, ['Revert']), + }, [t('revert')]), h('div.send-v2__customize-gas__buttons', [ - h('div.send-v2__customize-gas__cancel', { + h('div.send-v2__customize-gas__cancel.allcaps', { onClick: this.props.hideModal, - }, ['CANCEL']), + }, [t('cancel')]), - h(`div.send-v2__customize-gas__save${error ? '__error' : ''}`, { + h(`div.send-v2__customize-gas__save${error ? '__error' : ''}.allcaps`, { onClick: () => !error && this.save(gasPrice, gasLimit, gasTotal), - }, ['SAVE']), + }, [t('save')]), ]), ]), diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js index 40918cc53..e5359c1d6 100644 --- a/ui/app/components/dropdowns/components/account-dropdowns.js +++ b/ui/app/components/dropdowns/components/account-dropdowns.js @@ -10,6 +10,7 @@ const Identicon = require('../../identicon') const ethUtil = require('ethereumjs-util') const copyToClipboard = require('copy-to-clipboard') const { formatBalance } = require('../../../util') +const t = require('../../../../i18n') class AccountDropdowns extends Component { constructor (props) { @@ -121,7 +122,7 @@ class AccountDropdowns extends Component { flex: '3 3 auto', }, }, [ - h('span.account-dropdown-edit-button', { + h('span.account-dropdown-edit-button.allcaps', { style: { fontSize: '16px', }, @@ -129,7 +130,7 @@ class AccountDropdowns extends Component { actions.showEditAccountModal(identity) }, }, [ - 'Edit', + t('edit'), ]), ]), @@ -143,7 +144,7 @@ class AccountDropdowns extends Component { try { // Sometimes keyrings aren't loaded yet: const type = keyring.type const isLoose = type !== 'HD Key Tree' - return isLoose ? h('.keyring-label', 'IMPORTED') : null + return isLoose ? h('.keyring-label.allcaps', t('loose')) : null } catch (e) { return } } @@ -201,7 +202,7 @@ class AccountDropdowns extends Component { fontSize: '16px', lineHeight: '23px', }, - }, 'Create Account'), + }, t('createAccount')), ], ), h( @@ -235,7 +236,7 @@ class AccountDropdowns extends Component { fontSize: '16px', lineHeight: '23px', }, - }, 'Import Account'), + }, t('importAccount')), ] ), ] @@ -286,7 +287,7 @@ class AccountDropdowns extends Component { menuItemStyles, ), }, - 'Account Details', + t('accountDetails'), ), h( DropdownMenuItem, @@ -302,7 +303,7 @@ class AccountDropdowns extends Component { menuItemStyles, ), }, - 'View account on Etherscan', + t('etherscanView'), ), h( DropdownMenuItem, @@ -318,7 +319,7 @@ class AccountDropdowns extends Component { menuItemStyles, ), }, - 'Copy Address to clipboard', + t('copyAddress'), ), h( DropdownMenuItem, @@ -330,7 +331,7 @@ class AccountDropdowns extends Component { menuItemStyles, ), }, - 'Export Private Key', + t('exportPrivateKey'), ), h( DropdownMenuItem, @@ -345,7 +346,7 @@ class AccountDropdowns extends Component { menuItemStyles, ), }, - 'Add Token', + t('addToken'), ), ] @@ -463,4 +464,3 @@ function mapStateToProps (state) { } module.exports = connect(mapStateToProps, mapDispatchToProps)(AccountDropdowns) - diff --git a/ui/app/components/dropdowns/network-dropdown.js b/ui/app/components/dropdowns/network-dropdown.js index ff10c0758..5afe730c1 100644 --- a/ui/app/components/dropdowns/network-dropdown.js +++ b/ui/app/components/dropdowns/network-dropdown.js @@ -6,6 +6,7 @@ const actions = require('../../actions') const Dropdown = require('./components/dropdown').Dropdown const DropdownMenuItem = require('./components/dropdown').DropdownMenuItem const NetworkDropdownIcon = require('./components/network-dropdown-icon') +const t = require('../../../i18n') const R = require('ramda') // classes from nodes of the toggle element. @@ -93,13 +94,13 @@ NetworkDropdown.prototype.render = function () { }, [ h('div.network-dropdown-header', {}, [ - h('div.network-dropdown-title', {}, 'Networks'), + h('div.network-dropdown-title', {}, t('networks')), h('div.network-dropdown-divider'), h('div.network-dropdown-content', {}, - 'The default network for Ether transactions is Main Net.' + t('defaultNetwork') ), ]), @@ -121,7 +122,7 @@ NetworkDropdown.prototype.render = function () { style: { color: providerType === 'mainnet' ? '#ffffff' : '#9b9b9b', }, - }, 'Main Ethereum Network'), + }, t('mainnet')), ] ), @@ -143,7 +144,7 @@ NetworkDropdown.prototype.render = function () { style: { color: providerType === 'ropsten' ? '#ffffff' : '#9b9b9b', }, - }, 'Ropsten Test Network'), + }, t('ropsten')), ] ), @@ -165,7 +166,7 @@ NetworkDropdown.prototype.render = function () { style: { color: providerType === 'kovan' ? '#ffffff' : '#9b9b9b', }, - }, 'Kovan Test Network'), + }, t('kovan')), ] ), @@ -187,7 +188,7 @@ NetworkDropdown.prototype.render = function () { style: { color: providerType === 'rinkeby' ? '#ffffff' : '#9b9b9b', }, - }, 'Rinkeby Test Network'), + }, t('rinkeby')), ] ), @@ -209,7 +210,7 @@ NetworkDropdown.prototype.render = function () { style: { color: activeNetwork === 'http://localhost:8545' ? '#ffffff' : '#9b9b9b', }, - }, 'Localhost 8545'), + }, t('localhost')), ] ), @@ -233,7 +234,7 @@ NetworkDropdown.prototype.render = function () { style: { color: activeNetwork === 'custom' ? '#ffffff' : '#9b9b9b', }, - }, 'Custom RPC'), + }, t('customRPC')), ] ), @@ -248,15 +249,15 @@ NetworkDropdown.prototype.getNetworkName = function () { let name if (providerName === 'mainnet') { - name = 'Main Ethereum Network' + name = t('mainnet') } else if (providerName === 'ropsten') { - name = 'Ropsten Test Network' + name = t('ropsten') } else if (providerName === 'kovan') { - name = 'Kovan Test Network' + name = t('kovan') } else if (providerName === 'rinkeby') { - name = 'Rinkeby Test Network' + name = t('rinkeby') } else { - name = 'Unknown Private Network' + name = t('unknownNetwork') } return name diff --git a/ui/app/components/dropdowns/token-menu-dropdown.js b/ui/app/components/dropdowns/token-menu-dropdown.js index dc7a985e3..a4f93b505 100644 --- a/ui/app/components/dropdowns/token-menu-dropdown.js +++ b/ui/app/components/dropdowns/token-menu-dropdown.js @@ -3,6 +3,7 @@ const h = require('react-hyperscript') const inherits = require('util').inherits const connect = require('react-redux').connect const actions = require('../../actions') +const t = require('../../../i18n') module.exports = connect(null, mapDispatchToProps)(TokenMenuDropdown) @@ -43,7 +44,7 @@ TokenMenuDropdown.prototype.render = function () { showHideTokenConfirmationModal(this.props.token) this.props.onClose() }, - }, 'Hide Token'), + }, t('hideToken')), ]), ]), diff --git a/ui/app/components/ens-input.js b/ui/app/components/ens-input.js index 6553053f7..add67ea35 100644 --- a/ui/app/components/ens-input.js +++ b/ui/app/components/ens-input.js @@ -8,6 +8,7 @@ const ENS = require('ethjs-ens') const networkMap = require('ethjs-ens/lib/network-map.json') const ensRE = /.+\..+$/ const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' +const t = require('../../i18n') module.exports = EnsInput @@ -89,13 +90,13 @@ EnsInput.prototype.lookupEnsName = function () { log.info(`ENS attempting to resolve name: ${recipient}`) this.ens.lookup(recipient.trim()) .then((address) => { - if (address === ZERO_ADDRESS) throw new Error('No address has been set for this name.') + if (address === ZERO_ADDRESS) throw new Error(t('noAddressForName')) if (address !== ensResolution) { this.setState({ loadingEns: false, ensResolution: address, nickname: recipient.trim(), - hoverText: address + '\nClick to Copy', + hoverText: address + '\n' + t('clickCopy'), ensFailure: false, }) } diff --git a/ui/app/components/hex-as-decimal-input.js b/ui/app/components/hex-as-decimal-input.js index 4a71e9585..a43d44f89 100644 --- a/ui/app/components/hex-as-decimal-input.js +++ b/ui/app/components/hex-as-decimal-input.js @@ -4,6 +4,7 @@ const inherits = require('util').inherits const ethUtil = require('ethereumjs-util') const BN = ethUtil.BN const extend = require('xtend') +const t = require('../../i18n') module.exports = HexAsDecimalInput @@ -126,13 +127,13 @@ HexAsDecimalInput.prototype.constructWarning = function () { let message = name ? name + ' ' : '' if (min && max) { - message += `must be greater than or equal to ${min} and less than or equal to ${max}.` + message += t('betweenMinAndMax', [min, max]) } else if (min) { - message += `must be greater than or equal to ${min}.` + message += t('greaterThanMin', [min]) } else if (max) { - message += `must be less than or equal to ${max}.` + message += t('lessThanMax', [max]) } else { - message += 'Invalid input.' + message += t('invalidInput') } return message diff --git a/ui/app/components/modals/account-details-modal.js b/ui/app/components/modals/account-details-modal.js index c1f7a3236..75f989e86 100644 --- a/ui/app/components/modals/account-details-modal.js +++ b/ui/app/components/modals/account-details-modal.js @@ -8,6 +8,7 @@ const { getSelectedIdentity } = require('../../selectors') const genAccountLink = require('../../../lib/account-link.js') const QrView = require('../qr-code') const EditableLabel = require('../editable-label') +const t = require('../../../i18n') function mapStateToProps (state) { return { @@ -64,12 +65,12 @@ AccountDetailsModal.prototype.render = function () { h('button.btn-clear.account-modal__button', { onClick: () => global.platform.openWindow({ url: genAccountLink(address, network) }), - }, 'View account on Etherscan'), + }, t('etherscanView')), // Holding on redesign for Export Private Key functionality h('button.btn-clear.account-modal__button', { onClick: () => showExportPrivateKeyModal(), - }, 'Export private key'), + }, t('exportPrivateKey')), ]) } diff --git a/ui/app/components/modals/account-modal-container.js b/ui/app/components/modals/account-modal-container.js index c548fb7b3..08540aa76 100644 --- a/ui/app/components/modals/account-modal-container.js +++ b/ui/app/components/modals/account-modal-container.js @@ -5,6 +5,7 @@ const connect = require('react-redux').connect const actions = require('../../actions') const { getSelectedIdentity } = require('../../selectors') const Identicon = require('../identicon') +const t = require('../../../i18n') function mapStateToProps (state) { return { @@ -59,7 +60,7 @@ AccountModalContainer.prototype.render = function () { h('i.fa.fa-angle-left.fa-lg'), - h('span.account-modal-back__text', ' Back'), + h('span.account-modal-back__text', ' ' + t('back')), ]), diff --git a/ui/app/components/modals/buy-options-modal.js b/ui/app/components/modals/buy-options-modal.js index 74a7a847e..7eb73c3a6 100644 --- a/ui/app/components/modals/buy-options-modal.js +++ b/ui/app/components/modals/buy-options-modal.js @@ -4,6 +4,7 @@ const inherits = require('util').inherits const connect = require('react-redux').connect const actions = require('../../actions') const networkNames = require('../../../../app/scripts/config.js').networkNames +const t = require('../../../i18n') function mapStateToProps (state) { return { @@ -56,15 +57,15 @@ BuyOptions.prototype.render = function () { }, [ h('div.buy-modal-content-title', { style: {}, - }, 'Transfers'), - h('div', {}, 'How would you like to deposit Ether?'), + }, t('transfers')), + h('div', {}, t('howToDeposit')), ]), h('div.buy-modal-content-options.flex-column.flex-center', {}, [ isTestNetwork - ? this.renderModalContentOption(networkName, 'Test Faucet', () => toFaucet(network)) - : this.renderModalContentOption('Coinbase', 'Deposit with Fiat', () => toCoinbase(address)), + ? this.renderModalContentOption(networkName, t('testFaucet'), () => toFaucet(network)) + : this.renderModalContentOption('Coinbase', t('depositFiat'), () => toCoinbase(address)), // h('div.buy-modal-content-option', {}, [ // h('div.buy-modal-content-option-title', {}, 'Shapeshift'), @@ -72,8 +73,8 @@ BuyOptions.prototype.render = function () { // ]),, this.renderModalContentOption( - 'Direct Deposit', - 'Deposit from another account', + t('directDeposit'), + t('depositFromAccount'), () => this.goToAccountDetailsModal() ), @@ -84,7 +85,7 @@ BuyOptions.prototype.render = function () { background: 'white', }, onClick: () => { this.props.hideModal() }, - }, h('div.buy-modal-content-footer#buy-modal-content-footer-text', {}, 'Cancel')), + }, h('div.buy-modal-content-footer#buy-modal-content-footer-text', {}, t('cancel'))), ]), ]) } diff --git a/ui/app/components/modals/deposit-ether-modal.js b/ui/app/components/modals/deposit-ether-modal.js index 7547dbcf5..26ff3ea03 100644 --- a/ui/app/components/modals/deposit-ether-modal.js +++ b/ui/app/components/modals/deposit-ether-modal.js @@ -5,18 +5,18 @@ const connect = require('react-redux').connect const actions = require('../../actions') const networkNames = require('../../../../app/scripts/config.js').networkNames const ShapeshiftForm = require('../shapeshift-form') - -const DIRECT_DEPOSIT_ROW_TITLE = 'Directly Deposit Ether' -const DIRECT_DEPOSIT_ROW_TEXT = `If you already have some Ether, the quickest way to get Ether in -your new wallet by direct deposit.` -const COINBASE_ROW_TITLE = 'Buy on Coinbase' -const COINBASE_ROW_TEXT = `Coinbase is the world’s most popular way to buy and sell bitcoin, -ethereum, and litecoin.` -const SHAPESHIFT_ROW_TITLE = 'Deposit with ShapeShift' -const SHAPESHIFT_ROW_TEXT = `If you own other cryptocurrencies, you can trade and deposit Ether -directly into your MetaMask wallet. No Account Needed.` -const FAUCET_ROW_TITLE = 'Test Faucet' -const facuetRowText = networkName => `Get Ether from a faucet for the ${networkName}` +const t = require('../../../i18n') + +const DIRECT_DEPOSIT_ROW_TITLE = t('directDepositEther') +const DIRECT_DEPOSIT_ROW_TEXT = t('directDepositEtherExplainer') +const COINBASE_ROW_TITLE = t('buyCoinbase') +const COINBASE_ROW_TEXT = t('buyCoinbaseExplainer') +const SHAPESHIFT_ROW_TITLE = t('depositShapeShift') +const SHAPESHIFT_ROW_TEXT = t('depositShapeShiftExplainer') +const FAUCET_ROW_TITLE = t('testFaucet') +const facuetRowText = (networkName) => { + return t('getEtherFromFaucet', [networkName]) +} function mapStateToProps (state) { return { @@ -83,7 +83,7 @@ DepositEtherModal.prototype.renderRow = function ({ ]), - h('div.deposit-ether-modal__buy-row__logo', [logo]), + h('div.deposit-ether-modal__buy-row__logo-container', [logo]), h('div.deposit-ether-modal__buy-row__description', [ @@ -109,17 +109,17 @@ DepositEtherModal.prototype.render = function () { const isTestNetwork = ['3', '4', '42'].find(n => n === network) const networkName = networkNames[network] - return h('div.deposit-ether-modal', {}, [ + return h('div.page-container.page-container--full-width', {}, [ - h('div.deposit-ether-modal__header', [ + h('div.page-container__header', [ - h('div.deposit-ether-modal__header__title', ['Deposit Ether']), + h('div.page-container__title', [t('depositEther')]), - h('div.deposit-ether-modal__header__description', [ - 'To interact with decentralized applications using MetaMask, you’ll need Ether in your wallet.', + h('div.page-container__subtitle', [ + t('needEtherInWallet'), ]), - h('div.deposit-ether-modal__header__close', { + h('div.page-container__header-close', { onClick: () => { this.setState({ buyingWithShapeshift: false }) this.props.hideWarning() @@ -128,55 +128,64 @@ DepositEtherModal.prototype.render = function () { }), ]), + + h('.page-container__content', {}, [ + + h('div.deposit-ether-modal__buy-rows', [ + + this.renderRow({ + logo: h('img.deposit-ether-modal__buy-row__eth-logo', { src: '../../../images/eth_logo.svg' }), + title: DIRECT_DEPOSIT_ROW_TITLE, + text: DIRECT_DEPOSIT_ROW_TEXT, + buttonLabel: t('viewAccount'), + onButtonClick: () => this.goToAccountDetailsModal(), + hide: buyingWithShapeshift, + }), - h('div.deposit-ether-modal__buy-rows', [ - - this.renderRow({ - logo: h('img.deposit-ether-modal__buy-row__eth-logo', { src: '../../../images/eth_logo.svg' }), - title: DIRECT_DEPOSIT_ROW_TITLE, - text: DIRECT_DEPOSIT_ROW_TEXT, - buttonLabel: 'View Account', - onButtonClick: () => this.goToAccountDetailsModal(), - hide: buyingWithShapeshift, - }), - - this.renderRow({ - logo: h('i.fa.fa-tint.fa-2x'), - title: FAUCET_ROW_TITLE, - text: facuetRowText(networkName), - buttonLabel: 'Get Ether', - onButtonClick: () => toFaucet(network), - hide: !isTestNetwork || buyingWithShapeshift, - }), - - this.renderRow({ - logo: h('img.deposit-ether-modal__buy-row__coinbase-logo', { - src: '../../../images/coinbase logo.png', + this.renderRow({ + logo: h('i.fa.fa-tint.fa-2x'), + title: FAUCET_ROW_TITLE, + text: facuetRowText(networkName), + buttonLabel: t('getEther'), + onButtonClick: () => toFaucet(network), + hide: !isTestNetwork || buyingWithShapeshift, }), - title: COINBASE_ROW_TITLE, - text: COINBASE_ROW_TEXT, - buttonLabel: 'Continue to Coinbase', - onButtonClick: () => toCoinbase(address), - hide: isTestNetwork || buyingWithShapeshift, - }), - this.renderRow({ - logo: h('img.deposit-ether-modal__buy-row__shapeshift-logo', { - src: '../../../images/shapeshift logo.png', + this.renderRow({ + logo: h('div.deposit-ether-modal__logo', { + style: { + backgroundImage: 'url(\'../../../images/coinbase logo.png\')', + height: '40px', + }, + }), + title: COINBASE_ROW_TITLE, + text: COINBASE_ROW_TEXT, + buttonLabel: t('continueToCoinbase'), + onButtonClick: () => toCoinbase(address), + hide: isTestNetwork || buyingWithShapeshift, }), - title: SHAPESHIFT_ROW_TITLE, - text: SHAPESHIFT_ROW_TEXT, - buttonLabel: 'Buy with Shapeshift', - onButtonClick: () => this.setState({ buyingWithShapeshift: true }), - hide: isTestNetwork, - hideButton: buyingWithShapeshift, - hideTitle: buyingWithShapeshift, - onBackClick: () => this.setState({ buyingWithShapeshift: false }), - showBackButton: this.state.buyingWithShapeshift, - className: buyingWithShapeshift && 'deposit-ether-modal__buy-row__shapeshift-buy', - }), + + this.renderRow({ + logo: h('div.deposit-ether-modal__logo', { + style: { + backgroundImage: 'url(\'../../../images/shapeshift logo.png\')', + }, + }), + title: SHAPESHIFT_ROW_TITLE, + text: SHAPESHIFT_ROW_TEXT, + buttonLabel: t('shapeshiftBuy'), + onButtonClick: () => this.setState({ buyingWithShapeshift: true }), + hide: isTestNetwork, + hideButton: buyingWithShapeshift, + hideTitle: buyingWithShapeshift, + onBackClick: () => this.setState({ buyingWithShapeshift: false }), + showBackButton: this.state.buyingWithShapeshift, + className: buyingWithShapeshift && 'deposit-ether-modal__buy-row__shapeshift-buy', + }), + + buyingWithShapeshift && h(ShapeshiftForm), - buyingWithShapeshift && h(ShapeshiftForm), + ]), ]), ]) diff --git a/ui/app/components/modals/edit-account-name-modal.js b/ui/app/components/modals/edit-account-name-modal.js index e2361140d..6efa8d476 100644 --- a/ui/app/components/modals/edit-account-name-modal.js +++ b/ui/app/components/modals/edit-account-name-modal.js @@ -4,6 +4,7 @@ const inherits = require('util').inherits const connect = require('react-redux').connect const actions = require('../../actions') const { getSelectedAccount } = require('../../selectors') +const t = require('../../../i18n') function mapStateToProps (state) { return { @@ -50,7 +51,7 @@ EditAccountNameModal.prototype.render = function () { ]), h('div.edit-account-name-modal-title', { - }, ['Edit Account Name']), + }, [t('editAccountName')]), h('input.edit-account-name-modal-input', { placeholder: identity.name, @@ -60,7 +61,7 @@ EditAccountNameModal.prototype.render = function () { value: this.state.inputText, }, []), - h('button.btn-clear.edit-account-name-modal-save-button', { + h('button.btn-clear.edit-account-name-modal-save-button.allcaps', { onClick: () => { if (this.state.inputText.length !== 0) { saveAccountLabel(identity.address, this.state.inputText) @@ -69,7 +70,7 @@ EditAccountNameModal.prototype.render = function () { }, disabled: this.state.inputText.length === 0, }, [ - 'SAVE', + t('save'), ]), ]), diff --git a/ui/app/components/modals/export-private-key-modal.js b/ui/app/components/modals/export-private-key-modal.js index 422f23f44..017177cfd 100644 --- a/ui/app/components/modals/export-private-key-modal.js +++ b/ui/app/components/modals/export-private-key-modal.js @@ -7,6 +7,7 @@ const actions = require('../../actions') const AccountModalContainer = require('./account-modal-container') const { getSelectedIdentity } = require('../../selectors') const ReadOnlyInput = require('../readonly-input') +const t = require('../../../i18n') const copyToClipboard = require('copy-to-clipboard') function mapStateToProps (state) { @@ -48,8 +49,8 @@ ExportPrivateKeyModal.prototype.exportAccountAndGetPrivateKey = function (passwo ExportPrivateKeyModal.prototype.renderPasswordLabel = function (privateKey) { return h('span.private-key-password-label', privateKey - ? 'This is your private key (click to copy)' - : 'Type Your Password' + ? t('copyPrivateKey') + : t('typePassword') ) } @@ -86,8 +87,8 @@ ExportPrivateKeyModal.prototype.renderButtons = function (privateKey, password, ), (privateKey - ? this.renderButton('btn-clear export-private-key__button', () => hideModal(), 'Done') - : this.renderButton('btn-clear export-private-key__button', () => this.exportAccountAndGetPrivateKey(this.state.password, address), 'Confirm') + ? this.renderButton('btn-clear export-private-key__button', () => hideModal(), t('done')) + : this.renderButton('btn-clear export-private-key__button', () => this.exportAccountAndGetPrivateKey(this.state.password, address), t('confirm')) ), ]) @@ -120,7 +121,7 @@ ExportPrivateKeyModal.prototype.render = function () { h('div.account-modal-divider'), - h('span.modal-body-title', 'Show Private Keys'), + h('span.modal-body-title', t('showPrivateKeys')), h('div.private-key-password', {}, [ this.renderPasswordLabel(privateKey), @@ -130,10 +131,7 @@ ExportPrivateKeyModal.prototype.render = function () { !warning ? null : h('span.private-key-password-error', warning), ]), - h('div.private-key-password-warning', `Warning: Never disclose this key. - Anyone with your private keys can take steal any assets held in your - account.` - ), + h('div.private-key-password-warning', t('privateKeyWarning')), this.renderButtons(privateKey, this.state.password, address, hideModal), diff --git a/ui/app/components/modals/hide-token-confirmation-modal.js b/ui/app/components/modals/hide-token-confirmation-modal.js index 56c7ba299..33d8062c6 100644 --- a/ui/app/components/modals/hide-token-confirmation-modal.js +++ b/ui/app/components/modals/hide-token-confirmation-modal.js @@ -4,6 +4,7 @@ const inherits = require('util').inherits const connect = require('react-redux').connect const actions = require('../../actions') const Identicon = require('../identicon') +const t = require('../../../i18n') function mapStateToProps (state) { return { @@ -41,7 +42,7 @@ HideTokenConfirmationModal.prototype.render = function () { h('div.hide-token-confirmation__container', { }, [ h('div.hide-token-confirmation__title', {}, [ - 'Hide Token?', + t('hideTokenPrompt'), ]), h(Identicon, { @@ -54,19 +55,19 @@ HideTokenConfirmationModal.prototype.render = function () { h('div.hide-token-confirmation__symbol', {}, symbol), h('div.hide-token-confirmation__copy', {}, [ - 'You can add this token back in the future by going go to “Add token” in your accounts options menu.', + t('readdToken'), ]), h('div.hide-token-confirmation__buttons', {}, [ - h('button.btn-cancel.hide-token-confirmation__button', { + h('button.btn-cancel.hide-token-confirmation__button.allcaps', { onClick: () => hideModal(), }, [ - 'CANCEL', + t('cancel'), ]), - h('button.btn-clear.hide-token-confirmation__button', { + h('button.btn-clear.hide-token-confirmation__button.allcaps', { onClick: () => hideToken(address), }, [ - 'HIDE', + t('hide'), ]), ]), ]), diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index 8e9e58985..501b83430 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -6,6 +6,7 @@ const FadeModal = require('boron').FadeModal const actions = require('../../actions') const isMobileView = require('../../../lib/is-mobile-view') const isPopupOrNotification = require('../../../../app/scripts/lib/is-popup-or-notification') +const t = require('../../../i18n') // Modal Components const BuyOptions = require('./buy-options-modal') @@ -92,18 +93,20 @@ const MODALS = { display: 'flex', }, laptopModalStyle: { - width: '900px', - maxWidth: '900px', + width: '850px', top: 'calc(10% + 10px)', left: '0', right: '0', margin: '0 auto', boxShadow: '0 0 6px 0 rgba(0,0,0,0.3)', - borderRadius: '8px', + borderRadius: '7px', transform: 'none', + height: 'calc(80% - 20px)', + overflowY: 'hidden', }, contentStyle: { - borderRadius: '8px', + borderRadius: '7px', + height: '100%', }, }, @@ -171,9 +174,8 @@ const MODALS = { BETA_UI_NOTIFICATION_MODAL: { contents: [ h(NotifcationModal, { - header: 'Welcome to the New UI (Beta)', - message: `You are now using the new Metamask UI. Take a look around, try out new features like sending tokens, - and let us know if you have any issues.`, + header: t('uiWelcome'), + message: t('uiWelcomeMessage'), }), ], mobileModalStyle: { @@ -189,9 +191,8 @@ const MODALS = { OLD_UI_NOTIFICATION_MODAL: { contents: [ h(NotifcationModal, { - header: 'Old UI', - message: `You have returned to the old UI. You can switch back to the New UI through the option in the top - right dropdown menu.`, + header: t('oldUI'), + message: t('oldUIMessage'), }), ], mobileModalStyle: { diff --git a/ui/app/components/modals/new-account-modal.js b/ui/app/components/modals/new-account-modal.js index fc1fd413d..298b76af4 100644 --- a/ui/app/components/modals/new-account-modal.js +++ b/ui/app/components/modals/new-account-modal.js @@ -3,6 +3,7 @@ const PropTypes = require('prop-types') const h = require('react-hyperscript') const { connect } = require('react-redux') const actions = require('../../actions') +const t = require('../../../i18n') class NewAccountModal extends Component { constructor (props) { @@ -11,7 +12,7 @@ class NewAccountModal extends Component { const newAccountNumber = numberOfExistingAccounts + 1 this.state = { - newAccountName: `Account ${newAccountNumber}`, + newAccountName: `${t('account')} ${newAccountNumber}`, } } @@ -22,7 +23,7 @@ class NewAccountModal extends Component { h('div.new-account-modal-wrapper', { }, [ h('div.new-account-modal-header', {}, [ - 'New Account', + t('newAccount'), ]), h('div.modal-close-x', { @@ -30,19 +31,19 @@ class NewAccountModal extends Component { }), h('div.new-account-modal-content', {}, [ - 'Account Name', + t('accountName'), ]), h('div.new-account-input-wrapper', {}, [ h('input.new-account-input', { value: this.state.newAccountName, - placeholder: 'E.g. My new account', + placeholder: t('sampleAccountName'), onChange: event => this.setState({ newAccountName: event.target.value }), }, []), ]), h('div.new-account-modal-content.after-input', {}, [ - 'or', + t('or'), ]), h('div.new-account-modal-content.after-input.pointer', { @@ -50,13 +51,13 @@ class NewAccountModal extends Component { this.props.hideModal() this.props.showImportPage() }, - }, 'Import an account'), + }, t('importAnAccount')), - h('div.new-account-modal-content.button', {}, [ + h('div.new-account-modal-content.button.allcaps', {}, [ h('button.btn-clear', { onClick: () => this.props.createAccount(newAccountName), }, [ - 'SAVE', + t('save'), ]), ]), ]), diff --git a/ui/app/components/network.js b/ui/app/components/network.js index 3e91fa807..f3df2242a 100644 --- a/ui/app/components/network.js +++ b/ui/app/components/network.js @@ -3,6 +3,7 @@ const h = require('react-hyperscript') const classnames = require('classnames') const inherits = require('util').inherits const NetworkDropdownIcon = require('./dropdowns/components/network-dropdown-icon') +const t = require('../../i18n') module.exports = Network @@ -33,7 +34,7 @@ Network.prototype.render = function () { onClick: (event) => this.props.onClick(event), }, [ h('img', { - title: 'Attempting to connect to blockchain.', + title: t('attemptingConnect'), style: { width: '27px', }, @@ -41,22 +42,22 @@ Network.prototype.render = function () { }), ]) } else if (providerName === 'mainnet') { - hoverText = 'Main Ethereum Network' + hoverText = t('mainnet') iconName = 'ethereum-network' } else if (providerName === 'ropsten') { - hoverText = 'Ropsten Test Network' + hoverText = t('ropsten') iconName = 'ropsten-test-network' } else if (parseInt(networkNumber) === 3) { - hoverText = 'Ropsten Test Network' + hoverText = t('ropsten') iconName = 'ropsten-test-network' } else if (providerName === 'kovan') { - hoverText = 'Kovan Test Network' + hoverText = t('kovan') iconName = 'kovan-test-network' } else if (providerName === 'rinkeby') { - hoverText = 'Rinkeby Test Network' + hoverText = t('rinkeby') iconName = 'rinkeby-test-network' } else { - hoverText = 'Unknown Private Network' + hoverText = t('unknownNetwork') iconName = 'unknown-private-network' } @@ -84,7 +85,7 @@ Network.prototype.render = function () { backgroundColor: '#038789', // $blue-lagoon nonSelectBackgroundColor: '#15afb2', }), - h('.network-name', 'Main Network'), + h('.network-name', t('mainnet')), h('i.fa.fa-chevron-down.fa-lg.network-caret'), ]) case 'ropsten-test-network': @@ -93,7 +94,7 @@ Network.prototype.render = function () { backgroundColor: '#e91550', // $crimson nonSelectBackgroundColor: '#ec2c50', }), - h('.network-name', 'Ropsten Test Net'), + h('.network-name', t('ropsten')), h('i.fa.fa-chevron-down.fa-lg.network-caret'), ]) case 'kovan-test-network': @@ -102,7 +103,7 @@ Network.prototype.render = function () { backgroundColor: '#690496', // $purple nonSelectBackgroundColor: '#b039f3', }), - h('.network-name', 'Kovan Test Net'), + h('.network-name', t('kovan')), h('i.fa.fa-chevron-down.fa-lg.network-caret'), ]) case 'rinkeby-test-network': @@ -111,7 +112,7 @@ Network.prototype.render = function () { backgroundColor: '#ebb33f', // $tulip-tree nonSelectBackgroundColor: '#ecb23e', }), - h('.network-name', 'Rinkeby Test Net'), + h('.network-name', t('rinkeby')), h('i.fa.fa-chevron-down.fa-lg.network-caret'), ]) default: @@ -123,7 +124,7 @@ Network.prototype.render = function () { }, }), - h('.network-name', 'Private Network'), + h('.network-name', t('privateNetwork')), h('i.fa.fa-chevron-down.fa-lg.network-caret'), ]) } diff --git a/ui/app/components/notice.js b/ui/app/components/notice.js index 9d2e89cb0..8b0ce1e8b 100644 --- a/ui/app/components/notice.js +++ b/ui/app/components/notice.js @@ -4,6 +4,7 @@ const h = require('react-hyperscript') const ReactMarkdown = require('react-markdown') const linker = require('extension-link-enabler') const findDOMNode = require('react-dom').findDOMNode +const t = require('../../i18n') module.exports = Notice @@ -110,7 +111,7 @@ Notice.prototype.render = function () { style: { marginTop: '18px', }, - }, 'Accept'), + }, t('accept')), ]) ) } diff --git a/ui/app/components/pending-msg-details.js b/ui/app/components/pending-msg-details.js index 718a22de0..87e66855d 100644 --- a/ui/app/components/pending-msg-details.js +++ b/ui/app/components/pending-msg-details.js @@ -1,6 +1,7 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits +const t = require('../../i18n') const AccountPanel = require('./account-panel') @@ -39,7 +40,7 @@ PendingMsgDetails.prototype.render = function () { // message data h('.tx-data.flex-column.flex-justify-center.flex-grow.select-none', [ h('.flex-column.flex-space-between', [ - h('label.font-small', 'MESSAGE'), + h('label.font-small.allcaps', t('message')), h('span.font-small', msgParams.data), ]), ]), @@ -47,4 +48,3 @@ PendingMsgDetails.prototype.render = function () { ]) ) } - diff --git a/ui/app/components/pending-msg.js b/ui/app/components/pending-msg.js index 834719c53..dc406b955 100644 --- a/ui/app/components/pending-msg.js +++ b/ui/app/components/pending-msg.js @@ -2,6 +2,7 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits const PendingTxDetails = require('./pending-msg-details') +const t = require('../../i18n') module.exports = PendingMsg @@ -29,17 +30,14 @@ PendingMsg.prototype.render = function () { fontWeight: 'bold', textAlign: 'center', }, - }, 'Sign Message'), + }, t('signMessage')), h('.error', { style: { margin: '10px', }, }, [ - `Signing this message can have - dangerous side effects. Only sign messages from - sites you fully trust with your entire account. - This dangerous method will be removed in a future version. `, + t('signNotice'), h('a', { href: 'https://medium.com/metamask/the-new-secure-way-to-sign-data-in-your-browser-6af9dd2a1527', style: { color: 'rgb(247, 134, 28)' }, @@ -48,7 +46,7 @@ PendingMsg.prototype.render = function () { const url = 'https://medium.com/metamask/the-new-secure-way-to-sign-data-in-your-browser-6af9dd2a1527' global.platform.openWindow({ url }) }, - }, 'Read more here.'), + }, t('readMore')), ]), // message details @@ -58,13 +56,12 @@ PendingMsg.prototype.render = function () { h('.flex-row.flex-space-around', [ h('button', { onClick: state.cancelMessage, - }, 'Cancel'), + }, t('cancel')), h('button', { onClick: state.signMessage, - }, 'Sign'), + }, t('sign')), ]), ]) ) } - diff --git a/ui/app/components/pending-personal-msg-details.js b/ui/app/components/pending-personal-msg-details.js index 1050513f2..b896e9a7e 100644 --- a/ui/app/components/pending-personal-msg-details.js +++ b/ui/app/components/pending-personal-msg-details.js @@ -1,6 +1,7 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits +const t = require('../../i18n') const AccountPanel = require('./account-panel') const BinaryRenderer = require('./binary-renderer') @@ -45,7 +46,7 @@ PendingMsgDetails.prototype.render = function () { height: '260px', }, }, [ - h('label.font-small', { style: { display: 'block' } }, 'MESSAGE'), + h('label.font-small.allcaps', { style: { display: 'block' } }, t('message')), h(BinaryRenderer, { value: data, style: { @@ -57,4 +58,3 @@ PendingMsgDetails.prototype.render = function () { ]) ) } - diff --git a/ui/app/components/pending-tx/confirm-deploy-contract.js b/ui/app/components/pending-tx/confirm-deploy-contract.js index ae6c6ef7b..49fbe6387 100644 --- a/ui/app/components/pending-tx/confirm-deploy-contract.js +++ b/ui/app/components/pending-tx/confirm-deploy-contract.js @@ -9,6 +9,7 @@ const ethUtil = require('ethereumjs-util') const BN = ethUtil.BN const hexToBn = require('../../../../app/scripts/lib/hex-to-bn') const { conversionUtil } = require('../../conversion-util') +const t = require('../../../i18n') const { MIN_GAS_PRICE_HEX } = require('../send/send-constants') @@ -55,7 +56,7 @@ ConfirmDeployContract.prototype.onSubmit = function (event) { if (valid && this.verifyGasParams()) { this.props.sendTransaction(txMeta, event) } else { - this.props.dispatch(actions.displayWarning('Invalid Gas Parameters')) + this.props.dispatch(actions.displayWarning(t('invalidGasParams'))) this.setState({ submitting: false }) } } @@ -200,7 +201,7 @@ ConfirmDeployContract.prototype.renderGasFee = function () { return ( h('section.flex-row.flex-center.confirm-screen-row', [ - h('span.confirm-screen-label.confirm-screen-section-column', [ 'Gas Fee' ]), + h('span.confirm-screen-label.confirm-screen-section-column', [ t('gasFee') ]), h('div.confirm-screen-section-column', [ h('div.confirm-screen-row-info', `${fiatGas} ${currentCurrency.toUpperCase()}`), @@ -239,8 +240,8 @@ ConfirmDeployContract.prototype.renderTotalPlusGas = function () { return ( h('section.flex-row.flex-center.confirm-screen-total-box ', [ h('div.confirm-screen-section-column', [ - h('span.confirm-screen-label', [ 'Total ' ]), - h('div.confirm-screen-total-box__subtitle', [ 'Amount + Gas' ]), + h('span.confirm-screen-label', [ t('total') + ' ' ]), + h('div.confirm-screen-total-box__subtitle', [ t('amountPlusGas') ]), ]), h('div.confirm-screen-section-column', [ @@ -271,10 +272,10 @@ ConfirmDeployContract.prototype.render = function () { // Main Send token Card h('div.confirm-screen-wrapper.flex-column.flex-grow', [ h('h3.flex-center.confirm-screen-header', [ - h('button.confirm-screen-back-button', { + h('button.confirm-screen-back-button.allcaps', { onClick: () => backToAccountDetail(selectedAddress), - }, 'BACK'), - h('div.confirm-screen-title', 'Confirm Contract'), + }, t('back')), + h('div.confirm-screen-title', t('confirmContract')), h('div.confirm-screen-header-tip'), ]), h('div.flex-row.flex-center.confirm-screen-identicons', [ @@ -292,7 +293,7 @@ ConfirmDeployContract.prototype.render = function () { h('i.fa.fa-arrow-right.fa-lg'), h('div.confirm-screen-account-wrapper', [ h('i.fa.fa-file-text-o'), - h('span.confirm-screen-account-name', 'New Contract'), + h('span.confirm-screen-account-name', t('newContract')), h('span.confirm-screen-account-number', ' '), ]), ]), @@ -310,7 +311,7 @@ ConfirmDeployContract.prototype.render = function () { h('div.confirm-screen-rows', [ h('section.flex-row.flex-center.confirm-screen-row', [ - h('span.confirm-screen-label.confirm-screen-section-column', [ 'From' ]), + h('span.confirm-screen-label.confirm-screen-section-column', [ t('from') ]), h('div.confirm-screen-section-column', [ h('div.confirm-screen-row-info', fromName), h('div.confirm-screen-row-detail', `...${fromAddress.slice(fromAddress.length - 4)}`), @@ -318,9 +319,9 @@ ConfirmDeployContract.prototype.render = function () { ]), h('section.flex-row.flex-center.confirm-screen-row', [ - h('span.confirm-screen-label.confirm-screen-section-column', [ 'To' ]), + h('span.confirm-screen-label.confirm-screen-section-column', [ t('to') ]), h('div.confirm-screen-section-column', [ - h('div.confirm-screen-row-info', 'New Contract'), + h('div.confirm-screen-row-info', t('newContract')), ]), ]), @@ -335,12 +336,12 @@ ConfirmDeployContract.prototype.render = function () { onSubmit: this.onSubmit, }, [ // Cancel Button - h('div.cancel.btn-light.confirm-screen-cancel-button', { + h('div.cancel.btn-light.confirm-screen-cancel-button.allcaps', { onClick: (event) => this.cancel(event, txMeta), - }, 'CANCEL'), + }, t('cancel')), // Accept Button - h('button.confirm-screen-confirm-button', ['CONFIRM']), + h('button.confirm-screen-confirm-button.allcaps', [t('confirm')]), ]), ]) diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index 4666e047d..6624a378d 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -14,6 +14,7 @@ const { multiplyCurrencies, } = require('../../conversion-util') const GasFeeDisplay = require('../send/gas-fee-display-v2') +const t = require('../../../i18n') const { MIN_GAS_PRICE_HEX } = require('../send/send-constants') @@ -197,7 +198,7 @@ ConfirmSendEther.prototype.getData = function () { }, to: { address: txParams.to, - name: identities[txParams.to] ? identities[txParams.to].name : 'New Recipient', + name: identities[txParams.to] ? identities[txParams.to].name : t('newRecipient'), }, memo: txParams.memo || '', gasFeeInFIAT, @@ -311,7 +312,7 @@ ConfirmSendEther.prototype.render = function () { h('div.confirm-screen-rows', [ h('section.flex-row.flex-center.confirm-screen-row', [ - h('span.confirm-screen-label.confirm-screen-section-column', [ 'From' ]), + h('span.confirm-screen-label.confirm-screen-section-column', [ t('from') ]), h('div.confirm-screen-section-column', [ h('div.confirm-screen-row-info', fromName), h('div.confirm-screen-row-detail', `...${fromAddress.slice(fromAddress.length - 4)}`), @@ -319,7 +320,7 @@ ConfirmSendEther.prototype.render = function () { ]), h('section.flex-row.flex-center.confirm-screen-row', [ - h('span.confirm-screen-label.confirm-screen-section-column', [ 'To' ]), + h('span.confirm-screen-label.confirm-screen-section-column', [ t('to') ]), h('div.confirm-screen-section-column', [ h('div.confirm-screen-row-info', toName), h('div.confirm-screen-row-detail', `...${toAddress.slice(toAddress.length - 4)}`), @@ -327,7 +328,7 @@ ConfirmSendEther.prototype.render = function () { ]), h('section.flex-row.flex-center.confirm-screen-row', [ - h('span.confirm-screen-label.confirm-screen-section-column', [ 'Gas Fee' ]), + h('span.confirm-screen-label.confirm-screen-section-column', [ t('gasFee') ]), h('div.confirm-screen-section-column', [ h(GasFeeDisplay, { gasTotal: gasTotal || gasFeeInHex, @@ -341,8 +342,8 @@ ConfirmSendEther.prototype.render = function () { h('section.flex-row.flex-center.confirm-screen-total-box ', [ h('div.confirm-screen-section-column', [ - h('span.confirm-screen-label', [ 'Total ' ]), - h('div.confirm-screen-total-box__subtitle', [ 'Amount + Gas' ]), + h('span.confirm-screen-label', [ t('total') + ' ' ]), + h('div.confirm-screen-total-box__subtitle', [ t('amountPlusGas') ]), ]), h('div.confirm-screen-section-column', [ @@ -437,15 +438,15 @@ ConfirmSendEther.prototype.render = function () { onSubmit: this.onSubmit, }, [ // Cancel Button - h('div.cancel.btn-light.confirm-screen-cancel-button', { + h('div.cancel.btn-light.confirm-screen-cancel-button.allcaps', { onClick: (event) => { clearSend() this.cancel(event, txMeta) }, - }, 'CANCEL'), + }, t('cancel')), // Accept Button - h('button.confirm-screen-confirm-button', ['CONFIRM']), + h('button.confirm-screen-confirm-button.allcaps', [t('confirm')]), ]), ]) ) @@ -460,7 +461,7 @@ ConfirmSendEther.prototype.onSubmit = function (event) { if (valid && this.verifyGasParams()) { this.props.sendTransaction(txMeta, event) } else { - this.props.dispatch(actions.displayWarning('Invalid Gas Parameters')) + this.props.dispatch(actions.displayWarning(t('invalidGasParams'))) this.setState({ submitting: false }) } } diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index 476c1d259..ac773b1d2 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -6,6 +6,7 @@ const tokenAbi = require('human-standard-token-abi') const abiDecoder = require('abi-decoder') abiDecoder.addABI(tokenAbi) const actions = require('../../actions') +const t = require('../../../i18n') const clone = require('clone') const Identicon = require('../identicon') const GasFeeDisplay = require('../send/gas-fee-display-v2.js') @@ -64,8 +65,8 @@ function mapDispatchToProps (dispatch, ownProps) { updateTokenExchangeRate: () => dispatch(actions.updateTokenExchangeRate(symbol)), editTransaction: txMeta => { const { token: { address } } = ownProps - const { txParams, id } = txMeta - const tokenData = txParams.data && abiDecoder.decodeMethod(txParams.data) + const { txParams = {}, id } = txMeta + const tokenData = txParams.data && abiDecoder.decodeMethod(txParams.data) || {} const { params = [] } = tokenData const { value: to } = params[0] || {} const { value: tokenAmountInDec } = params[1] || {} @@ -169,7 +170,7 @@ ConfirmSendToken.prototype.getAmount = function () { ? +(sendTokenAmount * tokenExchangeRate * conversionRate).toFixed(2) : null, token: typeof value === 'undefined' - ? 'Unknown' + ? t('unknown') : +sendTokenAmount.toFixed(decimals), } @@ -241,7 +242,7 @@ ConfirmSendToken.prototype.getData = function () { }, to: { address: value, - name: identities[value] ? identities[value].name : 'New Recipient', + name: identities[value] ? identities[value].name : t('newRecipient'), }, memo: txParams.memo || '', } @@ -287,7 +288,7 @@ ConfirmSendToken.prototype.renderGasFee = function () { return ( h('section.flex-row.flex-center.confirm-screen-row', [ - h('span.confirm-screen-label.confirm-screen-section-column', [ 'Gas Fee' ]), + h('span.confirm-screen-label.confirm-screen-section-column', [ t('gasFee') ]), h('div.confirm-screen-section-column', [ h(GasFeeDisplay, { gasTotal: gasTotal || gasFeeInHex, @@ -309,8 +310,8 @@ ConfirmSendToken.prototype.renderTotalPlusGas = function () { ? ( h('section.flex-row.flex-center.confirm-screen-total-box ', [ h('div.confirm-screen-section-column', [ - h('span.confirm-screen-label', [ 'Total ' ]), - h('div.confirm-screen-total-box__subtitle', [ 'Amount + Gas' ]), + h('span.confirm-screen-label', [ t('total') + ' ' ]), + h('div.confirm-screen-total-box__subtitle', [ t('amountPlusGas') ]), ]), h('div.confirm-screen-section-column', [ @@ -322,13 +323,13 @@ ConfirmSendToken.prototype.renderTotalPlusGas = function () { : ( h('section.flex-row.flex-center.confirm-screen-total-box ', [ h('div.confirm-screen-section-column', [ - h('span.confirm-screen-label', [ 'Total ' ]), - h('div.confirm-screen-total-box__subtitle', [ 'Amount + Gas' ]), + h('span.confirm-screen-label', [ t('total') + ' ' ]), + h('div.confirm-screen-total-box__subtitle', [ t('amountPlusGas') ]), ]), h('div.confirm-screen-section-column', [ h('div.confirm-screen-row-info', `${tokenAmount} ${symbol}`), - h('div.confirm-screen-row-detail', `+ ${fiatGas} ${currentCurrency} Gas`), + h('div.confirm-screen-row-detail', `+ ${fiatGas} ${currentCurrency} ${t('gas')}`), ]), ]) ) @@ -350,10 +351,10 @@ ConfirmSendToken.prototype.render = function () { this.inputs = [] - const title = txMeta.lastGasPrice ? 'Reprice Transaction' : 'Confirm' + const title = txMeta.lastGasPrice ? 'Reprice Transaction' : t('confirm') const subtitle = txMeta.lastGasPrice ? 'Increase your gas fee to attempt to overwrite and speed up your transaction' - : 'Please review your transaction.' + : t('pleaseReviewTransaction') return ( h('div.confirm-screen-container.confirm-send-token', [ @@ -362,7 +363,7 @@ ConfirmSendToken.prototype.render = function () { h('div.page-container__header', [ !txMeta.lastGasPrice && h('button.confirm-screen-back-button', { onClick: () => editTransaction(txMeta), - }, 'Edit'), + }, t('edit')), h('div.page-container__title', title), h('div.page-container__subtitle', subtitle), ]), @@ -405,7 +406,7 @@ ConfirmSendToken.prototype.render = function () { h('div.confirm-screen-rows', [ h('section.flex-row.flex-center.confirm-screen-row', [ - h('span.confirm-screen-label.confirm-screen-section-column', [ 'From' ]), + h('span.confirm-screen-label.confirm-screen-section-column', [ t('from') ]), h('div.confirm-screen-section-column', [ h('div.confirm-screen-row-info', fromName), h('div.confirm-screen-row-detail', `...${fromAddress.slice(fromAddress.length - 4)}`), @@ -413,7 +414,7 @@ ConfirmSendToken.prototype.render = function () { ]), toAddress && h('section.flex-row.flex-center.confirm-screen-row', [ - h('span.confirm-screen-label.confirm-screen-section-column', [ 'To' ]), + h('span.confirm-screen-label.confirm-screen-section-column', [ t('to') ]), h('div.confirm-screen-section-column', [ h('div.confirm-screen-row-info', toName), h('div.confirm-screen-row-detail', `...${toAddress.slice(toAddress.length - 4)}`), @@ -431,12 +432,12 @@ ConfirmSendToken.prototype.render = function () { onSubmit: this.onSubmit, }, [ // Cancel Button - h('div.cancel.btn-light.confirm-screen-cancel-button', { + h('div.cancel.btn-light.confirm-screen-cancel-button.allcaps', { onClick: (event) => this.cancel(event, txMeta), - }, 'CANCEL'), + }, t('cancel')), // Accept Button - h('button.confirm-screen-confirm-button', ['CONFIRM']), + h('button.confirm-screen-confirm-button.allcaps', [t('confirm')]), ]), @@ -453,7 +454,7 @@ ConfirmSendToken.prototype.onSubmit = function (event) { if (valid && this.verifyGasParams()) { this.props.sendTransaction(txMeta, event) } else { - this.props.dispatch(actions.displayWarning('Invalid Gas Parameters')) + this.props.dispatch(actions.displayWarning(t('invalidGasParams'))) this.setState({ submitting: false }) } } diff --git a/ui/app/components/pending-typed-msg-details.js b/ui/app/components/pending-typed-msg-details.js index b5fd29f71..ae0a1171e 100644 --- a/ui/app/components/pending-typed-msg-details.js +++ b/ui/app/components/pending-typed-msg-details.js @@ -4,6 +4,7 @@ const inherits = require('util').inherits const AccountPanel = require('./account-panel') const TypedMessageRenderer = require('./typed-message-renderer') +const t = require('../../i18n') module.exports = PendingMsgDetails @@ -45,7 +46,7 @@ PendingMsgDetails.prototype.render = function () { height: '260px', }, }, [ - h('label.font-small', { style: { display: 'block' } }, 'YOU ARE SIGNING'), + h('label.font-small.allcaps', { style: { display: 'block' } }, t('youSign')), h(TypedMessageRenderer, { value: data, style: { diff --git a/ui/app/components/pending-typed-msg.js b/ui/app/components/pending-typed-msg.js index f8926d0a3..ccde5e8af 100644 --- a/ui/app/components/pending-typed-msg.js +++ b/ui/app/components/pending-typed-msg.js @@ -2,6 +2,7 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits const PendingTxDetails = require('./pending-typed-msg-details') +const t = require('../../i18n') module.exports = PendingMsg @@ -26,19 +27,19 @@ PendingMsg.prototype.render = function () { fontWeight: 'bold', textAlign: 'center', }, - }, 'Sign Message'), + }, t('signMessage')), // message details h(PendingTxDetails, state), // sign + cancel h('.flex-row.flex-space-around', [ - h('button', { + h('button.allcaps', { onClick: state.cancelTypedMessage, - }, 'Cancel'), - h('button', { + }, t('cancel')), + h('button.allcaps', { onClick: state.signTypedMessage, - }, 'Sign'), + }, t('sign')), ]), ]) diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index 99d078251..58743b641 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -7,6 +7,7 @@ const inherits = require('util').inherits const actions = require('../../actions') const selectors = require('../../selectors') const { isValidAddress, allNull } = require('../../util') +const t = require('../../../i18n') // const BalanceComponent = require('./balance-component') const Identicon = require('../identicon') @@ -126,14 +127,14 @@ SendTokenScreen.prototype.validate = function () { const amount = Number(stringAmount) const errors = { - to: !to ? 'Required' : null, - amount: !amount ? 'Required' : null, - gasPrice: !gasPrice ? 'Gas Price Required' : null, - gasLimit: !gasLimit ? 'Gas Limit Required' : null, + to: !to ? t('required') : null, + amount: !amount ? t('required') : null, + gasPrice: !gasPrice ? t('gasPriceRequired') : null, + gasLimit: !gasLimit ? t('gasLimitRequired') : null, } if (to && !isValidAddress(to)) { - errors.to = 'Invalid address' + errors.to = t('invalidAddress') } const isValid = Object.entries(errors).every(([key, value]) => value === null) @@ -233,11 +234,11 @@ SendTokenScreen.prototype.renderToAddressInput = function () { 'send-screen-input-wrapper--error': errorMessage, }), }, [ - h('div', ['To:']), + h('div', [t('to') + ':']), h('input.large-input.send-screen-input', { name: 'address', list: 'addresses', - placeholder: 'Address', + placeholder: t('address'), value: to, onChange: e => this.setState({ to: e.target.value, @@ -290,7 +291,7 @@ SendTokenScreen.prototype.renderAmountInput = function () { }), }, [ h('div.send-screen-amount-labels', [ - h('span', ['Amount']), + h('span', [t('amount')]), h(CurrencyToggle, { currentCurrency: tokenExchangeRate ? selectedCurrency : 'USD', currencies: tokenExchangeRate ? [ symbol, 'USD' ] : [], @@ -355,8 +356,8 @@ SendTokenScreen.prototype.renderGasInput = function () { }), h('div.send-screen-gas-labels', {}, [ - h('span', [ h('i.fa.fa-bolt'), 'Gas fee:']), - h('span', ['What\'s this?']), + h('span', [ h('i.fa.fa-bolt'), t('gasFee') + ':']), + h('span', [t('whatsThis')]), ]), h('div.large-input.send-screen-gas-input', [ h(GasFeeDisplay, { @@ -370,7 +371,7 @@ SendTokenScreen.prototype.renderGasInput = function () { h( 'div.send-screen-gas-input-customize', { onClick: () => this.setState({ isGasTooltipOpen: !isGasTooltipOpen }) }, - ['Customize'] + [t('customize')] ), ]), h('div.send-screen-input-wrapper__error-message', [ @@ -381,7 +382,7 @@ SendTokenScreen.prototype.renderGasInput = function () { SendTokenScreen.prototype.renderMemoInput = function () { return h('div.send-screen-input-wrapper', [ - h('div', {}, ['Transaction memo (optional)']), + h('div', {}, [t('transactionMemo')]), h( 'input.large-input.send-screen-input', { onChange: e => this.setState({ memo: e.target.value }) } @@ -397,10 +398,10 @@ SendTokenScreen.prototype.renderButtons = function () { h('button.send-token__button-next.btn-secondary', { className: !isValid && 'send-screen__send-button__disabled', onClick: () => isValid && this.submit(), - }, ['Next']), + }, [t('next')]), h('button.send-token__button-cancel.btn-tertiary', { onClick: () => backToAccountDetail(selectedAddress), - }, ['Cancel']), + }, [t('cancel')]), ]) } @@ -417,9 +418,9 @@ SendTokenScreen.prototype.render = function () { diameter: 75, address: selectedTokenAddress, }), - h('div.send-token__title', ['Send Tokens']), - h('div.send-token__description', ['Send Tokens to anyone with an Ethereum account']), - h('div.send-token__balance-text', ['Your Token Balance is:']), + h('div.send-token__title', [t('sendTokens')]), + h('div.send-token__description', [t('sendTokensAnywhere')]), + h('div.send-token__balance-text', [t('tokenBalance')]), h('div.send-token__token-balance', [ h(TokenBalance, { token: selectedToken, balanceOnly: true }), ]), diff --git a/ui/app/components/send/gas-fee-display-v2.js b/ui/app/components/send/gas-fee-display-v2.js index da1bdd05e..ca7fbd9a0 100644 --- a/ui/app/components/send/gas-fee-display-v2.js +++ b/ui/app/components/send/gas-fee-display-v2.js @@ -2,6 +2,7 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits const CurrencyDisplay = require('./currency-display') +const t = require('../../../i18n') module.exports = GasFeeDisplay @@ -30,7 +31,7 @@ GasFeeDisplay.prototype.render = function () { convertedPrefix: '$', readOnly: true, }) - : h('div.currency-display', 'Loading...'), + : h('div.currency-display', t('loading')), h('button.sliders-icon-container', { onClick, @@ -41,4 +42,3 @@ GasFeeDisplay.prototype.render = function () { ]) } - diff --git a/ui/app/components/send/gas-tooltip.js b/ui/app/components/send/gas-tooltip.js index 46aff3499..d925d3ed8 100644 --- a/ui/app/components/send/gas-tooltip.js +++ b/ui/app/components/send/gas-tooltip.js @@ -2,6 +2,7 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits const InputNumber = require('../input-number.js') +const t = require('../../../i18n') module.exports = GasTooltip @@ -81,7 +82,7 @@ GasTooltip.prototype.render = function () { 'marginTop': '81px', }, }, [ - h('span.gas-tooltip-label', {}, ['Gas Limit']), + h('span.gas-tooltip-label', {}, [t('gasLimit')]), h('i.fa.fa-info-circle'), ]), h(InputNumber, { @@ -97,4 +98,3 @@ GasTooltip.prototype.render = function () { ]), ]) } - diff --git a/ui/app/components/send/to-autocomplete.js b/ui/app/components/send/to-autocomplete.js index e0cdd0a58..72074229e 100644 --- a/ui/app/components/send/to-autocomplete.js +++ b/ui/app/components/send/to-autocomplete.js @@ -2,6 +2,7 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits const AccountListItem = require('./account-list-item') +const t = require('../../../i18n') module.exports = ToAutoComplete @@ -92,7 +93,7 @@ ToAutoComplete.prototype.render = function () { return h('div.send-v2__to-autocomplete', {}, [ h('input.send-v2__to-autocomplete__input', { - placeholder: 'Recipient Address', + placeholder: t('recipientAddress'), className: inError ? `send-v2__error-border` : '', value: to, onChange: event => onChange(event.target.value), @@ -111,4 +112,3 @@ ToAutoComplete.prototype.render = function () { ]) } - diff --git a/ui/app/components/shapeshift-form.js b/ui/app/components/shapeshift-form.js index 87eb1588a..f75d6176e 100644 --- a/ui/app/components/shapeshift-form.js +++ b/ui/app/components/shapeshift-form.js @@ -7,6 +7,7 @@ const { qrcode } = require('qrcode-npm') const { shapeShiftSubview, pairUpdate, buyWithShapeShift } = require('../actions') const { isValidAddress } = require('../util') const SimpleDropdown = require('./dropdowns/simple-dropdown') +const t = require('../../i18n') function mapStateToProps (state) { const { @@ -15,7 +16,7 @@ function mapStateToProps (state) { selectedAddress, } = state.metamask const { warning } = state.appState - + return { coinOptions, tokenExchangeRates, @@ -93,7 +94,7 @@ ShapeshiftForm.prototype.onBuyWithShapeShift = function () { })) .catch(() => this.setState({ showQrCode: false, - errorMessage: 'Invalid Request', + errorMessage: t('invalidRequest'), isLoading: false, })) } @@ -125,10 +126,10 @@ ShapeshiftForm.prototype.renderMarketInfo = function () { return h('div.shapeshift-form__metadata', {}, [ - this.renderMetadata('Status', limit ? 'Available' : 'Unavailable'), - this.renderMetadata('Limit', limit), - this.renderMetadata('Exchange Rate', rate), - this.renderMetadata('Minimum', minimum), + this.renderMetadata(t('status'), limit ? t('available') : t('unavailable')), + this.renderMetadata(t('limit'), limit), + this.renderMetadata(t('exchangeRate'), rate), + this.renderMetadata(t('min'), minimum), ]) } @@ -142,7 +143,7 @@ ShapeshiftForm.prototype.renderQrCode = function () { return h('div.shapeshift-form', {}, [ h('div.shapeshift-form__deposit-instruction', [ - `Deposit your ${depositCoin.toUpperCase()} to the address below:`, + t('depositCoin', depositCoin.toUpperCase()), ]), h('div', depositAddress), @@ -179,7 +180,7 @@ ShapeshiftForm.prototype.render = function () { h('div.shapeshift-form__selector', [ - h('div.shapeshift-form__selector-label', 'Deposit'), + h('div.shapeshift-form__selector-label', t('deposit')), h(SimpleDropdown, { selectedOption: this.state.depositCoin, @@ -199,7 +200,7 @@ ShapeshiftForm.prototype.render = function () { h('div.shapeshift-form__selector', [ h('div.shapeshift-form__selector-label', [ - 'Receive', + t('receive'), ]), h('div.shapeshift-form__selector-input', ['ETH']), @@ -217,7 +218,7 @@ ShapeshiftForm.prototype.render = function () { }, [ h('div.shapeshift-form__address-input-label', [ - 'Your Refund Address', + t('refundAddress'), ]), h('input.shapeshift-form__address-input', { @@ -239,7 +240,7 @@ ShapeshiftForm.prototype.render = function () { className: btnClass, disabled: !token, onClick: () => this.onBuyWithShapeShift(), - }, ['Buy']), + }, [t('buy')]), ]) } diff --git a/ui/app/components/shift-list-item.js b/ui/app/components/shift-list-item.js index 017bf9f0c..fddbc6821 100644 --- a/ui/app/components/shift-list-item.js +++ b/ui/app/components/shift-list-item.js @@ -6,6 +6,7 @@ const vreme = new (require('vreme'))() const explorerLink = require('etherscan-link').createExplorerLink const actions = require('../actions') const addressSummary = require('../util').addressSummary +const t = require('../../i18n') const CopyButton = require('./copyButton') const EthBalance = require('./eth-balance') @@ -75,7 +76,7 @@ ShiftListItem.prototype.renderUtilComponents = function () { value: this.props.depositAddress, }), h(Tooltip, { - title: 'QR Code', + title: t('qrCode'), }, [ h('i.fa.fa-qrcode.pointer.pop-hover', { onClick: () => props.dispatch(actions.reshowQrCode(props.depositAddress, props.depositType)), @@ -135,8 +136,8 @@ ShiftListItem.prototype.renderInfo = function () { color: '#ABA9AA', width: '100%', }, - }, `${props.depositType} to ETH via ShapeShift`), - h('div', 'No deposits received'), + }, t('toETHviaShapeShift', [props.depositType])), + h('div', t('noDeposits')), h('div', { style: { fontSize: 'x-small', @@ -158,8 +159,8 @@ ShiftListItem.prototype.renderInfo = function () { color: '#ABA9AA', width: '100%', }, - }, `${props.depositType} to ETH via ShapeShift`), - h('div', 'Conversion in progress'), + }, t('toETHviaShapeShift', [props.depositType])), + h('div', t('conversionProgress')), h('div', { style: { fontSize: 'x-small', @@ -184,7 +185,7 @@ ShiftListItem.prototype.renderInfo = function () { color: '#ABA9AA', width: '100%', }, - }, 'From ShapeShift'), + }, t('fromShapeShift')), h('div', formatDate(props.time)), h('div', { style: { @@ -196,7 +197,7 @@ ShiftListItem.prototype.renderInfo = function () { ]) case 'failed': - return h('span.error', '(Failed)') + return h('span.error', '(' + t('failed') + ')') default: return '' } diff --git a/ui/app/components/signature-request.js b/ui/app/components/signature-request.js index c5cc23aa8..7bf34e7b6 100644 --- a/ui/app/components/signature-request.js +++ b/ui/app/components/signature-request.js @@ -9,6 +9,7 @@ const classnames = require('classnames') const AccountDropdownMini = require('./dropdowns/account-dropdown-mini') const actions = require('../actions') +const t = require('../../i18n') const { conversionUtil } = require('../conversion-util') const { @@ -54,7 +55,7 @@ SignatureRequest.prototype.renderHeader = function () { h('div.request-signature__header-background'), - h('div.request-signature__header__text', 'Signature Request'), + h('div.request-signature__header__text', t('sigRequest')), h('div.request-signature__header__tip-container', [ h('div.request-signature__header__tip'), @@ -75,7 +76,7 @@ SignatureRequest.prototype.renderAccountDropdown = function () { return h('div.request-signature__account', [ - h('div.request-signature__account-text', ['Account:']), + h('div.request-signature__account-text', [t('account') + ':']), h(AccountDropdownMini, { selectedAccount, @@ -102,7 +103,7 @@ SignatureRequest.prototype.renderBalance = function () { return h('div.request-signature__balance', [ - h('div.request-signature__balance-text', ['Balance:']), + h('div.request-signature__balance-text', [t('balance')]), h('div.request-signature__balance-value', `${balanceInEther} ETH`), @@ -136,7 +137,7 @@ SignatureRequest.prototype.renderRequestInfo = function () { return h('div.request-signature__request-info', [ h('div.request-signature__headline', [ - `Your signature is being requested`, + t('yourSigRequested'), ]), ]) @@ -154,21 +155,18 @@ SignatureRequest.prototype.msgHexToText = function (hex) { SignatureRequest.prototype.renderBody = function () { let rows - let notice = 'You are signing:' + let notice = t('youSign') + ':' const { txData } = this.props const { type, msgParams: { data } } = txData if (type === 'personal_sign') { - rows = [{ name: 'Message', value: this.msgHexToText(data) }] + rows = [{ name: t('message'), value: this.msgHexToText(data) }] } else if (type === 'eth_signTypedData') { rows = data } else if (type === 'eth_sign') { - rows = [{ name: 'Message', value: data }] - notice = `Signing this message can have - dangerous side effects. Only sign messages from - sites you fully trust with your entire account. - This dangerous method will be removed in a future version. ` + rows = [{ name: t('message'), value: data }] + notice = t('signNotice') } return h('div.request-signature__body', {}, [ @@ -227,10 +225,10 @@ SignatureRequest.prototype.renderFooter = function () { return h('div.request-signature__footer', [ h('button.request-signature__footer__cancel-button', { onClick: cancel, - }, 'CANCEL'), + }, t('cancel')), h('button.request-signature__footer__sign-button', { onClick: sign, - }, 'SIGN'), + }, t('sign')), ]) } @@ -250,4 +248,3 @@ SignatureRequest.prototype.render = function () { ) } - diff --git a/ui/app/components/token-list.js b/ui/app/components/token-list.js index 8e06e0f27..01529aeda 100644 --- a/ui/app/components/token-list.js +++ b/ui/app/components/token-list.js @@ -5,6 +5,7 @@ const TokenTracker = require('eth-token-tracker') const TokenCell = require('./token-cell.js') const connect = require('react-redux').connect const selectors = require('../selectors') +const t = require('../../i18n') function mapStateToProps (state) { return { @@ -42,7 +43,7 @@ TokenList.prototype.render = function () { const { tokens, isLoading, error } = state if (isLoading) { - return this.message('Loading Tokens...') + return this.message(t('loadingTokens')) } if (error) { @@ -52,7 +53,7 @@ TokenList.prototype.render = function () { padding: '80px', }, }, [ - 'We had trouble loading your token balances. You can view them ', + t('troubleTokenBalances'), h('span.hotFix', { style: { color: 'rgba(247, 134, 28, 1)', @@ -63,7 +64,7 @@ TokenList.prototype.render = function () { url: `https://ethplorer.io/address/${userAddress}`, }) }, - }, 'here'), + }, t('here')), ]) } diff --git a/ui/app/components/transaction-list-item.js b/ui/app/components/transaction-list-item.js index a45cd441a..6d6e79bd5 100644 --- a/ui/app/components/transaction-list-item.js +++ b/ui/app/components/transaction-list-item.js @@ -11,6 +11,7 @@ const vreme = new (require('vreme'))() const Tooltip = require('./tooltip') const numberToBN = require('number-to-bn') const actions = require('../actions') +const t = require('../../i18n') const TransactionIcon = require('./transaction-list-item-icon') const ShiftListItem = require('./shift-list-item') @@ -85,7 +86,7 @@ TransactionListItem.prototype.render = function () { ]), h(Tooltip, { - title: 'Transaction Number', + title: t('transactionNumber'), position: 'right', }, [ h('span', { @@ -142,12 +143,12 @@ TransactionListItem.prototype.render = function () { style: { paddingRight: '2px', }, - }, 'Taking too long?'), + }, t('takesTooLong')), h('div', { style: { textDecoration: 'underline', }, - }, 'Retry with a higher gas price here'), + }, t('retryWithMoreGas')), ]), ]) ) @@ -176,11 +177,11 @@ function recipientField (txParams, transaction, isTx, isMsg) { let message if (isMsg) { - message = 'Signature Requested' + message = t('sigRequested') } else if (txParams.to) { message = addressSummary(txParams.to) } else { - message = 'Contract Deployment' + message = t('contractDeployment') } return h('div', { @@ -203,7 +204,7 @@ function renderErrorOrWarning (transaction) { // show rejected if (status === 'rejected') { - return h('span.error', ' (Rejected)') + return h('span.error', ' (' + t('rejected') + ')') } if (transaction.err || transaction.warning) { const { err, warning = {} } = transaction @@ -219,7 +220,7 @@ function renderErrorOrWarning (transaction) { title: message, position: 'bottom', }, [ - h(`span.error`, ` (Failed)`), + h(`span.error`, ` (` + t('failed') + `)`), ]) ) } @@ -231,7 +232,7 @@ function renderErrorOrWarning (transaction) { title: message, position: 'bottom', }, [ - h(`span.warning`, ` (Warning)`), + h(`span.warning`, ` (` + t('warning') + `)`), ]) } } diff --git a/ui/app/components/transaction-list.js b/ui/app/components/transaction-list.js index 69b72614c..07f7a06ae 100644 --- a/ui/app/components/transaction-list.js +++ b/ui/app/components/transaction-list.js @@ -3,6 +3,7 @@ const h = require('react-hyperscript') const inherits = require('util').inherits const TransactionListItem = require('./transaction-list-item') +const t = require('../../i18n') module.exports = TransactionList @@ -78,10 +79,9 @@ TransactionList.prototype.render = function () { style: { marginTop: '50px', }, - }, 'No transaction history.'), + }, t('noTransactionHistory')), ]), ]), ]) ) } - diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index 4c2b77af9..5ff1820a6 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -14,6 +14,7 @@ const { conversionUtil, multiplyCurrencies } = require('../conversion-util') const { calcTokenAmount } = require('../token-util') const { getCurrentCurrency } = require('../selectors') +const t = require('../../i18n') module.exports = connect(mapStateToProps, mapDispatchToProps)(TxListItem) @@ -74,7 +75,7 @@ TxListItem.prototype.getAddressText = function () { default: return address ? `${address.slice(0, 10)}...${address.slice(-4)}` - : 'Contract Deployment' + : t('contractDeployment') } } diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index 782de0266..08e37ebc8 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -10,6 +10,7 @@ const { formatDate } = require('../util') const { showConfTxPage } = require('../actions') const classnames = require('classnames') const { tokenInfoGetter } = require('../token-util') +const t = require('../../i18n') module.exports = connect(mapStateToProps, mapDispatchToProps)(TxList) @@ -56,7 +57,7 @@ TxList.prototype.renderTransaction = function () { : [h( 'div.tx-list-item.tx-list-item--empty', { key: 'tx-list-none' }, - [ 'No Transactions' ], + [ t('noTransactions') ], )] } @@ -110,7 +111,7 @@ TxList.prototype.renderTransactionListItem = function (transaction, conversionRa if (isUnapproved) { opts.onClick = () => showConfTxPage({id: transactionId}) - opts.transactionStatus = 'Not Started' + opts.transactionStatus = t('Not Started') } else if (transactionHash) { opts.onClick = () => this.view(transactionHash, transactionNetworkId) } diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index b25d8e0f9..96d776270 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -5,6 +5,7 @@ const ethUtil = require('ethereumjs-util') const inherits = require('util').inherits const actions = require('../actions') const selectors = require('../selectors') +const t = require('../../i18n') const BalanceComponent = require('./balance-component') const TxList = require('./tx-list') @@ -68,25 +69,25 @@ TxView.prototype.renderButtons = function () { return !selectedToken ? ( h('div.flex-row.flex-center.hero-balance-buttons', [ - h('button.btn-clear.hero-balance-button', { + h('button.btn-clear.hero-balance-button.allcaps', { onClick: () => showModal({ name: 'DEPOSIT_ETHER', }), - }, 'DEPOSIT'), + }, t('deposit')), - h('button.btn-clear.hero-balance-button', { + h('button.btn-clear.hero-balance-button.allcaps', { style: { marginLeft: '0.8em', }, onClick: showSendPage, - }, 'SEND'), + }, t('send')), ]) ) : ( h('div.flex-row.flex-center.hero-balance-buttons', [ h('button.btn-clear.hero-balance-button', { onClick: showSendTokenPage, - }, 'SEND'), + }, t('send')), ]) ) } @@ -100,9 +101,10 @@ TxView.prototype.render = function () { h('div.flex-row.phone-visible', { style: { - margin: '1.5em 1.2em 0', justifyContent: 'space-between', alignItems: 'center', + flex: '0 0 auto', + margin: '10px', }, }, [ @@ -110,11 +112,10 @@ TxView.prototype.render = function () { style: { fontSize: '1.3em', cursor: 'pointer', + padding: '10px', }, - onClick: () => { - this.props.sidebarOpen ? this.props.hideSidebar() : this.props.showSidebar() - }, - }, []), + onClick: () => this.props.sidebarOpen ? this.props.hideSidebar() : this.props.showSidebar(), + }), h('.identicon-wrapper.select-none', { style: { diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 34f27ca2a..18452205c 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -11,6 +11,7 @@ const actions = require('../actions') const BalanceComponent = require('./balance-component') const TokenList = require('./token-list') const selectors = require('../selectors') +const t = require('../../i18n') module.exports = connect(mapStateToProps, mapDispatchToProps)(WalletView) @@ -116,7 +117,7 @@ WalletView.prototype.render = function () { onClick: hideSidebar, }), - h('div.wallet-view__keyring-label', isLoose ? 'IMPORTED' : ''), + h('div.wallet-view__keyring-label.allcaps', isLoose ? t('imported') : ''), h('div.flex-column.flex-center.wallet-view__name-container', { style: { margin: '0 auto' }, @@ -133,13 +134,13 @@ WalletView.prototype.render = function () { selectedIdentity.name, ]), - h('button.btn-clear.wallet-view__details-button', 'DETAILS'), + h('button.btn-clear.wallet-view__details-button.allcaps', t('details')), ]), ]), h(Tooltip, { position: 'bottom', - title: this.state.hasCopied ? 'Copied!' : 'Copy to clipboard', + title: this.state.hasCopied ? t('copiedExclamation') : t('copyToClipboard'), wrapperClassName: 'wallet-view__tooltip', }, [ h('button.wallet-view__address', { @@ -172,7 +173,7 @@ WalletView.prototype.render = function () { showAddTokenPage() hideSidebar() }, - }, 'Add Token'), + }, t('addToken')), ]) } diff --git a/ui/app/css/itcss/components/hero-balance.scss b/ui/app/css/itcss/components/hero-balance.scss index 4af0c2c55..a3f051361 100644 --- a/ui/app/css/itcss/components/hero-balance.scss +++ b/ui/app/css/itcss/components/hero-balance.scss @@ -5,9 +5,6 @@ flex-direction: column; justify-content: flex-start; align-items: center; - margin: .3em .9em 0; - // height: 80vh; - // max-height: 225px; flex: 0 0 auto; } diff --git a/ui/app/css/itcss/components/index.scss b/ui/app/css/itcss/components/index.scss index 0219f9fb2..f107b7aca 100644 --- a/ui/app/css/itcss/components/index.scss +++ b/ui/app/css/itcss/components/index.scss @@ -55,3 +55,6 @@ @import './new-account.scss'; @import './tooltip.scss'; + +@import './welcome-screen.scss'; + diff --git a/ui/app/css/itcss/components/modal.scss b/ui/app/css/itcss/components/modal.scss index 53e3bff00..6c4106f8b 100644 --- a/ui/app/css/itcss/components/modal.scss +++ b/ui/app/css/itcss/components/modal.scss @@ -641,32 +641,40 @@ &__buy-rows { width: 100%; - padding: 33px; - padding-top: 0px; + padding: 0 30px; display: flex; flex-flow: column nowrap; flex: 1; - overflow-y: auto; @media screen and (max-width: 575px) { height: 0; } } + &__logo { + height: 60px; + background-repeat: no-repeat; + background-size: contain; + background-position: center; + width: 100%; + display: flex; + justify-content: center; + align-items: center; + } + &__buy-row { border-bottom: 1px solid $alto; display: flex; justify-content: space-between; align-items: center; - flex: 1; - padding-bottom: 25px; - padding-top: 25px; + flex: 1 0 auto; + padding: 30px 0 20px; + min-height: 170px; @media screen and (max-width: 575px) { - min-height: 360px; + min-height: 270px; flex-flow: column; - justify-content: center; - padding-top: 45px; + justify-content: flex-start; } &__back { @@ -692,30 +700,35 @@ } } - &__logo { + &__logo-container { display: flex; justify-content: center; - flex: 0.3 1 auto; + flex: 0 0 auto; + padding: 0 20px; - @media screen and (min-width: 575px) { - min-width: 215px; + @media screen and (min-width: 576px) { + width: 12rem; + } + + @media screen and (max-width: 575px) { + width: 100%; + max-height: 6rem; + padding-bottom: 20px; } } &__coinbase-logo { height: 40px; - width: 180px; } &__shapeshift-logo { height: 60px; - width: 174px; } &__eth-logo { border-radius: 50%; - width: 68px; height: 68px; + width: 68px; border: 3px solid $tundora; z-index: 25; padding: 4px; @@ -728,10 +741,11 @@ &__description { color: $cape-cod; - flex: 0.5 1 auto; + padding-bottom: 20px; + align-self: flex-start; @media screen and (min-width: 575px) { - min-width: 315px; + width: 15rem; } &__title { diff --git a/ui/app/css/itcss/components/new-account.scss b/ui/app/css/itcss/components/new-account.scss index c6c254ede..c2cefe4ad 100644 --- a/ui/app/css/itcss/components/new-account.scss +++ b/ui/app/css/itcss/components/new-account.scss @@ -161,15 +161,14 @@ display: flex; flex-flow: column; align-items: center; + padding: 30px 30px 0; &__input-label { color: $scorpion; font-family: Roboto; font-size: 16px; line-height: 21px; - margin-top: 29px; align-self: flex-start; - margin-left: 30px; } &__input { @@ -190,7 +189,7 @@ margin-top: 39px; display: flex; width: 100%; - justify-content: space-evenly; + justify-content: space-between; } &__button-cancel, diff --git a/ui/app/css/itcss/components/newui-sections.scss b/ui/app/css/itcss/components/newui-sections.scss index ecf5e1036..5cdda5e6c 100644 --- a/ui/app/css/itcss/components/newui-sections.scss +++ b/ui/app/css/itcss/components/newui-sections.scss @@ -51,6 +51,7 @@ $wallet-view-bg: $alabaster; cursor: pointer; display: flex; justify-content: center; + padding: 10px; } // wallet view and sidebar @@ -291,7 +292,6 @@ $wallet-view-bg: $alabaster; padding-right: 6px; } - // first time .first-view-main { display: flex; @@ -313,4 +313,23 @@ $wallet-view-bg: $alabaster; @media screen and (min-width: 1281px) { width: 62vw; } -}
\ No newline at end of file +} + +.unlock-screen-container { + z-index: $main-container-z-index; + font-family: Roboto; + display: flex; + justify-content: center; + align-items: center; + flex: 1 0 auto; + background: #f7f7f7; + width: 100%; +} + +.unlock-screen { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + flex: 1 0 auto; +} diff --git a/ui/app/css/itcss/components/welcome-screen.scss b/ui/app/css/itcss/components/welcome-screen.scss new file mode 100644 index 000000000..bfd174ad9 --- /dev/null +++ b/ui/app/css/itcss/components/welcome-screen.scss @@ -0,0 +1,59 @@ +.welcome-screen { + display: flex; + flex-flow: column; + justify-content: center; + align-items: center; + font-family: Roboto; + font-weight: 400; + width: 100%; + flex: 1 0 auto; + padding: 70px 0; + background: $white; + + @media screen and (max-width: 575px) { + padding: 0; + } + + &__info { + display: flex; + flex-flow: column; + width: 100%; + height: 100%; + align-items: center; + + &__header { + font-size: 1.65em; + margin-bottom: 14px; + + @media screen and (max-width: 575px) { + font-size: 1.5em; + } + } + + &__copy { + font-size: 1em; + width: 400px; + max-width: 90vw; + text-align: center; + + @media screen and (max-width: 575px) { + font-size: 0.9em; + } + } + } + + &__button { + height: 54px; + width: 198px; + box-shadow: 0 2px 4px 0 rgba(0,0,0,0.14); + color: #FFFFFF; + font-size: 20px; + font-weight: 500; + line-height: 26px; + text-align: center; + text-transform: uppercase; + margin: 35px 0 14px; + transition: 200ms ease-in-out; + background-color: rgba(247, 134, 28, 0.9); + } +} diff --git a/ui/app/css/itcss/generic/index.scss b/ui/app/css/itcss/generic/index.scss index 9b3d7475b..0077cb661 100644 --- a/ui/app/css/itcss/generic/index.scss +++ b/ui/app/css/itcss/generic/index.scss @@ -70,6 +70,10 @@ input.large-input { height: 36px; } +.allcaps { + text-transform: uppercase; +} + .page-container { width: 400px; background-color: $white; @@ -77,25 +81,30 @@ input.large-input { z-index: 25; display: flex; flex-flow: column; + border-radius: 7px; + height: 100%; &__header { display: flex; flex-flow: column; border-bottom: 1px solid $geyser; - padding: 1.15rem 0.95rem; + padding: 20px; flex: 0 0 auto; - background: $alabaster; position: relative; } - &__header-close::after { - content: '\00D7'; - font-size: 40px; + &__header-close { color: $tundora; position: absolute; - top: 21.5px; - right: 28.5px; + top: 20px; + right: 20px; cursor: pointer; + overflow: hidden; + + &::after { + content: '\00D7'; + font-size: 40px; + } } &__footer { @@ -114,7 +123,7 @@ input.large-input { &__footer-button { width: 165px; - height: 60px; + height: 55px; font-size: 1rem; text-transform: uppercase; margin-right: 1rem; @@ -130,7 +139,7 @@ input.large-input { font-family: Roboto; font-size: 2rem; font-weight: 500; - line-height: initial; + line-height: 2rem; } &__subtitle { @@ -174,6 +183,15 @@ input.large-input { } } } + + &--full-width { + width: initial; + } + + &__content { + height: 100%; + overflow-y: auto; + } } @media screen and (max-width: 250px) { @@ -200,5 +218,6 @@ input.large-input { width: 100%; overflow-y: auto; background-color: $white; + border-radius: 0; } } diff --git a/ui/app/first-time/init-menu.js b/ui/app/first-time/init-menu.js index 0e08da8db..370fdd5b7 100644 --- a/ui/app/first-time/init-menu.js +++ b/ui/app/first-time/init-menu.js @@ -6,6 +6,7 @@ const h = require('react-hyperscript') const Mascot = require('../components/mascot') const actions = require('../actions') const Tooltip = require('../components/tooltip') +const t = require('../../i18n') const getCaretCoordinates = require('textarea-caret') const environmentType = require('../../../app/scripts/lib/environment-type') const { OLD_UI_NETWORK_TYPE } = require('../../../app/scripts/config').enums @@ -59,7 +60,7 @@ InitializeMenuScreen.prototype.renderMenu = function (state) { color: '#7F8082', marginBottom: 10, }, - }, 'MetaMask'), + }, t('appName')), h('div', [ @@ -69,10 +70,10 @@ InitializeMenuScreen.prototype.renderMenu = function (state) { color: '#7F8082', display: 'inline', }, - }, 'Encrypt your new DEN'), + }, t('encryptNewDen')), h(Tooltip, { - title: 'Your DEN is your password-encrypted storage within MetaMask.', + title: t('denExplainer'), }, [ h('i.fa.fa-question-circle.pointer', { style: { @@ -92,7 +93,7 @@ InitializeMenuScreen.prototype.renderMenu = function (state) { h('input.large-input.letter-spacey', { type: 'password', id: 'password-box', - placeholder: 'New Password (min 8 chars)', + placeholder: t('newPassword'), onInput: this.inputChanged.bind(this), style: { width: 260, @@ -104,7 +105,7 @@ InitializeMenuScreen.prototype.renderMenu = function (state) { h('input.large-input.letter-spacey', { type: 'password', id: 'password-box-confirm', - placeholder: 'Confirm Password', + placeholder: t('confirmPassword'), onKeyPress: this.createVaultOnEnter.bind(this), onInput: this.inputChanged.bind(this), style: { @@ -119,7 +120,7 @@ InitializeMenuScreen.prototype.renderMenu = function (state) { style: { margin: 12, }, - }, 'Create'), + }, t('createDen')), h('.flex-row.flex-center.flex-grow', [ h('p.pointer', { @@ -129,7 +130,7 @@ InitializeMenuScreen.prototype.renderMenu = function (state) { color: 'rgb(247, 134, 28)', textDecoration: 'underline', }, - }, 'Import Existing DEN'), + }, t('importDen')), ]), h('.flex-row.flex-center.flex-grow', [ @@ -178,12 +179,12 @@ InitializeMenuScreen.prototype.createNewVaultAndKeychain = function () { var passwordConfirm = passwordConfirmBox.value if (password.length < 8) { - this.warning = 'password not long enough' + this.warning = t('passwordShort') this.props.dispatch(actions.displayWarning(this.warning)) return } if (password !== passwordConfirm) { - this.warning = 'passwords don\'t match' + this.warning = t('passwordMismatch') this.props.dispatch(actions.displayWarning(this.warning)) return } diff --git a/ui/app/keychains/hd/restore-vault.js b/ui/app/keychains/hd/restore-vault.js index d1761f17d..685094854 100644 --- a/ui/app/keychains/hd/restore-vault.js +++ b/ui/app/keychains/hd/restore-vault.js @@ -144,6 +144,19 @@ RestoreVaultScreen.prototype.createNewVaultAndRestore = function () { // check seed var seedBox = document.querySelector('textarea.twelve-word-phrase') var seed = seedBox.value.trim() + + // true if the string has more than a space between words. + if (seed.split(' ').length > 1) { + this.warning = 'there can only a space between words' + this.props.dispatch(actions.displayWarning(this.warning)) + return + } + // true if seed contains a character that is not between a-z or a space + if (!seed.match(/^[a-z ]+$/)) { + this.warning = 'seed words only have lowercase characters' + this.props.dispatch(actions.displayWarning(this.warning)) + return + } if (seed.split(' ').length !== 12) { this.warning = 'seed phrases are 12 words long' this.props.dispatch(actions.displayWarning(this.warning)) diff --git a/ui/app/main-container.js b/ui/app/main-container.js index 292abcc3d..eed4bd164 100644 --- a/ui/app/main-container.js +++ b/ui/app/main-container.js @@ -32,19 +32,7 @@ MainContainer.prototype.render = function () { return h(Settings, {key: 'config'}) default: log.debug('rendering locked screen') - contents = { - component: UnlockScreen, - style: { - boxShadow: 'none', - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - background: '#F7F7F7', - // must force 100%, because lock screen is full-width - width: '100%', - }, - key: 'locked', - } + return h('.unlock-screen-container', {}, h(UnlockScreen, { key: 'locked' })) } } diff --git a/ui/app/reducers/metamask.js b/ui/app/reducers/metamask.js index 2c93172cc..e6e02d057 100644 --- a/ui/app/reducers/metamask.js +++ b/ui/app/reducers/metamask.js @@ -45,6 +45,7 @@ function reduceMetamask (state, action) { featureFlags: {}, networkEndpointType: OLD_UI_NETWORK_TYPE, isRevealingSeedWords: false, + welcomeScreenSeen: false, }, state.metamask) switch (action.type) { @@ -349,6 +350,11 @@ function reduceMetamask (state, action) { networkEndpointType: action.value, }) + case actions.CLOSE_WELCOME_SCREEN: + return extend(metamaskState, { + welcomeScreenSeen: true, + }) + default: return metamaskState diff --git a/ui/app/unlock.js b/ui/app/unlock.js index cafe3a859..ac97d04d0 100644 --- a/ui/app/unlock.js +++ b/ui/app/unlock.js @@ -5,6 +5,7 @@ const connect = require('react-redux').connect const actions = require('./actions') const getCaretCoordinates = require('textarea-caret') const EventEmitter = require('events').EventEmitter +const t = require('../i18n') const { OLD_UI_NETWORK_TYPE } = require('../../app/scripts/config').enums const environmentType = require('../../app/scripts/lib/environment-type') @@ -28,83 +29,72 @@ UnlockScreen.prototype.render = function () { const state = this.props const warning = state.warning return ( - h('.flex-column', { - style: { - width: 'inherit', - }, - }, [ - h('.unlock-screen.flex-column.flex-center.flex-grow', [ - - h(Mascot, { - animationEventEmitter: this.animationEventEmitter, - }), - - h('h1', { - style: { - fontSize: '1.4em', - textTransform: 'uppercase', - color: '#7F8082', - }, - }, 'MetaMask'), - - h('input.large-input', { - type: 'password', - id: 'password-box', - placeholder: 'enter password', - style: { - background: 'white', - }, - onKeyPress: this.onKeyPress.bind(this), - onInput: this.inputChanged.bind(this), - }), - - h('.error', { - style: { - display: warning ? 'block' : 'none', - padding: '0 20px', - textAlign: 'center', - }, - }, warning), - - h('button.primary.cursor-pointer', { - onClick: this.onSubmit.bind(this), - style: { - margin: 10, - }, - }, 'Log In'), - ]), - - h('.flex-row.flex-center.flex-grow', [ - h('p.pointer', { - onClick: () => { - this.props.dispatch(actions.markPasswordForgotten()) - if (environmentType() === 'popup') { - global.platform.openExtensionInBrowser() - } - }, - style: { - fontSize: '0.8em', - color: 'rgb(247, 134, 28)', - textDecoration: 'underline', - }, - }, 'Restore from seed phrase'), - ]), - - h('.flex-row.flex-center.flex-grow', [ - h('p.pointer', { - onClick: () => { - this.props.dispatch(actions.setFeatureFlag('betaUI', false, 'OLD_UI_NOTIFICATION_MODAL')) - .then(() => this.props.dispatch(actions.setNetworkEndpoints(OLD_UI_NETWORK_TYPE))) - }, - style: { - fontSize: '0.8em', - color: '#aeaeae', - textDecoration: 'underline', - marginTop: '32px', - }, - }, 'Use classic interface'), - ]), - + h('.unlock-screen', [ + + h(Mascot, { + animationEventEmitter: this.animationEventEmitter, + }), + + h('h1', { + style: { + fontSize: '1.4em', + textTransform: 'uppercase', + color: '#7F8082', + }, + }, t('appName')), + + h('input.large-input', { + type: 'password', + id: 'password-box', + placeholder: 'enter password', + style: { + background: 'white', + }, + onKeyPress: this.onKeyPress.bind(this), + onInput: this.inputChanged.bind(this), + }), + + h('.error', { + style: { + display: warning ? 'block' : 'none', + padding: '0 20px', + textAlign: 'center', + }, + }, warning), + + h('button.primary.cursor-pointer', { + onClick: this.onSubmit.bind(this), + style: { + margin: 10, + }, + }, 'Log In'), + + h('p.pointer', { + onClick: () => { + this.props.dispatch(actions.markPasswordForgotten()) + if (environmentType() === 'popup') { + global.platform.openExtensionInBrowser() + } + }, + style: { + fontSize: '0.8em', + color: 'rgb(247, 134, 28)', + textDecoration: 'underline', + }, + }, 'Restore from seed phrase'), + + h('p.pointer', { + onClick: () => { + this.props.dispatch(actions.setFeatureFlag('betaUI', false, 'OLD_UI_NOTIFICATION_MODAL')) + .then(() => this.props.dispatch(actions.setNetworkEndpoints(OLD_UI_NETWORK_TYPE))) + }, + style: { + fontSize: '0.8em', + color: '#aeaeae', + textDecoration: 'underline', + marginTop: '32px', + }, + }, 'Use classic interface'), ]) ) } diff --git a/ui/app/welcome-screen.js b/ui/app/welcome-screen.js new file mode 100644 index 000000000..cdbb6dba8 --- /dev/null +++ b/ui/app/welcome-screen.js @@ -0,0 +1,56 @@ +import EventEmitter from 'events' +import h from 'react-hyperscript' +import { Component } from 'react' +import PropTypes from 'prop-types' +import {connect} from 'react-redux' +import {closeWelcomeScreen} from './actions' +import Mascot from './components/mascot' + +class WelcomeScreen extends Component { + static propTypes = { + closeWelcomeScreen: PropTypes.func.isRequired, + } + + constructor(props) { + super(props) + this.animationEventEmitter = new EventEmitter() + } + + initiateAccountCreation = () => { + this.props.closeWelcomeScreen() + } + + render () { + return h('div.welcome-screen', [ + + h('div.welcome-screen__info', [ + + h(Mascot, { + animationEventEmitter: this.animationEventEmitter, + width: '225', + height: '225', + }), + + h('div.welcome-screen__info__header', 'Welcome to MetaMask Beta'), + + h('div.welcome-screen__info__copy', 'MetaMask is a secure identity vault for Ethereum.'), + + h('div.welcome-screen__info__copy', `It allows you to hold ether & tokens, + and serves as your bridge to decentralized applications.`), + + h('button.welcome-screen__button', { + onClick: this.initiateAccountCreation, + }, 'Continue'), + + ]), + + ]) + } +} + +export default connect( + null, + dispatch => ({ + closeWelcomeScreen: () => dispatch(closeWelcomeScreen()), + }) +)(WelcomeScreen) |