Skip to content

Commit 1f09744

Browse files
authored
Merge pull request #6545 from cowprotocol/release/24-11-2025
Release 24-11-2025
2 parents 94cdbc0 + edd9c81 commit 1f09744

File tree

568 files changed

+26677
-4806
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

568 files changed

+26677
-4806
lines changed

apps/cowswap-frontend/.env

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,13 @@ INTEGRATION_TESTS_INFURA_KEY=
133133
# Path regex (to detect environment)
134134
# REACT_APP_PATH_REGEX_ENS="/ipfs"
135135

136-
137136
# CMS base URL
138137
# REACT_APP_CMS_BASE_URL=http://localhost:1337/api
139138

140139
# Notifications Telegram bot ID
141140
# REACT_APP_TG_BOT_ID=3713371337
141+
142+
#######################################
143+
# Crowdin translations
144+
#######################################
145+
# CROWDIN_PERSONAL_TOKEN

apps/cowswap-frontend/.gitignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
# See https://help.github.com/ignore-files/ for more about ignoring files.
22

3-
# generated contract types
3+
# generated language types
44
/src/lib/locales/**/*.js
55
/src/lib/locales/**/en-US.po
66
/src/lib/locales/**/pseudo.po
77
/src/locales/**/*.js
88
/src/locales/**/*.ts
99
/src/locales/**/*.json
10-
/src/locales/**/en-US.po
1110
/src/locales/**/pseudo.po
1211

1312
# dependencies
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { FC, ReactNode } from 'react'
2+
3+
import { DEFAULT_LOCALE } from '@cowprotocol/common-const'
4+
5+
import { i18n } from '@lingui/core'
6+
import { I18nProvider } from '@lingui/react'
7+
8+
interface ProviderProps {
9+
children: ReactNode
10+
}
11+
12+
i18n.load(DEFAULT_LOCALE, {})
13+
i18n.activate(DEFAULT_LOCALE)
14+
15+
export const LinguiWrapper: FC<ProviderProps> = ({ children }) => {
16+
return <I18nProvider i18n={i18n}>{children}</I18nProvider>
17+
}

apps/cowswap-frontend/src/api/cowProtocol/errors/OperatorError.ts

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { t } from '@lingui/core/macro'
2+
13
type ApiActionType = 'get' | 'create' | 'delete'
24

35
export interface ApiErrorObject {
@@ -108,7 +110,7 @@ function _mapActionToErrorDetail(action?: ApiActionType) {
108110
console.error(
109111
'[OperatorError::_mapActionToErrorDetails] Uncaught error mapping error action type to server error. Please try again later.',
110112
)
111-
return 'Something failed. Please try again later.'
113+
return `Something failed. Please try again later.`
112114
}
113115
}
114116

@@ -144,23 +146,33 @@ export default class OperatorError extends Error {
144146
case 404:
145147
return this.getErrorMessage(errorObject, action)
146148

147-
case 403:
148-
return `The order cannot be ${action === 'create' ? 'accepted' : 'cancelled'}. Your account is deny-listed.`
149+
case 403: {
150+
const acceptedText = t`accepted`
151+
const cancelledText = t`cancelled`
152+
const statusText = action === 'create' ? acceptedText : cancelledText
153+
return t`The order cannot be ${statusText}. Your account is deny-listed.`
154+
}
149155

150-
case 429:
151-
return `The order cannot be ${
152-
action === 'create' ? 'accepted. Too many order placements' : 'cancelled. Too many order cancellations'
153-
}. Please, retry in a minute`
156+
case 429: {
157+
const placementsText = t`accepted. Too many order placements`
158+
const cancellationsText = t`cancelled. Too many order cancellations`
159+
const msg = action === 'create' ? placementsText : cancellationsText
160+
return t`The order cannot be ${msg}. Please, retry in a minute`
161+
}
154162

155163
case 500:
156-
default:
164+
default: {
157165
console.error(
158166
`[OperatorError::getErrorFromStatusCode] Error ${
159167
action === 'create' ? 'creating' : 'cancelling'
160168
} the order, status code:`,
161169
statusCode || 'unknown',
162170
)
163-
return `Error ${action === 'create' ? 'creating' : 'cancelling'} the order`
171+
const creatingText = t`creating`
172+
const cancellingText = t`cancelling`
173+
const verb = action === 'create' ? creatingText : cancellingText
174+
return t`Error ${verb} the order`
175+
}
164176
}
165177
}
166178
constructor(apiError: ApiErrorObject) {

apps/cowswap-frontend/src/common/constants/banners.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
export const BANNER_IDS = {
33
DELEGATE: 'delegate-banner-v1',
44
LIMIT_ORDERS_INFO: 'limitOrders_showInfoBanner',
5+
LIMIT_ORDERS_PROTOCOL_FEE: 'limitOrders_cip74ProtocolFeeBanner',
56
COW_AMM: 'cow_amm_banner_2024_va',
67
ANNOUNCEMENT: 'announcementBannerClosed',
78
HIRING_SPEECH_BUBBLE: 'cowHiringSpeechBubble:v0',

apps/cowswap-frontend/src/common/constants/routes.ts

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ import EXPERIMENT_ICON from '@cowprotocol/assets/cow-swap/experiment.svg'
22
import { isInjectedWidget } from '@cowprotocol/common-utils'
33
import { BadgeTypes } from '@cowprotocol/ui'
44

5+
import { MessageDescriptor } from '@lingui/core'
6+
import { msg } from '@lingui/core/macro'
7+
58
export const TRADE_WIDGET_PREFIX = isInjectedWidget() ? '/widget' : ''
69

710
export const Routes = {
@@ -54,25 +57,45 @@ export interface IMenuItem {
5457
badgeType?: (typeof BadgeTypes)[keyof typeof BadgeTypes]
5558
}
5659

57-
export const MENU_ITEMS: IMenuItem[] = [
58-
{ route: Routes.SWAP, label: 'Swap', description: 'Trade tokens' },
59-
{ route: Routes.LIMIT_ORDER, label: 'Limit', fullLabel: 'Limit order', description: 'Set your own price' },
60-
{ route: Routes.ADVANCED_ORDERS, label: 'TWAP', description: 'Place orders with a time-weighted average price' },
60+
export interface I18nIMenuItem extends Omit<IMenuItem, 'label' | 'fullLabel' | 'description' | 'badge'> {
61+
label: MessageDescriptor
62+
fullLabel?: MessageDescriptor
63+
description: MessageDescriptor
64+
badge?: MessageDescriptor
65+
}
66+
67+
export const MENU_ITEMS: I18nIMenuItem[] = [
68+
{
69+
route: Routes.SWAP,
70+
label: msg`Swap`,
71+
description: msg`Trade tokens`,
72+
},
73+
{
74+
route: Routes.LIMIT_ORDER,
75+
label: msg`Limit`,
76+
fullLabel: msg`Limit order`,
77+
description: msg`Set your own price`,
78+
},
79+
{
80+
route: Routes.ADVANCED_ORDERS,
81+
label: msg`TWAP`,
82+
description: msg`Place orders with a time-weighted average price`,
83+
},
6184
]
6285

63-
export const HOOKS_STORE_MENU_ITEM: IMenuItem = {
86+
export const HOOKS_STORE_MENU_ITEM: I18nIMenuItem = {
6487
route: Routes.HOOKS,
65-
label: 'Hooks',
66-
description: 'Powerful tool to generate pre/post interaction for CoW Protocol',
88+
label: msg`Hooks`,
89+
description: msg`Powerful tool to generate pre/post interaction for CoW Protocol`,
6790
badgeImage: EXPERIMENT_ICON,
6891
badgeType: BadgeTypes.INFORMATION,
6992
}
7093

71-
export const YIELD_MENU_ITEM: IMenuItem = {
94+
export const YIELD_MENU_ITEM: I18nIMenuItem = {
7295
route: Routes.YIELD,
73-
label: 'Yield',
74-
fullLabel: 'Yield',
75-
description: 'Provide liquidity',
76-
badge: 'New',
96+
label: msg`Yield`,
97+
fullLabel: msg`Yield`,
98+
description: msg`Provide liquidity`,
99+
badge: msg`New`,
77100
badgeType: BadgeTypes.ALERT,
78101
}

apps/cowswap-frontend/src/common/containers/CoWAmmBanner/index.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import { ClosableBanner } from '@cowprotocol/ui'
88
import { useIsSmartContractWallet, useWalletInfo } from '@cowprotocol/wallet'
99
import { CurrencyAmount } from '@uniswap/sdk-core'
1010

11+
import { t } from '@lingui/core/macro'
12+
1113
import { useIsDarkMode } from 'legacy/state/user/hooks'
1214

1315
import { useTradeNavigate } from 'modules/trade'
@@ -80,8 +82,8 @@ export function CoWAmmBanner({ isTokenSelectorView }: BannerProps) {
8082
<CoWAmmBannerContent
8183
id={bannerId}
8284
isDarkMode={isDarkMode}
83-
title="CoW AMM"
84-
ctaText={isSmartContractWallet ? 'Booooost APR!' : 'Booooost APR gas-free!'}
85+
title={t`CoW AMM`}
86+
ctaText={isSmartContractWallet ? t`Booooost APR!` : t`Booooost APR gas-free!`}
8587
isTokenSelectorView={!!isTokenSelectorView}
8688
vampireAttackContext={vampireAttackContext}
8789
tokensByAddress={tokensByAddress}

apps/cowswap-frontend/src/common/containers/ConfirmationModal/index.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { useAtomValue } from 'jotai'
22

3-
import { confirmationModalContextAtom } from 'common/hooks/useConfirmationRequest'
3+
import { t } from '@lingui/core/macro'
4+
5+
import { confirmationModalContextAtom, DEFAULT_CONFIRMATION_MODAL_CONTEXT } from 'common/hooks/useConfirmationRequest'
46
import { ConfirmationModal as Pure, ConfirmationModalProps } from 'common/pure/ConfirmationModal'
57

68
// TODO: Add proper return type annotation
@@ -13,12 +15,12 @@ export function ConfirmationModal({ isOpen, onDismiss }: Pick<ConfirmationModalP
1315
<Pure
1416
isOpen={isOpen}
1517
onDismiss={onDismiss}
16-
title={title}
17-
callToAction={callToAction}
18+
title={title === DEFAULT_CONFIRMATION_MODAL_CONTEXT.title ? t`Confirm Action` : title}
19+
callToAction={callToAction === DEFAULT_CONFIRMATION_MODAL_CONTEXT.callToAction ? t`Confirm` : callToAction}
1820
description={description}
1921
onEnable={onEnable}
2022
warning={warning}
21-
confirmWord={confirmWord}
23+
confirmWord={confirmWord === DEFAULT_CONFIRMATION_MODAL_CONTEXT.confirmWord ? t`confirm` : confirmWord}
2224
action={action}
2325
skipInput={skipInput}
2426
/>

apps/cowswap-frontend/src/common/containers/InvalidLocalTimeWarning/index.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { ReactNode } from 'react'
22

3+
import { Trans } from '@lingui/react/macro'
4+
35
import { useLocalTimeOffset } from './localTimeOffsetState'
46

57
import { GlobalWarning } from '../../pure/GlobalWarning'
@@ -18,7 +20,10 @@ export function InvalidLocalTimeWarning(): ReactNode | null {
1820

1921
return (
2022
<GlobalWarning>
21-
Local device time is not accurate, CoW Swap most likely will not work correctly. Please adjust your device's time.
23+
<Trans>
24+
Local device time is not accurate, CoW Swap most likely will not work correctly. Please adjust your device's
25+
time.
26+
</Trans>
2227
</GlobalWarning>
2328
)
2429
}

apps/cowswap-frontend/src/common/containers/MultipleOrdersCancellationModal/index.tsx

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ import { Command } from '@cowprotocol/types'
66
import { ButtonPrimary } from '@cowprotocol/ui'
77
import { useWalletInfo } from '@cowprotocol/wallet'
88

9+
import { t } from '@lingui/core/macro'
10+
import { Trans } from '@lingui/react/macro'
11+
912
import { LegacyConfirmationModalContent } from 'legacy/components/TransactionConfirmationModal/LegacyConfirmationModalContent'
1013
import { useRequestOrderCancellation } from 'legacy/state/orders/hooks'
1114

@@ -68,7 +71,7 @@ export function MultipleOrdersCancellationModal(props: Props): ReactNode {
6871

6972
if (cancellationError) {
7073
const errorMessage = isRejectRequestProviderError(cancellationError)
71-
? 'User rejected signing the cancellation'
74+
? t`User rejected signing the cancellation`
7275
: getIsOrderBookTypedError(cancellationError)
7376
? cancellationError.body.description || cancellationError.body.errorType
7477
: (getProviderErrorMessage(cancellationError) ?? String(cancellationError))
@@ -86,9 +89,9 @@ export function MultipleOrdersCancellationModal(props: Props): ReactNode {
8689
<ConfirmationPendingContent
8790
modalMode
8891
onDismiss={onDismiss}
89-
title={<>Cancelling {ordersCount} orders</>}
90-
description="Canceling your order"
91-
operationLabel="cancellation"
92+
title={t`Cancelling ${ordersCount} orders`}
93+
description={t`Canceling your order`}
94+
operationLabel={t`cancellation`}
9295
/>
9396
</Modal>
9497
)
@@ -97,20 +100,24 @@ export function MultipleOrdersCancellationModal(props: Props): ReactNode {
97100
return (
98101
<Modal isOpen={isOpen} onDismiss={onDismiss}>
99102
<LegacyConfirmationModalContent
100-
title={`Cancel multiple orders: ${ordersCount}`}
103+
title={t`Cancel multiple orders: ${ordersCount}`}
101104
onDismiss={onDismiss}
102105
// TODO: Extract nested component outside render function
103106
// eslint-disable-next-line react/no-unstable-nested-components
104107
topContent={() => (
105108
<div>
106-
<p>Are you sure you want to cancel {ordersCount} orders?</p>
109+
<p>
110+
<Trans>Are you sure you want to cancel {ordersCount} orders?</Trans>
111+
</p>
107112
</div>
108113
)}
109114
// TODO: Extract nested component outside render function
110115
// eslint-disable-next-line react/no-unstable-nested-components
111116
bottomContent={() => (
112117
<div>
113-
<ButtonPrimary onClick={signAndSendCancellation}>Request cancellations</ButtonPrimary>
118+
<ButtonPrimary onClick={signAndSendCancellation}>
119+
<Trans>Request cancellations</Trans>
120+
</ButtonPrimary>
114121
</div>
115122
)}
116123
/>

0 commit comments

Comments
 (0)