diff --git a/public/locales/de.json b/public/locales/de.json index 8e337938d7..c1475b0709 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -6,6 +6,8 @@ "sponsor": "Unterstützen", "delete": "Löschen", "continue": "Weiter", + "cancel": "Abbrechen", + "save": "Speichern", "view_more": "Mehr ansehen", "view_less": "Weniger ansehen", "copy": "Kopieren", @@ -15,7 +17,9 @@ "setup": "Einrichtung", "search": "Suche", "invite": "Einladen", - "message_prompt": "Nachricht" + "message_prompt": "Nachricht", + "and": " und ", + "edit": "Bearbeiten" }, "errors": { "generic": "Etwas ist schiefgegangen!" @@ -27,7 +31,10 @@ "retry": "Erneut Versuchen", "previous": "Vorherige", "jump_to_page": "Spring zu Seite", - "next": "Nächste" + "next": "Nächste", + "open_pdf": "PDF öffnen", + "retry_download": "Herunterladen neu versuchen", + "open_file": "Datei öffnen" }, "UploadBoard": { "files": "Dateien", @@ -56,6 +63,9 @@ "not_decrypted_yet": "Diese Nachricht ist noch nicht entschlüsselt", "broken_message": "Kaputte Nachricht", "empty_message": "Leere Nachricht" + }, + "EventReaders": { + "seen_by": "Gesehen von" } }, "Organisms": { @@ -228,6 +238,26 @@ "reset_keys_subtitle": "Das Zurücksetzen der Quersignatur-Schlüssel ist nicht umkehrbar.", "reset_keys_message": "Jeder, bei dem du dich verifiziert hast, wird Sicherheitswarnungen erhalten und deine Nachrichtensicherung geht verloren. Dies ist mit hoher Wahrscheinlichkeit nicht das was du tun möchtest, es sei denn du hast den Sicherheitsschlüssel oder die Sicherheitsphrase und jede Sitzung von der aus du quersignieren könntest verloren." }, + "RoomSettings": { + "General": "Allgemein", + "Search": "Suche", + "Members": "Mitglieder", + "Emojis": "Emojis", + "Permissions": "Berechtigungen", + "Security": "Sicherheit", + "options": "Optionen", + "invite": "Einladen", + "leave": "Verlassen", + "leave_room": "Raum verlassen", + "leave_room_confirm_message": "Bist du sicher, dass du {{room_name}} verlassen möchtest?", + "leave_room_confirm_button": "Verlassen", + "notification_header": "Benachrichtigungen (Änderung betrifft nur dich)", + "visibility_header": "Sichtbarkeit des Raums (wer beitreten kann)", + "address_header": "Adressen des Raums", + "encryption_header": "Verschlüsselung", + "message_history_header": "Sichtbarkeit des Nachrichtenverlaufs", + "room_settings_subtitle": "Einstellungen des Raums" + }, "RoomCommon": { "user_joined": " ist dem Raum beigetreten", "user_left": " hat den Raum verlassen", @@ -247,7 +277,15 @@ "name_changed": " hat den Anzeigenamen in geändert", "name_removed": " hat den Anzeigenamen entfernt", "changed_room_name": " hat den Raum Name geändert", - "new_messages": "Neue Nachrichten" + "new_messages": "Neue Nachrichten", + "drop_files": "Dateien fallenlassen in", + "room": "Raum", + "drag_and_drop": "Dateien hierher ziehen und ablegen oder anklicken für Auswahldialog", + "jump_to_latest": "Zur neusten Nachricht springen", + "jump_to_unread": "Zu Ungelesen springen", + "mark_as_read": "Als gelesen markieren", + "is_following": " verfolgt das Gespräch.", + "are_following": " verfolgen das Gespräch." }, "DrawerBreadcrumb": { "home": "Home" @@ -413,6 +451,27 @@ "settings": "Berechtigungen für Einstellungen" } }, + "RoomProfile": { + "saving_room_name": "Speichere Namen des Raums...", + "saving_room_topic": "Speichere Thema des Raums...", + "save_success": "Erfolgreich gespeichert", + "save_failed": "Speichern fehlgeschlagen", + "remove_avatar_title": "Avatar entfernen", + "remove_avatar_subtitle": "Bist du sicher, dass du den Avatar des Raums entfernen möchtest?", + "remove_avatar_button": "Entfernen", + "permission_change_room_name": "Du hast nur die Berechtigung, den Namen des Raums zu ändern", + "permission_change_room_topic": "Du hast nur die Berechtigung, das Thema des Raums zu ändern", + "permission_change_space_name": "Du hast nur die Berechtigung, den Namen des Spaces zu ändern", + "permission_change_space_topic": "Du hast nur die Berechtigung, das Thema des Spaces zu ändern", + "name_label": "Name", + "topic_label": "Thema" + }, + "RoomVisibility": { + "private": "Privat (nur mit Einladung)", + "restricted": "Eingeschränkt (Mitglieder des Spaces können beitreten)", + "restricted_unsupported": "Eingeschränkt (Nicht unterstützt: Aktualisierung des Raums erforderlich)", + "public": "Öffentlich (jeder kann beitreten)" + }, "SpaceOptions": { "leave_space": "Space verlassen", "leave_space_confirmation": "Bist du sicher, dass du den Space {{space}} verlassen möchtest?", diff --git a/public/locales/en.json b/public/locales/en.json index 4992730052..a698ac8ed9 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -6,6 +6,8 @@ "sponsor": "Support", "delete": "Delete", "continue": "Continue", + "cancel": "Cancel", + "save": "Save", "view_more": "View more", "view_less": "View less", "copy": "Copy", @@ -15,7 +17,9 @@ "setup": "Setup", "search": "Search", "invite": "Invite", - "message_prompt": "Message" + "message_prompt": "Message", + "and": " and ", + "edit": "Edit" }, "errors": { "generic": "Something went wrong!" @@ -27,7 +31,10 @@ "retry": "Retry", "previous": "Previous", "jump_to_page": "Jump To Page", - "next": "Next" + "next": "Next", + "open_pdf": "Open PDF", + "retry_download": "Retry Download", + "open_file": "Open File" }, "UploadBoard": { "files": "Files", @@ -56,6 +63,9 @@ "not_decrypted_yet": "This message is not decrypted yet", "broken_message": "Broken message", "empty_message": "Empty message" + }, + "EventReaders": { + "seen_by": "Seen by" } }, "Organisms": { @@ -228,6 +238,26 @@ "reset_keys_subtitle": "Resetting cross-signing keys is permanent.", "reset_keys_message": "Anyone you have verified with will see security alerts and your message backup will lost. You almost certainly do not want to do this, unless you have lost Security Key or Phrase and every session you can cross-sign from." }, + "RoomSettings": { + "General": "General", + "Search": "Search", + "Members": "Members", + "Emojis": "Emojis", + "Permissions": "Permissions", + "Security": "Security", + "options": "Options", + "invite": "Invite", + "leave": "Leave", + "leave_room": "Leave room", + "leave_room_confirm_message": "Are you sure you want to leave {{room_name}}?", + "leave_room_confirm_button": "Leave", + "notification_header": "Notifications (Changing this will only affect you)", + "visibility_header": "Room visibility (Who can join)", + "address_header": "Room addresses", + "encryption_header": "Encryption", + "message_history_header": "Message history visibility", + "room_settings_subtitle": "room settings" + }, "RoomCommon": { "user_joined": " joined the room", "user_left": " left the room", @@ -247,7 +277,15 @@ "name_changed": " changed their display name to ", "name_removed": " removed their display name ", "changed_room_name": " changed room name", - "new_messages": "New Messages" + "new_messages": "New Messages", + "drop_files": "Drop Files in", + "room": "Room", + "drag_and_drop": "Drag and drop files here or click for selection dialog", + "jump_to_latest": "Jump to Latest", + "jump_to_unread": "Jump to Unread", + "mark_as_read": "Mark as Read", + "is_following": " is following the conversation.", + "are_following": " are following the conversation." }, "DrawerBreadcrumb": { "home": "Home" @@ -413,6 +451,27 @@ "settings": "Settings permissions" } }, + "RoomProfile": { + "saving_room_name": "Saving room name...", + "saving_room_topic": "Saving room topic...", + "save_success": "Saved successfully", + "save_failed": "Unable to save", + "remove_avatar_title": "Remove avatar", + "remove_avatar_subtitle": "Are you sure that you want to remove room avatar?", + "remove_avatar_button": "Remove", + "permission_change_room_name": "You have permission to change room name only", + "permission_change_room_topic": "You have permission to change room topic only", + "permission_change_space_name": "You have permission to change space name only", + "permission_change_space_topic": "You have permission to change space topic only", + "name_label": "Name", + "topic_label": "Topic" + }, + "RoomVisibility": { + "private": "Private (invite only)", + "restricted": "Restricted (space members can join)", + "restricted_unsupported": "Restricted (Unsupported: room required upgrade)", + "public": "Public (anyone can join)" + }, "SpaceOptions": { "leave_space": "Leave Space", "leave_space_confirmation": "Are you sure that you want to leave the {{space}} space?", diff --git a/src/app/components/event-readers/EventReaders.tsx b/src/app/components/event-readers/EventReaders.tsx index a5a2646f48..8f70c4c638 100644 --- a/src/app/components/event-readers/EventReaders.tsx +++ b/src/app/components/event-readers/EventReaders.tsx @@ -16,6 +16,7 @@ import { config, } from 'folds'; import { Room } from 'matrix-js-sdk'; +import { useTranslation } from 'react-i18next'; import { useRoomEventReaders } from '../../hooks/useRoomEventReaders'; import { getMemberDisplayName } from '../../utils/room'; import { getMxIdLocalPart } from '../../utils/matrix'; @@ -37,6 +38,8 @@ export const EventReaders = as<'div', EventReadersProps>( const getName = (userId: string) => getMemberDisplayName(room, userId) ?? getMxIdLocalPart(userId) ?? userId; + const { t } = useTranslation(); + return ( ( >
- Seen by + {t('Components.EventReaders.seen_by')} diff --git a/src/app/molecules/room-profile/RoomProfile.jsx b/src/app/molecules/room-profile/RoomProfile.jsx index 218119845e..0990ef5677 100644 --- a/src/app/molecules/room-profile/RoomProfile.jsx +++ b/src/app/molecules/room-profile/RoomProfile.jsx @@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react'; import PropTypes from 'prop-types'; import './RoomProfile.scss'; +import { useTranslation } from 'react-i18next'; import { twemojify } from '../../../util/twemojify'; import initMatrix from '../../../client/initMatrix'; @@ -30,6 +31,8 @@ function RoomProfile({ roomId }) { type: cons.status.PRE_FLIGHT, }); + const { t } = useTranslation(); + const mx = initMatrix.matrixClient; const isDM = initMatrix.roomList.directs.has(roomId); let avatarSrc = mx.getRoom(roomId).getAvatarUrl(mx.baseUrl, 36, 36, 'crop'); @@ -76,7 +79,7 @@ function RoomProfile({ roomId }) { const newName = roomNameInput.value; if (newName !== roomName && roomName.trim() !== '') { setStatus({ - msg: 'Saving room name...', + msg: t('Molecules.RoomProfile.saving_room_name'), type: cons.status.IN_FLIGHT, }); await mx.setRoomName(roomId, newName); @@ -87,7 +90,7 @@ function RoomProfile({ roomId }) { if (newTopic !== roomTopic) { if (isMountStore.getItem()) { setStatus({ - msg: 'Saving room topic...', + msg: t('Molecules.RoomProfile.saving_room_topic'), type: cons.status.IN_FLIGHT, }); } @@ -96,13 +99,13 @@ function RoomProfile({ roomId }) { } if (!isMountStore.getItem()) return; setStatus({ - msg: 'Saved successfully', + msg: t('Molecules.RoomProfile.save_success'), type: cons.status.SUCCESS, }); } catch (err) { if (!isMountStore.getItem()) return; setStatus({ - msg: err.message || 'Unable to save.', + msg: err.message || t('Molecules.RoomProfile.save_failed'), type: cons.status.ERROR, }); } @@ -119,9 +122,9 @@ function RoomProfile({ roomId }) { const handleAvatarUpload = async (url) => { if (url === null) { const isConfirmed = await confirmDialog( - 'Remove avatar', - 'Are you sure that you want to remove room avatar?', - 'Remove', + t('Molecules.RoomProfile.remove_avatar_title'), + t('Molecules.RoomProfile.remove_avatar_subtitle'), + t('Molecules.RoomProfile.remove_avatar_button'), 'caution', ); if (isConfirmed) { @@ -132,16 +135,25 @@ function RoomProfile({ roomId }) { const renderEditNameAndTopic = () => (
- {canChangeName && } - {canChangeTopic && } - {(!canChangeName || !canChangeTopic) && {`You have permission to change ${room.isSpaceRoom() ? 'space' : 'room'} ${canChangeName ? 'name' : 'topic'} only.`}} + {canChangeName && } + {canChangeTopic && } + {(!canChangeName || !canChangeTopic) && ( + + { + // eslint-disable-next-line no-nested-ternary + room.isSpaceRoom() + ? canChangeName ? 'Molecules.RoomProfile.permission_change_space_name' : 'Molecules.RoomProfile.permission_change_space_topic' + : canChangeName ? 'Molecules.RoomProfile.permission_change_room_name' : 'Molecules.RoomProfile.permission_change_room_topic' + } + + )} { status.type === cons.status.IN_FLIGHT && {status.msg}} { status.type === cons.status.SUCCESS && {status.msg}} { status.type === cons.status.ERROR && {status.msg}} { status.type !== cons.status.IN_FLIGHT && (
- - + +
)}
@@ -155,7 +167,7 @@ function RoomProfile({ roomId }) { setIsEditing(true)} /> )} @@ -189,4 +201,4 @@ RoomProfile.propTypes = { roomId: PropTypes.string.isRequired, }; -export default RoomProfile; +export default RoomProfile; \ No newline at end of file diff --git a/src/app/molecules/room-visibility/RoomVisibility.jsx b/src/app/molecules/room-visibility/RoomVisibility.jsx index 7a8528765d..4eee679ea7 100644 --- a/src/app/molecules/room-visibility/RoomVisibility.jsx +++ b/src/app/molecules/room-visibility/RoomVisibility.jsx @@ -2,6 +2,7 @@ import React, { useState, useEffect, useCallback } from 'react'; import PropTypes from 'prop-types'; import './RoomVisibility.scss'; +import { useTranslation } from 'react-i18next'; import initMatrix from '../../../client/initMatrix'; import Text from '../../atoms/text/Text'; @@ -75,19 +76,21 @@ function RoomVisibility({ roomId }) { const myPowerlevel = room.getMember(mx.getUserId())?.powerLevel || 0; const canChange = room.currentState.hasSufficientPowerLevelFor('state_default', myPowerlevel); + const { t } = useTranslation(); + const items = [{ iconSrc: isSpace ? SpaceLockIC : HashLockIC, - text: 'Private (invite only)', + text: 'Molecules.RoomVisibility.private', type: visibility.INVITE, unsupported: false, }, { iconSrc: isSpace ? SpaceIC : HashIC, - text: roomVersion < 8 ? 'Restricted (unsupported: required room upgrade)' : 'Restricted (space member can join)', + text: roomVersion < 8 ? 'Molecules.RoomVisibility.restricted_unsupported' : 'Molecules.RoomVisibility.restricted', type: visibility.RESTRICTED, unsupported: roomVersion < 8 || noSpaceParent, }, { iconSrc: isSpace ? SpaceGlobeIC : HashGlobeIC, - text: 'Public (anyone can join)', + text: 'Molecules.RoomVisibility.public', type: visibility.PUBLIC, unsupported: false, }]; @@ -104,7 +107,7 @@ function RoomVisibility({ roomId }) { disabled={(!canChange || item.unsupported)} > - {item.text} + {t(item.text)} @@ -118,4 +121,4 @@ RoomVisibility.propTypes = { roomId: PropTypes.string.isRequired, }; -export default RoomVisibility; +export default RoomVisibility; \ No newline at end of file diff --git a/src/app/organisms/room/RoomInput.tsx b/src/app/organisms/room/RoomInput.tsx index e6c4fb73c2..5dbe971452 100644 --- a/src/app/organisms/room/RoomInput.tsx +++ b/src/app/organisms/room/RoomInput.tsx @@ -29,6 +29,7 @@ import { config, toRem, } from 'folds'; +import { useTranslation } from 'react-i18next'; import { useMatrixClient } from '../../hooks/useMatrixClient'; import { @@ -369,6 +370,8 @@ export const RoomInput = forwardRef( }); }; + const { t } = useTranslation(); + return (
{selectedFiles.length > 0 && ( @@ -420,9 +423,9 @@ export const RoomInput = forwardRef( > - {`Drop Files in "${room?.name || 'Room'}"`} + {`${t('Organisms.RoomCommon.drop_files')} "${room?.name || t('Organisms.RoomCommon.room')}"`} - Drag and drop files here or click for selection dialog + {t('Organisms.RoomCommon.drag_and_drop')} diff --git a/src/app/organisms/room/RoomSettings.jsx b/src/app/organisms/room/RoomSettings.jsx index 6327734713..47e2df5a25 100644 --- a/src/app/organisms/room/RoomSettings.jsx +++ b/src/app/organisms/room/RoomSettings.jsx @@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react'; import PropTypes from 'prop-types'; import './RoomSettings.scss'; +import { useTranslation } from 'react-i18next'; import { blurOnBubbling } from '../../atoms/button/script'; import initMatrix from '../../../client/initMatrix'; @@ -41,12 +42,12 @@ import { useForceUpdate } from '../../hooks/useForceUpdate'; import { confirmDialog } from '../../molecules/confirm-dialog/ConfirmDialog'; const tabText = { - GENERAL: 'General', - SEARCH: 'Search', - MEMBERS: 'Members', - EMOJIS: 'Emojis', - PERMISSIONS: 'Permissions', - SECURITY: 'Security', + GENERAL: 'Organisms.RoomSettings.General', + SEARCH: 'Organisms.RoomSettings.Search', + MEMBERS: 'Organisms.RoomSettings.Members', + EMOJIS: 'Organisms.RoomSettings.Emojis', + PERMISSIONS: 'Organisms.RoomSettings.Permissions', + SECURITY: 'Organisms.RoomSettings.Security', }; const tabItems = [{ @@ -80,24 +81,26 @@ function GeneralSettings({ roomId }) { const room = mx.getRoom(roomId); const canInvite = room.canInvite(mx.getUserId()); + const { t } = useTranslation(); + return ( <>
- Options + {t('Organisms.RoomSettings.options')} openInviteUser(roomId)} iconSrc={AddUserIC} > - Invite + {t('Organisms.RoomSettings.invite')} { const isConfirmed = await confirmDialog( - 'Leave room', - `Are you sure that you want to leave "${room.name}" room?`, - 'Leave', + t('Organisms.RoomSettings.leave_room'), + t('Organisms.RoomSettings.leave_room_confirm_message', { room_name: room.name }), + t('Organisms.RoomSettings.leave_room_confirm_button'), 'danger', ); if (!isConfirmed) return; @@ -105,19 +108,19 @@ function GeneralSettings({ roomId }) { }} iconSrc={LeaveArrowIC} > - Leave + {t('Organisms.RoomSettings.leave')}
- Notification (Changing this will only affect you) + {t('Organisms.RoomSettings.notification_header')}
- Room visibility (who can join) + {t('Organisms.RoomSettings.visibility_header')}
- Room addresses + {t('Organisms.RoomSettings.address_header')}
@@ -129,14 +132,15 @@ GeneralSettings.propTypes = { }; function SecuritySettings({ roomId }) { + const { t } = useTranslation(); return ( <>
- Encryption + {t('Organisms.RoomSettings.encryption_header')}
- Message history visibility + {t('Organisms.RoomSettings.message_history_header')}
@@ -150,6 +154,7 @@ function RoomSettings({ roomId }) { const [, forceUpdate] = useForceUpdate(); const [selectedTab, setSelectedTab] = useState(tabItems[0]); const room = initMatrix.matrixClient.getRoom(roomId); + const { t } = useTranslation(); const handleTabChange = (tabItem) => { setSelectedTab(tabItem); @@ -188,7 +193,12 @@ function RoomSettings({ roomId }) { {`${room.name}`} - — room settings + + {' '} + — + {' '} + {t('Organisms.RoomSettings.room_settings_subtitle')} + @@ -219,4 +229,4 @@ RoomSettings.propTypes = { }; export default RoomSettings; -export { tabText }; +export { tabText }; \ No newline at end of file diff --git a/src/app/organisms/room/RoomTimeline.tsx b/src/app/organisms/room/RoomTimeline.tsx index 7e2475dd26..f6caa68d4c 100644 --- a/src/app/organisms/room/RoomTimeline.tsx +++ b/src/app/organisms/room/RoomTimeline.tsx @@ -1743,7 +1743,7 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli before={} onClick={handleJumpToUnread} > - Jump to Unread + {t('Organisms.RoomCommon.jump_to_unread')} } onClick={handleMarkAsRead} > - Mark as Read + {t('Organisms.RoomCommon.mark_as_read')} )} @@ -1821,7 +1821,7 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli before={} onClick={handleJumpToLatest} > - Jump to Latest + {t('Organisms.RoomCommon.jump_to_latest')} )} diff --git a/src/app/organisms/room/RoomViewFollowing.tsx b/src/app/organisms/room/RoomViewFollowing.tsx index 2f7a583e3f..f584e50168 100644 --- a/src/app/organisms/room/RoomViewFollowing.tsx +++ b/src/app/organisms/room/RoomViewFollowing.tsx @@ -14,6 +14,7 @@ import { import { Room } from 'matrix-js-sdk'; import classNames from 'classnames'; import FocusTrap from 'focus-trap-react'; +import { useTranslation } from 'react-i18next'; import { getMemberDisplayName } from '../../utils/room'; import { getMxIdLocalPart } from '../../utils/matrix'; @@ -39,6 +40,7 @@ export const RoomViewFollowing = as<'div', RoomViewFollowingProps>( ); const eventId = latestEvent?.getId(); + const { t } = useTranslation(); return ( <> @@ -77,7 +79,7 @@ export const RoomViewFollowing = as<'div', RoomViewFollowingProps>( <> {names[0]} - {' is following the conversation.'} + {t('Organisms.RoomCommon.is_following')} )} @@ -85,11 +87,11 @@ export const RoomViewFollowing = as<'div', RoomViewFollowingProps>( <> {names[0]} - {' and '} + {t('common.and')} {names[1]} - {' are following the conversation.'} + {t('Organisms.RoomCommon.are_following')} )} @@ -101,11 +103,11 @@ export const RoomViewFollowing = as<'div', RoomViewFollowingProps>( {names[1]} - {' and '} + {t('common.and')} {names[2]} - {' are following the conversation.'} + {t('Organisms.RoomCommon.are_following')} )} @@ -121,11 +123,11 @@ export const RoomViewFollowing = as<'div', RoomViewFollowingProps>( {names[2]} - {' and '} + {t('common.and')} {names.length - 3} others - {' are following the conversation.'} + {t('Organisms.RoomCommon.are_following')} )} diff --git a/src/app/organisms/room/message/FileContent.tsx b/src/app/organisms/room/message/FileContent.tsx index 9c65966708..f7f52b381d 100644 --- a/src/app/organisms/room/message/FileContent.tsx +++ b/src/app/organisms/room/message/FileContent.tsx @@ -17,6 +17,7 @@ import { import FileSaver from 'file-saver'; import { EncryptedAttachmentInfo } from 'browser-encrypt-attachment'; import FocusTrap from 'focus-trap-react'; +import { useTranslation } from 'react-i18next'; import { IFileInfo } from '../../../../types/matrix/common'; import { AsyncStatus, useAsyncCallback } from '../../../hooks/useAsyncCallback'; import { useMatrixClient } from '../../../hooks/useMatrixClient'; @@ -88,6 +89,8 @@ function ReadTextFile({ body, mimeType, url, encInfo }: Omit {textState.status === AsyncStatus.Success && ( @@ -141,7 +144,7 @@ function ReadTextFile({ body, mimeType, url, encInfo }: Omit - Open File + {t('Components.Files.open_file')} )} @@ -161,6 +164,8 @@ function ReadPdfFile({ body, mimeType, url, encInfo }: Omit {pdfState.status === AsyncStatus.Success && ( @@ -189,7 +194,7 @@ function ReadPdfFile({ body, mimeType, url, encInfo }: Omit )} {pdfState.status === AsyncStatus.Error ? ( - renderErrorButton(loadPdf, 'Open PDF') + renderErrorButton(loadPdf, t('Components.Files.open_pdf')) ) : ( )} @@ -226,8 +231,13 @@ function DownloadFile({ body, mimeType, url, info, encInfo }: FileContentProps) }, [mx, url, mimeType, encInfo, body]) ); + const { t } = useTranslation(); + return downloadState.status === AsyncStatus.Error ? ( - renderErrorButton(download, `Retry Download (${bytesToSize(info.size ?? 0)})`) + renderErrorButton( + download, + `${t('Components.Files.retry_download')} (${bytesToSize(info.size ?? 0)})` + ) ) : ( ); }