From fc5d701340156a40ad7215d0f780c795e571f006 Mon Sep 17 00:00:00 2001 From: meriadec <meriadec.pillet@gmail.com> Date: Thu, 22 Feb 2018 15:30:06 +0100 Subject: [PATCH] Add translations --- src/components/DashboardPage/AccountsOrder.js | 2 +- src/components/DashboardPage/index.js | 32 +++++++++++-------- src/components/GlobalSearch.js | 11 +++++-- src/components/SettingsPage/Display.js | 5 ++- src/components/SettingsPage/Profile.js | 10 +++--- src/components/SettingsPage/index.js | 1 + src/components/TopBar.js | 14 +++++--- src/components/TransactionsList/index.js | 29 ++++++++++------- static/i18n/en/translation.yml | 27 ++++++++++++++++ static/i18n/fr/translation.yml | 29 ++++++++++++++++- 10 files changed, 119 insertions(+), 41 deletions(-) diff --git a/src/components/DashboardPage/AccountsOrder.js b/src/components/DashboardPage/AccountsOrder.js index 218cb92a..849947b7 100644 --- a/src/components/DashboardPage/AccountsOrder.js +++ b/src/components/DashboardPage/AccountsOrder.js @@ -183,7 +183,7 @@ class AccountsOrder extends Component<Props, State> { value={sortItems.find(item => item.key === cachedValue)} > <Text ff="Open Sans|SemiBold" fontSize={4}> - {'Sort by'} + {t('global.sortBy')} </Text> <Box alignItems="center" diff --git a/src/components/DashboardPage/index.js b/src/components/DashboardPage/index.js index c175f9ba..8cdcab19 100644 --- a/src/components/DashboardPage/index.js +++ b/src/components/DashboardPage/index.js @@ -13,7 +13,7 @@ import sortBy from 'lodash/sortBy' import takeRight from 'lodash/takeRight' import type { MapStateToProps } from 'react-redux' -import type { Accounts } from 'types/common' +import type { Accounts, T } from 'types/common' import { space } from 'styles/theme' @@ -43,6 +43,7 @@ const mapDispatchToProps = { } type Props = { + t: T, accounts: Accounts, push: Function, } @@ -59,12 +60,7 @@ const ACCOUNTS_BY_LINE = 3 const ALL_TRANSACTIONS_LIMIT = 10 const TIMEOUT_REFRESH_DATAS = 5e3 -const itemsTimes = [ - { key: 'day', label: 'Day' }, - { key: 'week', label: 'Week' }, - { key: 'month', label: 'Month' }, - { key: 'year', label: 'Year' }, -] +const itemsTimes = [{ key: 'day' }, { key: 'week' }, { key: 'month' }, { key: 'year' }] const generateFakeData = v => ({ name: `Day ${v}`, @@ -132,6 +128,13 @@ class DashboardPage extends PureComponent<Props, State> { } } + componentWillMount() { + this._itemsTimes = itemsTimes.map(item => ({ + ...item, + label: this.props.t(`time.${item.key}`), + })) + } + componentDidMount() { this._mounted = true @@ -190,9 +193,10 @@ class DashboardPage extends PureComponent<Props, State> { _timeout = undefined _mounted = false + _itemsTimes = [] render() { - const { push, accounts } = this.props + const { push, accounts, t } = this.props const { accountsChunk, allTransactions, selectedTime, fakeDatas, fakeDatasMerge } = this.state let accountIndex = 0 @@ -203,17 +207,17 @@ class DashboardPage extends PureComponent<Props, State> { <Box horizontal alignItems="flex-end"> <Box> <Text color="dark" ff="Museo Sans" fontSize={7}> - {'Good morning, Khalil.'} + {t('dashboard.greetings', { name: 'Khalil' })} </Text> <Text color="grey" fontSize={5} ff="Museo Sans|Light"> {totalAccounts > 0 - ? `here is the summary of your ${totalAccounts} accounts` - : 'no accounts'} + ? t('dashboard.summary', { count: totalAccounts }) + : t('dashboard.noAccounts')} </Text> </Box> <Box ml="auto"> <Pills - items={itemsTimes} + items={this._itemsTimes} activeKey={selectedTime} onChange={item => this.setState({ selectedTime: item.key })} /> @@ -243,7 +247,7 @@ class DashboardPage extends PureComponent<Props, State> { <Box flow={4}> <Box horizontal alignItems="flex-end"> <Text color="dark" ff="Museo Sans" fontSize={6}> - {'Accounts'} + {t('sidebar.accounts')} </Text> <Box ml="auto" horizontal flow={1}> <AccountsOrder /> @@ -277,7 +281,7 @@ class DashboardPage extends PureComponent<Props, State> { ))} </Box> </Box> - <Card p={0} px={4} title="Recent activity"> + <Card p={0} px={4} title={t('dashboard.recentActivity')}> <TransactionsList withAccounts transactions={allTransactions} diff --git a/src/components/GlobalSearch.js b/src/components/GlobalSearch.js index b2429561..1e059ad8 100644 --- a/src/components/GlobalSearch.js +++ b/src/components/GlobalSearch.js @@ -3,6 +3,8 @@ import React, { PureComponent } from 'react' import styled from 'styled-components' +import type { T } from 'types/common' + import IconSearch from 'icons/Search' import Box from 'components/base/Box' @@ -30,7 +32,11 @@ type State = { isFocused: boolean, } -class GlobalSearch extends PureComponent<{}, State> { +type Props = { + t: T, +} + +class GlobalSearch extends PureComponent<Props, State> { state = { isFocused: false, } @@ -54,6 +60,7 @@ class GlobalSearch extends PureComponent<{}, State> { }) render() { + const { t } = this.props const { isFocused } = this.state return ( @@ -62,7 +69,7 @@ class GlobalSearch extends PureComponent<{}, State> { <IconSearch height={16} width={16} /> </Box> <Input - placeholder="Search" + placeholder={t('global.search')} innerRef={input => (this._input = input)} onBlur={this.handleBlur} onFocus={this.handleFocus} diff --git a/src/components/SettingsPage/Display.js b/src/components/SettingsPage/Display.js index d5e80d52..ad095538 100644 --- a/src/components/SettingsPage/Display.js +++ b/src/components/SettingsPage/Display.js @@ -1,7 +1,6 @@ // @flow import React, { PureComponent } from 'react' -import { translate } from 'react-i18next' import type { SettingsDisplay, T } from 'types/common' @@ -88,7 +87,7 @@ class TabProfile extends PureComponent<Props, State> { </Box> <Box horizontal justifyContent="flex-end"> <Button primary type="submit"> - Save + {t('global.save')} </Button> </Box> </Card> @@ -97,4 +96,4 @@ class TabProfile extends PureComponent<Props, State> { } } -export default translate()(TabProfile) +export default TabProfile diff --git a/src/components/SettingsPage/Profile.js b/src/components/SettingsPage/Profile.js index caf97df2..2f21e2c2 100644 --- a/src/components/SettingsPage/Profile.js +++ b/src/components/SettingsPage/Profile.js @@ -9,7 +9,7 @@ import set from 'lodash/set' import { setEncryptionKey } from 'helpers/db' -import type { SettingsProfile } from 'types/common' +import type { SettingsProfile, T } from 'types/common' import { unlock } from 'reducers/application' @@ -22,6 +22,7 @@ import Label from 'components/base/Label' type InputValue = SettingsProfile type Props = { + t: T, settings: SettingsProfile, onSaveSettings: Function, unlock: Function, @@ -80,6 +81,7 @@ class TabProfile extends PureComponent<Props, State> { } render() { + const { t } = this.props const { inputValue } = this.state const isPasswordChecked = get(inputValue, 'password.state', false) @@ -95,12 +97,12 @@ class TabProfile extends PureComponent<Props, State> { onClick={() => this.handleChangeInput('password.state')(!isPasswordChecked)} > <CheckBox isChecked={isPasswordChecked} /> - <div>{' Protect local data with a password'}</div> + <div>{t('settings.profile.protectWithPassword')}</div> </Box> </label> {get(inputValue, 'password.state') === true && ( <Box flow={1}> - <Label>Password</Label> + <Label>{t('settings.profile.password')}</Label> <Input value={get(inputValue, 'password.value', '')} onChange={this.handleChangeInput('password.value')} @@ -110,7 +112,7 @@ class TabProfile extends PureComponent<Props, State> { )} <Box horizontal justifyContent="flex-end"> <Button primary type="submit"> - Save + {t('global.save')} </Button> </Box> </Card> diff --git a/src/components/SettingsPage/index.js b/src/components/SettingsPage/index.js index 740ad75d..44bd987a 100644 --- a/src/components/SettingsPage/index.js +++ b/src/components/SettingsPage/index.js @@ -59,6 +59,7 @@ class SettingsPage extends PureComponent<Props, State> { const { tab } = this.state const props = { + t, settings, onSaveSettings: this.handleSaveSettings, } diff --git a/src/components/TopBar.js b/src/components/TopBar.js index 31e68e4e..700e3688 100644 --- a/src/components/TopBar.js +++ b/src/components/TopBar.js @@ -1,11 +1,14 @@ // @flow import React, { PureComponent } from 'react' +import { compose } from 'redux' +import { translate } from 'react-i18next' import { connect } from 'react-redux' import styled from 'styled-components' import { ipcRenderer } from 'electron' import type { MapStateToProps, MapDispatchToProps } from 'react-redux' +import type { T } from 'types/common' import { rgba } from 'styles/helpers' import { getAccounts } from 'reducers/accounts' @@ -80,6 +83,7 @@ const mapDispatchToProps: MapDispatchToProps<*, *, *> = { } type Props = { + t: T, hasAccounts: boolean, hasPassword: boolean, lock: Function, @@ -140,14 +144,14 @@ class TopBar extends PureComponent<Props, State> { handleLock = () => this.props.lock() render() { - const { hasPassword, hasAccounts } = this.props + const { hasPassword, hasAccounts, t } = this.props const { sync } = this.state return ( <Container bg="cream" color="warmGrey"> <Inner> <Box grow horizontal flow={4}> - <GlobalSearch /> + <GlobalSearch t={t} /> <Box justifyContent="center"> <IconDevices height={16} width={16} /> </Box> @@ -164,14 +168,14 @@ class TopBar extends PureComponent<Props, State> { items={[ { key: 'profile', - label: 'Edit profile', + label: t('mainDropdown.editProfile'), icon: <IconUser height={16} width={16} />, }, ...(hasPassword ? [ { key: 'lock', - label: 'Lock application', + label: t('mainDropdown.lockApplication'), icon: <IconUser height={16} width={16} />, onClick: this.handleLock, }, @@ -203,4 +207,4 @@ class TopBar extends PureComponent<Props, State> { } } -export default connect(mapStateToProps, mapDispatchToProps)(TopBar) +export default compose(connect(mapStateToProps, mapDispatchToProps), translate())(TopBar) diff --git a/src/components/TransactionsList/index.js b/src/components/TransactionsList/index.js index 4736ca7d..191709f1 100644 --- a/src/components/TransactionsList/index.js +++ b/src/components/TransactionsList/index.js @@ -3,12 +3,13 @@ import React, { Component } from 'react' import styled from 'styled-components' import moment from 'moment' +import { translate } from 'react-i18next' import get from 'lodash/get' import noop from 'lodash/noop' import isEqual from 'lodash/isEqual' import { getIconByCoinType } from '@ledgerhq/currencies/react' -import type { Transaction as TransactionType } from 'types/common' +import type { Transaction as TransactionType, T } from 'types/common' import Box from 'components/base/Box' import Defer from 'components/base/Defer' @@ -71,10 +72,12 @@ const Cell = styled(Box).attrs({ ` const Transaction = ({ + t, onAccountClick, tx, withAccounts, }: { + t: T, onAccountClick?: Function, tx: TransactionType, withAccounts?: boolean, @@ -117,7 +120,7 @@ const Transaction = ({ }} > <Box ff="Open Sans" fontSize={3} color="lead"> - {tx.balance > 0 ? 'From' : 'To'} + {tx.balance > 0 ? t('transactionsList.from') : t('transactionsList.to')} </Box> <Box color="dark" ff="Open Sans" fontSize={3}> {tx.address} @@ -142,6 +145,7 @@ Transaction.defaultProps = { } type Props = { + t: T, onAccountClick?: Function, transactions: Array<TransactionType>, withAccounts?: boolean, @@ -166,28 +170,31 @@ class TransactionsList extends Component<Props> { _hashCache = null render() { - const { transactions, withAccounts, onAccountClick } = this.props + const { transactions, withAccounts, onAccountClick, t } = this.props this._hashCache = this.getHashCache(transactions) return ( <Box flow={1}> <Box horizontal pt={4}> - <HeaderCol size={DATE_COL_SIZE}>{'Date'}</HeaderCol> - {withAccounts && <HeaderCol size={ACCOUNT_COL_SIZE}>{'Account'}</HeaderCol>} - <HeaderCol grow>{'Address'}</HeaderCol> + <HeaderCol size={DATE_COL_SIZE}>{t('transactionsList.date')}</HeaderCol> + {withAccounts && ( + <HeaderCol size={ACCOUNT_COL_SIZE}>{t('transactionsList.account')}</HeaderCol> + )} + <HeaderCol grow>{t('transactionsList.address')}</HeaderCol> <HeaderCol size={AMOUNT_COL_SIZE} justifyContent="flex-end"> - {'Amount'} + {t('transactionsList.amount')} </HeaderCol> </Box> <Defer> <Box> - {transactions.map(t => ( + {transactions.map(trans => ( <Transaction - key={`{${t.hash}-${t.account ? t.account.id : ''}`} + t={t} + key={`{${trans.hash}-${trans.account ? trans.account.id : ''}`} withAccounts={withAccounts} onAccountClick={onAccountClick} - tx={t} + tx={trans} /> ))} </Box> @@ -197,4 +204,4 @@ class TransactionsList extends Component<Props> { } } -export default TransactionsList +export default translate()(TransactionsList) diff --git a/static/i18n/en/translation.yml b/static/i18n/en/translation.yml index d0faf6f1..df5c145d 100644 --- a/static/i18n/en/translation.yml +++ b/static/i18n/en/translation.yml @@ -18,6 +18,11 @@ device: notConnected: Not connected dashboard: title: Dashboard + greetings: 'Good morning, {{name}}.' + summary: here is the summary of your account + summary_plural: 'here is the summary of your {{count}} accounts' + noAccounts: no accounts + recentActivity: Recent activity send: title: Send receive: @@ -39,6 +44,9 @@ settings: display: language: Language orderAccounts: Order accounts + profile: + protectWithPassword: Protect local data with a password + password: Password SelectAccount: placeholder: Select an account AccountPage: @@ -55,3 +63,22 @@ sendModal: Summary: Summary SecureValidation: Secure validation Confirmation: Confirmation +time: + day: Day + week: Week + month: Month + year: Year +global: + sortBy: Sort by + search: Search + save: Save +transactionsList: + date: Date + account: Account + address: Address + amount: Amount + from: From + to: To +mainDropdown: + editProfile: Edit profile + lockApplication: Lock application diff --git a/static/i18n/fr/translation.yml b/static/i18n/fr/translation.yml index 2151cb1e..c115c115 100644 --- a/static/i18n/fr/translation.yml +++ b/static/i18n/fr/translation.yml @@ -18,6 +18,11 @@ device: notConnected: Non connecté dashboard: title: Tableau de bord + greetings: 'Bonjour, {{name}}.' + summary: voici le résumé de votre compte + summary_plural: 'voici le résumé de vos {{count}} comptes' + noAccounts: aucun compte + recentActivity: Activité récente send: title: Envoyer receive: @@ -37,8 +42,11 @@ settings: blockchain: Blockchain profile: Profil display: - language: Langage + language: Langue orderAccounts: Ordre des comptes + profile: + protectWithPassword: Protégez les données locales avec un mot de passe + password: Mot de passe SelectAccount: placeholder: Sélectionner un compte AccountPage: @@ -55,3 +63,22 @@ sendModal: Summary: Résumé SecureValidation: Validation sécurisée Confirmation: Confirmation +time: + day: Jour + week: Semaine + month: Mois + year: Année +global: + sortBy: Trier par + search: Rechercher + save: Sauvegarder +transactionsList: + date: Date + account: Compte + address: Adresse + amount: Montant + from: Depuis + to: Vers +mainDropdown: + editProfile: Éditer le profil + lockApplication: Verrouiller l'application