Permalink
Browse files

feat(i18n): initial multi-language support

  • Loading branch information...
mrfelton committed Sep 17, 2018
1 parent 54ed782 commit aedd1ee2331dda20331b6e2dafaa2d115e7aa420
Showing with 4,146 additions and 344 deletions.
  1. +4 −1 .babelrc
  2. +15 −6 app/components/Activity/Activity.js
  3. +6 −15 app/components/Activity/Activity.scss
  4. +6 −1 app/components/Activity/Countdown/Countdown.js
  5. +6 −0 app/components/Activity/Countdown/messages.js
  6. +22 −9 app/components/Activity/Invoice/Invoice.js
  7. +10 −0 app/components/Activity/Invoice/messages.js
  8. +36 −11 app/components/Activity/InvoiceModal/InvoiceModal.js
  9. +12 −0 app/components/Activity/InvoiceModal/messages.js
  10. +23 −8 app/components/Activity/Payment/Payment.js
  11. +8 −0 app/components/Activity/Payment/messages.js
  12. +18 −6 app/components/Activity/PaymentModal/PaymentModal.js
  13. +8 −0 app/components/Activity/PaymentModal/messages.js
  14. +24 −8 app/components/Activity/Transaction/Transaction.js
  15. +10 −0 app/components/Activity/Transaction/messages.js
  16. +21 −9 app/components/Activity/TransactionModal/TransactionModal.js
  17. +9 −0 app/components/Activity/TransactionModal/messages.js
  18. +13 −0 app/components/Activity/messages.js
  19. +19 −6 app/components/Contacts/AddChannel/AddChannel.js
  20. +11 −0 app/components/Contacts/AddChannel/messages.js
  21. +15 −6 app/components/Contacts/ConnectManually/ConnectManually.js
  22. +9 −0 app/components/Contacts/ConnectManually/messages.js
  23. +28 −11 app/components/Contacts/Network/Network.js
  24. +16 −0 app/components/Contacts/Network/messages.js
  25. +18 −12 app/components/Contacts/SubmitChannelForm/SubmitChannelForm.js
  26. +11 −0 app/components/Contacts/SubmitChannelForm/messages.js
  27. +8 −3 app/components/Contacts/SuggestedNodes/SuggestedNodes.js
  28. +8 −0 app/components/Contacts/SuggestedNodes/messages.js
  29. +20 −8 app/components/Form/Pay/Pay.js
  30. +11 −0 app/components/Form/Pay/messages.js
  31. +18 −7 app/components/Form/Request/Request.js
  32. +9 −0 app/components/Form/Request/messages.js
  33. +6 −1 app/components/LoadingBolt/LoadingBolt.js
  34. +6 −0 app/components/LoadingBolt/messages.js
  35. +8 −2 app/components/Onboarding/Autopilot/Autopilot.js
  36. +7 −0 app/components/Onboarding/Autopilot/messages.js
  37. +13 −8 app/components/Onboarding/BtcPayServer/BtcPayServer.js
  38. +10 −0 app/components/Onboarding/BtcPayServer/messages.js
  39. +6 −2 app/components/Onboarding/ConnectionConfirm/ConnectionConfirm.js
  40. +7 −0 app/components/Onboarding/ConnectionConfirm/messages.js
  41. +13 −5 app/components/Onboarding/ConnectionDetails/ConnectionDetails.js
  42. +10 −0 app/components/Onboarding/ConnectionDetails/messages.js
  43. +11 −7 app/components/Onboarding/ConnectionType/ConnectionType.js
  44. +14 −0 app/components/Onboarding/ConnectionType/messages.js
  45. +9 −5 app/components/Onboarding/FormContainer/FormContainer.js
  46. +8 −0 app/components/Onboarding/FormContainer/messages.js
  47. +17 −4 app/components/Onboarding/Login/Login.js
  48. +7 −0 app/components/Onboarding/Login/messages.js
  49. +16 −8 app/components/Onboarding/NewWalletPassword/NewWalletPassword.js
  50. +10 −0 app/components/Onboarding/NewWalletPassword/messages.js
  51. +49 −38 app/components/Onboarding/Onboarding.js
  52. +7 −4 app/components/Onboarding/RecoverForm/RecoverForm.js
  53. +6 −0 app/components/Onboarding/RecoverForm/messages.js
  54. +8 −2 app/components/Onboarding/Signup/Signup.js
  55. +7 −0 app/components/Onboarding/Signup/messages.js
  56. +36 −16 app/components/Onboarding/Syncing/Syncing.js
  57. +17 −0 app/components/Onboarding/Syncing/messages.js
  58. +35 −0 app/components/Onboarding/messages.js
  59. +5 −1 app/components/Settings/Fiat/Fiat.js
  60. +6 −0 app/components/Settings/Fiat/messages.js
  61. +49 −0 app/components/Settings/Locale/Locale.js
  62. +42 −0 app/components/Settings/Locale/Locale.scss
  63. +3 −0 app/components/Settings/Locale/index.js
  64. +6 −0 app/components/Settings/Locale/messages.js
  65. +9 −1 app/components/Settings/Menu/Menu.js
  66. +7 −0 app/components/Settings/Menu/messages.js
  67. +6 −2 app/components/Settings/Settings.js
  68. +15 −8 app/components/Wallet/ReceiveModal/ReceiveModal.js
  69. +9 −0 app/components/Wallet/ReceiveModal/messages.js
  70. +13 −8 app/components/Wallet/Wallet.js
  71. +10 −0 app/components/Wallet/messages.js
  72. +11 −0 app/containers/Activity.js
  73. +9 −19 app/containers/Root.js
  74. +24 −13 app/index.js
  75. +125 −0 app/lib/utils/i18n.js
  76. +35 −5 app/lib/zap/menuBuilder.js
  77. +4 −4 app/reducers/activity.js
  78. +4 −0 app/reducers/index.js
  79. +2 −0 app/reducers/ipc.js
  80. +40 −0 app/reducers/locale.js
  81. +157 −0 app/translations/bg-BG.json
  82. +157 −0 app/translations/cs-CZ.json
  83. +157 −0 app/translations/de-DE.json
  84. +157 −0 app/translations/el-GR.json
  85. +157 −0 app/translations/en.json
  86. +157 −0 app/translations/es-ES.json
  87. +157 −0 app/translations/fr-FR.json
  88. +157 −0 app/translations/hr-HR.json
  89. +157 −0 app/translations/ja-JP.json
  90. +157 −0 app/translations/nl-NL.json
  91. +157 −0 app/translations/pt-BR.json
  92. +157 −0 app/translations/ro-RO.json
  93. +157 −0 app/translations/ru-RU.json
  94. +157 −0 app/translations/sv-SE.json
  95. +157 −0 app/translations/tr-TR.json
  96. +157 −0 app/translations/uk-UA.json
  97. +157 −0 app/translations/zh-CN.json
  98. +8 −2 package.json
  99. +41 −0 test/unit/__helpers__/intl-enzyme-test-helper.js.js
  100. +6 −4 test/unit/components/Form/Pay.spec.js
  101. +5 −3 test/unit/components/Form/Request.spec.js
  102. +4 −2 test/unit/components/LoadingBolt.spec.js
  103. +28 −28 test/unit/reducers/__snapshots__/activity.spec.js.snap
  104. +156 −15 yarn.lock
@@ -10,7 +10,10 @@
"stage-0",
"react"
],
"plugins": ["add-module-exports", "dynamic-import-webpack"],
"plugins": ["add-module-exports", "dynamic-import-webpack", ["react-intl-auto", {
"removePrefix": "app/",
"filebase": false
}]],
"env": {
"production": {
"presets": ["react-optimize"],
@@ -5,6 +5,8 @@ import searchIcon from 'icons/search.svg'
import xIcon from 'icons/x.svg'
import FaRepeat from 'react-icons/lib/fa/repeat'
import { FormattedMessage, injectIntl } from 'react-intl'
import Wallet from 'components/Wallet'
import LoadingBolt from 'components/LoadingBolt'
import Invoice from './Invoice'
@@ -13,6 +15,8 @@ import Transaction from './Transaction'
import styles from './Activity.scss'
import messages from './messages'
class Activity extends Component {
constructor(props, context) {
super(props, context)
@@ -87,7 +91,8 @@ class Activity extends Component {
updateSearchActive,
updateSearchText,
walletProps
walletProps,
intl
} = this.props
if (balance.channelBalance === null || balance.walletBalance === null) {
@@ -134,7 +139,7 @@ class Activity extends Component {
<header className={`${styles.header} ${styles.search}`}>
<section>
<input
placeholder="Search"
placeholder={intl.formatMessage({ ...messages.search })}
value={searchText}
onChange={event => updateSearchText(event.target.value)}
/>
@@ -160,7 +165,7 @@ class Activity extends Component {
className={f.key === filter.key ? styles.activeFilter : undefined}
onClick={() => changeFilter(f)}
>
<span>{f.name}</span>
<FormattedMessage {...messages[f.name]} />
<div className={f.key === filter.key ? styles.activeBorder : undefined} />
</li>
@@ -176,7 +181,7 @@ class Activity extends Component {
this.repeat = ref
}}
>
{refreshing ? <FaRepeat /> : 'Refresh'}
{refreshing ? <FaRepeat /> : <FormattedMessage {...messages.refresh} />}
</span>
</li>
<li className={styles.activeFilter} onClick={() => updateSearchActive(true)}>
@@ -204,7 +209,11 @@ class Activity extends Component {
{showExpiredToggle && (
<li>
<div className={styles.toggleExpired} onClick={toggleExpiredRequests}>
{showExpiredRequests ? 'Hide Expired Requests' : 'Show Expired Requests'}
{showExpiredRequests ? (
<FormattedMessage {...messages.hide_expired} />
) : (
<FormattedMessage {...messages.show_expired} />
)}
</div>
</li>
)}
@@ -240,4 +249,4 @@ Activity.propTypes = {
currencyName: PropTypes.string.isRequired
}
export default Activity
export default injectIntl(Activity)
@@ -284,23 +284,15 @@
font-size: 10px;
}
.icon,
h3,
span {
vertical-align: middle;
}
h3,
span {
font-size: 14px;
font-weight: bold;
letter-spacing: 1.2px;
.date {
font-size: 12px;
}
.icon {
display: inline-block;
flex: none;
position: relative;
vertical-align: middle;
width: 20px;
height: 20px;
background: #31343f;
@@ -321,17 +313,16 @@
h3 {
display: inline-block;
font-size: 14px;
font-weight: bold;
letter-spacing: 1.2px;
&::after {
content: ' ';
display: inline-block;
width: 3px;
}
}
span {
text-transform: uppercase;
}
}
.amount {
@@ -1,6 +1,9 @@
import React from 'react'
import PropTypes from 'prop-types'
import { FormattedMessage } from 'react-intl'
import messages from './messages'
import styles from './Countdown.scss'
class Countdown extends React.Component {
@@ -73,7 +76,9 @@ class Countdown extends React.Component {
return (
<span className={styles.container}>
<i className={styles.caption}>Expires in</i>
<i className={styles.caption}>
<FormattedMessage {...messages.expires} />
</i>
<i>{days > 0 && `${days}:`}</i>
<i>{hours > 0 && `${hours}:`}</i>
<i>{minutes > 0 && `${minutes}:`}</i>
@@ -0,0 +1,6 @@
import { defineMessages } from 'react-intl'
/* eslint-disable max-len */
export default defineMessages({
expires: 'Expires in'
})
@@ -1,42 +1,55 @@
import React from 'react'
import PropTypes from 'prop-types'
import Moment from 'react-moment'
import { btc } from 'lib/utils'
import Isvg from 'react-inlinesvg'
import Value from 'components/Value'
import checkmarkIcon from 'icons/check_circle.svg'
import { FormattedTime, FormattedMessage, injectIntl } from 'react-intl'
import messages from './messages'
import styles from '../Activity.scss'
const Invoice = ({ invoice, ticker, currentTicker, showActivityModal, currencyName }) => (
const Invoice = ({ invoice, ticker, currentTicker, showActivityModal, currencyName, intl }) => (
<div
className={`${styles.container} ${!invoice.settled ? styles.unpaid : undefined}`}
onClick={() => showActivityModal('INVOICE', invoice.payment_request)}
>
<div className={styles.activityTypeIcon}>
<section
className="hint--bottom"
data-hint={`Lightning invoice (${invoice.settled ? 'paid)' : 'unpaid'})`}
data-hint={
invoice.settled
? intl.formatMessage({ ...messages.type_paid })
: intl.formatMessage({ ...messages.type_unpaid })
}
>
<Isvg src={checkmarkIcon} />
</section>
</div>
<div className={styles.data}>
<div className={styles.title}>
<h3>{invoice.settled ? 'Received payment' : 'Requested payment'}</h3>
<h3>
{invoice.settled ? (
<FormattedMessage {...messages.received} />
) : (
<FormattedMessage {...messages.requested} />
)}
</h3>
</div>
<div className={styles.subtitle}>
<Moment format="h:mm a">
{invoice.settled ? invoice.settle_date * 1000 : invoice.creation_date * 1000}
</Moment>
<FormattedTime
value={invoice.settled ? invoice.settle_date * 1000 : invoice.creation_date * 1000}
/>
</div>
</div>
<div
className={`hint--top-left ${styles.amount} ${
invoice.settled ? styles.positive : styles.negative
}`}
data-hint="Invoice amount"
data-hint={intl.formatMessage({ ...messages.amount })}
>
<span>
<i className={styles.plus}>+</i>
@@ -66,4 +79,4 @@ Invoice.propTypes = {
currencyName: PropTypes.string.isRequired
}
export default Invoice
export default injectIntl(Invoice)
@@ -0,0 +1,10 @@
import { defineMessages } from 'react-intl'
/* eslint-disable max-len */
export default defineMessages({
received: 'Received payment',
requested: 'Requested payment',
type_paid: 'Lightning invoice (paid)',
type_unpaid: 'Lightning invoice (unpaid)',
amount: 'Invoice amount'
})
@@ -1,17 +1,18 @@
import React from 'react'
import PropTypes from 'prop-types'
import Moment from 'react-moment'
import QRCode from 'qrcode.react'
import copy from 'copy-to-clipboard'
import { showNotification } from 'lib/utils/notifications'
import FaAngleDown from 'react-icons/lib/fa/angle-down'
import Value from 'components/Value'
import { FormattedDate, FormattedTime, FormattedMessage } from 'react-intl'
import Countdown from '../Countdown'
import messages from './messages'
import styles from './InvoiceModal.scss'
const InvoiceModal = ({
@@ -29,7 +30,7 @@ const InvoiceModal = ({
}) => {
const copyPaymentRequest = () => {
copy(invoice.payment_request)
showNotification('Noice', 'Successfully copied to clipboard')
showNotification('Noice', <FormattedMessage {...messages.copied} />)
}
const countDownDate = parseInt(invoice.creation_date, 10) + parseInt(invoice.expiry, 10)
@@ -38,7 +39,9 @@ const InvoiceModal = ({
<div className={styles.container}>
<div className={styles.content}>
<section className={styles.left}>
<h2>Payment Request</h2>
<h2>
<FormattedMessage {...messages.pay_req} />
</h2>
<QRCode
value={invoice.payment_request}
renderAs="svg"
@@ -80,28 +83,50 @@ const InvoiceModal = ({
</section>
<section className={styles.date}>
<p>
<Moment format="MM/DD/YYYY">{invoice.creation_date * 1000}</Moment>
<FormattedDate
value={invoice.creation_date * 1000}
year="numeric"
month="long"
day="2-digit"
/>{' '}
<FormattedTime value={new Date(invoice.creation_date * 1000)} />
</p>
{!invoice.settled && <p className={styles.notPaid}>Not Paid</p>}
{invoice.settled && <p className={styles.paid}>Paid</p>}
{!invoice.settled && (
<p className={styles.notPaid}>
<FormattedMessage {...messages.not_paid} />
</p>
)}
{invoice.settled && (
<p className={styles.paid}>
<FormattedMessage {...messages.paid} />
</p>
)}
</section>
</div>
<div className={styles.memo}>
<h4>Memo</h4>
<h4>
<FormattedMessage {...messages.memo} />
</h4>
<p>{invoice.memo}</p>
</div>
<div className={styles.request}>
<h4>Request</h4>
<h4>
<FormattedMessage {...messages.request} />
</h4>
<p>{invoice.payment_request}</p>
</div>
</section>
</div>
<div className={styles.actions}>
<div>Save as image</div>
<div onClick={copyPaymentRequest}>Copy Request</div>
<div>
<FormattedMessage {...messages.save} />
</div>
<div onClick={copyPaymentRequest}>
<FormattedMessage {...messages.copy} />
</div>
</div>
</div>
)
@@ -0,0 +1,12 @@
import { defineMessages } from 'react-intl'
/* eslint-disable max-len */
export default defineMessages({
copy: 'Copy Request',
pay_req: 'Payment Request',
memo: 'Memo',
request: 'Request',
save: 'Save as image',
not_paid: 'Not Paid',
paid: 'Paid'
})
Oops, something went wrong.

0 comments on commit aedd1ee

Please sign in to comment.