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