diff --git a/public/locales/de.json b/public/locales/de.json index 2f51680038..ff7a91185b 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -2,7 +2,15 @@ "common": { "close": "Schließen", "options": "Optionen", + "delete": "Löschen", + "continue": "Weiter", + "view_more": "Mehr ansehen", + "view_less": "Weniger ansehen", + "copy": "Kopieren", + "download": "Herunterladen", "or": "oder", + "reset": "Zurücksetzen", + "setup": "Einrichtung", "search": "Suche", "invite": "Einladen", "message_prompt": "Nachricht" @@ -100,6 +108,75 @@ "about": "Über" } }, + "SecretStorageAccess": { + "incorrect_security_key": "Falscher Sicherheitsschlüssel", + "incorrect_security_phrase": "Falsche Sicherheitsphrase", + "security_phrase": "Sicherheitsphrase", + "security_key": "Sicherheitsschlüssel", + "use_security_key": "Verwende Sicherheitsschlüssel", + "use_security_phrase": "Verwende Sicherheitsphrase" + }, + "KeyBackup": { + "create_backup_title": "Schlüsselsicherung erstellen", + "create_backup_tooltip": "Sicherung erstellen", + "creating_backup": "Erstelle Sicherung...", + "backup_created": "Sicherung erfolgreich erstellt", + "backup_failed": "Erstellen der Sicherung fehlgeschlagen", + "restoring": "Stelle Schlüsselsicherung wieder her...", + "restoring_progress": "Schlüsselsicherung wiederherstellen... ({{progress}}/{{total}}", + "restore_backup_title": "Schlüsselsicherung wiederherstellen", + "restore_backup_tooltip": "Schlüsselsicherung wiederherstellen", + "restore_complete": "Schlüsselsicherung erfolgreich wiederhergestellt ({{progress}}/{{total}})", + "restore_failed_bad_key": "Wiederherstellung der Sicherung fehlgeschlagen. Ungültiger Schlüssel!", + "restore_failed_unknown": "Wiederherstellung der Sicherung fehlgeschlagen.", + "delete_key_backup_title": "Schlüsselsicherung löschen", + "delete_key_backup_tooltip": "Sicherung löschen", + "delete_key_backup_subtitle": "Das Löschen von Schlüsselsicherungen ist nicht umkehrbar.", + "delete_key_backup_message": "Alle auf dem Server gespeicherten verschlüsselten Nachrichten werden dauerhaft gelöscht.", + "encrypted_messages_backup_description": "Sichere die Schlüssel für deine verschlüsselten Nachrichten online in deinem Account, falls du den Zugriff auf deine Sitzungen verlierst. Deine Schlüssel werden mit einem eindeutigen Sicherheitsschlüssel gesichert.", + "encrypted_messages_backup_title": "Verschlüsselte Nachrichten sichern", + "encrypted_messages_backup_cross_signing_disabled": "Richte Quersignaturen ein, um deine verschlüsselten Nachrichten zu sichern." + }, + "DeviceManage": { + "edit_session_name_title": "Sitzungsnamen bearbeiten", + "edit_session_name_subtitle": "Sitzungsname", + "edit_session_name_tooltip": "Sitzungsnamen bearbeiten", + "current_device_label": "Aktuell", + "verify_session_button": "Verifizieren", + "unverified_sessions_title": "Unverifizierte Sitzungen", + "unverified_sessions_none": "Keine unverifizierten Sitzungen", + "unencrypted_sessions_title": "Sitzungen ohne Unterstützung für Verschlüsselung", + "verified_sessions_title": "Verifizierte Sitzungen", + "verified_sessions_none": "Keine verifizierten Sitzungen", + "setup_cross_signing_message": "Richte Quersignaturen ein, falls du deine verschlüsselten Sitzungen verlierst", + "loading_devices": "Lade Geräte...", + "logout_device_title": "{{device}} abmelden", + "logout_device_message": "Du bist dabei dich von der Sitzung für {{device}} abzumelden", + "last_activity": "Letzte Aktivität", + "verify_this_session": "Verifizieren Sie diese Sitzung entweder mit Ihrem Sicherheitsschlüssel/-phrase hier oder indem Sie die Emoji-Verifizierung aus einer verifizierten Sitzung heraus starten.", + "verify_other_session": "Überprüfen Sie andere Sitzungen durch Emoji-Verifizierung oder entfernen Sie unbekannte.", + "logout_device_confirm": "Abmeldung", + "logout_device_tooltip": "Sitzung entfernen", + "session_verification_title": "Sitzungsverifizierung", + "session_name_privacy_message": "Sitzungsnamen sind für jeden sichtbar, also gib hier keine privaten Informationen ein." + }, + "CrossSigning": { + "title": "Quersignaturen", + "setup_failed": "Die Einrichtung von Quersignaturen ist fehlgeschlagen. Bitte versuche es erneut", + "setup": "Quersignaturen einrichten", + "save_security_key_message": "Bitte speichere diesen Sicherheitsschlüssel an einem sicheren Ort", + "security_key_dialog_title": "Sicherheitsschlüssel", + "security_key_generation_message": "Wir werden einen Sicherheitsschlüssel generieren, den du verwenden kannst um Nachrichtensicherungen und Sitzungsverifizierungen zu verwalten.", + "security_key_generation_button": "Schlüssel erzeugen", + "security_phrase_message": "Alternativ kannst du eine 'Sicherheitsphrase' festlegen, so dass du dir den langen Sicherheitsschlüssel nicht merken musst, und optional den Schlüssel als Sicherung speichern.", + "security_phrase_label": "Sicherheitsphrase", + "security_phrase_confirm_label": "Sicherheitsphrase bestätigen", + "security_phrase_set_button": "Lege Phrase fest & erzeuge Schlüssel", + "setup_dialog_title": "Quersignaturen einrichten", + "setup_message": "Richte Quersignaturen ein, um deine Sitzungen zu verifizieren und den Überblick zu behalten. Wird auch benötigt, um verschlüsselte Nachrichten zu sichern.", + "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." + }, "RoomCommon": { "user_joined": " ist dem Raum beigetreten", "user_left": " hat den Raum verlassen", @@ -190,6 +267,100 @@ "notifications_heading": "Benachrichtigungen", "invite": "Einladen" }, + "RoomPermissions": { + "default_role": { + "name": "Standardrolle", + "description": "Standardrolle für alle Mitglieder festlegen" + }, + "send_messages": { + "name": "Nachrichten senden", + "description": "Mindestberechtigungsstufe festlegen, um Nachrichten in einem Raum senden zu können" + }, + "reactions": { + "name": "Reaktionen senden", + "description": "Mindestberechtigungsstufe festlegen, um Reaktionen in einem Raum senden zu können" + }, + "delete": { + "name": "Nachrichten von anderen löschen", + "description": "Mindestberechtigungsstufe festlegen, um Nachrichten anderer Benutzer in einem Raum löschen zu können" + }, + "notifications": { + "name": "Raum anpingen", + "description": "Mindestberechtigungsstufe festlegen, um einen Raum anpingen zu können" + }, + "manage_rooms": { + "name": "Räume in Spaces verwalten", + "description": "Mindestberechtigungsstufe festlegen, um Räume in Spaces verwalten zu können" + }, + "invite": { + "name": "Einladen", + "description": "Mindestberechtigungsstufe festlegen, um neue Mitglieder in einen Raum einladen zu können" + }, + "kick": { + "name": "Entfernen", + "description": "Mindestberechtigungsstufe festlegen, um Mitglieder aus einem Raum entfernen zu können" + }, + "ban": { + "name": "Bannen", + "description": "Mindestberechtigungsstufe festlegen, um Mitglieder eines Raums bannen zu können" + }, + "change_avatar": { + "name": "Avatar ändern", + "description": "Mindestberechtigungsstufe festlegen, um den Avatar eines Raums/Spaces ändern zu können" + }, + "change_name": { + "name": "Namen ändern", + "description": "Mindestberechtigungsstufe festlegen, um den Namen eines Raums/Spaces ändern zu können" + }, + "change_topic": { + "name": "Thema ändern", + "description": "Mindestberechtigungsstufe festlegen, um das Thema eines Raums/Spaces ändern zu können" + }, + "change_settings": { + "name": "Einstellungen ändern", + "description": "Mindestberechtigungsstufe festlegen, um die Einstellungen eines Raums/Spaces ändern zu können" + }, + "change_published_address": { + "name": "Veröffentlichte Adressen ändern", + "description": "Mindestberechtigungsstufe festlegen, um eine Hauptadresse festlegen und freigeben zu können" + }, + "change_permissions": { + "name": "Berechtigungen ändern", + "description": "Mindestberechtigungsstufe festlegen, um Berechtigungen ändern zu können" + }, + "enable_room_encryption": { + "name": "Verschlüsselung aktivieren", + "description": "Mindestberechtigungsstufe festlegen, um die Verschlüsselung eines Raums aktivieren zu können" + }, + "change_history_visibility": { + "name": "Sichtbarkeit des Verlaufs ändern", + "description": "Mindestberechtigungsstufe festlegen, um die Sichtbarkeit des Nachrichtenverlaufs eines Raums ändern zu können" + }, + "upgrade_room": { + "name": "Raum aktualisieren", + "description": "Mindestberechtigungsstufe festlegen, um einen Raum aktualisieren zu können" + }, + "pin_messages": { + "name": "Nachrichten anheften", + "description": "Mindestberechtigungsstufe festlegen, um Nachrichten in einem Raum anheften zu können" + }, + "change_acls": { + "name": "Server ACLs ändern", + "description": "Mindestberechtigungsstufe festlegen, um Server ACLs ändern zu können" + }, + "modify_widgets": { + "name": "Widgets modifizieren", + "description": "Mindestberechtigungsstufe festlegen, um in einem Raum Widgets modifizieren zu können" + }, + "groups": { + "general": "Allgemeine Berechtigungen", + "manage_members": "Berechtigungen von Mitgliedern verwalten", + "room": "Berechtigungen für Raum-Profil", + "space": "Berechtigungen für Space-Profil", + "other": "Andere Berechtigungen", + "settings": "Berechtigungen für Einstellungen" + } + }, "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 274dfa698a..8b45c9da28 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -2,7 +2,15 @@ "common": { "close": "Close", "options": "Options", + "delete": "Delete", + "continue": "Continue", + "view_more": "View more", + "view_less": "View less", + "copy": "Copy", + "download": "Download", "or": "Or", + "reset": "Reset", + "setup": "Setup", "search": "Search", "invite": "Invite", "message_prompt": "Message" @@ -100,6 +108,75 @@ "about": "About" } }, + "SecretStorageAccess": { + "incorrect_security_key": "Incorrect security key", + "incorrect_security_phrase": "Incorrect security phrase", + "security_phrase": "Security Phrase", + "security_key": "Security Key", + "use_security_key": "Use Security Key", + "use_security_phrase": "Use Security Phrase" + }, + "KeyBackup": { + "create_backup_title": "Create key backup", + "create_backup_tooltip": "Create backup", + "creating_backup": "Creating Backup...", + "backup_created": "Successfully created backup", + "backup_failed": "Failed to create backup", + "restoring": "Restoring backup keys...", + "restoring_progress": "Restoring backup keys... ({{progress}}/{{total}}", + "restore_backup_title": "Restore Key Backup", + "restore_backup_tooltip": "Restore Key Backup", + "restore_complete": "Successfully restored backup keys ({{progress}}/{{total}})", + "restore_failed_bad_key": "Failed to restore backup. Key is invalid!", + "restore_failed_unknown": "Failed to restore backup.", + "delete_key_backup_title": "Delete key backup", + "delete_key_backup_tooltip": "Delete backup", + "delete_key_backup_subtitle": "Deleting key backup is permanent.", + "delete_key_backup_message": "All encrypted message keys stored on the server will be permanently deleted.", + "encrypted_messages_backup_description": "Online backup your encrypted messages keys with your account data in case you lose access to your sessions. Your keys will be secured with a unique Security Key.", + "encrypted_messages_backup_title": "Encrypted messages backup", + "encrypted_messages_backup_cross_signing_disabled": "Setup cross signing to backup your encrypted messages." + }, + "DeviceManage": { + "edit_session_name_title": "Edit session name", + "edit_session_name_subtitle": "Session name", + "edit_session_name_tooltip": "Edit session name", + "current_device_label": "Current", + "verify_session_button": "Verify", + "unverified_sessions_title": "Unverified sessions", + "unverified_sessions_none": "No unverified sessions", + "unencrypted_sessions_title": "Sessions without encryption support", + "verified_sessions_title": "Verified sessions", + "verified_sessions_none": "No verified sessions", + "setup_cross_signing_message": "Setup cross signing in case you lose all your sessions", + "loading_devices": "Loading devices...", + "logout_device_title": "Logout {{device}}", + "logout_device_message": "You are about to log out the session for {{device}}", + "last_activity": "Last activity", + "verify_this_session": "Verify this session either with your Security Key/Phrase here or by initiating emoji verification from a verified session.", + "verify_other_session": "Verify other sessions by emoji verification or remove unfamiliar ones.", + "logout_device_confirm": "Logout", + "logout_device_tooltip": "Remove session", + "session_verification_title": "Session Verification", + "session_name_privacy_message": "Session names are visible to everyone, so do not put any private info here." + }, + "CrossSigning": { + "title": "Cross Signing", + "setup_failed": "Failed to setup cross signing. Please try again", + "setup": "Setup cross signing", + "save_security_key_message": "Please save this security key somewhere safe", + "security_key_dialog_title": "Security Key", + "security_key_generation_message": "We will generate a Security Key, which you can use to manage message backups and session verification.", + "security_key_generation_button": "Generate Key", + "security_phrase_message": "Alternatively you can set a 'Security Phrase' so you don't have to remember the long Security Key, and optionally save the key as a backup", + "security_phrase_label": "Security Phrase", + "security_phrase_confirm_label": "Confirm Security Phrase", + "security_phrase_set_button": "Set Phrase & Generate Key", + "setup_dialog_title": "Setup cross signing", + "setup_message": "Setup to verify and keep track of all your sessions. Also required to backup encrypted message.", + "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." + }, "RoomCommon": { "user_joined": " joined the room", "user_left": " left the room", @@ -190,6 +267,100 @@ "notifications_heading": "Notifications", "invite": "Invite" }, + "RoomPermissions": { + "default_role": { + "name": "Default role", + "description": "Set default role for all members" + }, + "send_messages": { + "name": "Send messages", + "description": "Set minimum power level to send messages in a room" + }, + "reactions": { + "name": "Send reactions", + "description": "Set minimum power level to send reactions in a room" + }, + "delete": { + "name": "Delete messages sent by others", + "description": "Set minumum power level to delete messages in a room" + }, + "notifications": { + "name": "Ping room", + "description": "Set minimum power level to ping room" + }, + "manage_rooms": { + "name": "Manage rooms in space", + "description": "Set minimum power level to manage rooms in space" + }, + "invite": { + "name": "Invite", + "description": "Set minimum power level to invite members" + }, + "kick": { + "name": "Kick", + "description": "Set minimum power level to kick members" + }, + "ban": { + "name": "Ban", + "description": "Set minimum power level to ban members" + }, + "change_avatar": { + "name": "Change avatar", + "description": "Set minimum power level to change room/space avatar" + }, + "change_name": { + "name": "Change name", + "description": "Set minimum power evel to change room/space name" + }, + "change_topic": { + "name": "Change topic", + "description": "Set minimum power level to change room/space topic" + }, + "change_settings": { + "name": "Change settings", + "description": "Set minimum power level to change settings" + }, + "change_published_address": { + "name": "Change published address", + "description": "Set minimum power level to publish and set main address" + }, + "change_permissions": { + "name": "Change permissions", + "description": "Set minimum power level to change permissions" + }, + "enable_room_encryption": { + "name": "Enable room encryption", + "description": "Set minimum power level to enable room encryption" + }, + "change_history_visibility": { + "name": "Change history visibility", + "description": "Set minimum power level to change room message history visibility" + }, + "upgrade_room": { + "name": "Upgrade room", + "description": "Set minimum power level to upgrade room" + }, + "pin_messages": { + "name": "Pin messages", + "description": "Set minimum power level to pin messages in a room" + }, + "change_acls": { + "name": "Change server ACLs", + "description": "Set minimum power level to change server ACLs" + }, + "modify_widgets": { + "name": "Modify widgets", + "description": "Set minimum power level to modify room widgets" + }, + "groups": { + "general": "General permissions", + "manage_members": "Manage members permissions", + "room": "Room profile permissions", + "space": "Space profile permissions", + "other": "Other permissions", + "settings": "Settings permissions" + } + }, "SpaceOptions": { "leave_space": "Leave Space", "leave_space_confirmation": "Are you sure that you want to leave the {{space}} space?", diff --git a/src/app/molecules/room-permissions/RoomPermissions.jsx b/src/app/molecules/room-permissions/RoomPermissions.jsx index da8720cdd9..61e312aeaf 100644 --- a/src/app/molecules/room-permissions/RoomPermissions.jsx +++ b/src/app/molecules/room-permissions/RoomPermissions.jsx @@ -2,6 +2,7 @@ import React, { useEffect } from 'react'; import PropTypes from 'prop-types'; import './RoomPermissions.scss'; +import { useTranslation } from 'react-i18next'; import initMatrix from '../../../client/initMatrix'; import { getPowerLabel } from '../../../util/matrixUtil'; import { openReusableContextMenu } from '../../../client/action/navigation'; @@ -19,140 +20,140 @@ import { useForceUpdate } from '../../hooks/useForceUpdate'; const permissionsInfo = { users_default: { - name: 'Default role', - description: 'Set default role for all members.', + name: 'Molecules.RoomPermissions.default_role.name', + description: 'Molecules.RoomPermissions.default_role.description', default: 0, }, events_default: { - name: 'Send messages', - description: 'Set minimum power level to send messages in room.', + name: 'Molecules.RoomPermissions.send_messages.name', + description: 'Molecules.RoomPermissions.send_messages.description', default: 0, }, 'm.reaction': { parent: 'events', - name: 'Send reactions', - description: 'Set minimum power level to send reactions in room.', + name: 'Molecules.RoomPermissions.reactions.name', + description: 'Molecules.RoomPermissions.reactions.description', default: 0, }, redact: { - name: 'Delete messages sent by others', - description: 'Set minimum power level to delete messages in room.', + name: 'Molecules.RoomPermissions.delete.name', + description: 'Molecules.RoomPermissions.delete.description', default: 50, }, notifications: { - name: 'Ping room', - description: 'Set minimum power level to ping room.', + name: 'Molecules.RoomPermissions.notifications.name', + description: 'Molecules.RoomPermissions.notifications.description', default: { room: 50, }, }, 'm.space.child': { parent: 'events', - name: 'Manage rooms in space', - description: 'Set minimum power level to manage rooms in space.', + name: 'Molecules.RoomPermissions.manage_rooms.name', + description: 'Molecules.RoomPermissions.manage_rooms.description', default: 50, }, invite: { - name: 'Invite', - description: 'Set minimum power level to invite members.', + name: 'Molecules.RoomPermissions.invite.name', + description: 'Molecules.RoomPermissions.invite.description', default: 50, }, kick: { - name: 'Kick', - description: 'Set minimum power level to kick members.', + name: 'Molecules.RoomPermissions.kick.name', + description: 'Molecules.RoomPermissions.kick.description', default: 50, }, ban: { - name: 'Ban', - description: 'Set minimum power level to ban members.', + name: 'Molecules.RoomPermissions.ban.name', + description: 'Molecules.RoomPermissions.ban.description', default: 50, }, 'm.room.avatar': { parent: 'events', - name: 'Change avatar', - description: 'Set minimum power level to change room/space avatar.', + name: 'Molecules.RoomPermissions.change_avatar.name', + description: 'Molecules.RoomPermissions.change_avatar.description', default: 50, }, 'm.room.name': { parent: 'events', - name: 'Change name', - description: 'Set minimum power level to change room/space name.', + name: 'Molecules.RoomPermissions.change_name.name', + description: 'Molecules.RoomPermissions.change_name.description', default: 50, }, 'm.room.topic': { parent: 'events', - name: 'Change topic', - description: 'Set minimum power level to change room/space topic.', + name: 'Molecules.RoomPermissions.change_topic.name', + description: 'Molecules.RoomPermissions.change_topic.description', default: 50, }, state_default: { - name: 'Change settings', - description: 'Set minimum power level to change settings.', + name: 'Molecules.RoomPermissions.change_settings.name', + description: 'Molecules.RoomPermissions.change_settings.description', default: 50, }, 'm.room.canonical_alias': { parent: 'events', - name: 'Change published address', - description: 'Set minimum power level to publish and set main address.', + name: 'Molecules.RoomPermissions.change_published_address.name', + description: 'Molecules.RoomPermissions.change_published_address.description', default: 50, }, 'm.room.power_levels': { parent: 'events', - name: 'Change permissions', - description: 'Set minimum power level to change permissions.', + name: 'Molecules.RoomPermissions.change_permissions.name', + description: 'Molecules.RoomPermissions.change_permissions.description', default: 50, }, 'm.room.encryption': { parent: 'events', - name: 'Enable room encryption', - description: 'Set minimum power level to enable room encryption.', + name: 'Molecules.RoomPermissions.enable_room_encryption.name', + description: 'Molecules.RoomPermissions.enable_room_encryption.description', default: 50, }, 'm.room.history_visibility': { parent: 'events', - name: 'Change history visibility', - description: 'Set minimum power level to change room messages history visibility.', + name: 'Molecules.RoomPermissions.change_history_visibility.name', + description: 'Molecules.RoomPermissions.change_history_visibility.description', default: 50, }, 'm.room.tombstone': { parent: 'events', - name: 'Upgrade room', - description: 'Set minimum power level to upgrade room.', + name: 'Molecules.RoomPermissions.upgrade_room.name', + description: 'Molecules.RoomPermissions.upgrade_room.description', default: 50, }, 'm.room.pinned_events': { parent: 'events', - name: 'Pin messages', - description: 'Set minimum power level to pin messages in room.', + name: 'Molecules.RoomPermissions.pin_messages.name', + description: 'Molecules.RoomPermissions.pin_messages.description', default: 50, }, 'm.room.server_acl': { parent: 'events', - name: 'Change server ACLs', - description: 'Set minimum power level to change server ACLs.', + name: 'Molecules.RoomPermissions.change_acls.name', + description: 'Molecules.RoomPermissions.change_acls.description', default: 50, }, 'im.vector.modular.widgets': { parent: 'events', - name: 'Modify widgets', - description: 'Set minimum power level to modify room widgets.', + name: 'Molecules.RoomPermissions.modify_widgets.name', + description: 'Molecules.RoomPermissions.modify_widgets.description', default: 50, }, }; const roomPermsGroups = { - 'General Permissions': ['users_default', 'events_default', 'm.reaction', 'redact', 'notifications'], - 'Manage members permissions': ['invite', 'kick', 'ban'], - 'Room profile permissions': ['m.room.avatar', 'm.room.name', 'm.room.topic'], - 'Settings permissions': ['state_default', 'm.room.canonical_alias', 'm.room.power_levels', 'm.room.encryption', 'm.room.history_visibility'], - 'Other permissions': ['m.room.tombstone', 'm.room.pinned_events', 'm.room.server_acl', 'im.vector.modular.widgets'], + 'Molecules.RoomPermissions.groups.general': ['users_default', 'events_default', 'm.reaction', 'redact', 'notifications'], + 'Molecules.RoomPermissions.groups.manage_members': ['invite', 'kick', 'ban'], + 'Molecules.RoomPermissions.groups.room': ['m.room.avatar', 'm.room.name', 'm.room.topic'], + 'Molecules.RoomPermissions.groups.settings': ['state_default', 'm.room.canonical_alias', 'm.room.power_levels', 'm.room.encryption', 'm.room.history_visibility'], + 'Molecules.RoomPermissions.groups.other': ['m.room.tombstone', 'm.room.pinned_events', 'm.room.server_acl', 'im.vector.modular.widgets'], }; const spacePermsGroups = { - 'General Permissions': ['users_default', 'm.space.child'], - 'Manage members permissions': ['invite', 'kick', 'ban'], - 'Space profile permissions': ['m.room.avatar', 'm.room.name', 'm.room.topic'], - 'Settings permissions': ['state_default', 'm.room.canonical_alias', 'm.room.power_levels'], + 'Molecules.RoomPermissions.groups.general': ['users_default', 'm.space.child'], + 'Molecules.RoomPermissions.groups.manage_members': ['invite', 'kick', 'ban'], + 'Molecules.RoomPermissions.groups.space': ['m.room.avatar', 'm.room.name', 'm.room.topic'], + 'Molecules.RoomPermissions.groups.settings': ['state_default', 'm.room.canonical_alias', 'm.room.power_levels'], }; function useRoomStateUpdate(roomId) { @@ -181,6 +182,8 @@ function RoomPermissions({ roomId }) { const canChangePermission = room.currentState.maySendStateEvent('m.room.power_levels', mx.getUserId()); const myPowerLevel = room.getMember(mx.getUserId())?.powerLevel ?? 100; + const { t } = useTranslation(); + const handlePowerSelector = (e, permKey, parentKey, powerLevel) => { const handlePowerLevelChange = (newPowerLevel) => { if (powerLevel === newPowerLevel) return; @@ -227,7 +230,7 @@ function RoomPermissions({ roomId }) { const groupedPermKeys = permsGroups[groupKey]; return (
- {groupKey} + {t(groupKey)} { groupedPermKeys.map((permKey) => { const permInfo = permissionsInfo[permKey]; @@ -247,8 +250,8 @@ function RoomPermissions({ roomId }) { return ( {permInfo.description}} + title={t(permInfo.name)} + content={{t(permInfo.description)}} options={( + +
); openReusableDialog( - Setup cross signing, + , renderFailure, ); }; @@ -47,13 +48,13 @@ const securityKeyDialog = (key) => { const renderSecurityKey = () => (
- Please save this security key somewhere safe. + {key.encodedPrivateKey}
- - + +
); @@ -62,12 +63,14 @@ const securityKeyDialog = (key) => { downloadKey(); openReusableDialog( - Security Key, + , () => renderSecurityKey(), ); }; function CrossSigningSetup() { + const { t } = useTranslation(); + const initialValues = { phrase: '', confirmPhrase: '' }; const [genWithPhrase, setGenWithPhrase] = useState(undefined); @@ -121,13 +124,12 @@ function CrossSigningSetup() {
- We will generate a Security Key, - which you can use to manage messages backup and session verification. + {t('Organisms.CrossSigning.security_key_generation_message')} - {genWithPhrase !== false && } + {genWithPhrase !== false && } {genWithPhrase === false && }
- OR + {t('common.or')} setup(values.phrase)} @@ -142,15 +144,13 @@ function CrossSigningSetup() { disabled={genWithPhrase !== undefined} > - Alternatively you can also set a Security Phrase - so you don't have to remember long Security Key, - and optionally save the Key as backup. + {t('Organisms.CrossSigning.security_phrase_message')} {errors.confirmPhrase && {errors.confirmPhrase}} - {genWithPhrase !== true && } + {genWithPhrase !== true && } {genWithPhrase === true && } )} @@ -183,17 +183,15 @@ const setupDialog = () => { }; function CrossSigningReset() { + const { t } = useTranslation(); return (
{twemojify('✋🧑‍🚒🤚')} - Resetting cross-signing keys is permanent. + {t('Organisms.CrossSigning.reset_keys_subtitle')} - Anyone you have verified with will see security alerts and your message backup will be 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. + {t('Organisms.CrossSigning.reset_keys_message')} - +
); } @@ -206,15 +204,16 @@ const resetDialog = () => { }; function CrossSignin() { + const { t } = useTranslation(); const isCSEnabled = useCrossSigningStatus(); return ( Setup to verify and keep track of all your sessions. Also required to backup encrypted message.} + title={t('Organisms.CrossSigning.title')} + content={{t('Organisms.CrossSigning.setup_message')}} options={( isCSEnabled - ? - : + ? + : )} /> ); diff --git a/src/app/organisms/settings/DeviceManage.jsx b/src/app/organisms/settings/DeviceManage.jsx index 4a4f141cd1..51b4ac356a 100644 --- a/src/app/organisms/settings/DeviceManage.jsx +++ b/src/app/organisms/settings/DeviceManage.jsx @@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react'; import './DeviceManage.scss'; import dateFormat from 'dateformat'; +import { useTranslation } from 'react-i18next'; import initMatrix from '../../../client/initMatrix'; import { isCrossVerified } from '../../../util/matrixUtil'; import { openReusableDialog, openEmojiVerification } from '../../../client/action/navigation'; @@ -30,6 +31,8 @@ import { accessSecretStorage } from './SecretStorageAccess'; const promptDeviceName = async (deviceName) => new Promise((resolve) => { let isCompleted = false; + const { t } = useTranslation(); + const renderContent = (onComplete) => { const handleSubmit = (e) => { e.preventDefault(); @@ -39,17 +42,17 @@ const promptDeviceName = async (deviceName) => new Promise((resolve) => { }; return (
- +
- - + +
); }; openReusableDialog( - Edit session name, + {t('Organisms.DeviceManage.edit_session_name_title')}, (requestClose) => renderContent((name) => { isCompleted = true; resolve(name); @@ -76,6 +79,8 @@ function DeviceManage() { setProcessing([]); }, [deviceList]); + const { t } = useTranslation(); + const addToProcessing = (device) => { const old = [...processing]; old.push(device.device_id); @@ -91,7 +96,7 @@ function DeviceManage() {
- Loading sessions... + {t('Organisms.DeviceManage.loading_devices')}
); @@ -114,14 +119,14 @@ function DeviceManage() { const handleRemove = async (device) => { const isConfirmed = await confirmDialog( - `Logout ${device.display_name}`, - `You are about to logout "${device.display_name}" session.`, - 'Logout', + t('Organisms.DeviceManage.logout_device_title', { device: device.display_name }), + t('Organisms.DeviceManage.logout_device_message', { device: device.display_name }), + t('Organisms.DeviceManage.logout_device_confirm'), 'danger', ); if (!isConfirmed) return; addToProcessing(device); - await authRequest(`Logout "${device.display_name}"`, async (auth) => { + await authRequest(t('Organisms.DeviceManage.logout_device_title', { device: device.display_name }), async (auth) => { await mx.deleteDevice(device.device_id, auth); }); @@ -130,7 +135,7 @@ function DeviceManage() { }; const verifyWithKey = async (device) => { - const keyData = await accessSecretStorage('Session verification'); + const keyData = await accessSecretStorage(t('Organisms.DeviceManage.session_verification_title')); if (!keyData) return; addToProcessing(device); await mx.checkOwnCrossSigningTrust(); @@ -164,7 +169,7 @@ function DeviceManage() { {displayName} {`${displayName ? ' — ' : ''}${deviceId}`} - {isCurrentDevice && Current} + {isCurrentDevice && {t('Organisms.DeviceManage.current_device_label')}} )} options={ @@ -172,9 +177,9 @@ function DeviceManage() { ? : ( <> - {(isCSEnabled && canVerify) && } - handleRename(device)} src={PencilIC} tooltip="Rename" /> - handleRemove(device)} src={BinIC} tooltip="Remove session" /> + {(isCSEnabled && canVerify) && } + handleRename(device)} src={PencilIC} tooltip={t('Organisms.DeviceManage.edit_session_name_tooltip')} /> + handleRemove(device)} src={BinIC} tooltip={t('Organisms.DeviceManage.logout_device_tooltip')} /> ) } @@ -182,7 +187,7 @@ function DeviceManage() { <> {lastTS && ( - Last activity + {t('Organisms.DeviceManage.last_activity')} {dateFormat(new Date(lastTS), ' hh:MM TT, dd/mm/yyyy')} @@ -216,14 +221,14 @@ function DeviceManage() { return (
- Unverified sessions + {t('Organisms.DeviceManage.unverified_sessions_title')} {!isMeVerified && isCSEnabled && (
)} @@ -233,7 +238,7 @@ function DeviceManage() { rounded variant="surface" iconSrc={InfoIC} - title="Verify other sessions by emoji verification or remove unfamiliar ones." + title={t('Organisms.DeviceManage.verify_other_session')} />
)} @@ -243,43 +248,43 @@ function DeviceManage() { rounded variant="caution" iconSrc={InfoIC} - title="Setup cross signing in case you lose all your sessions." + title={t('Organisms.DeviceManage.setup_cross_signing_message')} />
)} { unverified.length > 0 ? unverified.map((device) => renderDevice(device, false)) - : No unverified sessions + : {t('Organisms.DeviceManage.unverified_sessions_none')} }
{noEncryption.length > 0 && (
- Sessions without encryption support + {t('Organisms.DeviceManage.unencrypted_sessions_title')} {noEncryption.map((device) => renderDevice(device, null))}
)}
- Verified sessions + {t('Organisms.DeviceManage.verified_sessions_title')} { verified.length > 0 ? verified.map((device, index) => { if (truncated && index >= TRUNCATED_COUNT) return null; return renderDevice(device, true); }) - : No verified sessions + : {t('Organisms.DeviceManage.verified_sessions_none')} } { verified.length > TRUNCATED_COUNT && ( )} { deviceList.length > 0 && ( - Session names are visible to everyone, so do not put any private info here. + {t('Organisms.DeviceManage.session_name_privacy_message')} )}
); } -export default DeviceManage; +export default DeviceManage; \ No newline at end of file diff --git a/src/app/organisms/settings/KeyBackup.jsx b/src/app/organisms/settings/KeyBackup.jsx index 75f032bc32..c9ef2f16b8 100644 --- a/src/app/organisms/settings/KeyBackup.jsx +++ b/src/app/organisms/settings/KeyBackup.jsx @@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react'; import PropTypes from 'prop-types'; import './KeyBackup.scss'; +import { useTranslation } from 'react-i18next'; import { twemojify } from '../../../util/twemojify'; import initMatrix from '../../../client/initMatrix'; @@ -29,6 +30,8 @@ function CreateKeyBackupDialog({ keyData }) { const mx = initMatrix.matrixClient; const mountStore = useStore(); + const { t } = useTranslation(); + const doBackup = async () => { setDone(false); let info; @@ -60,19 +63,19 @@ function CreateKeyBackupDialog({ keyData }) { {done === false && (
- Creating backup... + {t('Organisms.KeyBackup.creating_backup')}
)} {done === true && ( <> {twemojify('✅')} - Successfully created backup + {t('Organisms.KeyBackup.backup_created')} )} {done === null && ( <> - Failed to create backup - + {t('Organisms.KeyBackup.backup_failed')} + )} @@ -83,6 +86,8 @@ CreateKeyBackupDialog.propTypes = { }; function RestoreKeyBackupDialog({ keyData }) { + const { t } = useTranslation(); + const [status, setStatus] = useState(false); const mx = initMatrix.matrixClient; const mountStore = useStore(); @@ -99,7 +104,7 @@ function RestoreKeyBackupDialog({ keyData }) { meBreath = true; }, 200); - setStatus({ message: `Restoring backup keys... (${progress.successes}/${progress.total})` }); + setStatus({ message: t('Organisms.KeyBackup.restoring_progress', { progress: progress.successes, total: progress.total }) }); }; try { @@ -111,14 +116,14 @@ function RestoreKeyBackupDialog({ keyData }) { { progressCallback }, ); if (!mountStore.getItem()) return; - setStatus({ done: `Successfully restored backup keys (${info.imported}/${info.total}).` }); + setStatus({ done: t('Organisms.KeyBackup.restore_complete', { progress: info.imported, total: info.total }) }); } catch (e) { if (!mountStore.getItem()) return; if (e.errcode === 'RESTORE_BACKUP_ERROR_BAD_KEY') { deletePrivateKey(keyData.keyId); - setStatus({ error: 'Failed to restore backup. Key is invalid!', errorCode: 'BAD_KEY' }); + setStatus({ error: t('Organisms.KeyBackup.restore_failed_bad_key'), errorCode: 'BAD_KEY' }); } else { - setStatus({ error: 'Failed to restore backup.', errCode: 'UNKNOWN' }); + setStatus({ error: t('Organisms.KeyBackup.restore_failed_unknown'), errCode: 'UNKNOWN' }); } } }; @@ -133,7 +138,7 @@ function RestoreKeyBackupDialog({ keyData }) { {(status === false || status.message) && (
- {status.message ?? 'Restoring backup keys...'} + {status.message ?? t('Organisms.KeyBackup.restoring')}
)} {status.done && ( @@ -145,7 +150,7 @@ function RestoreKeyBackupDialog({ keyData }) { {status.error && ( <> {status.error} - + )} @@ -159,6 +164,7 @@ function DeleteKeyBackupDialog({ requestClose }) { const [isDeleting, setIsDeleting] = useState(false); const mx = initMatrix.matrixClient; const mountStore = useStore(); + const { t } = useTranslation(); const deleteBackup = async () => { mountStore.setItem(true); @@ -177,12 +183,12 @@ function DeleteKeyBackupDialog({ requestClose }) { return (
{twemojify('🗑')} - Deleting key backup is permanent. - All encrypted messages keys stored on server will be deleted. + {t('Organisms.KeyBackup.delete_key_backup_subtitle')} + {t('Organisms.KeyBackup.delete_key_backup_message')} { isDeleting ? - : + : }
); @@ -196,6 +202,7 @@ function KeyBackup() { const isCSEnabled = useCrossSigningStatus(); const [keyBackup, setKeyBackup] = useState(undefined); const mountStore = useStore(); + const { t } = useTranslation(); const fetchKeyBackupVersion = async () => { const info = await mx.getKeyBackupVersion(); @@ -220,28 +227,28 @@ function KeyBackup() { }, [isCSEnabled]); const openCreateKeyBackup = async () => { - const keyData = await accessSecretStorage('Create Key Backup'); + const keyData = await accessSecretStorage(t('Organisms.KeyBackup.create_backup_title')); if (keyData === null) return; openReusableDialog( - Create Key Backup, + {t('Organisms.KeyBackup.create_backup_title')}, () => , () => fetchKeyBackupVersion(), ); }; const openRestoreKeyBackup = async () => { - const keyData = await accessSecretStorage('Restore Key Backup'); + const keyData = await accessSecretStorage(t('Organisms.KeyBackup.restore_backup_title')); if (keyData === null) return; openReusableDialog( - Restore Key Backup, + {t('Organisms.KeyBackup.restore_backup_title')}, () => , ); }; const openDeleteKeyBackup = () => openReusableDialog( - Delete Key Backup, + {t('Organisms.KeyBackup.delete_key_backup_title')}, (requestClose) => ( { @@ -254,28 +261,28 @@ function KeyBackup() { const renderOptions = () => { if (keyBackup === undefined) return ; - if (keyBackup === null) return ; + if (keyBackup === null) return ; return ( <> - - + + ); }; return ( - Online backup your encrypted messages keys with your account data in case you lose access to your sessions. Your keys will be secured with a unique Security Key. + {t('Organisms.KeyBackup.encrypted_messages_backup_description')} {!isCSEnabled && ( )} @@ -285,4 +292,4 @@ function KeyBackup() { ); } -export default KeyBackup; +export default KeyBackup; \ No newline at end of file diff --git a/src/app/organisms/settings/SecretStorageAccess.jsx b/src/app/organisms/settings/SecretStorageAccess.jsx index e4fceb078e..4fa5e0687e 100644 --- a/src/app/organisms/settings/SecretStorageAccess.jsx +++ b/src/app/organisms/settings/SecretStorageAccess.jsx @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import './SecretStorageAccess.scss'; import { deriveKey } from 'matrix-js-sdk/lib/crypto/key_passphrase'; +import { useTranslation } from 'react-i18next'; import initMatrix from '../../../client/initMatrix'; import { openReusableDialog } from '../../../client/action/navigation'; import { getDefaultSSKey, getSSKeyInfo } from '../../../util/matrixUtil'; @@ -24,6 +25,7 @@ function SecretStorageAccess({ onComplete }) { const [process, setProcess] = useState(false); const [error, setError] = useState(null); const mountStore = useStore(); + const { t } = useTranslation(); const toggleWithPhrase = () => setWithPhrase(!withPhrase); @@ -39,7 +41,7 @@ function SecretStorageAccess({ onComplete }) { if (!mountStore.getItem()) return; if (!isCorrect) { - setError(`Incorrect Security ${key ? 'Key' : 'Phrase'}`); + setError(t(key ? 'Organisms.SecretStorageAccess.incorrect_security_key' : 'Organisms.SecretStorageAccess.incorrect_security_phrase')); setProcess(false); return; } @@ -51,7 +53,7 @@ function SecretStorageAccess({ onComplete }) { }); } catch (e) { if (!mountStore.getItem()) return; - setError(`Incorrect Security ${key ? 'Key' : 'Phrase'}`); + setError(t(key ? 'Organisms.SecretStorageAccess.incorrect_security_key' : 'Organisms.SecretStorageAccess.incorrect_security_phrase')); setProcess(false); } }; @@ -76,7 +78,7 @@ function SecretStorageAccess({ onComplete }) {
{error}} {!process && (
- - {isPassphrase && } + + {isPassphrase && }
)}
@@ -130,4 +132,4 @@ export const accessSecretStorage = (title) => new Promise((resolve) => { ); }); -export default SecretStorageAccess; +export default SecretStorageAccess; \ No newline at end of file