diff --git a/apps/browser-extension-wallet/src/components/MainLoader/MainLoader.tsx b/apps/browser-extension-wallet/src/components/MainLoader/MainLoader.tsx index 2e38db01c1..e05e448b2d 100644 --- a/apps/browser-extension-wallet/src/components/MainLoader/MainLoader.tsx +++ b/apps/browser-extension-wallet/src/components/MainLoader/MainLoader.tsx @@ -5,18 +5,17 @@ import { useTranslation } from 'react-i18next'; import styles from './MainLoader.module.scss'; export interface MainLoaderProps { - text?: string; overlay?: boolean; } -export const MainLoader = ({ text, overlay = false }: MainLoaderProps): React.ReactElement => { +export const MainLoader = ({ overlay = false }: MainLoaderProps): React.ReactElement => { const { t } = useTranslation(); return (

- {text ?? t('general.loading')} + {t('general.loading')}

); diff --git a/apps/browser-extension-wallet/src/components/MainMenu/DropdownMenuOverlay/DropdownMenuOverlay.tsx b/apps/browser-extension-wallet/src/components/MainMenu/DropdownMenuOverlay/DropdownMenuOverlay.tsx index 83c979d10c..ef8d3515ae 100644 --- a/apps/browser-extension-wallet/src/components/MainMenu/DropdownMenuOverlay/DropdownMenuOverlay.tsx +++ b/apps/browser-extension-wallet/src/components/MainMenu/DropdownMenuOverlay/DropdownMenuOverlay.tsx @@ -8,6 +8,8 @@ import { Links, LockWallet, NetworkChoise, + LanguageChoice, + LanguageInfo, RenameWalletDrawer, Separator, SettingsLink, @@ -98,6 +100,11 @@ export const DropdownMenuOverlay: VFC = ({ sendAnalyticsEvent(PostHogAction.UserWalletProfileNetworkClick); }; + const handleLanguageChoice = () => { + setCurrentSection(Sections.Language); + sendAnalyticsEvent(PostHogAction.UserWalletProfileLanguageClick); + }; + const goBackToMainSection = useCallback(() => setCurrentSection(Sections.Main), []); useEffect(() => { @@ -209,6 +216,7 @@ export const DropdownMenuOverlay: VFC = ({ /> )} + {lockWalletButton && ( <> @@ -219,6 +227,7 @@ export const DropdownMenuOverlay: VFC = ({ )} {currentSection === Sections.NetworkInfo && } + {currentSection === Sections.Language && } {currentSection === Sections.WalletAccounts && } {isRenamingWallet && ( setIsRenamingWallet(false)} /> diff --git a/apps/browser-extension-wallet/src/components/MainMenu/DropdownMenuOverlay/components/LanguageChoice.tsx b/apps/browser-extension-wallet/src/components/MainMenu/DropdownMenuOverlay/components/LanguageChoice.tsx new file mode 100644 index 0000000000..fa60ff0ff1 --- /dev/null +++ b/apps/browser-extension-wallet/src/components/MainMenu/DropdownMenuOverlay/components/LanguageChoice.tsx @@ -0,0 +1,44 @@ +import React, { useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import cn from 'classnames'; +import styles from '../DropdownMenuOverlay.module.scss'; +import { useBackgroundServiceAPIContext } from '@providers'; +import { storage as webStorage } from 'webextension-polyfill'; + +type LanguageChoiceProps = { + onClick: () => void; +}; + +export const LanguageChoice = ({ onClick }: LanguageChoiceProps): React.ReactElement => { + const { t } = useTranslation(); + const { getBackgroundStorage } = useBackgroundServiceAPIContext(); + const [language, setLanguage] = useState('en'); + const [loadingLanguage, setLoadingLanguage] = useState(true); + + useEffect(() => { + const getLanguage = async () => { + const { languageChoice } = await getBackgroundStorage(); + if (languageChoice) setLanguage(languageChoice); + setLoadingLanguage(false); + }; + getLanguage(); + webStorage.onChanged.addListener(getLanguage); + }, [getBackgroundStorage, setLoadingLanguage]); + + return ( +
onClick()} + > +
+ {t('browserView.topNavigationBar.links.language')} + {!loadingLanguage && ( + + {language || 'en'} + + )} +
+
+ ); +}; diff --git a/apps/browser-extension-wallet/src/components/MainMenu/DropdownMenuOverlay/components/LanguageInfo.tsx b/apps/browser-extension-wallet/src/components/MainMenu/DropdownMenuOverlay/components/LanguageInfo.tsx new file mode 100644 index 0000000000..e7f770b2eb --- /dev/null +++ b/apps/browser-extension-wallet/src/components/MainMenu/DropdownMenuOverlay/components/LanguageInfo.tsx @@ -0,0 +1,71 @@ +/* eslint-disable unicorn/no-null */ +import React, { useCallback, useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { NavigationButton, PostHogAction } from '@lace/common'; +import styles from './NetworkInfo.module.scss'; +import { useBackgroundServiceAPIContext } from '@providers'; +import { Radio, RadioChangeEvent } from 'antd'; +import { usePostHogClientContext } from '@providers/PostHogClientProvider'; +import { storage as webStorage } from 'webextension-polyfill'; +import type { Language } from '@lace/translation'; + +type LanguageChoiceProps = { + onBack: () => void; +}; + +const LANG_CHOICES = ['en', 'es']; // hardcoding for v1 only + +export const LanguageInfo = ({ onBack }: LanguageChoiceProps): React.ReactElement => { + const { t } = useTranslation(); + const [language, setLanguage] = useState(null); + const posthog = usePostHogClientContext(); + + const { getBackgroundStorage, handleChangeLanguage } = useBackgroundServiceAPIContext(); + + useEffect(() => { + const getLanguage = async () => { + const { languageChoice } = await getBackgroundStorage(); + if (languageChoice) setLanguage(languageChoice); + }; + webStorage.onChanged.addListener(getLanguage); + getLanguage(); + }, [getBackgroundStorage]); + + const handleLanguageChangeRequest = useCallback( + (e: RadioChangeEvent) => { + handleChangeLanguage(e.target.value); + posthog.sendEvent(PostHogAction.UserWalletProfileLanguageSelectClick, { language: e.target.value }); + }, + [handleChangeLanguage, posthog] + ); + + return ( +
+
+ +
+
+
+ {t('browserView.settings.wallet.language.title')} +
+
+ {t('browserView.settings.wallet.language.drawerDescription')} +
+
+
+ + {LANG_CHOICES.map((choice) => ( + + {choice} + + ))} + +
+
+ ); +}; diff --git a/apps/browser-extension-wallet/src/components/MainMenu/DropdownMenuOverlay/components/NetworkInfo.module.scss b/apps/browser-extension-wallet/src/components/MainMenu/DropdownMenuOverlay/components/NetworkInfo.module.scss index 8b881dff1a..9915627f89 100644 --- a/apps/browser-extension-wallet/src/components/MainMenu/DropdownMenuOverlay/components/NetworkInfo.module.scss +++ b/apps/browser-extension-wallet/src/components/MainMenu/DropdownMenuOverlay/components/NetworkInfo.module.scss @@ -35,3 +35,10 @@ font-size: 14px !important; } } + +.radioGroup { + color: var(--text-color-primary) !important; + label { + color: var(--text-color-primary) !important; + } +} diff --git a/apps/browser-extension-wallet/src/components/MainMenu/DropdownMenuOverlay/components/index.ts b/apps/browser-extension-wallet/src/components/MainMenu/DropdownMenuOverlay/components/index.ts index 83a1cedd44..d5aae19376 100644 --- a/apps/browser-extension-wallet/src/components/MainMenu/DropdownMenuOverlay/components/index.ts +++ b/apps/browser-extension-wallet/src/components/MainMenu/DropdownMenuOverlay/components/index.ts @@ -12,3 +12,5 @@ export * from './NetworkInfo'; export * from './AddNewWalletLink'; export * from './AddNewBitcoinWalletLink'; export * from './RenameWalletDrawer'; +export * from './LanguageInfo'; +export * from './LanguageChoice'; diff --git a/apps/browser-extension-wallet/src/components/MainMenu/DropdownMenuOverlay/types.ts b/apps/browser-extension-wallet/src/components/MainMenu/DropdownMenuOverlay/types.ts index 232d2156ad..6c06239768 100644 --- a/apps/browser-extension-wallet/src/components/MainMenu/DropdownMenuOverlay/types.ts +++ b/apps/browser-extension-wallet/src/components/MainMenu/DropdownMenuOverlay/types.ts @@ -1,5 +1,6 @@ export enum Sections { Main = 'main', NetworkInfo = 'network_info', - WalletAccounts = 'wallet_accounts' + WalletAccounts = 'wallet_accounts', + Language = 'language' } diff --git a/apps/browser-extension-wallet/src/hooks/useAppInit.ts b/apps/browser-extension-wallet/src/hooks/useAppInit.ts index 5db80a87e1..955994171b 100644 --- a/apps/browser-extension-wallet/src/hooks/useAppInit.ts +++ b/apps/browser-extension-wallet/src/hooks/useAppInit.ts @@ -9,6 +9,9 @@ import { setBackgroundStorage } from '@lib/scripts/background/storage'; import { useCustomSubmitApi } from '@hooks/useCustomSubmitApi'; import { bitcoinWalletManager } from '@lib/wallet-api-ui'; import { useCurrentBlockchain } from '@src/multichain'; +import { useBackgroundServiceAPIContext } from '@providers'; +import { initI18n } from '@lace/translation'; +import { Message, MessageTypes } from '@lib/scripts/types'; export const useAppInit = (): void => { const { @@ -26,6 +29,28 @@ export const useAppInit = (): void => { const walletState = useWalletState(); const { environmentName, currentChain } = useWalletStore(); const { getCustomSubmitApiForNetwork } = useCustomSubmitApi(); + const backgroundServices = useBackgroundServiceAPIContext(); + + useEffect(() => { + const subscription = backgroundServices.requestMessage$?.subscribe(({ type, data }: Message): void => { + if (type === MessageTypes.CHANGE_LANGUAGE) { + initI18n(data); + backgroundServices.setBackgroundStorage({ languageChoice: data }); + } + }); + + backgroundServices + .getBackgroundStorage() + .then((bs) => { + initI18n(bs.languageChoice ?? globalThis.navigator.language ?? 'en'); + }) + .catch((error) => { + // eslint-disable-next-line no-console + console.log(error); + }); + + return () => subscription.unsubscribe(); + }, [backgroundServices]); useEffect(() => { setWalletState(walletState); diff --git a/apps/browser-extension-wallet/src/lib/scripts/background/config.ts b/apps/browser-extension-wallet/src/lib/scripts/background/config.ts index 8277d1d129..2dd90e932a 100644 --- a/apps/browser-extension-wallet/src/lib/scripts/background/config.ts +++ b/apps/browser-extension-wallet/src/lib/scripts/background/config.ts @@ -23,6 +23,7 @@ export const backgroundServiceProperties: RemoteApiProperties handleOpenNamiBrowser: RemoteApiPropertyType.MethodReturningPromise, closeAllTabsAndOpenPopup: RemoteApiPropertyType.MethodReturningPromise, handleChangeTheme: RemoteApiPropertyType.MethodReturningPromise, + handleChangeLanguage: RemoteApiPropertyType.MethodReturningPromise, handleChangeMode: RemoteApiPropertyType.MethodReturningPromise, clearBackgroundStorage: RemoteApiPropertyType.MethodReturningPromise, getBackgroundStorage: RemoteApiPropertyType.MethodReturningPromise, diff --git a/apps/browser-extension-wallet/src/lib/scripts/background/services/utilityServices.ts b/apps/browser-extension-wallet/src/lib/scripts/background/services/utilityServices.ts index 1cf1b1d83d..11bff277af 100644 --- a/apps/browser-extension-wallet/src/lib/scripts/background/services/utilityServices.ts +++ b/apps/browser-extension-wallet/src/lib/scripts/background/services/utilityServices.ts @@ -42,6 +42,7 @@ import { POPUP_WINDOW_NAMI_TITLE } from '@utils/constants'; import { catchAndBrandExtensionApiError } from '@utils/catch-and-brand-extension-api-error'; import { initCardanoTokenPrices } from './cardanoTokenPrices'; import { pollController$ } from '../session/poll-controller'; +import { Language } from '@lace/translation'; export const requestMessage$ = new Subject(); export const backendFailures$ = new BehaviorSubject(0); @@ -181,6 +182,8 @@ const closeAllTabsAndOpenPopup = async () => { const handleChangeTheme = (data: ChangeThemeData) => requestMessage$.next({ type: MessageTypes.CHANGE_THEME, data }); +const handleChangeLanguage = (data: Language) => requestMessage$.next({ type: MessageTypes.CHANGE_LANGUAGE, data }); + const handleChangeMode = (data: ChangeModeData) => requestMessage$.next({ type: MessageTypes.CHANGE_MODE, data }); const { ADA_PRICE_CHECK_INTERVAL, SAVED_PRICE_DURATION } = config(); @@ -352,6 +355,7 @@ export const exposeBackgroundService = (wallet$: Observable): void migrationState$, coinPrices, handleChangeTheme, + handleChangeLanguage, handleChangeMode, clearBackgroundStorage, getBackgroundStorage, diff --git a/apps/browser-extension-wallet/src/lib/scripts/types/background-service.ts b/apps/browser-extension-wallet/src/lib/scripts/types/background-service.ts index f95e4cd541..9175034986 100644 --- a/apps/browser-extension-wallet/src/lib/scripts/types/background-service.ts +++ b/apps/browser-extension-wallet/src/lib/scripts/types/background-service.ts @@ -3,6 +3,7 @@ import { themes } from '@providers/ThemeProvider'; import { BackgroundStorage, MigrationState } from './storage'; import { CoinPrices } from './prices'; import type { clearBackgroundStorage } from '../background/storage'; +import { Language } from '@lace/translation'; export enum BaseChannels { BACKGROUND_ACTIONS = 'background-actions' @@ -31,7 +32,8 @@ export enum MessageTypes { HTTP_CONNECTION = 'http-connnection', WS_CONNECTION = 'ws-connnection', OPEN_COLLATERAL_SETTINGS = 'open-collateral-settings', - CHANGE_MODE = 'change-mode' + CHANGE_MODE = 'change-mode', + CHANGE_LANGUAGE = 'change-language' } export enum BrowserViewSections { @@ -84,12 +86,22 @@ interface ChangeMode { type: MessageTypes.CHANGE_MODE; data: ChangeModeData; } +interface ChangeThemeMessage { + type: MessageTypes.CHANGE_THEME; + data: ChangeThemeData; +} + +interface ChangeLanguageMessage { + type: MessageTypes.CHANGE_LANGUAGE; + data: Language; +} export type Message = | ChangeThemeMessage | HTTPConnectionMessage | WSConnectionMessage | OpenBrowserMessage - | ChangeMode; + | ChangeMode + | ChangeLanguageMessage; export type UnhandledError = { type: 'error' | 'unhandledrejection'; @@ -104,6 +116,7 @@ export type BackgroundService = { migrationState$: BehaviorSubject; coinPrices: CoinPrices; handleChangeTheme: (data: ChangeThemeData) => void; + handleChangeLanguage: (data: Language) => void; handleChangeMode: (data: ChangeModeData) => void; setBackgroundStorage: (data: BackgroundStorage) => Promise; getBackgroundStorage: () => Promise; diff --git a/apps/browser-extension-wallet/src/lib/scripts/types/storage.ts b/apps/browser-extension-wallet/src/lib/scripts/types/storage.ts index 7d0de03948..b612fbbccb 100644 --- a/apps/browser-extension-wallet/src/lib/scripts/types/storage.ts +++ b/apps/browser-extension-wallet/src/lib/scripts/types/storage.ts @@ -8,6 +8,7 @@ import { RawFeatureFlagPayloads } from '@lib/scripts/types/feature-flags'; import { LogLevelString } from '@lace/common'; +import { Language } from '@lace/translation'; export interface PendingMigrationState { from: string; @@ -49,6 +50,7 @@ export interface BackgroundStorage { dappInjectCompatibilityMode?: boolean; optedInBeta?: boolean; logLevel?: LogLevelString; + languageChoice?: Language; } export type BackgroundStorageKeys = keyof BackgroundStorage; diff --git a/apps/browser-extension-wallet/src/views/bitcoin-mode/features/activity/components/Activity.tsx b/apps/browser-extension-wallet/src/views/bitcoin-mode/features/activity/components/Activity.tsx index 57b8c2f82d..cf0dc763b7 100644 --- a/apps/browser-extension-wallet/src/views/bitcoin-mode/features/activity/components/Activity.tsx +++ b/apps/browser-extension-wallet/src/views/bitcoin-mode/features/activity/components/Activity.tsx @@ -173,7 +173,7 @@ export const Activity = (): React.ReactElement => { id: transaction.transactionHash, formattedTimestamp: transaction.status === Bitcoin.TransactionStatus.Pending - ? 'PENDING' + ? t('browserView.activity.entry.name.pending') : formattedTimestamp(new Date(transaction.timestamp * 1000)), amount: `${new BigNumber(net.toString()).dividedBy(100_000_000).toFixed(8, BigNumber.ROUND_HALF_UP)} BTC`, fiatAmount: `${computeBalance(Number(net) / SATS_IN_BTC, fiatCurrency.code, bitcoinPrice)} ${ @@ -194,7 +194,7 @@ export const Activity = (): React.ReactElement => { items }; }); - }, [addresses, recentTransactions, bitcoinPrice, explorerBaseUrl, pendingTransaction, fiatCurrency]); + }, [addresses, recentTransactions, bitcoinPrice, explorerBaseUrl, pendingTransaction, fiatCurrency, t]); const isLoading = addresses.length === 0 || explorerBaseUrl.length === 0 || currentCursor === null || !activityFetched; diff --git a/apps/browser-extension-wallet/src/views/bitcoin-mode/features/multi-wallet/restore-wallet/steps/EnterPgpPrivateKey.tsx b/apps/browser-extension-wallet/src/views/bitcoin-mode/features/multi-wallet/restore-wallet/steps/EnterPgpPrivateKey.tsx index 3d23758716..77c8355257 100644 --- a/apps/browser-extension-wallet/src/views/bitcoin-mode/features/multi-wallet/restore-wallet/steps/EnterPgpPrivateKey.tsx +++ b/apps/browser-extension-wallet/src/views/bitcoin-mode/features/multi-wallet/restore-wallet/steps/EnterPgpPrivateKey.tsx @@ -19,6 +19,7 @@ import { TextArea } from '@lace/common'; import { ShieldedPgpKeyData } from '@src/types'; import { useWalletOnboarding } from '../../walletOnboardingContext'; import { useAnalyticsContext } from '@providers'; +import { useTranslation } from 'react-i18next'; interface Validation { error?: string; @@ -53,6 +54,7 @@ const decryptQrCodeMnemonicWithPrivateKey = async ({ pgpInfo }: DecryptProps): P }; export const EnterPgpPrivateKey: VFC = () => { + const { t } = useTranslation(); const { postHogActions } = useWalletOnboarding(); const analytics = useAnalyticsContext(); const { back, createWalletData, next, pgpInfo, setPgpInfo, setMnemonic } = useRestoreWallet(); @@ -74,7 +76,7 @@ export const EnterPgpPrivateKey: VFC = () => { pgpPrivateKey: e.target.value, privateKeyIsDecrypted: privateKey.isDecrypted() }); - setValidation({ success: 'valid PGP private key' }); + setValidation({ success: t('pgp.validPrivateKey') }); } catch (error) { if (error.message === 'Misformed armored text') { setValidation({ error: i18n.t('pgp.error.misformedArmoredText') }); @@ -84,7 +86,7 @@ export const EnterPgpPrivateKey: VFC = () => { } } }, - [setValidation, pgpInfo, setPgpInfo] + [setValidation, pgpInfo, setPgpInfo, t] ); const handleNext = () => { @@ -127,7 +129,7 @@ export const EnterPgpPrivateKey: VFC = () => { pgpPrivateKey: fileinfo as string, privateKeyIsDecrypted: pk.isDecrypted() }); - setValidation({ error: null, success: 'valid PGP private key' }); + setValidation({ error: null, success: t('pgp.validPrivateKey') }); setPrivateKeyFile(keyFile?.name); }) .catch((error) => { @@ -145,7 +147,7 @@ export const EnterPgpPrivateKey: VFC = () => { setValidation({ error: error.message }); } }, - [setValidation, setPrivateKeyFile, setPgpInfo, pgpInfo] + [setValidation, setPrivateKeyFile, setPgpInfo, pgpInfo, t] ); useEffect(() => { diff --git a/apps/browser-extension-wallet/src/views/bitcoin-mode/features/multi-wallet/restore-wallet/steps/ScanShieldedMessage.tsx b/apps/browser-extension-wallet/src/views/bitcoin-mode/features/multi-wallet/restore-wallet/steps/ScanShieldedMessage.tsx index 8c72014b52..dfb64080da 100644 --- a/apps/browser-extension-wallet/src/views/bitcoin-mode/features/multi-wallet/restore-wallet/steps/ScanShieldedMessage.tsx +++ b/apps/browser-extension-wallet/src/views/bitcoin-mode/features/multi-wallet/restore-wallet/steps/ScanShieldedMessage.tsx @@ -18,7 +18,7 @@ import { } from '@input-output-hk/lace-ui-toolkit'; import { i18n } from '@lace/translation'; import jsQR, { QRCode } from 'jsqr'; -import { Trans } from 'react-i18next'; +import { Trans, useTranslation } from 'react-i18next'; import styles from './ScanShieldedMessage.module.scss'; import cn from 'classnames'; import { useAnalyticsContext } from '@providers'; @@ -46,6 +46,7 @@ interface ByteChunk { type ScannedCode = [ByteChunk, ByteChunk, ByteChunk]; export const ScanShieldedMessage: VFC = () => { + const { t } = useTranslation(); const { postHogActions } = useWalletOnboarding(); const analytics = useAnalyticsContext(); const { back, next, pgpInfo, setPgpInfo, setWalletMetadata } = useRestoreWallet(); @@ -59,7 +60,7 @@ export const ScanShieldedMessage: VFC = () => { const endVideoTracks = () => { if (streamRef.current) { - streamRef.current.getVideoTracks().forEach((t) => t.stop()); + streamRef.current.getVideoTracks().forEach((track) => track.stop()); streamRef.current = null; } }; @@ -155,7 +156,7 @@ export const ScanShieldedMessage: VFC = () => { // User may have scanned the wallet address QR code if (Wallet.Cardano.Address.fromString(code.data)) { setValidation({ - error: { title: 'Wrong QR code identified', description: 'Scan paper wallet private QR code' } + error: { title: t('pgp.wrongQrCodeHeading'), description: t('pgp.scanWalletPrivateQrCode') } }); void analytics.sendEventToPostHog(postHogActions.restore.SCAN_QR_CODE_READ_ERROR); } else if (isCodeDataCorrectFormatForPaperWallet) { @@ -164,12 +165,14 @@ export const ScanShieldedMessage: VFC = () => { next(); // Immediately move to next step } else { - setValidation({ error: { title: 'Unidentified QR code', description: 'Scan your Lace paper wallet' } }); + setValidation({ + error: { title: t('pgp.unidentifiedQrCodeHeading'), description: t('pgp.scanWalletPrivateQrCode') } + }); await analytics.sendEventToPostHog(postHogActions.restore.SCAN_QR_CODE_READ_ERROR); } setScanState('scanning'); }, - [next, setValidation, setScanState, onScanSuccess, analytics, postHogActions.restore.SCAN_QR_CODE_READ_ERROR] + [next, setValidation, setScanState, onScanSuccess, analytics, postHogActions.restore.SCAN_QR_CODE_READ_ERROR, t] ); useEffect(() => { diff --git a/apps/browser-extension-wallet/src/views/bitcoin-mode/features/multi-wallet/restore-wallet/steps/WalletOverview.tsx b/apps/browser-extension-wallet/src/views/bitcoin-mode/features/multi-wallet/restore-wallet/steps/WalletOverview.tsx index e76c36091e..d6e69209cb 100644 --- a/apps/browser-extension-wallet/src/views/bitcoin-mode/features/multi-wallet/restore-wallet/steps/WalletOverview.tsx +++ b/apps/browser-extension-wallet/src/views/bitcoin-mode/features/multi-wallet/restore-wallet/steps/WalletOverview.tsx @@ -26,6 +26,7 @@ import styles from './WalletOverview.module.scss'; import { useAnalyticsContext } from '@providers'; import { useWalletOnboarding } from '../../walletOnboardingContext'; import { useFetchCoinPrice } from '@hooks'; +import { useTranslation } from 'react-i18next'; const TOAST_DEFAULT_DURATION = 3; @@ -34,6 +35,7 @@ const handleOpenCoingeckoLink = () => { }; export const WalletOverview = (): JSX.Element => { + const { t } = useTranslation(); const coinPricing = useFetchCoinPrice(); const { postHogActions } = useWalletOnboarding(); const analytics = useAnalyticsContext(); @@ -136,10 +138,10 @@ export const WalletOverview = (): JSX.Element => { let subtitle = `${Wallet.util.lovelacesToAdaString(walletBalances.ada.toString())} ${adaSymbol}`; if (walletBalances.otherItems.size > 0) { - subtitle += ` +${walletBalances.otherItems.size} other asset(s)`; + subtitle += ` +${walletBalances.otherItems.size} ${t('generic.otherAssets')}`; } return subtitle; - }, [walletBalances.ada, walletBalances.otherItems, walletMetadata.chain, walletBalances.fetched, isLoading]); + }, [walletBalances.ada, walletBalances.otherItems, walletMetadata.chain, walletBalances.fetched, isLoading, t]); return ( void; @@ -101,13 +94,23 @@ export const SendStepOne: React.FC = ({ const [feeRate, setFeeRate] = useState(1); const handleResolver = useHandleResolver(); + const fees: RecommendedFee[] = useMemo( + () => [ + { key: 'fast', label: t('bitcoinSendMode.fee.high'), feeRate: 10, estimatedTime: '~10 min' }, + { key: 'standard', label: t('bitcoinSendMode.fee.average'), feeRate: 5, estimatedTime: '~30 min' }, + { key: 'slow', label: t('bitcoinSendMode.fee.slow'), feeRate: 1, estimatedTime: '~60 min' }, + { key: 'custom', label: t('bitcoinSendMode.fee.custom'), estimatedTime: '~?? min' } + ], + [t] + ); + const getFees = useCallback( () => fees.map((fee) => ({ ...fee, feeRate: fee.key !== 'custom' ? feeMarkets?.[fee.key]?.feeRate || fee.feeRate : fee.feeRate })), - [feeMarkets] + [feeMarkets, fees] ); const [handleVerificationState, setHandleVerificationState] = useState(); @@ -332,11 +335,7 @@ export const SendStepOne: React.FC = ({ {isPopupView && {t('browserView.transaction.send.title')}} {hasUtxosInMempool && ( - + )} = ({ setIsSummaryOpen(!isSummaryOpen)} open={isSummaryOpen} - title="Transaction hash" + title={t('generic.transactionHash')} plain > diff --git a/apps/browser-extension-wallet/src/views/browser-view/components/FundWalletBanner/FundWalletBanner.tsx b/apps/browser-extension-wallet/src/views/browser-view/components/FundWalletBanner/FundWalletBanner.tsx index 4b50b2d1e1..b10c0b75c3 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/components/FundWalletBanner/FundWalletBanner.tsx +++ b/apps/browser-extension-wallet/src/views/browser-view/components/FundWalletBanner/FundWalletBanner.tsx @@ -61,7 +61,9 @@ export const FundWalletBanner = ({