diff --git a/public/locales/de.json b/public/locales/de.json
index 98020e116..8e337938d 100644
--- a/public/locales/de.json
+++ b/public/locales/de.json
@@ -2,6 +2,8 @@
"common": {
"close": "Schließen",
"options": "Optionen",
+ "source_code": "Quellcode",
+ "sponsor": "Unterstützen",
"delete": "Löschen",
"continue": "Weiter",
"view_more": "Mehr ansehen",
@@ -36,7 +38,8 @@
"invited": " hat eingeladen",
"reject_invite": " hat die Einladung abgelehnt ",
"requested_join": " hat angefragt dem Raum bei zu tretten ",
- "joined": " ist dem Raum beigetreten"
+ "joined": " ist dem Raum beigetreten",
+ "left_room": " hat den Raum verlassen "
},
"RoomIntro": {
"created_by_on": "Erstellt von am {{time}}",
@@ -44,6 +47,15 @@
"invite_member": "Nutzer einladen",
"open_old_room": "Alten Raum öffnen",
"join_old_room": "Altem Raum beitreten"
+ },
+ "MessageContentFallback": {
+ "message_deleted": "Diese Nachricht wurde gelöscht",
+ "unsupported_message": "Nicht unterstützte Nachricht",
+ "failed_to_load_message": "Meldung konnte nicht geladen werden",
+ "unable_to_decrypt": "Nachricht kann nicht entschlüsselt werden",
+ "not_decrypted_yet": "Diese Nachricht ist noch nicht entschlüsselt",
+ "broken_message": "Kaputte Nachricht",
+ "empty_message": "Leere Nachricht"
}
},
"Organisms": {
@@ -106,6 +118,45 @@
"emoji": "Emoji",
"security": "Sicherheit",
"about": "Über"
+ },
+ "notifications_and_sound": {
+ "title": "Benachrichtungen & Töne",
+ "desktop": {
+ "title": "Desktop-Benachrichtigungen",
+ "description": "Bei Eintreffen neuer Nachrichten Desktop-Benachrichtigung anzeigen."
+ },
+ "sound": {
+ "title": "Benachrichtigungstöne",
+ "description": "Bei Eintreffen neuer Nachrichten Ton abspielen."
+ }
+ },
+ "security": {
+ "cross_signing": {
+ "title": "Quersignaturen und Sicherung"
+ },
+ "export_import_encryption_keys": {
+ "title": "Schlüssel exportieren/importieren"
+ },
+ "export_encryption_keys": {
+ "title": "Raumschlüssel exportieren",
+ "description": "Raumschlüssel für die Entschlüsselung alter Nachrichten einer anderen Sitzung exportieren. Um Raumschlüssel zu verschlüsseln muss ein Kennwort vergeben werden, das während des Importierens verwendet wird."
+ },
+ "import_encryption_keys": {
+ "title": "Raumschlüssel importieren",
+ "description": "Raumschlüssel für die Entschlüsselung alter Nachrichten einer anderen Sitzung importieren. Um Raumschlüssel zu entschlüsseln muss das Kennwort eingegeben werden, das während des Exportierens verwendet wurde."
+ }
+ },
+ "logout": {
+ "title": "Abmelden",
+ "dialog": {
+ "title": "Abmelden",
+ "description": "Bist du sicher, dass du dich von dieser Sitzung abmelden möchtest?",
+ "confirm": "Abmelden"
+ }
+ },
+ "about": {
+ "application": "Anwendung",
+ "credits": "Credits"
}
},
"SecretStorageAccess": {
@@ -195,7 +246,8 @@
"name_set": " hat den Anzeigenamen gewählt",
"name_changed": " hat den Anzeigenamen in geändert",
"name_removed": " hat den Anzeigenamen entfernt",
- "changed_room_name": " hat den Raum Name geändert"
+ "changed_room_name": " hat den Raum Name geändert",
+ "new_messages": "Neue Nachrichten"
},
"DrawerBreadcrumb": {
"home": "Home"
@@ -444,5 +496,10 @@
"logout_prompt": "Abmeldung",
"clear_cache": "Zwischenspeicher löschen & neuladen"
}
+ },
+ "Time": {
+ "today": "Heute",
+ "yesterday": "Gestern",
+ "timeHourMinute": "HH:mm"
}
}
diff --git a/public/locales/en.json b/public/locales/en.json
index 671955836..499273005 100644
--- a/public/locales/en.json
+++ b/public/locales/en.json
@@ -2,6 +2,8 @@
"common": {
"close": "Close",
"options": "Options",
+ "source_code": "Source code",
+ "sponsor": "Support",
"delete": "Delete",
"continue": "Continue",
"view_more": "View more",
@@ -36,7 +38,8 @@
"invited": " invited ",
"reject_invite": " rejected the invitation ",
"requested_join": " request to join room ",
- "joined": " joined the room"
+ "joined": " joined the room",
+ "left_room": " left the room "
},
"RoomIntro": {
"created_by_on": "Created by on {{time}}",
@@ -44,6 +47,15 @@
"invite_member": "Invite Member",
"open_old_room": "Open Old Room",
"join_old_room": "Join Old Room"
+ },
+ "MessageContentFallback": {
+ "message_deleted": "This message has been deleted",
+ "unsupported_message": "Unsupported message",
+ "failed_to_load_message": "Failed to load message",
+ "unable_to_decrypt": "Unable to decrypt message",
+ "not_decrypted_yet": "This message is not decrypted yet",
+ "broken_message": "Broken message",
+ "empty_message": "Empty message"
}
},
"Organisms": {
@@ -106,6 +118,45 @@
"emoji": "Emoji",
"security": "Security",
"about": "About"
+ },
+ "notifications_and_sound": {
+ "title": "Notifications & Sound",
+ "desktop": {
+ "title": "Desktop notifications",
+ "description": "Show desktop notifications when new messages arrive."
+ },
+ "sound": {
+ "title": "Notification sound",
+ "description": "Play a sound when new messages arrive."
+ }
+ },
+ "security": {
+ "cross_signing": {
+ "title": "Cross signing and backup"
+ },
+ "export_import_encryption_keys": {
+ "title": "Export / Import encryption keys"
+ },
+ "export_encryption_keys": {
+ "title": "Export E2E room keys",
+ "description": "Export end-to-end encryption room keys to decrypt old messages in other session. In order to encrypt keys you need to set a password, which will be used while importing."
+ },
+ "import_encryption_keys": {
+ "title": "Import E2E room keys",
+ "description": "To decrypt older messages, Export E2EE room keys from Element (Settings > Security & Privacy > Encryption > Cryptography) and import them here. Imported keys are encrypted so you\\'ll have to enter the password you set in order to decrypt it."
+ }
+ },
+ "logout": {
+ "title": "Logout",
+ "dialog": {
+ "title": "Logout",
+ "description": "Are you sure that you want to logout your session?",
+ "confirm": "Logout"
+ }
+ },
+ "about": {
+ "application": "Application",
+ "credits": "Credits"
}
},
"SecretStorageAccess": {
@@ -195,7 +246,8 @@
"name_set": " set their display name to ",
"name_changed": " changed their display name to ",
"name_removed": " removed their display name ",
- "changed_room_name": " changed room name"
+ "changed_room_name": " changed room name",
+ "new_messages": "New Messages"
},
"DrawerBreadcrumb": {
"home": "Home"
@@ -444,5 +496,10 @@
"logout_prompt": "Logout",
"clear_cache": "Clear cache & reload"
}
+ },
+ "Time": {
+ "today": "Today",
+ "yesterday": "Yesterday",
+ "timeHourMinute": "hh:mm A"
}
}
diff --git a/src/app/components/message/MessageContentFallback.tsx b/src/app/components/message/MessageContentFallback.tsx
index 9edb96784..9a34e118f 100644
--- a/src/app/components/message/MessageContentFallback.tsx
+++ b/src/app/components/message/MessageContentFallback.tsx
@@ -1,5 +1,6 @@
import { Box, Icon, Icons, Text, as, color, config } from 'folds';
import React from 'react';
+import { Trans } from 'react-i18next';
const warningStyle = { color: color.Warning.Main, opacity: config.opacity.P300 };
const criticalStyle = { color: color.Critical.Main, opacity: config.opacity.P300 };
@@ -9,9 +10,9 @@ export const MessageDeletedContent = as<'div', { children?: never; reason?: stri
{reason ? (
- This message has been deleted. {reason}
+ . {reason}
) : (
- This message has been deleted
+
)}
)
@@ -20,42 +21,42 @@ export const MessageDeletedContent = as<'div', { children?: never; reason?: stri
export const MessageUnsupportedContent = as<'div', { children?: never }>(({ ...props }, ref) => (
- Unsupported message
+
));
export const MessageFailedContent = as<'div', { children?: never }>(({ ...props }, ref) => (
- Failed to load message
+
));
export const MessageBadEncryptedContent = as<'div', { children?: never }>(({ ...props }, ref) => (
- Unable to decrypt message
+
));
export const MessageNotDecryptedContent = as<'div', { children?: never }>(({ ...props }, ref) => (
- This message is not decrypted yet
+
));
export const MessageBrokenContent = as<'div', { children?: never }>(({ ...props }, ref) => (
- Broken message
+
));
export const MessageEmptyContent = as<'div', { children?: never }>(({ ...props }, ref) => (
- Empty message
+
));
diff --git a/src/app/components/message/Time.tsx b/src/app/components/message/Time.tsx
index de11cf896..fef28cc45 100644
--- a/src/app/components/message/Time.tsx
+++ b/src/app/components/message/Time.tsx
@@ -1,6 +1,8 @@
import React from 'react';
import { Text, as } from 'folds';
-import { timeDayMonYear, timeHourMinute, today, yesterday } from '../../utils/time';
+import { useTranslation } from 'react-i18next';
+import dayjs from 'dayjs';
+import { timeDayMonYear, today, yesterday } from '../../utils/time';
export type TimeProps = {
compact?: boolean;
@@ -8,15 +10,17 @@ export type TimeProps = {
};
export const Time = as<'span', TimeProps>(({ compact, ts, ...props }, ref) => {
+ const { t } = useTranslation();
+
+ const timeHourMinute = dayjs(ts).format(t('Time.timeHourMinute'));
+
let time = '';
- if (compact) {
- time = timeHourMinute(ts);
- } else if (today(ts)) {
- time = timeHourMinute(ts);
+ if (compact || today(ts)) {
+ time = timeHourMinute;
} else if (yesterday(ts)) {
- time = `Yesterday ${timeHourMinute(ts)}`;
+ time = `${t('Time.yesterday')} ${timeHourMinute}`;
} else {
- time = `${timeDayMonYear(ts)} ${timeHourMinute(ts)}`;
+ time = `${timeDayMonYear(ts)} ${timeHourMinute}`;
}
return (
diff --git a/src/app/components/room-intro/RoomIntro.tsx b/src/app/components/room-intro/RoomIntro.tsx
index a54af1965..a9963cf10 100644
--- a/src/app/components/room-intro/RoomIntro.tsx
+++ b/src/app/components/room-intro/RoomIntro.tsx
@@ -2,6 +2,7 @@ import React, { useCallback } from 'react';
import { Avatar, AvatarFallback, AvatarImage, Box, Button, Spinner, Text, as, color } from 'folds';
import { Room } from 'matrix-js-sdk';
import { useTranslation, Trans } from 'react-i18next';
+import dayjs from 'dayjs';
import { openInviteUser, selectRoom } from '../../../client/action/navigation';
import { useStateEvent } from '../../hooks/useStateEvent';
import { IRoomCreateContent, Membership, StateEvent } from '../../../types/matrix/room';
@@ -9,7 +10,7 @@ import { getMemberDisplayName, getStateEvent } from '../../utils/room';
import { useMatrixClient } from '../../hooks/useMatrixClient';
import { getMxIdLocalPart } from '../../utils/matrix';
import { AsyncStatus, useAsyncCallback } from '../../hooks/useAsyncCallback';
-import { timeDayMonthYear, timeHourMinute } from '../../utils/time';
+import { timeDayMonthYear } from '../../utils/time';
export type RoomIntroProps = {
room: Room;
@@ -69,7 +70,7 @@ export const RoomIntro = as<'div', RoomIntroProps>(({ room, ...props }, ref) =>
@{creatorName} }}
- values={{ time: `${timeDayMonthYear(ts)} ${timeHourMinute(ts)}` }}
+ values={{ time: `${timeDayMonthYear(ts)} ${dayjs(ts).format(t('Time.timeHourMinute'))}` }}
/>
)}
diff --git a/src/app/hooks/useMemberEventParser.tsx b/src/app/hooks/useMemberEventParser.tsx
index fc2c5318d..d5fc7740b 100644
--- a/src/app/hooks/useMemberEventParser.tsx
+++ b/src/app/hooks/useMemberEventParser.tsx
@@ -152,7 +152,7 @@ export const useMemberEventParser = (): MemberEventParser => {
senderId === userId ? (
<>
{userName}
- {' left the room '}
+ {t('Components.MemberEvent.left_room')}
{content.reason}
>
) : (
diff --git a/src/app/organisms/room/RoomTimeline.tsx b/src/app/organisms/room/RoomTimeline.tsx
index 989d50440..7e2475dd2 100644
--- a/src/app/organisms/room/RoomTimeline.tsx
+++ b/src/app/organisms/room/RoomTimeline.tsx
@@ -1693,7 +1693,7 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
- New Messages
+ {t('Organisms.RoomCommon.new_messages')}
@@ -1706,8 +1706,8 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
{(() => {
- if (today(mEvent.getTs())) return 'Today';
- if (yesterday(mEvent.getTs())) return 'Yesterday';
+ if (today(mEvent.getTs())) return t('Time.today');
+ if (yesterday(mEvent.getTs())) return t('Time.yesterday');
return timeDayMonthYear(mEvent.getTs());
})()}
diff --git a/src/app/organisms/settings/Settings.jsx b/src/app/organisms/settings/Settings.jsx
index a81764723..53f6f88d9 100644
--- a/src/app/organisms/settings/Settings.jsx
+++ b/src/app/organisms/settings/Settings.jsx
@@ -233,6 +233,8 @@ function NotificationsSection() {
const [, updateState] = useState({});
+ const { t } = useTranslation();
+
const renderOptions = () => {
if (window.Notification === undefined) {
return Not supported in this browser.;
@@ -264,21 +266,21 @@ function NotificationsSection() {
return (
<>
- Notification & Sound
+ {t('Organisms.Settings.notifications_and_sound.title')}Show desktop notification when new messages arrive.}
+ content={{t('Organisms.Settings.notifications_and_sound.desktop.description')}}
/>
{ toggleNotificationSounds(); updateState({}); }}
/>
)}
- content={Play sound when new messages arrive.}
+ content={{t('Organisms.Settings.notifications_and_sound.desktop.description')}}
/>
@@ -298,30 +300,32 @@ function EmojiSection() {
}
function SecuritySection() {
+ const { t } = useTranslation();
+
return (
- Cross signing and backup
+ {t('Organisms.Settings.security.cross_signing.title')}
- Export/Import encryption keys
+ {t('Organisms.Settings.security.export_import_encryption_keys.title')}
- Export end-to-end encryption room keys to decrypt old messages in other session. In order to encrypt keys you need to set a password, which will be used while importing.
+ {t('Organisms.Settings.security.export_encryption_keys.description')}
>
)}
/>
- {'To decrypt older messages, Export E2EE room keys from Element (Settings > Security & Privacy > Encryption > Cryptography) and import them here. Imported keys are encrypted so you\'ll have to enter the password you set in order to decrypt it.'}
+ {t('Organisms.Settings.security.import_encryption_keys.description')}
>
)}
@@ -332,10 +336,12 @@ function SecuritySection() {
}
function AboutSection() {
+ const { t } = useTranslation();
+
return (