diff --git a/libs/i18n/src/locales/en/ledger.json b/libs/i18n/src/locales/en/ledger.json new file mode 100644 index 000000000..a0c15ba17 --- /dev/null +++ b/libs/i18n/src/locales/en/ledger.json @@ -0,0 +1,18 @@ +{ + "Date from": "Date from", + "Date to": "Date to", + "Download": "Download", + "Download all to .csv file": "Download all to .csv file", + "Download has been started": "Download has been started", + "Downloading for {{asset}} from {{startDate}} till {{endDate}}": "Downloading for {{asset}} from {{startDate}} till {{endDate}}", + "Export ledger entries": "Export ledger entries", + "Get file here": "Get file here", + "Please note this can take several minutes.": "Please note this can take several minutes.", + "Select asset": "Select asset", + "Something went wrong": "Something went wrong", + "Still in progress": "Still in progress", + "The downloaded file uses the UTC time zone for all listed times. Your time zone is UTC{{offset}}.": "The downloaded file uses the UTC time zone for all listed times. Your time zone is UTC{{offset}}.", + "Try again later": "Try again later", + "You will be notified here when your file is ready.": "You will be notified here when your file is ready.", + "Your file is ready": "Your file is ready" +} diff --git a/libs/ledger/__mocks__/react-i18next.ts b/libs/ledger/__mocks__/react-i18next.ts new file mode 100644 index 000000000..7c2343f52 --- /dev/null +++ b/libs/ledger/__mocks__/react-i18next.ts @@ -0,0 +1,14 @@ +export const useTranslation = () => ({ + t: (label: string, replacements?: Record) => { + let translatedLabel = label; + if (typeof replacements === 'object' && replacements !== null) { + Object.keys(replacements).forEach((key) => { + translatedLabel = translatedLabel.replace( + `{{${key}}}`, + replacements[key] + ); + }); + } + return translatedLabel; + }, +}); diff --git a/libs/ledger/src/lib/ledger-download-store.tsx b/libs/ledger/src/lib/ledger-download-store.tsx index eb19de4df..bb613572b 100644 --- a/libs/ledger/src/lib/ledger-download-store.tsx +++ b/libs/ledger/src/lib/ledger-download-store.tsx @@ -3,8 +3,8 @@ import type { ReactNode } from 'react'; import { useCallback, useEffect } from 'react'; import type { Toast } from '@vegaprotocol/ui-toolkit'; import { useToasts, Intent } from '@vegaprotocol/ui-toolkit'; -import { t } from '@vegaprotocol/i18n'; import { subscribeWithSelector } from 'zustand/middleware'; +import { useT } from './use-t'; type DownloadSettings = { title: string; @@ -52,24 +52,31 @@ export const useLedgerDownloadFile = create()( })) ); -const ErrorContent = ({ message }: { message?: string }) => ( - <> -

{t('Something went wrong')}

-

{message || t('Try again later')}

- -); +const ErrorContent = ({ message }: { message?: string }) => { + const t = useT(); + return ( + <> +

{t('Something went wrong')}

+

{message || t('Try again later')}

+ + ); +}; -const InfoContent = ({ progress = false }) => ( - <> -

{t('Please note this can take several minutes.')}

-

{t('You will be notified here when your file is ready.')}

-

- {progress ? t('Still in progress') : t('Download has been started')} -

- -); +const InfoContent = ({ progress = false }) => { + const t = useT(); + return ( + <> +

{t('Please note this can take several minutes.')}

+

{t('You will be notified here when your file is ready.')}

+

+ {progress ? t('Still in progress') : t('Download has been started')} +

+ + ); +}; export const useLedgerDownloadManager = () => { + const t = useT(); const queue = useLedgerDownloadFile((store) => store.queue); const updateQueue = useLedgerDownloadFile((store) => store.updateQueue); const removeItem = useLedgerDownloadFile((store) => store.removeItem); @@ -88,48 +95,51 @@ export const useLedgerDownloadManager = () => { [removeToast, removeItem] ); - const createToast = (item: DownloadSettings) => { - let content: ReactNode; - switch (true) { - case item.isError: - content = ; - break; - case Boolean(item.blob): - content = ( + const createToast = useCallback( + (item: DownloadSettings) => { + let content: ReactNode; + switch (true) { + case item.isError: + content = ; + break; + case Boolean(item.blob): + content = ( + <> +

{t('Your file is ready')}

+ onDownloadClose(item.link)} + href={URL.createObjectURL(item.blob as Blob)} + download={item.filename} + className="underline" + > + {t('Get file here')} + + + ); + break; + default: + content = ; + } + const toast: Toast = { + id: item.link, + intent: item.intent || Intent.Primary, + content: ( <> -

{t('Your file is ready')}

- onDownloadClose(item.link)} - href={URL.createObjectURL(item.blob as Blob)} - download={item.filename} - className="underline" - > - {t('Get file here')} - +

{item.title}

+ {content} - ); - break; - default: - content = ; - } - const toast: Toast = { - id: item.link, - intent: item.intent || Intent.Primary, - content: ( - <> -

{item.title}

- {content} - - ), - onClose: () => onDownloadClose(item.link), - loader: !item.isDownloaded && !item.isError, - }; - if (hasToast(toast.id)) { - updateToast(toast.id, toast); - } else { - setToast(toast); - } - }; + ), + onClose: () => onDownloadClose(item.link), + loader: !item.isDownloaded && !item.isError, + }; + if (hasToast(toast.id)) { + updateToast(toast.id, toast); + } else { + setToast(toast); + } + }, + [hasToast, setToast, onDownloadClose, updateToast, t] + ); useEffect(() => { queue.forEach((item) => { diff --git a/libs/ledger/src/lib/ledger-export-form.tsx b/libs/ledger/src/lib/ledger-export-form.tsx index 135a63f38..d5e3c886f 100644 --- a/libs/ledger/src/lib/ledger-export-form.tsx +++ b/libs/ledger/src/lib/ledger-export-form.tsx @@ -14,9 +14,9 @@ import { toNanoSeconds, VEGA_ID_REGEX, } from '@vegaprotocol/utils'; -import { t } from '@vegaprotocol/i18n'; import { localLoggerFactory } from '@vegaprotocol/logger'; import { useLedgerDownloadFile } from './ledger-download-store'; +import { useT } from './use-t'; const DEFAULT_EXPORT_FILE_NAME = 'ledger_entries.csv'; @@ -70,6 +70,7 @@ interface Props { } export const LedgerExportForm = ({ partyId, vegaUrl, assets }: Props) => { + const t = useT(); const now = useRef(new Date()); const [dateFrom, setDateFrom] = useState(() => { return formatForInput(subDays(now.current, 7)); @@ -116,11 +117,14 @@ export const LedgerExportForm = ({ partyId, vegaUrl, assets }: Props) => { const startDownload = async (event: React.FormEvent) => { event.preventDefault(); - const title = t('Downloading for %s from %s till %s', [ - assets[assetId], - format(new Date(dateFrom), 'dd MMMM yyyy HH:mm'), - format(new Date(dateTo || Date.now()), 'dd MMMM yyyy HH:mm'), - ]); + const title = t( + 'Downloading for {{asset}} from {{startDate}} till {{endDate}}', + { + asset: assets[assetId], + startDate: format(new Date(dateFrom), 'dd MMMM yyyy HH:mm'), + endDate: format(new Date(dateTo || Date.now()), 'dd MMMM yyyy HH:mm'), + } + ); const downloadStoreItem = { title, @@ -225,8 +229,8 @@ export const LedgerExportForm = ({ partyId, vegaUrl, assets }: Props) => { {offset && (

{t( - 'The downloaded file uses the UTC time zone for all listed times. Your time zone is UTC%s.', - [toHoursAndMinutes(offset)] + 'The downloaded file uses the UTC time zone for all listed times. Your time zone is UTC{{offset}}.', + { offset: toHoursAndMinutes(offset) } )}

)} diff --git a/libs/ledger/src/lib/use-t.jsx b/libs/ledger/src/lib/use-t.jsx new file mode 100644 index 000000000..6916b16a2 --- /dev/null +++ b/libs/ledger/src/lib/use-t.jsx @@ -0,0 +1,3 @@ +import { useTranslation } from 'react-i18next'; + +export const useT = () => useTranslation('ledger').t;