Commit c4846c88 authored by Justin Domingue's avatar Justin Domingue Committed by GitHub

feat(i18n): improve i18n (#1692)

* replaced i18next with lingui

* integrate lingui in i18n and update dev setup

* updated components to @lingui

* fix compile error after rebase

* detect locale

* add all previous languages to linguirc

* address pr feedback

* remove it for now

* ignore generate *js files, various fixes

* added more translations

* fixed yarn build command

* wrapped more hardcoded english around <Trans>

* finished second round of translations

* added support for pseudo-en locale

* improvements

* moved copy.tsx to different branch

* moved extra files to different branch

* regenerated po

* clean up

* more fixes

* regenerate po

* remove messages.js

* clean up

* addressed pr feedback

* regenerated po
parent dbbffd17
......@@ -3,6 +3,7 @@
# generated contract types
/src/types/v3
/src/abis/types
/src/locales/**/*.js
# dependencies
/node_modules
......
module.exports = {
catalogs: [
{
path: '<rootDir>/src/locales/{locale}/messages',
include: ['<rootDir>'],
exclude: ['**/node_modules/**', '**/build/**'],
},
],
compileNamespace: 'cjs',
fallbackLocales: {
'pseudo-en': 'en',
},
format: 'po',
locales: ['en', 'pseudo-en'],
orderBy: 'messageId',
pseudoLocale: 'pseudo-en',
rootDir: '.',
runtimeConfigModule: ['@lingui/core', 'i18n'],
sourceLocale: 'en',
}
......@@ -6,6 +6,11 @@
"devDependencies": {
"@emotion/core": "^11.0.0",
"@ethersproject/experimental": "^5.2.0",
"@lingui/cli": "^3.9.0",
"@lingui/detect-locale": "^3.9.0",
"@lingui/loader": "^3.9.0",
"@lingui/macro": "^3.9.0",
"@lingui/react": "^3.9.0",
"@metamask/jazzicon": "^2.0.0",
"@popperjs/core": "^2.4.4",
"@reach/dialog": "^0.10.3",
......@@ -24,6 +29,9 @@
"@styled-system/css": "^5.1.5",
"@typechain/ethers-v5": "^7.0.0",
"@types/jest": "^25.2.1",
"@types/lingui__core": "^2.7.1",
"@types/lingui__macro": "^2.7.4",
"@types/lingui__react": "^2.8.3",
"@types/lodash.flatmap": "^4.5.6",
"@types/luxon": "^1.24.4",
"@types/multicodec": "^1.0.0",
......@@ -70,9 +78,6 @@
"eslint-plugin-react": "^7.19.0",
"eslint-plugin-react-hooks": "^4.0.0",
"ethers": "^5.2.0",
"i18next": "^15.0.9",
"i18next-browser-languagedetector": "^3.0.1",
"i18next-xhr-backend": "^2.0.1",
"inter-ui": "^3.13.1",
"lightweight-charts": "^3.3.0",
"lodash.flatmap": "^4.5.0",
......@@ -89,7 +94,6 @@
"react-dom": "^17.0.1",
"react-feather": "^2.0.8",
"react-ga": "^2.5.7",
"react-i18next": "^10.7.0",
"react-markdown": "^4.3.1",
"react-popper": "^2.2.3",
"react-redux": "^7.2.2",
......@@ -123,10 +127,12 @@
"compile-contract-types": "yarn compile-external-abi-types && yarn compile-v3-contract-types",
"compile-external-abi-types": "typechain --target ethers-v5 --out-dir src/abis/types './src/abis/**/*.json'",
"compile-v3-contract-types": "typechain --target ethers-v5 --out-dir src/types/v3 './node_modules/@uniswap/?(v3-core|v3-periphery)/artifacts/contracts/**/*.json'",
"build": "yarn compile-contract-types && react-scripts build",
"build": "yarn compile-contract-types yarn i18n:extract && yarn i18n:compile && react-scripts build",
"i18n:extract": "lingui extract",
"i18n:compile": "lingui compile",
"integration-test": "start-server-and-test 'serve build -l 3000' http://localhost:3000 'cypress run'",
"postinstall": "yarn compile-contract-types",
"start": "yarn compile-contract-types && react-scripts start",
"start": "yarn compile-contract-types && yarn i18n:extract && yarn i18n:compile && react-scripts start",
"storybook": "start-storybook -p 6006",
"test": "react-scripts test --env=jsdom"
},
......
......@@ -4,7 +4,7 @@ import Badge, { BadgeVariant } from 'components/Badge'
import styled from 'styled-components/macro'
import { MouseoverTooltip } from '../../components/Tooltip'
import { useTranslation } from 'react-i18next'
import { Trans, t } from '@lingui/macro'
import { AlertCircle } from 'react-feather'
const BadgeWrapper = styled.div`
......@@ -40,35 +40,51 @@ export default function RangeBadge({
removed: boolean | undefined
inRange: boolean | undefined
}) {
const { t } = useTranslation()
return (
<BadgeWrapper>
{removed ? (
<MouseoverTooltip text={`Your position has 0 liquidity, and is not earning fees.`}>
<MouseoverTooltip
text={t({
id: 'pools.labels.inactiveTooltip',
message: 'Your position has 0 liquidity, and is not earning fees.',
})}
>
<Badge variant={BadgeVariant.DEFAULT}>
<AlertCircle width={14} height={14} />
&nbsp;
<BadgeText>{t('Inactive')}</BadgeText>
<BadgeText>
<Trans id="pools.labels.inactive">Inactive</Trans>
</BadgeText>
</Badge>
</MouseoverTooltip>
) : inRange ? (
<MouseoverTooltip
text={`The price of this pool is within your selected range. Your position is currently earning fees.`}
text={t({
id: 'pools.labels.inRangeTooltip',
message: 'The price of this pool is within your selected range. Your position is currently earning fees.',
})}
>
<Badge variant={BadgeVariant.DEFAULT}>
<ActiveDot /> &nbsp;
<BadgeText>{t('In range')}</BadgeText>
<BadgeText>
<Trans id="pools.labels.inRange">In range</Trans>
</BadgeText>
</Badge>
</MouseoverTooltip>
) : (
<MouseoverTooltip
text={`The price of this pool is outside of your selected range. Your position is not currently earning fees.`}
text={t({
id: 'pools.labels.outOfRangeTooltip',
message:
'The price of this pool is outside of your selected range. Your position is not currently earning fees.',
})}
>
<Badge variant={BadgeVariant.WARNING}>
<AlertCircle width={14} height={14} />
&nbsp;
<BadgeText>{t('Out of range')}</BadgeText>
<BadgeText>
<Trans id="pools.labels.outOfRange">Out of range</Trans>
</BadgeText>
</Badge>
</MouseoverTooltip>
)}
......
......@@ -13,7 +13,7 @@ import { TYPE } from '../../theme'
import { Input as NumericalInput } from '../NumericalInput'
import { ReactComponent as DropDown } from '../../assets/images/dropdown.svg'
import { useActiveWeb3React } from '../../hooks/web3'
import { useTranslation } from 'react-i18next'
import { Trans, t } from '@lingui/macro'
import useTheme from '../../hooks/useTheme'
import { Lock } from 'react-feather'
import { AutoColumn } from 'components/Column'
......@@ -183,8 +183,6 @@ export default function CurrencyInputPanel({
locked = false,
...rest
}: CurrencyInputPanelProps) {
const { t } = useTranslation()
const [modalOpen, setModalOpen] = useState(false)
const { account } = useActiveWeb3React()
const selectedCurrencyBalance = useCurrencyBalance(account ?? undefined, currency ?? undefined)
......@@ -201,7 +199,9 @@ export default function CurrencyInputPanel({
<AutoColumn gap="sm" justify="center">
<Lock />
<TYPE.label fontSize="12px" textAlign="center">
<Trans id="currencies.input.priceOutsideWarning">
The market price is outside your specified price range. Single-asset deposit only.
</Trans>
</TYPE.label>
</AutoColumn>
</FixedContainer>
......@@ -237,7 +237,7 @@ export default function CurrencyInputPanel({
? currency.symbol.slice(0, 4) +
'...' +
currency.symbol.slice(currency.symbol.length - 5, currency.symbol.length)
: currency?.symbol) || t('selectToken')}
: currency?.symbol) || t({ id: 'currencies.search.selectToken', message: 'Select a token' })}
</StyledTokenName>
)}
</RowFixed>
......@@ -276,7 +276,9 @@ export default function CurrencyInputPanel({
: ''}
</TYPE.body>
{showMaxButton && selectedCurrencyBalance ? (
<StyledBalanceMax onClick={onMax}>(Max)</StyledBalanceMax>
<StyledBalanceMax onClick={onMax}>
<Trans id="currencies.input.max">(Max)</Trans>
</StyledBalanceMax>
) : null}
</RowFixed>
) : (
......
import React from 'react'
import { FeeAmount } from '@uniswap/v3-sdk'
import { useTranslation } from 'react-i18next'
import { t } from '@lingui/macro'
import { AutoColumn } from 'components/Column'
import { DynamicSection } from 'pages/AddLiquidity/styled'
import { TYPE } from 'theme'
......@@ -23,14 +23,15 @@ export default function FeeSelector({
feeAmount?: FeeAmount
handleFeePoolSelect: (feeAmount: FeeAmount) => void
}) {
const { t } = useTranslation()
return (
<AutoColumn gap="16px">
<DynamicSection gap="md" disabled={disabled}>
<TYPE.label>{t('selectPool')}</TYPE.label>
<TYPE.label>{t({ id: 'pools.feeSelector.title', message: 'Select Pool' })}</TYPE.label>
<TYPE.main fontSize={14} fontWeight={400} style={{ marginBottom: '.5rem', lineHeight: '125%' }}>
Select a pool type based on your preferred liquidity provider fee.
{t({
id: 'pools.feeSelector.subtitle',
message: 'Select a pool type based on your preferred liquidity provider fee.',
})}
</TYPE.main>
<RowBetween>
<ButtonRadioChecked
......@@ -39,9 +40,9 @@ export default function FeeSelector({
onClick={() => handleFeePoolSelect(FeeAmount.LOW)}
>
<AutoColumn gap="sm" justify="flex-start">
<ResponsiveText>0.05% {t('fee')}</ResponsiveText>
<ResponsiveText>{t({ id: 'pools.feeSelector.lowFee', message: `0.05% fee` })}</ResponsiveText>
<TYPE.main fontWeight={400} fontSize="12px" textAlign="left">
Best for stable pairs.
{t({ id: 'pools.feeSelector.lowFeeHint', message: 'Best for stable pairs.' })}
</TYPE.main>
</AutoColumn>
</ButtonRadioChecked>
......@@ -51,9 +52,9 @@ export default function FeeSelector({
onClick={() => handleFeePoolSelect(FeeAmount.MEDIUM)}
>
<AutoColumn gap="sm" justify="flex-start">
<ResponsiveText>0.3% {t('fee')}</ResponsiveText>
<ResponsiveText>{t({ id: 'pools.feeSelector.mediumFee', message: `0.3% fee` })}</ResponsiveText>
<TYPE.main fontWeight={400} fontSize="12px" textAlign="left">
Best for most pairs.
{t({ id: 'pools.feeSelector.mediumFeeHint', message: 'Best for most pairs.' })}
</TYPE.main>
</AutoColumn>
</ButtonRadioChecked>
......@@ -63,9 +64,9 @@ export default function FeeSelector({
onClick={() => handleFeePoolSelect(FeeAmount.HIGH)}
>
<AutoColumn gap="sm" justify="flex-start">
<ResponsiveText>1% {t('fee')}</ResponsiveText>
<ResponsiveText>{t({ id: 'pools.feeSelector.highFee', message: '1% fee' })}</ResponsiveText>
<TYPE.main fontWeight={400} fontSize="12px" textAlign="left">
Best for exotic pairs.
{t({ id: 'pools.feeSelector.highFeeHint', message: 'Best for exotic pairs.' })}
</TYPE.main>
</AutoColumn>
</ButtonRadioChecked>
......
......@@ -3,7 +3,7 @@ import React, { useState } from 'react'
import { Text } from 'rebass'
import { NavLink } from 'react-router-dom'
import { darken } from 'polished'
import { useTranslation } from 'react-i18next'
import { Trans } from '@lingui/macro'
import { Moon, Sun } from 'react-feather'
import styled from 'styled-components/macro'
......@@ -309,7 +309,6 @@ const NETWORK_LABELS: { [chainId: number]: string } = {
export default function Header() {
const { account, chainId } = useActiveWeb3React()
const { t } = useTranslation()
const userEthBalance = useETHBalances(account ? [account] : [])?.[account ?? '']
// const [isDark] = useDarkModeManager()
......@@ -341,7 +340,7 @@ export default function Header() {
</HeaderRow>
<HeaderLinks>
<StyledNavLink id={`swap-nav-link`} to={'/swap'}>
{t('swap')}
<Trans id="nav.swap">Swap</Trans>
</StyledNavLink>
<StyledNavLink
id={`pool-nav-link`}
......@@ -354,13 +353,15 @@ export default function Header() {
pathname.startsWith('/find')
}
>
{t('pool')}
<Trans id="nav.pool">Pool</Trans>
</StyledNavLink>
<StyledNavLink id={`stake-nav-link`} to={'/vote'}>
Vote
<Trans id="nav.vote">Vote</Trans>
</StyledNavLink>
<StyledExternalLink id={`stake-nav-link`} href={'https://info.uniswap.org'}>
<Trans id="nav.charts">
Charts <span style={{ fontSize: '11px', textDecoration: 'none !important' }}></span>
</Trans>
</StyledExternalLink>
</HeaderLinks>
<HeaderControls>
......@@ -374,7 +375,13 @@ export default function Header() {
<UNIWrapper onClick={toggleClaimModal}>
<UNIAmount active={!!account && !availableClaim} style={{ pointerEvents: 'auto' }}>
<TYPE.white padding="0 2px">
{claimTxn && !claimTxn?.receipt ? <Dots>Claiming UNI</Dots> : 'Claim UNI'}
{claimTxn && !claimTxn?.receipt ? (
<Dots>
<Trans id="claim.buttons.claimingUNI">Claiming UNI</Trans>
</Dots>
) : (
<Trans id="claim.buttons.claimUNI">Claim UNI</Trans>
)}
</TYPE.white>
</UNIAmount>
<CardNoise />
......@@ -383,7 +390,7 @@ export default function Header() {
<AccountElement active={!!account} style={{ pointerEvents: 'auto' }}>
{account && userEthBalance ? (
<BalanceText style={{ flexShrink: 0 }} pl="0.75rem" pr="0.5rem" fontWeight={500}>
{userEthBalance?.toSignificant(4)} ETH
<Trans id="wallet.ethBalance">{userEthBalance?.toSignificant(4)} ETH</Trans>
</BalanceText>
) : null}
<Web3Status />
......
import React from 'react'
import styled from 'styled-components/macro'
import { darken } from 'polished'
import { useTranslation } from 'react-i18next'
import { Trans } from '@lingui/macro'
import { NavLink, Link as HistoryLink } from 'react-router-dom'
import { Percent } from '@uniswap/sdk-core'
......@@ -60,14 +60,13 @@ const StyledArrowLeft = styled(ArrowLeft)`
`
export function SwapPoolTabs({ active }: { active: 'swap' | 'pool' }) {
const { t } = useTranslation()
return (
<Tabs style={{ marginBottom: '20px', display: 'none', padding: '1rem 1rem 0 1rem' }}>
<StyledNavLink id={`swap-nav-link`} to={'/swap'} isActive={() => active === 'swap'}>
{t('swap')}
<Trans id="nav.swap">Swap</Trans>
</StyledNavLink>
<StyledNavLink id={`pool-nav-link`} to={'/pool'} isActive={() => active === 'pool'}>
{t('pool')}
<Trans id="nav.pool">Pool</Trans>
</StyledNavLink>
</Tabs>
)
......@@ -80,7 +79,9 @@ export function FindPoolTabs({ origin }: { origin: string }) {
<HistoryLink to={origin}>
<StyledArrowLeft />
</HistoryLink>
<ActiveText>Import Pool</ActiveText>
<ActiveText>
<Trans id="nav.importPool">Import Pool</Trans>
</ActiveText>
</RowBetween>
</Tabs>
)
......@@ -118,7 +119,13 @@ export function AddRemoveTabs({
<StyledArrowLeft stroke={theme.text2} />
</HistoryLink>
<TYPE.mediumHeader fontWeight={500} fontSize={20}>
{creating ? 'Create a pair' : adding ? 'Add Liquidity' : 'Remove Liquidity'}
{creating ? (
<Trans id="pools.buttons.createPair">Create a pair</Trans>
) : adding ? (
<Trans id="pools.buttons.addLiquidity">Add Liquidity</Trans>
) : (
<Trans id="pools.buttons.removeLiquidity">Remove Liquidity</Trans>
)}
</TYPE.mediumHeader>
<SettingsTab placeholderSlippage={defaultSlippage} />
</RowBetween>
......
import PositionListItem from 'components/PositionListItem'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { Trans } from '@lingui/macro'
import styled from 'styled-components/macro'
import { MEDIA_WIDTHS } from 'theme'
import { PositionDetails } from 'types/position'
......@@ -39,18 +39,20 @@ export type PositionListProps = React.PropsWithChildren<{
}>
export default function PositionList({ positions }: PositionListProps) {
const { t } = useTranslation()
return (
<>
<DesktopHeader>
<div>
{t('Your positions')}
<Trans id="pool.yourPositions">Your positions</Trans>
{positions && ' (' + positions.length + ')'}
</div>
<div>{t('Price range')}</div>
<div>
<Trans id="pool.priceRange">Price range</Trans>
</div>
</DesktopHeader>
<MobileHeader>Your positions</MobileHeader>
<MobileHeader>
<Trans id="pool.yourPositions">Your positions</Trans>
</MobileHeader>
{positions.map((p) => {
return <PositionListItem key={p.tokenId.toString()} positionDetails={p} />
})}
......
......@@ -7,7 +7,7 @@ import { RowBetween, RowFixed } from 'components/Row'
import CurrencyLogo from 'components/CurrencyLogo'
import { unwrappedToken } from 'utils/unwrappedToken'
import { Break } from 'components/earn/styled'
import { useTranslation } from 'react-i18next'
import { Trans } from '@lingui/macro'
import { Currency } from '@uniswap/sdk-core'
import RateToggle from 'components/RateToggle'
import DoubleCurrencyLogo from 'components/DoubleLogo'
......@@ -26,8 +26,6 @@ export const PositionPreview = ({
inRange: boolean
baseCurrencyDefault?: Currency | undefined
}) => {
const { t } = useTranslation()
const theme = useContext(ThemeContext)
const currency0 = unwrappedToken(position.pool.token0)
......@@ -97,8 +95,12 @@ export const PositionPreview = ({
</RowBetween>
<Break />
<RowBetween>
<TYPE.label>{t('feeTier')}</TYPE.label>
<TYPE.label>{position?.pool?.fee / 10000}%</TYPE.label>
<TYPE.label>
<Trans id="pools.labels.feeTier">Fee Tier</Trans>
</TYPE.label>
<TYPE.label>
<Trans id="pools.labels.feeTierValue">{position?.pool?.fee / 10000}%</Trans>
</TYPE.label>
</RowBetween>
</AutoColumn>
</LightCard>
......@@ -116,40 +118,53 @@ export const PositionPreview = ({
<RowBetween>
<LightCard width="48%" padding="8px">
<AutoColumn gap="4px" justify="center">
<TYPE.main fontSize="12px">Min Price</TYPE.main>
<TYPE.main fontSize="12px">
<Trans id="pools.minPriceLabel">Min Price</Trans>
</TYPE.main>
<TYPE.mediumHeader textAlign="center">{`${priceLower.toSignificant(5)}`}</TYPE.mediumHeader>
<TYPE.main
textAlign="center"
fontSize="12px"
>{` ${quoteCurrency.symbol}/${baseCurrency.symbol}`}</TYPE.main>
<TYPE.main textAlign="center" fontSize="12px">
<Trans id="currencies.denominated">
{quoteCurrency.symbol} per {baseCurrency.symbol}
</Trans>
</TYPE.main>
<TYPE.small textAlign="center" color={theme.text3} style={{ marginTop: '4px' }}>
<Trans id="pools.minMaxPriceHint">
Your position will be 100% composed of {baseCurrency?.symbol} at this price
</Trans>
</TYPE.small>
</AutoColumn>
</LightCard>
<LightCard width="48%" padding="8px">
<AutoColumn gap="4px" justify="center">
<TYPE.main fontSize="12px">Max Price</TYPE.main>
<TYPE.main fontSize="12px">
<Trans id="pools.maxPrice">Max Price</Trans>
</TYPE.main>
<TYPE.mediumHeader textAlign="center">{`${priceUpper.toSignificant(5)}`}</TYPE.mediumHeader>
<TYPE.main
textAlign="center"
fontSize="12px"
>{` ${quoteCurrency.symbol} per ${baseCurrency.symbol}`}</TYPE.main>
<TYPE.main textAlign="center" fontSize="12px">
<Trans id="currencies.denominated">
{quoteCurrency.symbol} per {baseCurrency.symbol}
</Trans>
</TYPE.main>
<TYPE.small textAlign="center" color={theme.text3} style={{ marginTop: '4px' }}>
<Trans id="pools.minMaxPriceHint">
Your position will be 100% composed of {quoteCurrency?.symbol} at this price
</Trans>
</TYPE.small>
</AutoColumn>
</LightCard>
</RowBetween>
<LightCard padding="12px ">
<AutoColumn gap="4px" justify="center">
<TYPE.main fontSize="12px">Current price</TYPE.main>
<TYPE.main fontSize="12px">
<Trans id="pools.currentPrice">Current price</Trans>
</TYPE.main>
<TYPE.mediumHeader>{`${price.toSignificant(5)} `}</TYPE.mediumHeader>
<TYPE.main
textAlign="center"
fontSize="12px"
>{` ${quoteCurrency.symbol} per ${baseCurrency.symbol}`}</TYPE.main>
<TYPE.main textAlign="center" fontSize="12px">
<Trans id="currencies.denominated">
{quoteCurrency.symbol} per {baseCurrency.symbol}
</Trans>
</TYPE.main>
</AutoColumn>
</LightCard>
</AutoColumn>
......
import { Currency, Ether, Token } from '@uniswap/sdk-core'
import React, { KeyboardEvent, RefObject, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import ReactGA from 'react-ga'
import { useTranslation } from 'react-i18next'
import { t, Trans } from '@lingui/macro'
import { FixedSizeList } from 'react-window'
import { Text } from 'rebass'
import { useActiveWeb3React } from '../../hooks/web3'
......@@ -63,7 +63,6 @@ export function CurrencySearch({
showImportView,
setImportToken,
}: CurrencySearchProps) {
const { t } = useTranslation()
const { chainId } = useActiveWeb3React()
const theme = useTheme()
......@@ -172,7 +171,7 @@ export function CurrencySearch({
<PaddedColumn gap="16px">
<RowBetween>
<Text fontWeight={500} fontSize={16}>
Select a token
<Trans id="currencies.search.selectToken">Select a token</Trans>
</Text>
<CloseIcon onClick={onDismiss} />
</RowBetween>
......@@ -180,7 +179,7 @@ export function CurrencySearch({
<SearchInput
type="text"
id="token-search-input"
placeholder={t('tokenSearchPlaceholder')}
placeholder={t({ id: 'currencies.search.placeholder', message: 'Search name or paste address' })}
autoComplete="off"
value={searchQuery}
ref={inputRef as RefObject<HTMLInputElement>}
......@@ -218,7 +217,7 @@ export function CurrencySearch({
) : (
<Column style={{ padding: '20px', height: '100%' }}>
<TYPE.main color={theme.text3} textAlign="center" mb="20px">
No results found.
<Trans id="currencies.search.noResults">No results found.</Trans>
</TYPE.main>
</Column>
)}
......@@ -229,7 +228,9 @@ export function CurrencySearch({
<IconWrapper size="16px" marginRight="6px">
<Edit />
</IconWrapper>
<TYPE.main color={theme.blue1}>Manage Token Lists</TYPE.main>
<TYPE.main color={theme.blue1}>
<Trans id="tokenLists.manage">Manage Token Lists</Trans>
</TYPE.main>
</RowFixed>
</ButtonText>
</Row>
......
......@@ -20,6 +20,7 @@ import { useFetchListCallback } from 'hooks/useFetchListCallback'
import { removeList, enableList } from 'state/lists/actions'
import { CurrencyModalView } from './CurrencySearchModal'
import { useAllLists } from 'state/lists/hooks'
import { Trans } from '@lingui/macro'
const Wrapper = styled.div`
position: relative;
......@@ -80,7 +81,9 @@ export function ImportList({ listURL, list, setModalView, onDismiss }: ImportPro
<PaddedColumn gap="14px" style={{ width: '100%', flex: '1 1' }}>
<RowBetween>
<ArrowLeft style={{ cursor: 'pointer' }} onClick={() => setModalView(CurrencyModalView.manage)} />
<TYPE.mediumHeader>Import List</TYPE.mediumHeader>
<TYPE.mediumHeader>
<Trans id="tokenLists.importList">Import List</Trans>
</TYPE.mediumHeader>
<CloseIcon onClick={onDismiss} />
</RowBetween>
</PaddedColumn>
......@@ -98,7 +101,7 @@ export function ImportList({ listURL, list, setModalView, onDismiss }: ImportPro
</TYPE.body>
<TextDot />
<TYPE.main fontSize={'16px'} ml="6px">
{list.tokens.length} tokens
<Trans id="tokensLists.numberOfTokens">{list.tokens.length} tokens</Trans>
</TYPE.main>
</RowFixed>
<ExternalLink href={`https://tokenlists.org/token-list?url=${listURL}`}>
......@@ -114,18 +117,22 @@ export function ImportList({ listURL, list, setModalView, onDismiss }: ImportPro
<AutoColumn justify="center" style={{ textAlign: 'center', gap: '16px', marginBottom: '12px' }}>
<AlertTriangle stroke={theme.red1} size={32} />
<TYPE.body fontWeight={500} fontSize={20} color={theme.red1}>
Import at your own risk{' '}
<Trans id="tokenLists.importWarning">Import at your own risk</Trans>
</TYPE.body>
</AutoColumn>
<AutoColumn style={{ textAlign: 'center', gap: '16px', marginBottom: '12px' }}>
<TYPE.body fontWeight={500} color={theme.red1}>
<Trans id="tokenLists.importHint1">
By adding this list you are implicitly trusting that the data is correct. Anyone can create a list,
including creating fake versions of existing lists and lists that claim to represent projects that do
not have one.
</Trans>
</TYPE.body>
<TYPE.body fontWeight={600} color={theme.red1}>
<Trans id="tokenLists.importHint2">
If you purchase a token from this list, you may not be able to sell it back.
</Trans>
</TYPE.body>
</AutoColumn>
<AutoRow justify="center" style={{ cursor: 'pointer' }} onClick={() => setConfirmed(!confirmed)}>
......@@ -136,7 +143,7 @@ export function ImportList({ listURL, list, setModalView, onDismiss }: ImportPro
onChange={() => setConfirmed(!confirmed)}
/>
<TYPE.body ml="10px" fontSize="16px" color={theme.red1} fontWeight={500}>
I understand
<Trans id="common.IUnderstand">I understand</Trans>
</TYPE.body>
</AutoRow>
</Card>
......@@ -148,7 +155,7 @@ export function ImportList({ listURL, list, setModalView, onDismiss }: ImportPro
padding="10px 1rem"
onClick={handleAddList}
>
Import
<Trans id="tokenLists.buttons.import">Import</Trans>
</ButtonPrimary>
{addError ? (
<TYPE.error title={addError} style={{ textOverflow: 'ellipsis', overflow: 'hidden' }} error>
......
import React, { useState, useEffect } from 'react'
import { useWeb3React } from '@web3-react/core'
import styled from 'styled-components/macro'
import { useTranslation } from 'react-i18next'
import { Trans } from '@lingui/macro'
import { network } from '../../connectors'
import { useEagerConnect, useInactiveListener } from '../../hooks/web3'
......@@ -20,7 +20,6 @@ const Message = styled.h2`
`
export default function Web3ReactManager({ children }: { children: JSX.Element }) {
const { t } = useTranslation()
const { active } = useWeb3React()
const { active: networkActive, error: networkError, activate: activateNetwork } = useWeb3React(NetworkContextName)
......@@ -58,7 +57,11 @@ export default function Web3ReactManager({ children }: { children: JSX.Element }
if (!active && networkError) {
return (
<MessageWrapper>
<Message>{t('unknownError')}</Message>
<Message>
<Trans id="errors.unknown">
Oops! An unknown error occurred. Please refresh the page, or visit from another browser or device.
</Trans>
</Message>
</MessageWrapper>
)
}
......
......@@ -3,7 +3,7 @@ import { UnsupportedChainIdError, useWeb3React } from '@web3-react/core'
import { darken, lighten } from 'polished'
import React, { useMemo } from 'react'
import { Activity } from 'react-feather'
import { useTranslation } from 'react-i18next'
import { t, Trans } from '@lingui/macro'
import styled, { css } from 'styled-components'
import CoinbaseWalletIcon from '../../assets/images/coinbaseWalletIcon.svg'
import FortmaticIcon from '../../assets/images/fortmaticIcon.png'
......@@ -136,25 +136,25 @@ function StatusIcon({ connector }: { connector: AbstractConnector }) {
} else if (connector === walletconnect) {
return (
<IconWrapper size={16}>
<img src={WalletConnectIcon} alt={''} />
<img src={WalletConnectIcon} alt={'WalletConnect'} />
</IconWrapper>
)
} else if (connector === walletlink) {
return (
<IconWrapper size={16}>
<img src={CoinbaseWalletIcon} alt={''} />
<img src={CoinbaseWalletIcon} alt={'CoinbaseWallet'} />
</IconWrapper>
)
} else if (connector === fortmatic) {
return (
<IconWrapper size={16}>
<img src={FortmaticIcon} alt={''} />
<img src={FortmaticIcon} alt={'Fortmatic'} />
</IconWrapper>
)
} else if (connector === portis) {
return (
<IconWrapper size={16}>
<img src={PortisIcon} alt={''} />
<img src={PortisIcon} alt={'Portis'} />
</IconWrapper>
)
}
......@@ -162,7 +162,6 @@ function StatusIcon({ connector }: { connector: AbstractConnector }) {
}
function Web3StatusInner() {
const { t } = useTranslation()
const { account, connector, error } = useWeb3React()
const { ENSName } = useENSName(account ?? undefined)
......@@ -185,7 +184,10 @@ function Web3StatusInner() {
<Web3StatusConnected id="web3-status-connected" onClick={toggleWalletModal} pending={hasPendingTransactions}>
{hasPendingTransactions ? (
<RowBetween>
<Text>{pending?.length} Pending</Text> <Loader stroke="white" />
<Text>
<Trans id="transactions.pending">{pending?.length} Pending</Trans>
</Text>{' '}
<Loader stroke="white" />
</RowBetween>
) : (
<>
......@@ -200,13 +202,19 @@ function Web3StatusInner() {
return (
<Web3StatusError onClick={toggleWalletModal}>
<NetworkIcon />
<Text>{error instanceof UnsupportedChainIdError ? 'Wrong Network' : 'Error'}</Text>
<Text>
{error instanceof UnsupportedChainIdError
? t({ id: 'error.wrongNetwork', message: 'Wrong Network' })
: t({ id: 'error.generic', message: 'Error' })}
</Text>
</Web3StatusError>
)
} else {
return (
<Web3StatusConnect id="connect-wallet" onClick={toggleWalletModal} faded={!account}>
<Text>{t('Connect to a wallet')}</Text>
<Text>
<Trans id="wallet.connectLongForm">Connect to a wallet</Trans>
</Text>
</Web3StatusConnect>
)
}
......
import i18next from 'i18next'
import { initReactI18next } from 'react-i18next'
import XHR from 'i18next-xhr-backend'
import LanguageDetector from 'i18next-browser-languagedetector'
i18next
.use(XHR)
.use(LanguageDetector)
.use(initReactI18next)
.init({
backend: {
loadPath: `./locales/{{lng}}.json`,
},
react: {
useSuspense: true,
},
fallbackLng: 'en',
preload: ['en'],
keySeparator: false,
interpolation: { escapeValue: false },
})
export default i18next
import React from 'react'
import { i18n } from '@lingui/core'
import { I18nProvider } from '@lingui/react'
import { detect, fromUrl } from '@lingui/detect-locale'
import { ReactNode, useEffect } from 'react'
export const locales = ['en', 'pseudo-en']
export const defaultLocale = 'en'
// load locale data for each supported language
locales.forEach((locale) => i18n.loadLocaleData(locale, { plurals: () => null }))
const getDetectedLocale = () => {
const detected =
detect(
fromUrl('lang'), // helps local development
defaultLocale
) ?? defaultLocale
return locales.includes(detected) ? detected : defaultLocale
}
export async function dynamicActivate(locale: string) {
const { messages } = await import(`@lingui/loader!./locales/${locale}/messages.po`)
i18n.load(locale, messages)
i18n.activate(locale)
}
export function LanguageProvider({ children }: { children: ReactNode }) {
useEffect(() => {
dynamicActivate(getDetectedLocale())
}, [])
return <I18nProvider i18n={i18n}>{children}</I18nProvider>
}
......@@ -8,7 +8,7 @@ import { Provider } from 'react-redux'
import { HashRouter } from 'react-router-dom'
import Blocklist from './components/Blocklist'
import { NetworkContextName } from './constants/misc'
import './i18n'
import { LanguageProvider } from './i18n'
import App from './pages/App'
import store from './state'
import * as serviceWorkerRegistration from './serviceWorkerRegistration'
......@@ -60,6 +60,7 @@ function Updaters() {
ReactDOM.render(
<StrictMode>
<LanguageProvider>
<FixedGlobalStyle />
<Web3ReactProvider getLibrary={getLibrary}>
<Web3ProviderNetwork getLibrary={getLibrary}>
......@@ -76,6 +77,7 @@ ReactDOM.render(
</Blocklist>
</Web3ProviderNetwork>
</Web3ReactProvider>
</LanguageProvider>
</StrictMode>,
document.getElementById('root')
)
......
This diff is collapsed.
This diff is collapsed.
......@@ -38,7 +38,7 @@ import { Dots } from '../Pool/styleds'
import { currencyId } from '../../utils/currencyId'
import UnsupportedCurrencyFooter from 'components/swap/UnsupportedCurrencyFooter'
import { DynamicSection, CurrencyDropdown, StyledInput, Wrapper, ScrollablePage } from './styled'
import { useTranslation } from 'react-i18next'
import { Trans, t } from '@lingui/macro'
import {
useV3MintState,
useV3MintActionHandlers,
......@@ -64,8 +64,6 @@ export default function AddLiquidity({
},
history,
}: RouteComponentProps<{ currencyIdA?: string; currencyIdB?: string; feeAmount?: string; tokenId?: string }>) {
const { t } = useTranslation()
const { account, chainId, library } = useActiveWeb3React()
const theme = useContext(ThemeContext)
const toggleWalletModal = useWalletModalToggle() // toggle wallet when disconnected
......@@ -261,8 +259,14 @@ export default function AddLiquidity({
setAttemptingTxn(false)
addTransaction(response, {
summary: noLiquidity
? `Create pool and add ${currencyA?.symbol}/${currencyB?.symbol} V3 liquidity`
: `Add ${currencyA?.symbol}/${currencyB?.symbol} V3 liquidity`,
? t({
id: 'transactions.summary.createPoolAndAddLiquidity',
message: `Create pool and add ${currencyA?.symbol}/${currencyB?.symbol} V3 liquidity`,
})
: t({
id: 'transactions.summary.addLiquidity',
message: `Add ${currencyA?.symbol}/${currencyB?.symbol} V3 liquidity`,
}),
})
setTxHash(response.hash)
ReactGA.event({
......@@ -410,7 +414,7 @@ export default function AddLiquidity({
bottomContent={() => (
<ButtonPrimary style={{ marginTop: '1rem' }} onClick={onAdd}>
<Text fontWeight={500} fontSize={20}>
Add
<Trans id="transactions.confirmation.button">Add</Trans>
</Text>
</ButtonPrimary>
)}
......@@ -431,9 +435,13 @@ export default function AddLiquidity({
<>
<AutoColumn gap="md">
<RowBetween paddingBottom="20px">
<TYPE.label>Select pair</TYPE.label>
<TYPE.label>
<Trans id="addLiquidity.labels.selectPair">Select pair</Trans>
</TYPE.label>
<ButtonText onClick={clearAll}>
<TYPE.blue fontSize="12px">Clear All</TYPE.blue>
<TYPE.blue fontSize="12px">
<Trans id="common.clearAll">Clear All</Trans>
</TYPE.blue>
</ButtonText>
</RowBetween>
<RowBetween>
......@@ -471,7 +479,11 @@ export default function AddLiquidity({
)}
{hasExistingPosition && existingPosition ? (
<PositionPreview position={existingPosition} title={'Selected Range'} inRange={!outOfRange} />
<PositionPreview
position={existingPosition}
title={t({ id: 'addLiquidity.labels.selectedRange', message: 'Selected Range' })}
inRange={!outOfRange}
/>
) : (
<>
<FeeSelector
......@@ -484,7 +496,9 @@ export default function AddLiquidity({
<DynamicSection disabled={!currencyA || !currencyB}>
<AutoColumn gap="md">
<RowBetween>
<TYPE.label>{t('selectStartingPrice')}</TYPE.label>
<TYPE.label>
<Trans id="addLiquidity.labels.selectStartingPrice">Set Starting Price</Trans>
</TYPE.label>
{baseCurrency && quoteCurrency ? (
<RateToggle
currencyA={baseCurrency}
......@@ -510,7 +524,9 @@ export default function AddLiquidity({
/>
</OutlineCard>
<RowBetween style={{ backgroundColor: theme.bg1, padding: '12px', borderRadius: '12px' }}>
<TYPE.main>Current {baseCurrency?.symbol} Price:</TYPE.main>
<TYPE.main>
<Trans id="addLiquidity.labels.currentPrice">Current {baseCurrency?.symbol} Price:</Trans>
</TYPE.main>
<TYPE.main>
{price ? (
<TYPE.main>
......@@ -554,7 +570,9 @@ export default function AddLiquidity({
<DynamicSection gap="md" disabled={!feeAmount || invalidPool || (noLiquidity && !startPriceTypedValue)}>
<RowBetween>
<TYPE.label>{t('selectLiquidityRange')}</TYPE.label>
<TYPE.label>
<Trans id="addLiquidity.labels.selectLiquidityRange">Set Price Range</Trans>
</TYPE.label>
{baseCurrency && quoteCurrency ? (
<RateToggle
......@@ -619,7 +637,10 @@ export default function AddLiquidity({
<RowBetween>
<AlertTriangle stroke={theme.yellow3} size="16px" />
<TYPE.yellow ml="12px" fontSize="12px">
{t('inactiveRangeWarning')}
<Trans id="inactiveRangeWarning">
Your position will not earn fees or be used in trades until the market price moves into your
range.
</Trans>
</TYPE.yellow>
</RowBetween>
</YellowCard>
......@@ -630,7 +651,9 @@ export default function AddLiquidity({
<RowBetween>
<AlertTriangle stroke={theme.yellow3} size="16px" />
<TYPE.yellow ml="12px" fontSize="12px">
{t('invalidRangeWarning')}
<Trans id="error.invalidRangeWarning">
Invalid range selected. The min price must be lower than the max price.
</Trans>
</TYPE.yellow>
</RowBetween>
</YellowCard>
......@@ -643,7 +666,11 @@ export default function AddLiquidity({
disabled={tickLower === undefined || tickUpper === undefined || invalidPool || invalidRange}
>
<AutoColumn gap="md">
<TYPE.label>{hasExistingPosition ? 'Add more liquidity' : t('depositAmounts')}</TYPE.label>
<TYPE.label>
{hasExistingPosition
? 'Add more liquidity'
: t({ id: 'liquidity.depositAmounts', message: 'Deposit Amounts' })}
</TYPE.label>
<CurrencyInputPanel
value={formattedAmounts[Field.CURRENCY_A]}
......@@ -677,11 +704,13 @@ export default function AddLiquidity({
<div>
{addIsUnsupported ? (
<ButtonPrimary disabled={true} borderRadius="12px" padding={'12px'}>
<TYPE.main mb="4px">{t('unsupportedAsset')}</TYPE.main>
<TYPE.main mb="4px">
<Trans id="error.unsupportedAsset">Unsupported Asset</Trans>
</TYPE.main>
</ButtonPrimary>
) : !account ? (
<ButtonLight onClick={toggleWalletModal} borderRadius="12px" padding={'12px'}>
{t('connectWallet')}
<Trans id="wallet.connect">Connect wallet</Trans>
</ButtonLight>
) : (
<AutoColumn gap={'md'}>
......
This diff is collapsed.
import React from 'react'
import styled from 'styled-components/macro'
import { TYPE } from 'theme'
import { useTranslation } from 'react-i18next'
import { Trans } from '@lingui/macro'
import { ExternalLink } from '../../theme'
import { AutoColumn } from 'components/Column'
import Squiggle from '../../assets/images/squiggle.png'
......@@ -118,29 +118,31 @@ const StyledImage = styled.img`
`
export default function CTACards() {
const { t } = useTranslation()
return (
<CTASection>
<CTA1 href={'https://docs.uniswap.org/concepts/introduction/liquidity-user-guide'}>
<ResponsiveColumn>
<HeaderText>{t('Uniswap V3 is here!')}</HeaderText>
<HeaderText>
<Trans id="cta.v3.launchAnnouncement">Uniswap V3 is here!</Trans>
</HeaderText>
<TYPE.body fontWeight={300} style={{ alignItems: 'center', display: 'flex', maxWidth: '80%' }}>
{t('Check out our v3 LP walkthrough and migration guides.')}
<Trans id="cta.v3.walkthroughAndMigration">Check out our v3 LP walkthrough and migration guides.</Trans>
</TYPE.body>
<RowBetween align="flex-end">
<HeaderText>{t('')}</HeaderText>
<HeaderText></HeaderText>
<StyledImage src={Squiggle} />
</RowBetween>
</ResponsiveColumn>
</CTA1>
<CTA2 href={'https://info.uniswap.org/#/pools'}>
<ResponsiveColumn>
<HeaderText style={{ alignSelf: 'flex-start' }}>{t('Top pools')}</HeaderText>
<HeaderText style={{ alignSelf: 'flex-start' }}>
<Trans id="cta.topPools">Top pools</Trans>
</HeaderText>
<TYPE.body fontWeight={300} style={{ alignSelf: 'flex-start' }}>
{t('Explore popular pools on Uniswap Analytics.')}
<Trans id="cta.v3.explore">Explore popular pools on Uniswap Analytics.</Trans>
</TYPE.body>
<HeaderText style={{ alignSelf: 'flex-end' }}>{t('')}</HeaderText>
<HeaderText style={{ alignSelf: 'flex-end' }}></HeaderText>
</ResponsiveColumn>
</CTA2>
</CTASection>
......
This diff is collapsed.
......@@ -8,7 +8,7 @@ import { RowBetween, RowFixed } from 'components/Row'
import { useActiveWeb3React } from 'hooks/web3'
import { useV3Positions } from 'hooks/useV3Positions'
import { BookOpen, ChevronDown, Download, Inbox, PlusCircle, ChevronsRight, Layers } from 'react-feather'
import { useTranslation } from 'react-i18next'
import { Trans } from '@lingui/macro'
import { Link } from 'react-router-dom'
import { useWalletModalToggle } from 'state/application/hooks'
import styled, { ThemeContext } from 'styled-components'
......@@ -108,7 +108,7 @@ const ShowInactiveToggle = styled.div`
export default function Pool() {
const { account } = useActiveWeb3React()
const toggleWalletModal = useWalletModalToggle()
const { t } = useTranslation()
const theme = useContext(ThemeContext)
const [userHideClosedPositions, setUserHideClosedPositions] = useUserHideClosedPositions()
......@@ -129,7 +129,7 @@ export default function Pool() {
content: (
<MenuItem>
<PlusCircle size={16} style={{ marginRight: '12px' }} />
{t('Create a pool')}
<Trans id="pools.menu.create">Create a pool</Trans>
</MenuItem>
),
link: '/add/ETH',
......@@ -139,7 +139,7 @@ export default function Pool() {
content: (
<MenuItem>
<ChevronsRight size={16} style={{ marginRight: '12px' }} />
{t('Migrate')}
<Trans id="pools.menu.migrate">Migrate</Trans>
</MenuItem>
),
link: '/migrate/v2',
......@@ -149,7 +149,7 @@ export default function Pool() {
content: (
<MenuItem>
<Layers size={16} style={{ marginRight: '12px' }} />
{t('V2 liquidity')}
<Trans id="pools.menu.v2Liquidity">V2 liquidity</Trans>
</MenuItem>
),
link: '/pool/v2',
......@@ -159,7 +159,7 @@ export default function Pool() {
content: (
<MenuItem>
<BookOpen size={16} style={{ marginRight: '12px' }} />
{t('Learn')}
<Trans id="pools.menu.learn">Learn</Trans>
</MenuItem>
),
link: 'https://docs.uniswap.org/',
......@@ -175,7 +175,9 @@ export default function Pool() {
<AutoColumn gap="lg" style={{ width: '100%' }}>
<TitleRow style={{ marginTop: '1rem' }} padding={'0'}>
<HideSmall>
<TYPE.mediumHeader>{t('Pools Overview')}</TYPE.mediumHeader>
<TYPE.mediumHeader>
<Trans id="pools.heading.poolsOverview">Pools Overview</Trans>
</TYPE.mediumHeader>
</HideSmall>
<ButtonRow>
<Menu
......@@ -184,14 +186,14 @@ export default function Pool() {
ToggleUI={(props: any) => (
<MoreOptionsButton {...props}>
<TYPE.body style={{ alignItems: 'center', display: 'flex' }}>
{t('More')}
<Trans id="pools.menu.more">More</Trans>
<ChevronDown size={15} />
</TYPE.body>
</MoreOptionsButton>
)}
/>
<ResponsiveButtonPrimary id="join-pool-button" as={Link} to="/add/ETH">
+ {t('New Position')}
+ <Trans id="pools.buttons.newPosition">New Position</Trans>
</ResponsiveButtonPrimary>
</ButtonRow>
</TitleRow>
......@@ -200,7 +202,9 @@ export default function Pool() {
{closedPositions.length > 0 ? (
<ShowInactiveToggle>
<TYPE.darkGray>{t('Hide closed positions')}</TYPE.darkGray>
<TYPE.darkGray>
<Trans id="pools.toggle.hideClosedPositions">Hide closed positions</Trans>
</TYPE.darkGray>
<Toggle
isActive={userHideClosedPositions}
toggle={() => setUserHideClosedPositions(!userHideClosedPositions)}
......@@ -230,11 +234,13 @@ export default function Pool() {
<NoLiquidity>
<TYPE.mediumHeader color={theme.text3} textAlign="center">
<Inbox size={48} strokeWidth={1} style={{ marginBottom: '.5rem' }} />
<div>{t('Your V3 liquidity positions will appear here.')}</div>
<div>
<Trans id="pools.emptyStateHint">Your V3 liquidity positions will appear here.</Trans>
</div>
</TYPE.mediumHeader>
{!account ? (
<ButtonPrimary style={{ marginTop: '2em', padding: '8px 16px' }} onClick={toggleWalletModal}>
{t('Connect a wallet')}
<Trans id="wallet.connect">Connect a wallet</Trans>
</ButtonPrimary>
) : (
<ButtonGray
......@@ -243,7 +249,7 @@ export default function Pool() {
id="import-pool-link"
style={{ marginTop: '2em', padding: '8px 16px', borderRadius: '12px', width: 'fit-content' }}
>
{t('Migrate V2 liquidity')}?&nbsp;&nbsp;
<Trans id="pools.buttons.migrateV2Liquidity">Migrate V2 liquidity</Trans>?&nbsp;&nbsp;
<Download size={16} />
</ButtonGray>
)}
......@@ -265,7 +271,7 @@ export default function Pool() {
>
<Layers size={14} style={{ marginRight: '8px' }} />
{t('View V2 Liquidity')}
<Trans id="pools.buttons.viewV2Liquidity">View V2 Liquidity</Trans>
</ButtonOutlined>
{positions && positions.length > 0 && (
<ButtonOutlined
......@@ -282,7 +288,7 @@ export default function Pool() {
>
<ChevronsRight size={16} style={{ marginRight: '8px' }} />
{t('Migrate Liquidity')}
<Trans id="pools.buttons.migrateLiquidity">Migrate Liquidity</Trans>
</ButtonOutlined>
)}
</RowFixed>
......
......@@ -22,6 +22,7 @@ import { Dots } from '../Pool/styleds'
import { BlueCard } from '../../components/Card'
import { TYPE } from '../../theme'
import { useLocation } from 'react-router'
import { Trans } from '@lingui/macro'
enum Fields {
TOKEN0 = 0,
......@@ -81,7 +82,11 @@ export default function PoolFinder() {
const prerequisiteMessage = (
<LightCard padding="45px 10px">
<Text textAlign="center">
{!account ? 'Connect to a wallet to find pools' : 'Select a token to find your liquidity.'}
{!account ? (
<Trans id="pools.label.connectWalletToFindPools">Connect to a wallet to find pools</Trans>
) : (
<Trans id="pools.labels.selectTokenToFindLiquidity">Select a token to find your liquidity.</Trans>
)}
</Text>
</LightCard>
)
......@@ -93,7 +98,9 @@ export default function PoolFinder() {
<BlueCard>
<AutoColumn gap="10px">
<TYPE.link fontWeight={400} color={'primaryText1'}>
<Trans id="pools.hint.toolHelperText">
<b>Tip:</b> Use this tool to find pairs that don&apos;t automatically appear in the interface.
</Trans>
</TYPE.link>
</AutoColumn>
</BlueCard>
......@@ -112,7 +119,7 @@ export default function PoolFinder() {
</Row>
) : (
<Text fontWeight={500} fontSize={20} marginLeft={'12px'}>
Select a Token
<Trans id="currencies.search.selectToken">Select a token</Trans>
</Text>
)}
</ButtonDropdownLight>
......@@ -136,7 +143,7 @@ export default function PoolFinder() {
</Row>
) : (
<Text fontWeight={500} fontSize={20} marginLeft={'12px'}>
Select a Token
<Trans id="currencies.search.selectToken">Select a token</Trans>
</Text>
)}
</ButtonDropdownLight>
......@@ -146,10 +153,12 @@ export default function PoolFinder() {
style={{ justifyItems: 'center', backgroundColor: '', padding: '12px 0px', borderRadius: '12px' }}
>
<Text textAlign="center" fontWeight={500}>
Pool Found!
<Trans id="pools.labels.poolFound">Pool Found!</Trans>
</Text>
<StyledInternalLink to={`/pool`}>
<Text textAlign="center">Manage this pool.</Text>
<Text textAlign="center">
<Trans id="pools.buttons.manage">Manage this pool.</Trans>
</Text>
</StyledInternalLink>
</ColumnCenter>
)}
......@@ -161,9 +170,13 @@ export default function PoolFinder() {
) : (
<LightCard padding="45px 10px">
<AutoColumn gap="sm" justify="center">
<Text textAlign="center">You don’t have liquidity in this pool yet.</Text>
<Text textAlign="center">
<Trans id="pools.label.noLiquidityInPoolYet">You don’t have liquidity in this pool yet.</Trans>
</Text>
<StyledInternalLink to={`/add/${currencyId(currency0)}/${currencyId(currency1)}`}>
<Text textAlign="center">Add liquidity.</Text>
<Text textAlign="center">
<Trans id="pools.buttons.addLiquidityPoolFinder">Add liquidity.</Trans>
</Text>
</StyledInternalLink>
</AutoColumn>
</LightCard>
......@@ -171,9 +184,11 @@ export default function PoolFinder() {
) : validPairNoLiquidity ? (
<LightCard padding="45px 10px">
<AutoColumn gap="sm" justify="center">
<Text textAlign="center">No pool found.</Text>
<Text textAlign="center">
<Trans id="pools.error.noPoolFound">No pool found.</Trans>
</Text>
<StyledInternalLink to={`/add/${currencyId(currency0)}/${currencyId(currency1)}`}>
Create pool.
<Trans id="pools.buttons.createPool">Create pool.</Trans>
</StyledInternalLink>
</AutoColumn>
</LightCard>
......@@ -181,7 +196,7 @@ export default function PoolFinder() {
<LightCard padding="45px 10px">
<AutoColumn gap="sm" justify="center">
<Text textAlign="center" fontWeight={500}>
Invalid pair.
<Trans id="pools.errors.invalidPair">Invalid pair.</Trans>
</Text>
</AutoColumn>
</LightCard>
......@@ -189,7 +204,7 @@ export default function PoolFinder() {
<LightCard padding="45px 10px">
<AutoColumn gap="sm" justify="center">
<Text textAlign="center">
Loading
<Trans id="common.loading">Loading</Trans>
<Dots />
</Text>
</AutoColumn>
......
......@@ -33,6 +33,7 @@ import useTheme from 'hooks/useTheme'
import { AddRemoveTabs } from 'components/NavigationTabs'
import RangeBadge from 'components/Badge/RangeBadge'
import Toggle from 'components/Toggle'
import { t, Trans } from '@lingui/macro'
export const UINT128MAX = BigNumber.from(2).pow(128).sub(1)
......@@ -151,7 +152,10 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
setTxnHash(response.hash)
setAttemptingTxn(false)
addTransaction(response, {
summary: `Remove ${liquidityValue0.currency.symbol}/${liquidityValue1.currency.symbol} V3 liquidity`,
summary: t({
id: 'transactions.summary.removeLiquidityV3',
message: `Remove ${liquidityValue0.currency.symbol}/${liquidityValue1.currency.symbol} V3 liquidity`,
}),
})
})
})
......@@ -186,16 +190,19 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
setTxnHash('')
}, [onPercentSelectForSlider, txnHash])
const pendingText = `Removing ${liquidityValue0?.toSignificant(6)} ${
const pendingText = t({
id: 'removeLiquidity.confirming.pending',
message: `Removing ${liquidityValue0?.toSignificant(6)} ${
liquidityValue0?.currency?.symbol
} and ${liquidityValue1?.toSignificant(6)} ${liquidityValue1?.currency?.symbol}`
} and ${liquidityValue1?.toSignificant(6)} ${liquidityValue1?.currency?.symbol}`,
})
function modalHeader() {
return (
<AutoColumn gap={'sm'} style={{ padding: '16px' }}>
<RowBetween align="flex-end">
<Text fontSize={16} fontWeight={500}>
Pooled {liquidityValue0?.currency?.symbol}:
<Trans id="pool.pooledCurrency">Pooled {liquidityValue0?.currency?.symbol}:</Trans>
</Text>
<RowFixed>
<Text fontSize={16} fontWeight={500} marginLeft={'6px'}>
......@@ -206,7 +213,7 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
</RowBetween>
<RowBetween align="flex-end">
<Text fontSize={16} fontWeight={500}>
Pooled {liquidityValue1?.currency?.symbol}:
<Trans id="pool.pooledCurrency">Pooled {liquidityValue1?.currency?.symbol}:</Trans>
</Text>
<RowFixed>
<Text fontSize={16} fontWeight={500} marginLeft={'6px'}>
......@@ -218,11 +225,13 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
{feeValue0?.greaterThan(0) || feeValue1?.greaterThan(0) ? (
<>
<TYPE.italic fontSize={12} color={theme.text2} textAlign="left" padding={'8px 0 0 0'}>
{`You will also collect fees earned from this position.`}
<Trans id="removeLiquidity.hints.collectFeesEarn">
You will also collect fees earned from this position.
</Trans>
</TYPE.italic>
<RowBetween>
<Text fontSize={16} fontWeight={500}>
{feeValue0?.currency?.symbol} Fees Earned:
<Trans id="removeLiquidity.label.feesEarned">{feeValue0?.currency?.symbol} Fees Earned:</Trans>
</Text>
<RowFixed>
<Text fontSize={16} fontWeight={500} marginLeft={'6px'}>
......@@ -233,7 +242,7 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
</RowBetween>
<RowBetween>
<Text fontSize={16} fontWeight={500}>
{feeValue1?.currency?.symbol} Fees Earned:
<Trans id="removeLiquidity.label.feesEarned">{feeValue1?.currency?.symbol} Fees Earned:</Trans>
</Text>
<RowFixed>
<Text fontSize={16} fontWeight={500} marginLeft={'6px'}>
......@@ -245,7 +254,7 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
</>
) : null}
<ButtonPrimary mt="16px" onClick={burn}>
Remove
<Trans id="buttons.remove">Remove</Trans>
</ButtonPrimary>
</AutoColumn>
)
......@@ -260,7 +269,7 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
hash={txnHash ?? ''}
content={() => (
<ConfirmationModalContent
title={'Remove Liquidity'}
title={t({ id: 'removeLiquidity.labels.removeLiquidity', message: 'Remove Liquidity' })}
onDismiss={handleDismissConfirmation}
topContent={modalHeader}
/>
......@@ -294,21 +303,25 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
</RowBetween>
<LightCard>
<AutoColumn gap="md">
<TYPE.main fontWeight={400}>Amount</TYPE.main>
<TYPE.main fontWeight={400}>
<Trans id="labels.amount">Amount</Trans>
</TYPE.main>
<RowBetween>
<ResponsiveHeaderText>{percentForSlider}%</ResponsiveHeaderText>
<ResponsiveHeaderText>
<Trans id="removeLiquidity.labels.percentForSlider">{percentForSlider}%</Trans>
</ResponsiveHeaderText>
<AutoRow gap="4px" justify="flex-end">
<SmallMaxButton onClick={() => onPercentSelect(25)} width="20%">
25%
<Trans id="number.25Percent">25%</Trans>
</SmallMaxButton>
<SmallMaxButton onClick={() => onPercentSelect(50)} width="20%">
50%
<Trans id="number.50Percent">50%</Trans>
</SmallMaxButton>
<SmallMaxButton onClick={() => onPercentSelect(75)} width="20%">
75%
<Trans id="number.75Percent">75%</Trans>
</SmallMaxButton>
<SmallMaxButton onClick={() => onPercentSelect(100)} width="20%">
Max
<Trans id="labels.max">Max</Trans>
</SmallMaxButton>
</AutoRow>
</RowBetween>
......@@ -319,7 +332,7 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
<AutoColumn gap="md">
<RowBetween>
<Text fontSize={16} fontWeight={500}>
Pooled {liquidityValue0?.currency?.symbol}:
<Trans id="pool.pooledCurrency">Pooled {liquidityValue0?.currency?.symbol}:</Trans>
</Text>
<RowFixed>
<Text fontSize={16} fontWeight={500} marginLeft={'6px'}>
......@@ -330,7 +343,7 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
</RowBetween>
<RowBetween>
<Text fontSize={16} fontWeight={500}>
Pooled {liquidityValue1?.currency?.symbol}:
<Trans id="pool.pooledCurrency">Pooled {liquidityValue1?.currency?.symbol}:</Trans>
</Text>
<RowFixed>
<Text fontSize={16} fontWeight={500} marginLeft={'6px'}>
......@@ -344,7 +357,9 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
<Break />
<RowBetween>
<Text fontSize={16} fontWeight={500}>
<Trans id="removeLiquidity.label.feesEarned">
{feeValue0?.currency?.symbol} Fees Earned:
</Trans>
</Text>
<RowFixed>
<Text fontSize={16} fontWeight={500} marginLeft={'6px'}>
......@@ -376,7 +391,9 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
liquidityValue0.currency.wrapped.equals(WETH9[liquidityValue0.currency.chainId]) ||
liquidityValue1.currency.wrapped.equals(WETH9[liquidityValue1.currency.chainId])) ? (
<RowBetween>
<TYPE.main>Collect as WETH</TYPE.main>
<TYPE.main>
<Trans id="pools.labels.collectFeesAsWETH">Collect as WETH</Trans>
</TYPE.main>
<Toggle
id="receive-as-weth"
isActive={receiveWETH}
......@@ -392,7 +409,11 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
disabled={removed || percent === 0 || !liquidityValue0}
onClick={() => setShowConfirm(true)}
>
{removed ? 'Inactive' : error ?? 'Remove'}
{removed ? (
<Trans id="labels.inactive">Inactive</Trans>
) : (
error ?? <Trans id="labels.remove">Remove</Trans>
)}
</ButtonConfirmed>
</AutoColumn>
</div>
......
......@@ -41,6 +41,7 @@ import { Field } from '../../state/burn/actions'
import { useWalletModalToggle } from '../../state/application/hooks'
import { useUserSlippageToleranceWithDefault } from '../../state/user/hooks'
import { BigNumber } from '@ethersproject/bignumber'
import { t, Trans } from '@lingui/macro'
const DEFAULT_REMOVE_LIQUIDITY_SLIPPAGE_TOLERANCE = new Percent(5, 100)
......@@ -265,15 +266,12 @@ export default function RemoveLiquidity({
setAttemptingTxn(false)
addTransaction(response, {
summary:
'Remove ' +
parsedAmounts[Field.CURRENCY_A]?.toSignificant(3) +
' ' +
currencyA?.symbol +
' and ' +
parsedAmounts[Field.CURRENCY_B]?.toSignificant(3) +
' ' +
currencyB?.symbol,
summary: t({
id: 'transactions.summary.removeLiquidity',
message: `Remove ${parsedAmounts[Field.CURRENCY_A]?.toSignificant(3)} ${
currencyA?.symbol
} and ${parsedAmounts[Field.CURRENCY_B]?.toSignificant(3)} ${currencyB?.symbol}`,
}),
})
setTxHash(response.hash)
......@@ -322,9 +320,10 @@ export default function RemoveLiquidity({
</RowBetween>
<TYPE.italic fontSize={12} color={theme.text2} textAlign="left" padding={'12px 0 0 0'}>
{`Output is estimated. If the price changes by more than ${allowedSlippage.toSignificant(
4
)}% your transaction will revert.`}
<Trans id="removeLiquidity.hint.outputEstimated">
Output is estimated. If the price changes by more than {allowedSlippage.toSignificant(4)}% your transaction
will revert.
</Trans>
</TYPE.italic>
</AutoColumn>
)
......@@ -335,7 +334,9 @@ export default function RemoveLiquidity({
<>
<RowBetween>
<Text color={theme.text2} fontWeight={500} fontSize={16}>
{'UNI ' + currencyA?.symbol + '/' + currencyB?.symbol} Burned
<Trans id="removeLiquidity.labels.UNIBurned">
UNI {currencyA?.symbol}/{currencyB?.symbol} Burned
</Trans>
</Text>
<RowFixed>
<DoubleCurrencyLogo currency0={currencyA} currency1={currencyB} margin={true} />
......@@ -348,7 +349,7 @@ export default function RemoveLiquidity({
<>
<RowBetween>
<Text color={theme.text2} fontWeight={500} fontSize={16}>
Price
<Trans id="removeLiquidity.labels.modalPrice">Price</Trans>
</Text>
<Text fontWeight={500} fontSize={16} color={theme.text1}>
1 {currencyA?.symbol} = {tokenA ? pair.priceOf(tokenA).toSignificant(6) : '-'} {currencyB?.symbol}
......@@ -364,16 +365,19 @@ export default function RemoveLiquidity({
)}
<ButtonPrimary disabled={!(approval === ApprovalState.APPROVED || signatureData !== null)} onClick={onRemove}>
<Text fontWeight={500} fontSize={20}>
Confirm
<Trans id="buttons.confirm">Confirm</Trans>
</Text>
</ButtonPrimary>
</>
)
}
const pendingText = `Removing ${parsedAmounts[Field.CURRENCY_A]?.toSignificant(6)} ${
currencyA?.symbol
} and ${parsedAmounts[Field.CURRENCY_B]?.toSignificant(6)} ${currencyB?.symbol}`
const pendingText = t({
id: 'removeLiquidity.confirming.pending',
message: `Removing ${parsedAmounts[Field.CURRENCY_A]?.toSignificant(6)} ${currencyA?.symbol} and ${parsedAmounts[
Field.CURRENCY_B
]?.toSignificant(6)} ${currencyB?.symbol}`,
})
const liquidityPercentChangeCallback = useCallback(
(value: number) => {
......@@ -434,7 +438,7 @@ export default function RemoveLiquidity({
hash={txHash ? txHash : ''}
content={() => (
<ConfirmationModalContent
title={'You will receive'}
title={t({ id: 'removeLiquidity.labels.confirmationTitle', message: 'You will receive' })}
onDismiss={handleDismissConfirmation}
topContent={modalHeader}
bottomContent={modalBottom}
......@@ -446,22 +450,30 @@ export default function RemoveLiquidity({
<BlueCard>
<AutoColumn gap="10px">
<TYPE.link fontWeight={400} color={'primaryText1'}>
<Trans id="removeLiquidity.hints.removingPoolTokensConvertsPosition">
<b>Tip:</b> Removing pool tokens converts your position back into underlying tokens at the current
rate, proportional to your share of the pool. Accrued fees are included in the amounts you receive.
</Trans>
</TYPE.link>
</AutoColumn>
</BlueCard>
<LightCard>
<AutoColumn gap="20px">
<RowBetween>
<Text fontWeight={500}>Remove Amount</Text>
<Text fontWeight={500}>
<Trans id="removeLiquidity.buttons.RemoveAmount">Remove Amount</Trans>
</Text>
<ClickableText
fontWeight={500}
onClick={() => {
setShowDetailed(!showDetailed)
}}
>
{showDetailed ? 'Simple' : 'Detailed'}
{showDetailed ? (
<Trans id="common.simple">Simple</Trans>
) : (
<Trans id="common.detailed">Detailed</Trans>
)}
</ClickableText>
</RowBetween>
<Row style={{ alignItems: 'flex-end' }}>
......@@ -591,7 +603,7 @@ export default function RemoveLiquidity({
{pair && (
<div style={{ padding: '10px 20px' }}>
<RowBetween>
Price:
<Trans id="removeLiquidity.labels.price">Price:</Trans>
<div>
1 {currencyA?.symbol} = {tokenA ? pair.priceOf(tokenA).toSignificant(6) : '-'} {currencyB?.symbol}
</div>
......@@ -606,7 +618,9 @@ export default function RemoveLiquidity({
)}
<div style={{ position: 'relative' }}>
{!account ? (
<ButtonLight onClick={toggleWalletModal}>Connect Wallet</ButtonLight>
<ButtonLight onClick={toggleWalletModal}>
<Trans id="wallet.connect">Connect Wallet</Trans>
</ButtonLight>
) : (
<RowBetween>
<ButtonConfirmed
......@@ -618,11 +632,13 @@ export default function RemoveLiquidity({
fontSize={16}
>
{approval === ApprovalState.PENDING ? (
<Dots>Approving</Dots>
<Dots>
<Trans id="transactions.approving">Approving</Trans>
</Dots>
) : approval === ApprovalState.APPROVED || signatureData !== null ? (
'Approved'
<Trans id="transactions.approved">Approved</Trans>
) : (
'Approve'
<Trans id="transactions.approve">Approve</Trans>
)}
</ButtonConfirmed>
<ButtonError
......@@ -633,7 +649,7 @@ export default function RemoveLiquidity({
error={!isValid && !!parsedAmounts[Field.CURRENCY_A] && !!parsedAmounts[Field.CURRENCY_B]}
>
<Text fontSize={16} fontWeight={500}>
{error || 'Remove'}
{error || <Trans id="removeLiquidity.buttons.remove">Remove</Trans>}
</Text>
</ButtonError>
</RowBetween>
......
......@@ -55,6 +55,7 @@ import { isTradeBetter } from '../../utils/isTradeBetter'
import { maxAmountSpend } from '../../utils/maxAmountSpend'
import { warningSeverity } from '../../utils/prices'
import AppBody from '../AppBody'
import { t, Trans } from '@lingui/macro'
const StyledInfo = styled(Info)`
opacity: 0.4;
......@@ -376,7 +377,11 @@ export default function Swap({ history }: RouteComponentProps) {
<AutoColumn gap={'md'}>
<div style={{ display: 'relative' }}>
<CurrencyInputPanel
label={independentField === Field.OUTPUT && !showWrap ? 'From (at most)' : 'From'}
label={
independentField === Field.OUTPUT && !showWrap
? t({ id: 'swap.labels.fromAtMost', message: 'From (at most)' })
: t({ id: 'swap.labels.from', message: 'From' })
}
value={formattedAmounts[Field.INPUT]}
showMaxButton={showMaxButton}
currency={currencies[Field.INPUT]}
......@@ -401,7 +406,11 @@ export default function Swap({ history }: RouteComponentProps) {
<CurrencyInputPanel
value={formattedAmounts[Field.OUTPUT]}
onUserInput={handleTypeOutput}
label={independentField === Field.INPUT && !showWrap ? 'To (at least)' : 'To'}
label={
independentField === Field.INPUT && !showWrap
? t({ id: 'swap.labels.toAtLeast', message: 'To (at least)' })
: t({ id: 'swap.labels.to', message: 'To' })
}
showMaxButton={false}
hideBalance={false}
fiatValue={fiatValueOutput ?? undefined}
......@@ -421,7 +430,7 @@ export default function Swap({ history }: RouteComponentProps) {
<ArrowDown size="16" color={theme.text2} />
</ArrowWrapper>
<LinkStyledButton id="remove-recipient-button" onClick={() => onChangeRecipient(null)}>
- Remove send
<Trans id="swap.labels.removeSend">- Remove send</Trans>
</LinkStyledButton>
</AutoRow>
<AddressInputPanel id="recipient" value={recipient} onChange={onChangeRecipient} />
......@@ -455,7 +464,10 @@ export default function Swap({ history }: RouteComponentProps) {
>
<ArrowLeft color={theme.text3} size={12} /> &nbsp;
<TYPE.main style={{ lineHeight: '120%' }} fontSize={12}>
<HideSmall>Back to </HideSmall>V3
<Trans id="swap.buttons.backToV3">
<HideSmall>Back to</HideSmall>
V3
</Trans>
</TYPE.main>
</ButtonGray>
)
......@@ -498,22 +510,36 @@ export default function Swap({ history }: RouteComponentProps) {
<BottomGrouping>
{swapIsUnsupported ? (
<ButtonPrimary disabled={true}>
<TYPE.main mb="4px">Unsupported Asset</TYPE.main>
<TYPE.main mb="4px">
<Trans id="error.unsupportedAssets">Unsupported Asset</Trans>
</TYPE.main>
</ButtonPrimary>
) : !account ? (
<ButtonLight onClick={toggleWalletModal}>Connect Wallet</ButtonLight>
<ButtonLight onClick={toggleWalletModal}>
<Trans id="wallet.connect">Connect Wallet</Trans>
</ButtonLight>
) : showWrap ? (
<ButtonPrimary disabled={Boolean(wrapInputError)} onClick={onWrap}>
{wrapInputError ??
(wrapType === WrapType.WRAP ? 'Wrap' : wrapType === WrapType.UNWRAP ? 'Unwrap' : null)}
(wrapType === WrapType.WRAP ? (
<Trans id="swap.buttons.wrap">Wrap</Trans>
) : wrapType === WrapType.UNWRAP ? (
<Trans id="swap.buttons.unwrap">Unwrap</Trans>
) : null)}
</ButtonPrimary>
) : routeNotFound && userHasSpecifiedInputOutput ? (
<GreyCard style={{ textAlign: 'center' }}>
<TYPE.main mb="4px">
{isLoadingRoute ? (
<Dots>Loading</Dots>
<Dots>
<Trans id="common.loading">Loading</Trans>
</Dots>
) : singleHopOnly ? (
<Trans id="swap.labels.insufficientLiquiditySingleHopOnly">
Insufficient liquidity for this trade. Try enabling multi-hop trades.
</Trans>
) : (
`Insufficient liquidity for this trade.${singleHopOnly ? ' Try enabling multi-hop trades.' : ''}`
<Trans id="swap.labels.insufficientLiquidity">Insufficient liquidity for this trade.</Trans>
)}
</TYPE.main>
</GreyCard>
......@@ -541,9 +567,15 @@ export default function Swap({ history }: RouteComponentProps) {
style={{ marginRight: '8px', flexShrink: 0 }}
/>
{/* we need to shorten this string on mobile */}
{approvalState === ApprovalState.APPROVED || signatureState === UseERC20PermitState.SIGNED
? 'You can now trade ' + currencies[Field.INPUT]?.symbol
: 'Allow the Uniswap Protocol to use your ' + currencies[Field.INPUT]?.symbol}
{approvalState === ApprovalState.APPROVED || signatureState === UseERC20PermitState.SIGNED ? (
<Trans id="swap.buttons.tradeCurrency">
You can now trade {currencies[Field.INPUT]?.symbol}
</Trans>
) : (
<Trans id="swap.buttons.allowUniswapToUseCurrency">
Allow the Uniswap Protocol to use your {currencies[Field.INPUT]?.symbol}
</Trans>
)}
</span>
{approvalState === ApprovalState.PENDING ? (
<Loader stroke="white" />
......@@ -552,11 +584,12 @@ export default function Swap({ history }: RouteComponentProps) {
<CheckCircle size="20" color={theme.green1} />
) : (
<MouseoverTooltip
text={
'You must give the Uniswap smart contracts permission to use your ' +
currencies[Field.INPUT]?.symbol +
'. You only have to do this once per token.'
}
text={t({
id: 'swap.hints.permission',
message: `You must give the Uniswap smart contracts permission to use your ${
currencies[Field.INPUT]?.symbol
}. You only have to do this once per token.`,
})}
>
<HelpCircle size="20" color={'white'} style={{ marginLeft: '8px' }} />
</MouseoverTooltip>
......@@ -587,7 +620,13 @@ export default function Swap({ history }: RouteComponentProps) {
error={isValid && priceImpactSeverity > 2}
>
<Text fontSize={16} fontWeight={500}>
{priceImpactTooHigh ? `High Price Impact` : `Swap${priceImpactSeverity > 2 ? ' Anyway' : ''}`}
{priceImpactTooHigh ? (
<Trans id="swap.buttons.highPriceImpact">High Price Impact</Trans>
) : priceImpactSeverity > 2 ? (
<Trans id="swap.buttons.swapAnyway">Swap Anyway</Trans>
) : (
<Trans id="swap.buttons.swap">Swap</Trans>
)}
</Text>
</ButtonError>
</AutoColumn>
......@@ -612,11 +651,15 @@ export default function Swap({ history }: RouteComponentProps) {
error={isValid && priceImpactSeverity > 2 && !swapCallbackError}
>
<Text fontSize={20} fontWeight={500}>
{swapInputError
? swapInputError
: priceImpactTooHigh
? `Price Impact Too High`
: `Swap${priceImpactSeverity > 2 ? ' Anyway' : ''}`}
{swapInputError ? (
swapInputError
) : priceImpactTooHigh ? (
<Trans id="swap.buttons.priceImpactTooHigh">Price Impact Too High</Trans>
) : priceImpactSeverity > 2 ? (
<Trans id="swap.buttons.swapAnyway">Swap Anyway</Trans>
) : (
<Trans id="swap.buttons.swap">Swap</Trans>
)}
</Text>
</ButtonError>
)}
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment