diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ae2711e25..881669a1a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,177 @@ +Changes in [2.0.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.0.0) (2020-01-27) +=================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.0.0-rc.2...v2.0.0) + + * Ensure a plaintext version of the composer ends up on the clipboard + [\#3923](https://github.com/matrix-org/matrix-react-sdk/pull/3923) + * Move & upgrade babel runtime into dependencies (like it wants) + [\#3921](https://github.com/matrix-org/matrix-react-sdk/pull/3921) + * Don't list every single alias when there's many + [\#3919](https://github.com/matrix-org/matrix-react-sdk/pull/3919) + +Changes in [2.0.0-rc.2](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.0.0-rc.2) (2020-01-20) +============================================================================================================= +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.0.0-rc.1...v2.0.0-rc.2) + + * Add prepublish script + [\#3877](https://github.com/matrix-org/matrix-react-sdk/pull/3877) + +Changes in [2.0.0-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.0.0-rc.1) (2020-01-20) +============================================================================================================= +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v1.7.6...v2.0.0-rc.1) + +BREAKING CHANGES +================ + * The react-sdk node module now exports ES6 rather than ES5. If you + wish to supports target that aren't compatible with ES6, you + will need to transpile the react-sdk to a suitable dialect. + +All Changes +=========== + * Fix arrows keys moving through edit history + [\#3874](https://github.com/matrix-org/matrix-react-sdk/pull/3874) + * Fix error about MessagePanel not being available for read markers + [\#3867](https://github.com/matrix-org/matrix-react-sdk/pull/3867) + * Adjust secret storage to work before sync + [\#3864](https://github.com/matrix-org/matrix-react-sdk/pull/3864) + * Update from Weblate + [\#3872](https://github.com/matrix-org/matrix-react-sdk/pull/3872) + * Remove unused deps and dev-deps + [\#3870](https://github.com/matrix-org/matrix-react-sdk/pull/3870) + * Tidy Jest test stuff and dependencies + [\#3869](https://github.com/matrix-org/matrix-react-sdk/pull/3869) + * Move feature flag check for new session toast + [\#3865](https://github.com/matrix-org/matrix-react-sdk/pull/3865) + * Catch exception in checkTerms if no ID server + [\#3863](https://github.com/matrix-org/matrix-react-sdk/pull/3863) + * Catch exception if passphrase dialog cancelled + [\#3862](https://github.com/matrix-org/matrix-react-sdk/pull/3862) + * Disable key request dialogs with cross-signing + [\#3860](https://github.com/matrix-org/matrix-react-sdk/pull/3860) + * Toasts for new, unverified sessions + [\#3859](https://github.com/matrix-org/matrix-react-sdk/pull/3859) + * Check for a matrixclient before trying to use it + [\#3861](https://github.com/matrix-org/matrix-react-sdk/pull/3861) + * Room header & message box shields now reflect cross-signing state + [\#3850](https://github.com/matrix-org/matrix-react-sdk/pull/3850) + * Fix Array.concat undefined + [\#3857](https://github.com/matrix-org/matrix-react-sdk/pull/3857) + * Update chokidar to fix reskindex not working + [\#3856](https://github.com/matrix-org/matrix-react-sdk/pull/3856) + * Make the new DM invite dialog work for regular invites too + [\#3854](https://github.com/matrix-org/matrix-react-sdk/pull/3854) + * Fix event handler leak in MemberStatusMessageAvatar + [\#3855](https://github.com/matrix-org/matrix-react-sdk/pull/3855) + * Move DM creation logic into DMInviteDialog + [\#3843](https://github.com/matrix-org/matrix-react-sdk/pull/3843) + * Remove all text when cutting in the composer + [\#3848](https://github.com/matrix-org/matrix-react-sdk/pull/3848) + * Add a ToastStore + [\#3853](https://github.com/matrix-org/matrix-react-sdk/pull/3853) + * 'Members' button always toggle the right panel + [\#3804](https://github.com/matrix-org/matrix-react-sdk/pull/3804) + * Fix timing of when Composer considers itself to be modified + [\#3842](https://github.com/matrix-org/matrix-react-sdk/pull/3842) + * Compute download file icon immediately + [\#3851](https://github.com/matrix-org/matrix-react-sdk/pull/3851) + * Fix not being able to open profiles from the timeline + [\#3852](https://github.com/matrix-org/matrix-react-sdk/pull/3852) + * Add post-login complete security flow + [\#3847](https://github.com/matrix-org/matrix-react-sdk/pull/3847) + * Added cut/copy and pasting user pills from editor. + [\#3828](https://github.com/matrix-org/matrix-react-sdk/pull/3828) + * Fix imports for help & support tab + [\#3846](https://github.com/matrix-org/matrix-react-sdk/pull/3846) + * Humanize the recent DM rooms ourselves for translations + [\#3841](https://github.com/matrix-org/matrix-react-sdk/pull/3841) + * Improve the quality of invite suggestions by filtering out DMs + [\#3840](https://github.com/matrix-org/matrix-react-sdk/pull/3840) + * Fix linter and tests on develop + [\#3845](https://github.com/matrix-org/matrix-react-sdk/pull/3845) + * Fix sourcemaps by refactoring the build system + [\#3839](https://github.com/matrix-org/matrix-react-sdk/pull/3839) + * Don't error on unverified/unknown devices. + [\#3837](https://github.com/matrix-org/matrix-react-sdk/pull/3837) + * Padlock icons in room header + [\#3835](https://github.com/matrix-org/matrix-react-sdk/pull/3835) + * Don't allow upgrade from untrusted key backup. + [\#3822](https://github.com/matrix-org/matrix-react-sdk/pull/3822) + * Emoji verification: Change name of 🔒 to lock + [\#3825](https://github.com/matrix-org/matrix-react-sdk/pull/3825) + * Room padlock decorations only if cross-signing is enabled + [\#3838](https://github.com/matrix-org/matrix-react-sdk/pull/3838) + * Enable end-to-end tests for sourcemaps (+Windows instructions) + [\#3827](https://github.com/matrix-org/matrix-react-sdk/pull/3827) + * Repair community member info panel + [\#3832](https://github.com/matrix-org/matrix-react-sdk/pull/3832) + * Add feature flag around the presence indicator in room list + [\#3831](https://github.com/matrix-org/matrix-react-sdk/pull/3831) + * Display a padlock icon beside invite-only rooms in the room list + [\#3821](https://github.com/matrix-org/matrix-react-sdk/pull/3821) + * Update from Weblate + [\#3830](https://github.com/matrix-org/matrix-react-sdk/pull/3830) + * Fix listener leak on RoomView + [\#3826](https://github.com/matrix-org/matrix-react-sdk/pull/3826) + * Regenerate i18n for sourcemaps branch + [\#3824](https://github.com/matrix-org/matrix-react-sdk/pull/3824) + * Fix tests for sourcemaps branch + [\#3823](https://github.com/matrix-org/matrix-react-sdk/pull/3823) + * Jest + [\#3724](https://github.com/matrix-org/matrix-react-sdk/pull/3724) + * Sourcemaps: develop -> feature branch + [\#3817](https://github.com/matrix-org/matrix-react-sdk/pull/3817) + * Support pasting a bunch of identifiers into the invite dialog + [\#3820](https://github.com/matrix-org/matrix-react-sdk/pull/3820) + * Support 3PIDs (email addresses) in the invite dialog + [\#3819](https://github.com/matrix-org/matrix-react-sdk/pull/3819) + * Placeholder PR for cleaner diffs: ES6 + [\#3765](https://github.com/matrix-org/matrix-react-sdk/pull/3765) + * Misc fixes for ES6 imports/exports + [\#3766](https://github.com/matrix-org/matrix-react-sdk/pull/3766) + * Wire up the invite targets dialog to a real composer and show selections + [\#3815](https://github.com/matrix-org/matrix-react-sdk/pull/3815) + * Change ref handling in TextualBody to prevent it parsing generated nodes + [\#3711](https://github.com/matrix-org/matrix-react-sdk/pull/3711) + * Render encoded html entities in og:description + [\#3789](https://github.com/matrix-org/matrix-react-sdk/pull/3789) + * Update package.json for new build process + cosmetics + [\#3767](https://github.com/matrix-org/matrix-react-sdk/pull/3767) + * Convert CommonJS exports to ES6 exports + [\#3761](https://github.com/matrix-org/matrix-react-sdk/pull/3761) + * Round 2 of CommonJS to ES6 imports + [\#3764](https://github.com/matrix-org/matrix-react-sdk/pull/3764) + * Strip all variation selectors on emoji + [\#3814](https://github.com/matrix-org/matrix-react-sdk/pull/3814) + * Use the new js-sdk imports and import from src + [\#3763](https://github.com/matrix-org/matrix-react-sdk/pull/3763) + * Convert many imports to handle ES6 exports + [\#3762](https://github.com/matrix-org/matrix-react-sdk/pull/3762) + * Fix userinfo for users not in the room + [\#3812](https://github.com/matrix-org/matrix-react-sdk/pull/3812) + * Attempt to fix e2e tests + [\#3811](https://github.com/matrix-org/matrix-react-sdk/pull/3811) + * Add bunch of null-guards and similar to fix React Errors/complaints + [\#3752](https://github.com/matrix-org/matrix-react-sdk/pull/3752) + * Delegate all room alias validation to the RoomAliasField validator + [\#3807](https://github.com/matrix-org/matrix-react-sdk/pull/3807) + * Support filtering and searching for users to invite in DMs + [\#3802](https://github.com/matrix-org/matrix-react-sdk/pull/3802) + * Add suggestions for which users to invite to chat + [\#3801](https://github.com/matrix-org/matrix-react-sdk/pull/3801) + * Use `flex-start` instead of `start` for postcss + [\#3760](https://github.com/matrix-org/matrix-react-sdk/pull/3760) + * Define getLanguageFromBrowser() for LanguageDropdown + [\#3769](https://github.com/matrix-org/matrix-react-sdk/pull/3769) + * Introduce babel's export-default-from plugin to fix build errors + [\#3768](https://github.com/matrix-org/matrix-react-sdk/pull/3768) + * Add a bit of debugging to incorrect components in the Skinner + [\#3770](https://github.com/matrix-org/matrix-react-sdk/pull/3770) + * [BREAKING] Refactor the entire build process for babel@7 and TypeScript + (chunk 1 of many) + [\#3722](https://github.com/matrix-org/matrix-react-sdk/pull/3722) + * Implementation of new potential skinning mechanism + [\#3723](https://github.com/matrix-org/matrix-react-sdk/pull/3723) + Changes in [1.7.6](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v1.7.6) (2020-01-13) =================================================================================================== [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v1.7.6-rc.2...v1.7.6) diff --git a/package.json b/package.json index 0c1d66058a..f0b7e04c73 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "1.7.6", + "version": "2.0.0", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { @@ -80,7 +80,7 @@ "is-ip": "^2.0.0", "linkifyjs": "^2.1.6", "lodash": "^4.17.14", - "matrix-js-sdk": "3.0.0", + "matrix-js-sdk": "4.0.0", "pako": "^1.0.5", "png-chunks-extract": "^1.0.0", "prop-types": "^15.5.8", diff --git a/res/css/_common.scss b/res/css/_common.scss index abc57a95ed..b92a618504 100644 --- a/res/css/_common.scss +++ b/res/css/_common.scss @@ -386,7 +386,13 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus { text-align: right; } -.mx_Dialog button, .mx_Dialog input[type="submit"] { +/* XXX: Our button style are a mess: buttons that happen to appear in dialogs get special styles applied + * to them that no button anywhere else in the app gets by default. In practice, buttons in other places + * in the app look the same by being AccessibleButtons, or possibly by having explict button classes. + * We should go through and have one consistent set of styles for buttons throughout the app. + * For now, I am duplicating the selectors here for mx_Dialog and mx_DialogButtons. + */ +.mx_Dialog button, .mx_Dialog input[type="submit"], .mx_Dialog_buttons button, .mx_Dialog_buttons input[type="submit"] { @mixin mx_DialogButton; margin-left: 0px; margin-right: 8px; @@ -402,27 +408,27 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus { margin-right: 0px; } -.mx_Dialog button:hover, .mx_Dialog input[type="submit"]:hover { +.mx_Dialog button:hover, .mx_Dialog input[type="submit"]:hover, .mx_Dialog_buttons button:hover, .mx_Dialog_buttons input[type="submit"]:hover { @mixin mx_DialogButton_hover; } -.mx_Dialog button:focus, .mx_Dialog input[type="submit"]:focus { +.mx_Dialog button:focus, .mx_Dialog input[type="submit"]:focus, .mx_Dialog_buttons button:focus, .mx_Dialog_buttons input[type="submit"]:focus { filter: brightness($focus-brightness); } -.mx_Dialog button.mx_Dialog_primary, .mx_Dialog input[type="submit"].mx_Dialog_primary { +.mx_Dialog button.mx_Dialog_primary, .mx_Dialog input[type="submit"].mx_Dialog_primary, .mx_Dialog_buttons button.mx_Dialog_primary, .mx_Dialog_buttons input[type="submit"].mx_Dialog_primary { color: $accent-fg-color; background-color: $accent-color; min-width: 156px; } -.mx_Dialog button.danger, .mx_Dialog input[type="submit"].danger { +.mx_Dialog button.danger, .mx_Dialog input[type="submit"].danger, .mx_Dialog_buttons button.danger, .mx_Dialog_buttons input[type="submit"].danger { background-color: $warning-color; border: solid 1px $warning-color; color: $accent-fg-color; } -.mx_Dialog button:disabled, .mx_Dialog input[type="submit"]:disabled { +.mx_Dialog button:disabled, .mx_Dialog input[type="submit"]:disabled, .mx_Dialog_buttons button:disabled, .mx_Dialog_buttons input[type="submit"]:disabled { background-color: $light-fg-color; border: solid 1px $light-fg-color; opacity: 0.7; diff --git a/res/css/views/auth/_AuthBody.scss b/res/css/views/auth/_AuthBody.scss index d342de6d75..51b9775811 100644 --- a/res/css/views/auth/_AuthBody.scss +++ b/res/css/views/auth/_AuthBody.scss @@ -15,13 +15,10 @@ limitations under the License. */ .mx_AuthBody { - width: 500px; background-color: $authpage-body-bg-color; border-radius: 0 4px 4px 0; padding: 25px 60px; box-sizing: border-box; - font-size: 12px; - color: $authpage-secondary-color; h2 { font-size: 24px; @@ -99,6 +96,12 @@ limitations under the License. border-radius: 4px; } +.mx_AuthBody_loginRegister { + width: 500px; + font-size: 12px; + color: $authpage-secondary-color; +} + .mx_AuthBody_editServerDetails { padding-left: 1em; font-size: 12px; diff --git a/res/css/views/dialogs/secretstorage/_CreateSecretStorageDialog.scss b/res/css/views/dialogs/secretstorage/_CreateSecretStorageDialog.scss index ed5aaa05a3..53e82670e1 100644 --- a/res/css/views/dialogs/secretstorage/_CreateSecretStorageDialog.scss +++ b/res/css/views/dialogs/secretstorage/_CreateSecretStorageDialog.scss @@ -78,6 +78,10 @@ limitations under the License. align-items: center; } +.mx_CreateSecretStorageDialog_recoveryKeyButtons .mx_AccessibleButton { + margin-right: 10px; +} + .mx_CreateSecretStorageDialog_recoveryKeyButtons button { flex: 1; white-space: nowrap; diff --git a/res/css/views/right_panel/_UserInfo.scss b/res/css/views/right_panel/_UserInfo.scss index 8aad5240aa..9db636ae6b 100644 --- a/res/css/views/right_panel/_UserInfo.scss +++ b/res/css/views/right_panel/_UserInfo.scss @@ -109,7 +109,7 @@ limitations under the License. justify-content: center; // override the calculated sizes so that the letter isn't HUGE - font-size: 26px !important; + font-size: 56px !important; width: 100% !important; } diff --git a/src/DeviceListener.js b/src/DeviceListener.js index a4c5785db4..630d1a61c0 100644 --- a/src/DeviceListener.js +++ b/src/DeviceListener.js @@ -20,10 +20,13 @@ import * as sdk from './index'; import { _t } from './languageHandler'; import ToastStore from './stores/ToastStore'; -function toastKey(device) { - return 'newsession_' + device.deviceId; +function toastKey(deviceId) { + return 'newsession_' + deviceId; } +const KEY_BACKUP_POLL_INTERVAL = 5 * 60 * 1000; +const THIS_DEVICE_TOAST_KEY = 'setupencryption'; + export default class DeviceListener { static sharedInstance() { if (!global.mx_DeviceListener) global.mx_DeviceListener = new DeviceListener(); @@ -31,44 +34,120 @@ export default class DeviceListener { } constructor() { + // set of device IDs we're currently showing toasts for + this._activeNagToasts = new Set(); // device IDs for which the user has dismissed the verify toast ('Later') this._dismissed = new Set(); + // has the user dismissed any of the various nag toasts to setup encryption on this device? + this._dismissedThisDeviceToast = false; + + // cache of the key backup info + this._keyBackupInfo = null; + this._keyBackupFetchedAt = null; } start() { MatrixClientPeg.get().on('crypto.devicesUpdated', this._onDevicesUpdated); MatrixClientPeg.get().on('deviceVerificationChanged', this._onDeviceVerificationChanged); - this.recheck(); + MatrixClientPeg.get().on('userTrustStatusChanged', this._onUserTrustStatusChanged); + this._recheck(); } stop() { if (MatrixClientPeg.get()) { MatrixClientPeg.get().removeListener('crypto.devicesUpdated', this._onDevicesUpdated); MatrixClientPeg.get().removeListener('deviceVerificationChanged', this._onDeviceVerificationChanged); + MatrixClientPeg.get().removeListener('userTrustStatusChanged', this._onUserTrustStatusChanged); } this._dismissed.clear(); } dismissVerification(deviceId) { this._dismissed.add(deviceId); - this.recheck(); + this._recheck(); + } + + dismissEncryptionSetup() { + this._dismissedThisDeviceToast = true; + this._recheck(); } _onDevicesUpdated = (users) => { if (!users.includes(MatrixClientPeg.get().getUserId())) return; - this.recheck(); + this._recheck(); } _onDeviceVerificationChanged = (users) => { if (!users.includes(MatrixClientPeg.get().getUserId())) return; - this.recheck(); + this._recheck(); } - async recheck() { + _onUserTrustStatusChanged = (userId, trustLevel) => { + if (userId !== MatrixClientPeg.get().getUserId()) return; + this._recheck(); + } + + // The server doesn't tell us when key backup is set up, so we poll + // & cache the result + async _getKeyBackupInfo() { + const now = (new Date()).getTime(); + if (!this._keyBackupInfo || this._keyBackupFetchedAt < now - KEY_BACKUP_POLL_INTERVAL) { + this._keyBackupInfo = await MatrixClientPeg.get().getKeyBackupVersion(); + this._keyBackupFetchedAt = now; + } + return this._keyBackupInfo; + } + + async _recheck() { if (!SettingsStore.isFeatureEnabled("feature_cross_signing")) return; const cli = MatrixClientPeg.get(); - if (!cli.isCryptoEnabled()) return false; + if (!cli.isCryptoEnabled()) return; + if (!cli.getCrossSigningId()) { + if (this._dismissedThisDeviceToast) { + ToastStore.sharedInstance().dismissToast(THIS_DEVICE_TOAST_KEY); + return; + } + + // cross signing isn't enabled - nag to enable it + // There are 3 different toasts for: + if (cli.getStoredCrossSigningForUser(cli.getUserId())) { + // Cross-signing on account but this device doesn't trust the master key (verify this session) + ToastStore.sharedInstance().addOrReplaceToast({ + key: THIS_DEVICE_TOAST_KEY, + title: _t("Verify this session"), + icon: "verification_warning", + props: {kind: 'verify_this_session'}, + component: sdk.getComponent("toasts.SetupEncryptionToast"), + }); + } else { + const backupInfo = await this._getKeyBackupInfo(); + if (backupInfo) { + // No cross-signing on account but key backup available (upgrade encryption) + ToastStore.sharedInstance().addOrReplaceToast({ + key: THIS_DEVICE_TOAST_KEY, + title: _t("Encryption upgrade available"), + icon: "verification_warning", + props: {kind: 'upgrade_encryption'}, + component: sdk.getComponent("toasts.SetupEncryptionToast"), + }); + } else { + // No cross-signing or key backup on account (set up encryption) + ToastStore.sharedInstance().addOrReplaceToast({ + key: THIS_DEVICE_TOAST_KEY, + title: _t("Set up encryption"), + icon: "verification_warning", + props: {kind: 'set_up_encryption'}, + component: sdk.getComponent("toasts.SetupEncryptionToast"), + }); + } + } + return; + } else { + ToastStore.sharedInstance().dismissToast(THIS_DEVICE_TOAST_KEY); + } + + const newActiveToasts = new Set(); const devices = await cli.getStoredDevicesForUser(cli.getUserId()); for (const device of devices) { @@ -76,16 +155,24 @@ export default class DeviceListener { const deviceTrust = await cli.checkDeviceTrust(cli.getUserId(), device.deviceId); if (deviceTrust.isCrossSigningVerified() || this._dismissed.has(device.deviceId)) { - ToastStore.sharedInstance().dismissToast(toastKey(device)); + ToastStore.sharedInstance().dismissToast(toastKey(device.deviceId)); } else { + this._activeNagToasts.add(device.deviceId); ToastStore.sharedInstance().addOrReplaceToast({ - key: toastKey(device), + key: toastKey(device.deviceId), title: _t("New Session"), icon: "verification_warning", props: {deviceId: device.deviceId}, component: sdk.getComponent("toasts.NewSessionToast"), }); + newActiveToasts.add(device.deviceId); } } + + // clear any other outstanding toasts (eg. logged out devices) + for (const deviceId of this._activeNagToasts) { + if (!newActiveToasts.has(deviceId)) ToastStore.sharedInstance().dismissToast(toastKey(deviceId)); + } + this._activeNagToasts = newActiveToasts; } } diff --git a/src/TextForEvent.js b/src/TextForEvent.js index 6a2744109b..cdfea45ad7 100644 --- a/src/TextForEvent.js +++ b/src/TextForEvent.js @@ -444,10 +444,19 @@ function textForHistoryVisibilityEvent(event) { function textForEncryptionEvent(event) { const senderName = event.sender ? event.sender.name : event.getSender(); - return _t('%(senderName)s turned on end-to-end encryption (algorithm %(algorithm)s).', { - senderName, - algorithm: event.getContent().algorithm, - }); + if (event.getContent().algorithm === "m.megolm.v1.aes-sha2") { + return _t('%(senderName)s turned on end-to-end encryption.', { + senderName, + }); + } + return _t( + '%(senderName)s turned on end-to-end encryption ' + + '(unrecognised algorithm %(algorithm)s).', + { + senderName, + algorithm: event.getContent().algorithm, + }, + ); } // Currently will only display a change if a user's power level is changed diff --git a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js index 8fd881fc32..0867cae6f4 100644 --- a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js +++ b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js @@ -16,6 +16,7 @@ limitations under the License. */ import React from 'react'; +import PropTypes from 'prop-types'; import * as sdk from '../../../../index'; import {MatrixClientPeg} from '../../../../MatrixClientPeg'; import { scorePassword } from '../../../../utils/PasswordScorer'; @@ -52,6 +53,15 @@ function selectText(target) { * Secret Storage in account data. */ export default class CreateSecretStorageDialog extends React.PureComponent { + static propTypes = { + hasCancel: PropTypes.bool, + accountPassword: PropTypes.string, + }; + + defaultProps = { + hasCancel: true, + }; + constructor(props) { super(props); @@ -73,7 +83,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent { // does the server offer a UI auth flow with just m.login.password // for /keys/device_signing/upload? canUploadKeysWithPasswordOnly: null, - accountPassword: '', + accountPassword: props.accountPassword, accountPasswordCorrect: null, // set if we are 'upgrading' encryption (making an SSSS store from // an existing key backup secret). @@ -82,9 +92,12 @@ export default class CreateSecretStorageDialog extends React.PureComponent { this._fetchBackupInfo(); this._queryKeyUploadAuth(); + + MatrixClientPeg.get().on('crypto.keyBackupStatus', this._onKeyBackupStatusChange); } componentWillUnmount() { + MatrixClientPeg.get().removeListener('crypto.keyBackupStatus', this._onKeyBackupStatusChange); if (this._setZxcvbnResultTimeout !== null) { clearTimeout(this._setZxcvbnResultTimeout); } @@ -92,7 +105,10 @@ export default class CreateSecretStorageDialog extends React.PureComponent { async _fetchBackupInfo() { const backupInfo = await MatrixClientPeg.get().getKeyBackupVersion(); - const backupSigStatus = await MatrixClientPeg.get().isKeyBackupTrusted(backupInfo); + const backupSigStatus = ( + // we may not have started crypto yet, in which case we definitely don't trust the backup + MatrixClientPeg.get().isCryptoEnabled() && await MatrixClientPeg.get().isKeyBackupTrusted(backupInfo) + ); const phase = backupInfo ? (backupSigStatus.usable ? PHASE_MIGRATE : PHASE_RESTORE_KEY_BACKUP) : @@ -127,6 +143,10 @@ export default class CreateSecretStorageDialog extends React.PureComponent { } } + _onKeyBackupStatusChange = () => { + this._fetchBackupInfo(); + } + _collectRecoveryKeyNode = (n) => { this._recoveryKeyNode = n; } @@ -229,7 +249,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent { _onRestoreKeyBackupClick = () => { const RestoreKeyBackupDialog = sdk.getComponent('dialogs.keybackup.RestoreKeyBackupDialog'); Modal.createTrackedDialog( - 'Restore Backup', '', RestoreKeyBackupDialog, null, null, + 'Restore Backup', '', RestoreKeyBackupDialog, {showSummary: false}, null, /* priority = */ false, /* static = */ true, ); } @@ -411,6 +431,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent { _renderPhasePassPhrase() { const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); const Field = sdk.getComponent('views.elements.Field'); + const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); let strengthMeter; let helpText; @@ -472,9 +493,9 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
{_t("Advanced")} -

+

; } @@ -554,6 +575,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent { ); } + const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); return

{_t( "Your recovery key is a safety net - you can use it to restore " + @@ -572,12 +594,12 @@ export default class CreateSecretStorageDialog extends React.PureComponent { {this._encodedRecoveryKey}

- - +
@@ -740,7 +762,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent { onFinished={this.props.onFinished} title={this._titleForPhase(this.state.phase)} headerImage={headerImage} - hasCancel={[PHASE_PASSPHRASE].includes(this.state.phase)} + hasCancel={this.props.hasCancel && [PHASE_PASSPHRASE].includes(this.state.phase)} >
{content} diff --git a/src/components/structures/InteractiveAuth.js b/src/components/structures/InteractiveAuth.js index 53bb990e26..3d63029b06 100644 --- a/src/components/structures/InteractiveAuth.js +++ b/src/components/structures/InteractiveAuth.js @@ -20,7 +20,7 @@ import React, {createRef} from 'react'; import createReactClass from 'create-react-class'; import PropTypes from 'prop-types'; -import {getEntryComponentForLoginType} from '../views/auth/InteractiveAuthEntryComponents'; +import getEntryComponentForLoginType from '../views/auth/InteractiveAuthEntryComponents'; import * as sdk from '../../index'; diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 0486ce764c..133d74db45 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -89,12 +89,15 @@ export const VIEWS = { // showing flow to trust this new device with cross-signing COMPLETE_SECURITY: 6, + // flow to setup SSSS / cross-signing on this account + E2E_SETUP: 7, + // we are logged in with an active matrix client. - LOGGED_IN: 7, + LOGGED_IN: 8, // We are logged out (invalid token) but have our local state again. The user // should log back in to rehydrate the client. - SOFT_LOGOUT: 8, + SOFT_LOGOUT: 9, }; // Actions that are redirected through the onboarding process prior to being @@ -253,6 +256,9 @@ export default createReactClass({ // logout page. Lifecycle.loadSession({}); } + + this._accountPassword = null; + this._accountPasswordTimer = null; }, componentDidMount: function() { @@ -349,6 +355,8 @@ export default createReactClass({ window.removeEventListener("focus", this.onFocus); window.removeEventListener('resize', this.handleResize); this.state.resizeNotifier.removeListener("middlePanelResized", this._dispatchTimelineResize); + + if (this._accountPasswordTimer !== null) clearTimeout(this._accountPasswordTimer); }, componentWillUpdate: function(props, state) { @@ -657,7 +665,9 @@ export default createReactClass({ if ( !Lifecycle.isSoftLogout() && this.state.view !== VIEWS.LOGIN && - this.state.view !== VIEWS.COMPLETE_SECURITY + this.state.view !== VIEWS.REGISTER && + this.state.view !== VIEWS.COMPLETE_SECURITY && + this.state.view !== VIEWS.E2E_SETUP ) { this._onLoggedIn(); } @@ -1724,6 +1734,10 @@ export default createReactClass({ this.showScreen("forgot_password"); }, + onRegisterFlowComplete: function(credentials, password) { + return this.onUserCompletedLoginFlow(credentials, password); + }, + // returns a promise which resolves to the new MatrixClient onRegistered: function(credentials) { return Lifecycle.setLoggedIn(credentials); @@ -1812,7 +1826,14 @@ export default createReactClass({ this._loggedInView = ref; }, - async onUserCompletedLoginFlow(credentials) { + async onUserCompletedLoginFlow(credentials, password) { + this._accountPassword = password; + // self-destruct the password after 5mins + if (this._accountPasswordTimer !== null) clearTimeout(this._accountPasswordTimer); + this._accountPasswordTimer = setTimeout(() => { + this._accountPassword = null; + this._accountPasswordTimer = null; + }, 60 * 5 * 1000); // Wait for the client to be logged in (but not started) // which is enough to ask the server about account data. const loggedIn = new Promise(resolve => { @@ -1826,7 +1847,7 @@ export default createReactClass({ }); // Create and start the client in the background - Lifecycle.setLoggedIn(credentials); + const setLoggedInPromise = Lifecycle.setLoggedIn(credentials); await loggedIn; const cli = MatrixClientPeg.get(); @@ -1847,12 +1868,20 @@ export default createReactClass({ if (masterKeyInStorage) { this.setStateForNewView({ view: VIEWS.COMPLETE_SECURITY }); + } else if (SettingsStore.isFeatureEnabled("feature_cross_signing")) { + // This will only work if the feature is set to 'enable' in the config, + // since it's too early in the lifecycle for users to have turned the + // labs flag on. + this.setStateForNewView({ view: VIEWS.E2E_SETUP }); } else { this._onLoggedIn(); } + + return setLoggedInPromise; }, - onCompleteSecurityFinished() { + // complete security / e2e setup has finished + onCompleteSecurityE2eSetupFinished() { this._onLoggedIn(); }, @@ -1872,7 +1901,15 @@ export default createReactClass({ const CompleteSecurity = sdk.getComponent('structures.auth.CompleteSecurity'); view = ( + ); + } else if (this.state.view === VIEWS.E2E_SETUP) { + const E2eSetup = sdk.getComponent('structures.auth.E2eSetup'); + view = ( + ); } else if (this.state.view === VIEWS.POST_REGISTRATION) { @@ -1939,7 +1976,7 @@ export default createReactClass({ email={this.props.startingFragmentQueryParams.email} brand={this.props.config.brand} makeRegistrationUrl={this._makeRegistrationUrl} - onLoggedIn={this.onRegistered} + onLoggedIn={this.onRegisterFlowComplete} onLoginClick={this.onLoginClick} onServerConfigChange={this.onServerConfigChange} {...this.getServerProperties()} diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 5c243f04bc..60fff5f1e3 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -766,7 +766,7 @@ export default createReactClass({ onUserVerificationChanged: function(userId, _trustStatus) { const room = this.state.room; - if (!room.currentState.getMember(userId)) { + if (!room || !room.currentState.getMember(userId)) { return; } this._updateE2EStatus(room); diff --git a/src/components/structures/ToastContainer.js b/src/components/structures/ToastContainer.js index 8a05f62e61..283fbdd96a 100644 --- a/src/components/structures/ToastContainer.js +++ b/src/components/structures/ToastContainer.js @@ -23,9 +23,11 @@ export default class ToastContainer extends React.Component { constructor() { super(); this.state = {toasts: ToastStore.sharedInstance().getToasts()}; - } - componentDidMount() { + // Start listening here rather than in componentDidMount because + // toasts may dismiss themselves in their didMount if they find + // they're already irrelevant by the time they're mounted, and + // our own componentDidMount is too late. ToastStore.sharedInstance().on('update', this._onToastStoreUpdate); } diff --git a/src/components/structures/TopLeftMenuButton.js b/src/components/structures/TopLeftMenuButton.js index 967805d099..ebd7aaae89 100644 --- a/src/components/structures/TopLeftMenuButton.js +++ b/src/components/structures/TopLeftMenuButton.js @@ -17,7 +17,7 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; -import {TopLeftMenu} from '../views/context_menus/TopLeftMenu'; +import TopLeftMenu from '../views/context_menus/TopLeftMenu'; import BaseAvatar from '../views/avatars/BaseAvatar'; import {MatrixClientPeg} from '../../MatrixClientPeg'; import * as Avatar from '../../Avatar'; diff --git a/src/components/structures/auth/CompleteSecurity.js b/src/components/structures/auth/CompleteSecurity.js index 89711fcb1d..206cdb743e 100644 --- a/src/components/structures/auth/CompleteSecurity.js +++ b/src/components/structures/auth/CompleteSecurity.js @@ -35,7 +35,21 @@ export default class CompleteSecurity extends React.Component { this.state = { phase: PHASE_INTRO, + // this serves dual purpose as the object for the request logic and + // the presence of it insidicating that we're in 'verify mode'. + // Because of the latter, it lives in the state. + verificationRequest: null, }; + MatrixClientPeg.get().on("crypto.verification.request", this.onVerificationRequest); + } + + componentWillUnmount() { + if (this.state.verificationRequest) { + this.state.verificationRequest.off("change", this.onVerificationRequestChange); + } + if (MatrixClientPeg.get()) { + MatrixClientPeg.get().removeListener("crypto.verification.request", this.onVerificationRequest); + } } onStartClick = async () => { @@ -55,6 +69,27 @@ export default class CompleteSecurity extends React.Component { } } + onVerificationRequest = (request) => { + if (request.otherUserId !== MatrixClientPeg.get().getUserId()) return; + + if (this.state.verificationRequest) { + this.state.verificationRequest.off("change", this.onVerificationRequestChange); + } + request.on("change", this.onVerificationRequestChange); + this.setState({ + verificationRequest: request, + }); + } + + onVerificationRequestChange = () => { + if (this.state.verificationRequest.cancelled) { + this.state.verificationRequest.off("change", this.onVerificationRequestChange); + this.setState({ + verificationRequest: null, + }); + } + } + onSkipClick = () => { this.setState({ phase: PHASE_CONFIRM_SKIP, @@ -87,7 +122,13 @@ export default class CompleteSecurity extends React.Component { let icon; let title; let body; - if (phase === PHASE_INTRO) { + + if (this.state.verificationRequest) { + const IncomingSasDialog = sdk.getComponent("views.dialogs.IncomingSasDialog"); + body = ; + } else if (phase === PHASE_INTRO) { icon = ; title = _t("Complete security"); body = ( diff --git a/src/components/structures/auth/E2eSetup.js b/src/components/structures/auth/E2eSetup.js new file mode 100644 index 0000000000..29b4345761 --- /dev/null +++ b/src/components/structures/auth/E2eSetup.js @@ -0,0 +1,50 @@ +/* +Copyright 2020 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import React from 'react'; +import PropTypes from 'prop-types'; +import AsyncWrapper from '../../../AsyncWrapper'; +import * as sdk from '../../../index'; + +export default class E2eSetup extends React.Component { + static propTypes = { + onFinished: PropTypes.func.isRequired, + accountPassword: PropTypes.string, + }; + + constructor() { + super(); + // awkwardly indented because https://github.com/eslint/eslint/issues/11310 + this._createStorageDialogPromise = + import("../../../async-components/views/dialogs/secretstorage/CreateSecretStorageDialog"); + } + + render() { + const AuthPage = sdk.getComponent("auth.AuthPage"); + const AuthBody = sdk.getComponent("auth.AuthBody"); + return ( + + + + + + ); + } +} diff --git a/src/components/structures/auth/Login.js b/src/components/structures/auth/Login.js index 7bc2dbcbae..c8b2a1ea9c 100644 --- a/src/components/structures/auth/Login.js +++ b/src/components/structures/auth/Login.js @@ -58,6 +58,11 @@ export default createReactClass({ displayName: 'Login', propTypes: { + // Called when the user has logged in. Params: + // - The object returned by the login API + // - The user's password, if applicable, (may be cached in memory for a + // short time so the user is not required to re-enter their password + // for operations like uploading cross-signing keys). onLoggedIn: PropTypes.func.isRequired, // If true, the component will consider itself busy. @@ -181,7 +186,7 @@ export default createReactClass({ username, phoneCountry, phoneNumber, password, ).then((data) => { this.setState({serverIsAlive: true}); // it must be, we logged in. - this.props.onLoggedIn(data); + this.props.onLoggedIn(data, password); }, (error) => { if (this._unmounted) { return; diff --git a/src/components/structures/auth/Registration.js b/src/components/structures/auth/Registration.js index fdf2f51e00..171d3ada26 100644 --- a/src/components/structures/auth/Registration.js +++ b/src/components/structures/auth/Registration.js @@ -45,7 +45,13 @@ export default createReactClass({ displayName: 'Registration', propTypes: { + // Called when the user has logged in. Params: + // - object with userId, deviceId, homeserverUrl, identityServerUrl, accessToken + // - The user's password, if available and applicable (may be cached in memory + // for a short time so the user is not required to re-enter their password + // for operations like uploading cross-signing keys). onLoggedIn: PropTypes.func.isRequired, + clientSecret: PropTypes.string, sessionId: PropTypes.string, makeRegistrationUrl: PropTypes.func.isRequired, @@ -348,7 +354,7 @@ export default createReactClass({ homeserverUrl: this.state.matrixClient.getHomeserverUrl(), identityServerUrl: this.state.matrixClient.getIdentityServerUrl(), accessToken: response.access_token, - }); + }, this.state.formVals.password); this._setupPushers(cli); // we're still busy until we get unmounted: don't show the registration form again diff --git a/src/components/views/auth/AuthBody.js b/src/components/views/auth/AuthBody.js index fe20d76afb..b74b7d866a 100644 --- a/src/components/views/auth/AuthBody.js +++ b/src/components/views/auth/AuthBody.js @@ -33,6 +33,10 @@ export default class AuthBody extends React.PureComponent { const classes = { 'mx_AuthBody': true, 'mx_AuthBody_noHeader': !this.props.header, + // XXX The login pages all use a smaller fonts size but we don't want this + // for subsequent auth screens like the e2e setup. Doing this a terrible way + // for now. + 'mx_AuthBody_loginRegister': this.props.header, }; return
diff --git a/src/components/views/auth/InteractiveAuthEntryComponents.js b/src/components/views/auth/InteractiveAuthEntryComponents.js index 869e81c1f7..801420da95 100644 --- a/src/components/views/auth/InteractiveAuthEntryComponents.js +++ b/src/components/views/auth/InteractiveAuthEntryComponents.js @@ -641,7 +641,7 @@ const AuthEntryComponents = [ TermsAuthEntry, ]; -export function getEntryComponentForLoginType(loginType) { +export default function getEntryComponentForLoginType(loginType) { for (const c of AuthEntryComponents) { if (c.LOGIN_TYPE == loginType) { return c; diff --git a/src/components/views/context_menus/TopLeftMenu.js b/src/components/views/context_menus/TopLeftMenu.js index 528e4790c2..51ec202b90 100644 --- a/src/components/views/context_menus/TopLeftMenu.js +++ b/src/components/views/context_menus/TopLeftMenu.js @@ -27,7 +27,7 @@ import {MatrixClientPeg} from '../../../MatrixClientPeg'; import {MenuItem} from "../../structures/ContextMenu"; import * as sdk from "../../../index"; -export class TopLeftMenu extends React.Component { +export default class TopLeftMenu extends React.Component { static propTypes = { displayName: PropTypes.string.isRequired, userId: PropTypes.string.isRequired, diff --git a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js index 77fdee5e8a..0c432ba542 100644 --- a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js +++ b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js @@ -16,6 +16,7 @@ limitations under the License. */ import React from 'react'; +import PropTypes from 'prop-types'; import * as sdk from '../../../../index'; import {MatrixClientPeg} from '../../../../MatrixClientPeg'; import { MatrixClient } from 'matrix-js-sdk'; @@ -32,6 +33,16 @@ const RESTORE_TYPE_SECRET_STORAGE = 2; * Dialog for restoring e2e keys from a backup and the user's recovery key */ export default class RestoreKeyBackupDialog extends React.PureComponent { + static propTypes = { + // if false, will close the dialog as soon as the restore completes succesfully + // default: true + showSummary: PropTypes.bool, + }; + + defaultProps = { + showSummary: true, + }; + constructor(props) { super(props); this.state = { @@ -96,6 +107,10 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { const recoverInfo = await MatrixClientPeg.get().restoreKeyBackupWithPassword( this.state.passPhrase, undefined, undefined, this.state.backupInfo, ); + if (!this.props.showSummary) { + this.props.onFinished(true); + return; + } this.setState({ loading: false, recoverInfo, @@ -119,6 +134,10 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { const recoverInfo = await MatrixClientPeg.get().restoreKeyBackupWithRecoveryKey( this.state.recoveryKey, undefined, undefined, this.state.backupInfo, ); + if (!this.props.showSummary) { + this.props.onFinished(true); + return; + } this.setState({ loading: false, recoverInfo, @@ -253,6 +272,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { title = _t("Error"); content = _t("No backup found!"); } else if (this.state.recoverInfo) { + const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); title = _t("Backup Restored"); let failedToDecrypt; if (this.state.recoverInfo.total > this.state.recoverInfo.imported) { @@ -264,6 +284,11 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { content =

{_t("Restored %(sessionCount)s session keys", {sessionCount: this.state.recoverInfo.imported})}

{failedToDecrypt} +
; } else if (backupHasPassphrase && !this.state.forceRecoveryKey) { const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); diff --git a/src/components/views/emojipicker/EmojiPicker.js b/src/components/views/emojipicker/EmojiPicker.js index 1f508ceedc..ca8f0c0565 100644 --- a/src/components/views/emojipicker/EmojiPicker.js +++ b/src/components/views/emojipicker/EmojiPicker.js @@ -20,7 +20,7 @@ import PropTypes from 'prop-types'; import * as sdk from '../../../index'; import { _t } from '../../../languageHandler'; -import * as recent from './recent'; +import * as recent from '../../../emojipicker/recent'; import {DATA_BY_CATEGORY, getEmojiFromUnicode} from "../../../emoji"; export const CATEGORY_HEADER_HEIGHT = 22; diff --git a/src/components/views/rooms/RoomBreadcrumbs.js b/src/components/views/rooms/RoomBreadcrumbs.js index 5a15a7518b..f9408d3259 100644 --- a/src/components/views/rooms/RoomBreadcrumbs.js +++ b/src/components/views/rooms/RoomBreadcrumbs.js @@ -363,7 +363,7 @@ export default class RoomBreadcrumbs extends React.Component { } let dmIndicator; - if (this._isDmRoom(r.room)) { + if (this._isDmRoom(r.room) && !SettingsStore.isFeatureEnabled("feature_cross_signing")) { dmIndicator = : undefined; + const dmUserId = DMRoomMap.shared().getUserIdForRoomId(this.props.room.roomId); const joinRules = this.props.room && this.props.room.currentState.getStateEvents("m.room.join_rules", ""); const joinRule = joinRules && joinRules.getContent().join_rule; let privateIcon; - if (SettingsStore.isFeatureEnabled("feature_cross_signing")) { + // Don't show an invite-only icon for DMs. Users know they're invite-only. + if (!dmUserId && SettingsStore.isFeatureEnabled("feature_cross_signing")) { if (joinRule == "invite") { privateIcon = ; } diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index 9d2334de82..41975fe7b8 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -478,8 +478,9 @@ export default createReactClass({ let dmIndicator; let dmOnline; - // If we can place a shield, do that instead - if (dmUserId && !this.state.e2eStatus) { + /* Post-cross-signing we don't show DM indicators at all, instead relying on user + context to let them know when that is. */ + if (dmUserId && !SettingsStore.isFeatureEnabled("feature_cross_signing")) { dmIndicator = { + _onReviewClick = async () => { const cli = MatrixClientPeg.get(); const DeviceVerifyDialog = sdk.getComponent('views.dialogs.DeviceVerifyDialog'); @@ -47,10 +47,10 @@ export default class VerifySessionToast extends React.PureComponent { render() { const FormButton = sdk.getComponent("elements.FormButton"); return (
-
{_t("Other users may not trust it")}
+
{_t("Review & verify your new session")}
- +
); } diff --git a/src/components/views/toasts/SetupEncryptionToast.js b/src/components/views/toasts/SetupEncryptionToast.js new file mode 100644 index 0000000000..841ee66ac7 --- /dev/null +++ b/src/components/views/toasts/SetupEncryptionToast.js @@ -0,0 +1,68 @@ +/* +Copyright 2020 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import React from 'react'; +import PropTypes from 'prop-types'; +import * as sdk from "../../../index"; +import { _t } from '../../../languageHandler'; +import DeviceListener from '../../../DeviceListener'; +import { accessSecretStorage } from '../../../CrossSigningManager'; + +export default class SetupEncryptionToast extends React.PureComponent { + static propTypes = { + toastKey: PropTypes.string.isRequired, + kind: PropTypes.oneOf(['set_up_encryption', 'verify_this_session', 'upgrade_encryption']).isRequired, + }; + + _onLaterClick = () => { + DeviceListener.sharedInstance().dismissEncryptionSetup(); + }; + + _onSetupClick = async () => { + accessSecretStorage(); + }; + + getDescription() { + switch (this.props.kind) { + case 'set_up_encryption': + case 'upgrade_encryption': + return _t('Verify your other devices easier'); + case 'verify_this_session': + return _t('Other users may not trust it'); + } + } + + getSetupCaption() { + switch (this.props.kind) { + case 'set_up_encryption': + case 'upgrade_encryption': + return _t('Upgrade'); + case 'verify_this_session': + return _t('Verify'); + } + } + + render() { + const FormButton = sdk.getComponent("elements.FormButton"); + return (
+
{this.getDescription()}
+
+ + +
+
); + } +} diff --git a/src/components/views/toasts/VerificationRequestToast.js b/src/components/views/toasts/VerificationRequestToast.js index 7c5ddfd51d..1015ed0313 100644 --- a/src/components/views/toasts/VerificationRequestToast.js +++ b/src/components/views/toasts/VerificationRequestToast.js @@ -39,6 +39,13 @@ export default class VerificationRequestToast extends React.PureComponent { this.setState({counter}); }, 1000); request.on("change", this._checkRequestIsPending); + // We should probably have a separate class managing the active verification toasts, + // rather than monitoring this in the toast component itself, since we'll get problems + // like the toasdt not going away when the verification is cancelled unless it's the + // one on the top (ie. the one that's mounted). + // As a quick & dirty fix, check the toast is still relevant when it mounts (this prevents + // a toast hanging around after logging in if you did a verification as part of login). + this._checkRequestIsPending(); } componentWillUnmount() { diff --git a/src/emoji.js b/src/emoji.js index 125864e381..20b05531ca 100644 --- a/src/emoji.js +++ b/src/emoji.js @@ -79,13 +79,13 @@ EMOJIBASE.forEach(emoji => { }); /** - * Strips variation selectors from a string - * NB. Skin tone modifers are not variation selectors: + * Strips variation selectors from the end of given string + * NB. Skin tone modifiers are not variation selectors: * this function does not touch them. (Should it?) * * @param {string} str string to strip * @returns {string} stripped string */ function stripVariation(str) { - return str.replace(/[\uFE00-\uFE0F]/, ""); + return str.replace(/[\uFE00-\uFE0F]$/, ""); } diff --git a/src/components/views/emojipicker/recent.js b/src/emojipicker/recent.js similarity index 100% rename from src/components/views/emojipicker/recent.js rename to src/emojipicker/recent.js diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 47b6a7e9d3..6297270540 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -88,6 +88,9 @@ "%(weekDayName)s, %(monthName)s %(day)s %(time)s": "%(weekDayName)s, %(monthName)s %(day)s %(time)s", "%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s": "%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s", "%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s %(time)s": "%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s %(time)s", + "Verify this session": "Verify this session", + "Encryption upgrade available": "Encryption upgrade available", + "Set up encryption": "Set up encryption", "New Session": "New Session", "Who would you like to add to this community?": "Who would you like to add to this community?", "Warning: any person you add to a community will be publicly visible to anyone who knows the community ID": "Warning: any person you add to a community will be publicly visible to anyone who knows the community ID", @@ -256,7 +259,8 @@ "%(senderName)s made future room history visible to all room members.": "%(senderName)s made future room history visible to all room members.", "%(senderName)s made future room history visible to anyone.": "%(senderName)s made future room history visible to anyone.", "%(senderName)s made future room history visible to unknown (%(visibility)s).": "%(senderName)s made future room history visible to unknown (%(visibility)s).", - "%(senderName)s turned on end-to-end encryption (algorithm %(algorithm)s).": "%(senderName)s turned on end-to-end encryption (algorithm %(algorithm)s).", + "%(senderName)s turned on end-to-end encryption.": "%(senderName)s turned on end-to-end encryption.", + "%(senderName)s turned on end-to-end encryption (unrecognised algorithm %(algorithm)s).": "%(senderName)s turned on end-to-end encryption (unrecognised algorithm %(algorithm)s).", "%(userId)s from %(fromPowerLevel)s to %(toPowerLevel)s": "%(userId)s from %(fromPowerLevel)s to %(toPowerLevel)s", "%(senderName)s changed the power level of %(powerLevelDiffText)s.": "%(senderName)s changed the power level of %(powerLevelDiffText)s.", "%(senderName)s changed the pinned messages for the room.": "%(senderName)s changed the pinned messages for the room.", @@ -511,8 +515,12 @@ "Headphones": "Headphones", "Folder": "Folder", "Pin": "Pin", - "Other users may not trust it": "Other users may not trust it", + "Review & verify your new session": "Review & verify your new session", "Later": "Later", + "Review": "Review", + "Verify your other devices easier": "Verify your other devices easier", + "Other users may not trust it": "Other users may not trust it", + "Upgrade": "Upgrade", "Verify": "Verify", "Decline (%(counter)s)": "Decline (%(counter)s)", "Accept to continue:": "Accept to continue:", @@ -1524,7 +1532,6 @@ "Upgrading a room is an advanced action and is usually recommended when a room is unstable due to bugs, missing features or security vulnerabilities.": "Upgrading a room is an advanced action and is usually recommended when a room is unstable due to bugs, missing features or security vulnerabilities.", "This usually only affects how the room is processed on the server. If you're having problems with your Riot, please report a bug.": "This usually only affects how the room is processed on the server. If you're having problems with your Riot, please report a bug.", "You'll upgrade this room from to .": "You'll upgrade this room from to .", - "Upgrade": "Upgrade", "Sign out and remove encryption keys?": "Sign out and remove encryption keys?", "Clear Storage and Sign Out": "Clear Storage and Sign Out", "Send Logs": "Send Logs", @@ -2018,7 +2025,6 @@ "Set up secret storage": "Set up secret storage", "Restore your Key Backup": "Restore your Key Backup", "Upgrade your encryption": "Upgrade your encryption", - "Set up encryption": "Set up encryption", "Recovery key": "Recovery key", "Keep it safe": "Keep it safe", "Storing secrets...": "Storing secrets...", diff --git a/src/i18n/strings/eo.json b/src/i18n/strings/eo.json index 4ac519d16a..243aebb52d 100644 --- a/src/i18n/strings/eo.json +++ b/src/i18n/strings/eo.json @@ -1851,7 +1851,7 @@ "Error unsubscribing from list": "Eraris malabono de la listo", "Please try again or view your console for hints.": "Bonvolu reprovi aĆ­ serĉi helpilojn en via konzolo.", "You have not ignored anyone.": "Vi neniun malatentis.", - "You are not subscribed to any lists": "Vi neniun liston abonis.", + "You are not subscribed to any lists": "Vi neniun liston abonis", "Unsubscribe": "Malaboni", "View rules": "Montri regulojn", "You are currently subscribed to:": "Vi nun abonas:", @@ -1867,5 +1867,28 @@ "Widget ID": "Identigilo de fenestraÄ”o", "Widgets do not use message encryption.": "FenestraÄ”oj ne uzas ĉifradon de mesaĝoj.", "Widget added by": "FenestraÄ”on aldonis", - "This widget may use cookies.": "Ĉi tiu fenestraÄ”o povas uzi kuketojn." + "This widget may use cookies.": "Ĉi tiu fenestraÄ”o povas uzi kuketojn.", + "%(senderName)s added %(addedAddresses)s and %(count)s other addresses to this room|other": "%(senderName)s aldonis %(addedAddresses)s kaj %(count)s aliajn adresojn al ĉi tiu ĉambro", + "%(senderName)s removed %(removedAddresses)s and %(count)s other addresses from this room|other": "%(senderName)s forigis %(removedAddresses)s kaj %(count)s aliajn adresojn el ĉi tiu ĉambro", + "%(senderName)s removed %(countRemoved)s and added %(countAdded)s addresses to this room": "%(senderName)s forigis %(countRemoved)s kaj aldonis %(countAdded)s adresojn al ĉi tiu ĉambro", + "%(senderName)s turned on end-to-end encryption.": "%(senderName)s Ɲaltis tutvojan ĉifradon.", + "%(senderName)s turned on end-to-end encryption (unrecognised algorithm %(algorithm)s).": "%(senderName)s Ɲaltis tutvojan ĉifradon (nerekonita algoritmo %(algorithm)s).", + "a few seconds ago": "antaĆ­ kelkaj sekundoj", + "about a minute ago": "antaĆ­ ĉirkaĆ­ minuto", + "%(num)s minutes ago": "antaĆ­ %(num)s minutoj", + "about an hour ago": "antaĆ­ ĉirkaĆ­ horo", + "%(num)s hours ago": "antaĆ­ %(num)s horoj", + "about a day ago": "antaĆ­ ĉirkaĆ­ tago", + "%(num)s days ago": "antaĆ­ %(num)s tagoj", + "a few seconds from now": "kelkajn sekundojn de nun", + "about a minute from now": "ĉirkaĆ­ minuton de nun", + "%(num)s minutes from now": "%(num)s minutojn de nun", + "about an hour from now": "ĉirkaĆ­ horon de nun", + "%(num)s hours from now": "%(num)s horojn de nun", + "about a day from now": "ĉirkaĆ­ tagon de nun", + "%(num)s days from now": "%(num)s tagojn de nun", + "Lock": "Seruro", + "Other users may not trust it": "Aliaj uzantoj eble ne kredas ĝin", + "Later": "Pli poste", + "Verify": "Kontroli" } diff --git a/src/i18n/strings/eu.json b/src/i18n/strings/eu.json index 97cef0c70d..1ab4bd15b1 100644 --- a/src/i18n/strings/eu.json +++ b/src/i18n/strings/eu.json @@ -1617,7 +1617,7 @@ "Resend edit": "Birbidali edizioa", "Resend %(unsentCount)s reaction(s)": "Birbidali %(unsentCount)s erreakzio", "Resend removal": "Birbidali kentzeko agindua", - "Forgotten your password?": "Pasahitza ahaztu duzu?", + "Forgotten your password?": "Pasahitza ahaztuta?", "Sign in and regain access to your account.": "Hasi saioa eta berreskuratu zure kontua.", "You're signed out": "Saioa amaitu duzu", "Clear personal data": "Garbitu datu pertsonalak", @@ -2074,5 +2074,41 @@ "Done": "Egina", "Without completing security on this device, it won’t have access to encrypted messages.": "Gailu honetan segurtasuna osatu ezean, ez du zifratutako mezuetara sarbiderik izango.", "Go Back": "Joan atzera", - "Secret Storage will be set up using your existing key backup details. Your secret storage passphrase and recovery key will be the same as they were for your key backup.": "Biltegi sekretua oraingo gakoen babeskopiaren xehetasunak erabiliz ezarriko da. Zure biltegi sekretuaren pasa-esaldia eta berreskuratze gakoa zure gakoen babes-kopiarako zenerabiltzanak izango dira." + "Secret Storage will be set up using your existing key backup details. Your secret storage passphrase and recovery key will be the same as they were for your key backup.": "Biltegi sekretua oraingo gakoen babeskopiaren xehetasunak erabiliz ezarriko da. Zure biltegi sekretuaren pasa-esaldia eta berreskuratze gakoa zure gakoen babes-kopiarako zenerabiltzanak izango dira.", + "%(senderName)s added %(addedAddresses)s and %(count)s other addresses to this room|other": "%(senderName)s erabiltzaileak %(addedAddresses)s helbideak eta beste %(count)s gehitu dizkio gela honi", + "%(senderName)s removed %(removedAddresses)s and %(count)s other addresses from this room|other": "%(senderName)s erabiltzaileak %(removedAddresses)s helbideak eta beste %(count)s kendu dizkio gela honi", + "%(senderName)s removed %(countRemoved)s and added %(countAdded)s addresses to this room": "%(senderName)s erabiltzaileak %(countRemoved)s helbide kendu eta %(countAdded)s gehitu dizkio gela honi", + "%(senderName)s turned on end-to-end encryption.": "%(senderName)s erabiltzaileak muturretik muturrera zifratzea aktibatu du.", + "%(senderName)s turned on end-to-end encryption (unrecognised algorithm %(algorithm)s).": "%(senderName)s erabiltzaileak muturretik muturrera zifratzea gaitu du (%(algorithm)s algoritmo ezezaguna).", + "Someone is using an unknown device": "Baten bat gailu ezezagun bat erabiltzen ari da", + "This room is end-to-end encrypted": "Gela hau muturretik muturrera zifratuta dago", + "Everyone in this room is verified": "Gelako guztiak egiaztatuta daude", + "Encrypted by a deleted device": "Ezabatutako gailu batek zifratua", + "Invite only": "Gonbidapenez besterik ez", + "Send a reply
": "Bidali erantzuna
", + "Send a message
": "Bidali mezua
", + "Reject & Ignore user": "Ukatu eta ezikusi erabiltzailea", + "Unknown Command": "Agindu ezezaguna", + "Unrecognised command: %(commandText)s": "Agindu ezezaguna: %(commandText)s", + "You can use /help to list available commands. Did you mean to send this as a message?": "/help erabili dezakezu agindu erabilgarrien zerrenda ikusteko. Ala mezu gisa bidali nahi zenuen hau?", + "Hint: Begin your message with // to start it with a slash.": "Aholkua: Hasi zure mezua // idatziz barra batekin hasi nahi baduzu.", + "Send as message": "Bidali mezu gisa", + "Verify User": "Egiaztatu erabiltzailea", + "For extra security, verify this user by checking a one-time code on both of your devices.": "Segurtasun gehiagorako, egiaztatu erabiltzaile hau aldi-bakarrerako kode bat bi gailuetan egiaztatuz.", + "For maximum security, do this in person.": "Segurtasun gorenerako, egin hau aurrez aurre.", + "Start Verification": "Hasi egiaztaketa", + "If you can't find someone, ask them for their username, share your username (%(userId)s) or profile link.": "Ez baduzu baten bat aurkitzen, eskatu bere erabiltzaile-izena, partekatu zurea (%(userId)s) edo partekatu profilaren esteka.", + "Enter your account password to confirm the upgrade:": "Sartu zure kontuaren pasa-hitza eguneraketa baieztatzeko:", + "You'll need to authenticate with the server to confirm the upgrade.": "Zerbitzariarekin autentifikatu beharko duzu eguneraketa baieztatzeko.", + "Upgrade this device to allow it to verify other devices, granting them access to encrypted messages and marking them as trusted for other users.": "Eguneratu gailu hau honek beste gailuak egiaztatu ahal izateko, horrela zifratutako mezuetara sarbidea emanez eta beste erabiltzaileentzat fidagarri gisa markatzeko.", + "Set up encryption on this device to allow it to verify other devices, granting them access to encrypted messages and marking them as trusted for other users.": "Ezarri zifratzea gailu honetan honek beste gailuak egiaztatu ahal izateko, horrela zifratutako mezuetara sarbidea emanez eta beste erabiltzaileentzat fidagarri gisa markatzeko.", + "Secure your encryption keys with a passphrase. For maximum security this should be different to your account password:": "Babestu zure zifratze gakoak pasa-esaldi batekin. Segurtasun gorenerako hau eta zure kontuaren pasahitza desberdinak izan beharko lukete:", + "Enter a passphrase": "Sartu pasa-esaldia", + "Enter your passphrase a second time to confirm it.": "Sartu zure pasa-esaldia berriro hau baieztatzeko.", + "This device can now verify other devices, granting them access to encrypted messages and marking them as trusted for other users.": "Gailu honek beste gailuak egiaztatu ditzake, horrela zifratutako mezuetara sarbidea emanez eta beste erabiltzaileentzat fidagarri gisa markatuz.", + "Verify other users in their profile.": "Egiaztatu beste erabiltzaileak bere profiletan.", + "Upgrade your encryption": "Eguneratu zure zifratzea", + "Set up encryption": "Ezarri zifratzea", + "Encryption upgraded": "Zifratzea eguneratuta", + "Encryption setup complete": "Zifratzearen ezarpena egina" } diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index d1c4f7379c..1ddcc55544 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -2075,5 +2075,41 @@ "Secret Storage will be set up using your existing key backup details. Your secret storage passphrase and recovery key will be the same as they were for your key backup.": "Le coffre secret sera configurĂ© en utilisant les dĂ©tails existants de votre sauvegarde de clĂ©s. Votre phrase de passe et votre clĂ© de rĂ©cupĂ©ration seront les mĂȘmes que celles de votre sauvegarde de clĂ©s.", "New Session": "Nouvelle session", "Other users may not trust it": "D’autres utilisateurs pourraient ne pas lui faire confiance", - "Later": "Plus tard" + "Later": "Plus tard", + "Verify User": "VĂ©rifier l’utilisateur", + "For extra security, verify this user by checking a one-time code on both of your devices.": "Pour une meilleure sĂ©curitĂ©, vĂ©rifiez cet utilisateur en comparant un code Ă  usage unique sur vos deux appareils.", + "For maximum security, do this in person.": "Pour une sĂ©curitĂ© maximale, faites-le en personne.", + "Start Verification": "Commencer la vĂ©rification", + "Encrypted by a deleted device": "ChiffrĂ© par un appareil supprimĂ©", + "Unknown Command": "Commande inconnue", + "Unrecognised command: %(commandText)s": "Commande non reconnue : %(commandText)s", + "You can use /help to list available commands. Did you mean to send this as a message?": "Vous pouvez utiliser /help pour obtenir la liste des commandes disponibles. Vouliez-vous envoyer un message ?", + "Hint: Begin your message with // to start it with a slash.": "Astuce : Votre message doit dĂ©marrer par // pour commencer par une barre oblique.", + "Send as message": "Envoyer comme message", + "%(senderName)s added %(addedAddresses)s and %(count)s other addresses to this room|other": "%(senderName)s a ajoutĂ© %(addedAddresses)s et %(count)s autres adresses Ă  ce salon", + "%(senderName)s removed %(removedAddresses)s and %(count)s other addresses from this room|other": "%(senderName)s a supprimĂ© %(removedAddresses)s et %(count)s autres adresses de ce salon", + "%(senderName)s removed %(countRemoved)s and added %(countAdded)s addresses to this room": "%(senderName)s a supprimĂ© %(countRemoved)s et ajoutĂ© %(countAdded)s adresses Ă  ce salon", + "Reject & Ignore user": "Rejeter et ignorer l’utilisateur", + "Enter your account password to confirm the upgrade:": "Saisissez le mot de passe de votre compte pour confirmer la mise Ă  niveau :", + "You'll need to authenticate with the server to confirm the upgrade.": "Vous devrez vous identifier avec le serveur pour confirmer la mise Ă  niveau.", + "Upgrade this device to allow it to verify other devices, granting them access to encrypted messages and marking them as trusted for other users.": "Mettez Ă  niveau cet appareil pour lui permettre de vĂ©rifier d’autres appareils, qui pourront alors accĂ©der aux messages chiffrĂ©s et seront vus comme fiables par les autres utilisateurs.", + "Set up encryption on this device to allow it to verify other devices, granting them access to encrypted messages and marking them as trusted for other users.": "Configurez le chiffrement sur cet appareil pour lui permettre de vĂ©rifier d’autres appareils, qui pourront alors accĂ©der aux messages chiffrĂ©s et seront vus comme fiables par les autres utilisateurs.", + "Secure your encryption keys with a passphrase. For maximum security this should be different to your account password:": "SĂ©curisez vos clĂ©s de chiffrement avec une phrase de passe. Pour une sĂ©curitĂ© maximale, elle devrait ĂȘtre diffĂ©rente du mot de passe de votre compte :", + "Enter a passphrase": "Saisissez une phrase de passe", + "Enter your passphrase a second time to confirm it.": "Saisissez votre phrase de passe une seconde fois pour la confirmer.", + "This device can now verify other devices, granting them access to encrypted messages and marking them as trusted for other users.": "Cet appareil peut Ă  prĂ©sent vĂ©rifier d’autres appareils, qui pourront alors accĂ©der aux messages chiffrĂ©s et seront vus comme fiables par les autres utilisateurs.", + "Verify other users in their profile.": "VĂ©rifiez d’autres utilisateurs dans leur profil.", + "Upgrade your encryption": "Mettre Ă  niveau votre chiffrement", + "Set up encryption": "Configurer le chiffrement", + "Encryption upgraded": "Chiffrement mis Ă  niveau", + "Encryption setup complete": "Configuration du chiffrement terminĂ©", + "%(senderName)s turned on end-to-end encryption.": "%(senderName)s a activĂ© le chiffrement de bout en bout.", + "%(senderName)s turned on end-to-end encryption (unrecognised algorithm %(algorithm)s).": "%(senderName)s a activĂ© le chiffrement de bout en bout (algorithme %(algorithm)s non reconnu).", + "Someone is using an unknown device": "Quelqu'un utilise un appareil inconnu", + "This room is end-to-end encrypted": "Ce salon est chiffrĂ© de bout en bout", + "Everyone in this room is verified": "Tout le monde dans ce salon est vĂ©rifiĂ©", + "Invite only": "Uniquement sur invitation", + "Send a reply
": "Envoyer une rĂ©ponse
", + "Send a message
": "Envoyer un message
", + "If you can't find someone, ask them for their username, share your username (%(userId)s) or profile link.": "Si vous n’arrivez pas Ă  trouver quelqu’un, demandez-lui son nom d’utilisateur, partagez votre nom d’utilisateur (%(userId)s) ou votre lien de profil." } diff --git a/src/i18n/strings/hu.json b/src/i18n/strings/hu.json index e5b9f637f1..d2b877a8de 100644 --- a/src/i18n/strings/hu.json +++ b/src/i18n/strings/hu.json @@ -138,7 +138,7 @@ "Failed to toggle moderator status": "ModerĂĄtor stĂĄtuszt nem sikerĂŒlt ĂĄtĂĄllĂ­tani", "Failed to unban": "KizĂĄrĂĄs visszavonĂĄsa sikertelen", "Failed to upload profile picture!": "Profil kĂ©p feltöltĂ©se sikertelen!", - "Failed to verify email address: make sure you clicked the link in the email": "E-mail cĂ­m ellenƑrzĂ©se sikertelen: ellenƑrizd, hogy az e-mailnĂ©l lĂ©vƑ linkre rĂĄkattintottĂĄl", + "Failed to verify email address: make sure you clicked the link in the email": "E-mail cĂ­m ellenƑrzĂ©se sikertelen: ellenƑrizd, hogy az e-mailben lĂ©vƑ hivatkozĂĄsra kattintottĂĄl", "Failure to create room": "Szoba lĂ©trehozĂĄsa sikertelen", "Favourites": "Kedvencek", "Fill screen": "KĂ©pernyƑ kitöltĂ©se", @@ -355,7 +355,7 @@ "You need to be able to invite users to do that.": "Hogy ezt csinĂĄlhasd meg kell tudnod hĂ­vni felhasznĂĄlĂłkat.", "You need to be logged in.": "Be kell jelentkezz.", "Your email address does not appear to be associated with a Matrix ID on this Homeserver.": "Ez az e-mail cĂ­m, Ășgy nĂ©z ki, nincs összekötve a Matrix azonosĂ­tĂłval ezen a Matrix szerveren.", - "Your password was successfully changed. You will not receive push notifications on other devices until you log back in to them": "A jelszavadat sikeresen megvĂĄltoztattuk. Nem kapsz \"push\" Ă©rtesĂ­tĂ©seket amĂ­g a többi eszközön vissza nem jelentkezel", + "Your password was successfully changed. You will not receive push notifications on other devices until you log back in to them": "A jelszavadat sikeresen megvĂĄltoztattuk. Addig nem fogsz lekĂŒldĂ©ses Ă©rtesĂ­tĂ©seket kapni, amĂ­g a többi eszközön vissza nem jelentkezel", "You seem to be in a call, are you sure you want to quit?": "Úgy tƱnik hĂ­vĂĄsban vagy, biztosan kilĂ©psz?", "You seem to be uploading files, are you sure you want to quit?": "Úgy tƱnik fĂĄjlokat töltesz fel, biztosan kilĂ©psz?", "You will not be able to undo this change as you are promoting the user to have the same power level as yourself.": "Nem leszel kĂ©pes visszavonni ezt a vĂĄltoztatĂĄst mivel a felhasznĂĄlĂłt ugyanarra a szintre emeled amin te vagy.", @@ -451,7 +451,7 @@ "Username available": "Szabad felhasznĂĄlĂłi nĂ©v", "Username not available": "A felhasznĂĄlĂłi nĂ©v foglalt", "Something went wrong!": "Valami tönkrement!", - "If you already have a Matrix account you can log in instead.": "Ha mĂĄr van Matrix fiĂłkod akkor belĂ©phetsz helyette.", + "If you already have a Matrix account you can log in instead.": "Ha mĂĄr van Matrix fiĂłkod, akkor belĂ©phetsz helyette.", "Your browser does not support the required cryptography extensions": "A böngĂ©szƑd nem tĂĄmogatja a szĂŒksĂ©ges titkosĂ­tĂĄsi kiterjesztĂ©st", "Not a valid Riot keyfile": "Nem Ă©rvĂ©nyes Riot kulcsfĂĄjl", "Authentication check failed: incorrect password?": "AzonosĂ­tĂĄs sikertelen: hibĂĄs jelszĂł?", @@ -929,7 +929,7 @@ "To continue using the %(homeserverDomain)s homeserver you must review and agree to our terms and conditions.": "A %(homeserverDomain)s szerver hasznĂĄlatĂĄnak folytatĂĄsĂĄhoz el kell olvasnod Ă©s el kell fogadnod az ĂĄltalĂĄnos szerzƑdĂ©si feltĂ©teleket.", "Review terms and conditions": "ÁltalĂĄnos SzerzƑdĂ©si FeltĂ©telek elolvasĂĄsa", "To continue, please enter your password:": "FolytatĂĄshoz add meg a jelszavad:", - "This will make your account permanently unusable. You will not be able to log in, and no one will be able to re-register the same user ID. This will cause your account to leave all rooms it is participating in, and it will remove your account details from your identity server. This action is irreversible.": "Ez vĂ©gleg hasznĂĄlhatatlannĂĄ teszi a fiĂłkodat. EzutĂĄn nem fogsz tudni bejelentkezni, Ă©s mĂĄs sem tud majd ezzel az azonosĂ­tĂłval fiĂłkot lĂ©trehozni. Minden szobĂĄbĂłl amibe belĂ©ptĂ©l ki fogsz lĂ©pni, Ă©s törölni fogja minden fiĂłk adatod az \"identity\" szerverrƑl. Ez a mƱvelet visszafordĂ­thatatlan.", + "This will make your account permanently unusable. You will not be able to log in, and no one will be able to re-register the same user ID. This will cause your account to leave all rooms it is participating in, and it will remove your account details from your identity server. This action is irreversible.": "Ez vĂ©gleg hasznĂĄlhatatlannĂĄ teszi a fiĂłkodat. EzutĂĄn nem fogsz tudni bejelentkezni, Ă©s mĂĄs sem tud majd ezzel az azonosĂ­tĂłval fiĂłkot lĂ©trehozni. Minden szobĂĄbĂłl amibe belĂ©ptĂ©l ki fogsz lĂ©pni, Ă©s törölni fogja minden fiĂłk adatod az szemĂ©lyazonossĂĄgod biztosĂ­tĂł szerverrƑl. Ez a mƱvelet visszafordĂ­thatatlan.", "Deactivating your account does not by default cause us to forget messages you have sent. If you would like us to forget your messages, please tick the box below.": "A fiĂłkod felfĂŒggesztĂ©se nem jelenti alapĂ©rtelmezetten azt, hogy az ĂĄltalad kĂŒldött ĂŒzenetek elfelejtƑdnek. Ha törölni szeretnĂ©d az ĂĄltalad kĂŒldött ĂŒzeneteket, pipĂĄld be a jelölƑnĂ©gyzetet alul.", "Message visibility in Matrix is similar to email. Our forgetting your messages means that messages you have sent will not be shared with any new or unregistered users, but registered users who already have access to these messages will still have access to their copy.": "Az ĂŒzenetek lĂĄthatĂłsĂĄga a Matrix-ban hasonlĂ­t az emailhez. Az ĂĄltalad kĂŒldött ĂŒzenet törlĂ©se azt jelenti, hogy nem osztjuk meg Ășj-, vagy vendĂ©g felhasznĂĄlĂłval de a mĂĄr regisztrĂĄlt felhasznĂĄlĂłk akik mĂĄr hozzĂĄfĂ©rtek az ĂŒzenethez tovĂĄbbra is elĂ©rik a sajĂĄt mĂĄsolatukat.", "Please forget all messages I have sent when my account is deactivated (Warning: this will cause future users to see an incomplete view of conversations)": "KĂ©rlek töröld az összes ĂĄltalam kĂŒldött ĂŒzenetet amikor a fiĂłkomat felfĂŒggesztem (Figyelem: ez azt eredmĂ©nyezheti, hogy a jövƑbeni felhasznĂĄlĂłk csak rĂ©szleges beszĂ©lgetĂ©st lĂĄtnak majd)", @@ -981,7 +981,7 @@ "Please contact your service administrator to get this limit increased.": "A korlĂĄt emelĂ©se Ă©rdekĂ©ben kĂ©rlek vedd fel a kapcsolatot a szolgĂĄltatĂĄs adminisztrĂĄtorĂĄval.", "This homeserver has hit its Monthly Active User limit so some users will not be able to log in.": "Ez a Matrix szerver elĂ©rte a havi aktĂ­v felhasznĂĄlĂłi korlĂĄtjĂĄt nĂ©hĂĄny felhasznĂĄlĂł nem fog tudni bejelentkezni.", "This homeserver has exceeded one of its resource limits so some users will not be able to log in.": "Ez a Matrix szerver tĂșllĂ©pte valamelyik erƑforrĂĄs korlĂĄtjĂĄt Ă­gy nĂ©hĂĄny felhasznĂĄlĂł nem tud majd bejelentkezni.", - "Upgrade Room Version": "Szoba verziĂłjĂĄnak frissĂ­tĂ©se", + "Upgrade Room Version": "Szoba verziĂłjĂĄnak fejlesztĂ©se", "Create a new room with the same name, description and avatar": "KĂ©szĂ­ts egy Ășj szobĂĄt ugyanazzal a nĂ©vvel, leĂ­rĂĄssal Ă©s profilkĂ©ppel", "Update any local room aliases to point to the new room": "ÁllĂ­ts ĂĄt minden helyi alternatĂ­v nevet erre a szobĂĄra", "Stop users from speaking in the old version of the room, and post a message advising users to move to the new room": "A felhasznĂĄlĂłknak tiltsd meg, hogy a rĂ©gi szobĂĄban beszĂ©lgessenek. KĂŒldj egy ĂŒzenetet amiben megkĂ©red a felhasznĂĄlĂłkat, hogy menjenek ĂĄt az Ășj szobĂĄba", @@ -996,9 +996,9 @@ "The conversation continues here.": "A beszĂ©lgetĂ©s itt folytatĂłdik.", "This room is a continuation of another conversation.": "Ebben a szobĂĄban folytatĂłdik egy mĂĄsik beszĂ©lgetĂ©s.", "Click here to see older messages.": "Ide kattintva megnĂ©zheted a rĂ©gi ĂŒzeneteket.", - "Failed to upgrade room": "A szoba frissĂ­tĂ©se sikertelen", - "The room upgrade could not be completed": "A szoba frissĂ­tĂ©sĂ©t nem sikerĂŒlt befejezni", - "Upgrade this room to version %(version)s": "A szoba frissĂ­tĂ©se %(version)s verziĂłra", + "Failed to upgrade room": "A szoba fejlesztĂ©se sikertelen", + "The room upgrade could not be completed": "A szoba fejlesztĂ©sĂ©t nem sikerĂŒlt befejezni", + "Upgrade this room to version %(version)s": "A szoba fejlesztĂ©se %(version)s verziĂłra", "Forces the current outbound group session in an encrypted room to be discarded": "A jelenlegi csoport munkamenet törlĂ©sĂ©t kikĂ©nyszerĂ­ti a titkosĂ­tott szobĂĄban", "Registration Required": "RegisztrĂĄciĂłt igĂ©nyel", "You need to register to do this. Would you like to register now?": "Hogy ezt megtedd regisztrĂĄlnod kell. SzeretnĂ©l regisztrĂĄlni?", @@ -1053,7 +1053,7 @@ "Print it and store it somewhere safe": "Nyomtad ki Ă©s tĂĄrold biztonsĂĄgos helyen", "Save it on a USB key or backup drive": "Mentsd el egy Pendrive-ra vagy a biztonsĂĄgi mentĂ©sekhez", "Copy it to your personal cloud storage": "MĂĄsold fel a szemĂ©lyes felhƑdbe", - "Without setting up Secure Message Recovery, you won't be able to restore your encrypted message history if you log out or use another device.": "A BiztonsĂĄgos Üzenet VisszaĂĄllĂ­tĂĄs beĂĄllĂ­tĂĄsa nĂ©lkĂŒl ha kijelentkezel vagy mĂĄsik eszközt hasznĂĄlsz, akkor nem tudod visszaĂĄllĂ­tani a rĂ©gi titkosĂ­tott ĂŒzeneteidet.", + "Without setting up Secure Message Recovery, you won't be able to restore your encrypted message history if you log out or use another device.": "A BiztonsĂĄgos ĂŒzenet-visszaĂĄllĂ­tĂĄs beĂĄllĂ­tĂĄsa nĂ©lkĂŒl ha kijelentkezel vagy mĂĄsik eszközt hasznĂĄlsz, akkor nem tudod visszaĂĄllĂ­tani a rĂ©gi titkosĂ­tott ĂŒzeneteidet.", "Set up Secure Message Recovery": "BiztonsĂĄgos Üzenet VisszaĂĄllĂ­tĂĄs beĂĄllĂ­tĂĄsa", "Keep it safe": "Tartsd biztonsĂĄgban", "Create Key Backup": "Kulcs mentĂ©s kĂ©szĂ­tĂ©se", @@ -1140,9 +1140,9 @@ "Invite anyway and never warn me again": "MindenkĂ©ppen meghĂ­v Ă©s ne figyelmeztess többet", "Invite anyway": "MindenkĂ©ppen meghĂ­v", "Whether or not you're logged in (we don't record your username)": "Se akkor ha bejelentkezel se akkor ha nem; mi nem tĂĄroljuk a felhasznĂĄlĂłi nevedet", - "Upgrades a room to a new version": "Szoba frissĂ­tĂ©se Ășj verziĂłra", + "Upgrades a room to a new version": "Szoba fejlesztĂ©se Ășj verziĂłra", "Sets the room name": "SzobanĂ©v beĂĄllĂ­tĂĄsa", - "%(senderDisplayName)s upgraded this room.": "%(senderDisplayName)s frissĂ­tette a szobĂĄt.", + "%(senderDisplayName)s upgraded this room.": "%(senderDisplayName)s fejlesztette a szobĂĄt.", "%(displayName)s is typing 
": "%(displayName)s gĂ©pel 
", "%(names)s and %(count)s others are typing 
|other": "%(names)s Ă©s %(count)s mĂĄsik gĂ©pelnek 
", "%(names)s and %(count)s others are typing 
|one": "%(names)s Ă©s mĂ©g valaki gĂ©pelnek 
", @@ -1156,7 +1156,7 @@ "Show avatars in user and room mentions": "ProfilkĂ©p mutatĂĄsa a felhasznĂĄlĂł Ă©s szoba emlĂ­tĂ©seknĂ©l", "Enable big emoji in chat": "Nagy Emojik engedĂ©lyezĂ©se a csevegĂ©sekben", "Send typing notifications": "GĂ©pelĂ©s visszajelzĂ©s kĂŒldĂ©se", - "Enable Community Filter Panel": "KözössĂ©gi szƱrƑ panel engedĂ©lyezĂ©se", + "Enable Community Filter Panel": "KözössĂ©gi szƱrƑ panel bekapcsolĂĄsa", "Messages containing my username": "Üzenetek amik a nevemet tartalmazzĂĄk", "The other party cancelled the verification.": "A mĂĄsik fĂ©l törölte az ellenƑrzĂ©st.", "Verified!": "EllenƑrizve!", @@ -1460,9 +1460,9 @@ "%(senderName)s revoked the invitation for %(targetDisplayName)s to join the room.": "%(senderName)s visszavonta %(targetDisplayName)s a szobĂĄba valĂł belĂ©pĂ©sĂ©hez szĂŒksĂ©ges meghĂ­vĂłjĂĄt.", "Enable desktop notifications for this device": "Asztali Ă©rtesĂ­tĂ©sek engedĂ©lyezĂ©se ehhez az eszközhöz", "Enable audible notifications for this device": "HallhatĂł Ă©rtesĂ­tĂ©sek engedĂ©lyezĂ©se ehhez az eszközhöz", - "Upgrade this room to the recommended room version": "A szoba frissĂ­tĂ©se a javasolt verziĂłra", + "Upgrade this room to the recommended room version": "A szoba fejlesztĂ©se a javasolt verziĂłra", "This room is running room version , which this homeserver has marked as unstable.": "A szoba verziĂłja: , amit a Matrix szerver instabilnak tekint.", - "Upgrading this room will shut down the current instance of the room and create an upgraded room with the same name.": "A szoba frissĂ­tĂ©se bezĂĄrja ezt a szobĂĄt Ă©s Ășj, frissĂ­tett verziĂłval ugyanezen a nĂ©ven lĂ©trehoz egy Ășjat.", + "Upgrading this room will shut down the current instance of the room and create an upgraded room with the same name.": "A szoba fejlesztĂ©se bezĂĄrja ezt a szobĂĄt Ă©s Ășj, frissĂ­tett verziĂłval ugyanezen a nĂ©ven lĂ©trehoz egy Ășjat.", "Failed to revoke invite": "A meghĂ­vĂł visszavonĂĄsa sikertelen", "Could not revoke the invite. The server may be experiencing a temporary problem or you do not have sufficient permissions to revoke the invite.": "A meghĂ­vĂłt nem lehet visszavonni. Vagy a szervernek ĂĄtmenetileg problĂ©mĂĄi vannak vagy nincs megfelelƑ jogosultsĂĄgod a meghĂ­vĂł visszavonĂĄsĂĄhoz.", "Revoke invite": "MeghĂ­vĂł visszavonĂĄsa", @@ -1507,7 +1507,7 @@ "Sends the given message coloured as a rainbow": "A megadott ĂŒzenetet szivĂĄrvĂĄny szĂ­nben kĂŒldi el", "Sends the given emote coloured as a rainbow": "A megadott hangulatjelet szivĂĄrvĂĄny szĂ­nben kĂŒldi el", "The user's homeserver does not support the version of the room.": "A felhasznĂĄlĂł matrix szervere nem tĂĄmogatja a megadott szoba verziĂłt.", - "When rooms are upgraded": "Ha a szobĂĄk frissĂŒltek", + "When rooms are upgraded": "Ha a szobĂĄk fejlesztĂ©sre kerĂŒlnek", "This device is not backing up your keys, but you do have an existing backup you can restore from and add to going forward.": "Ez az eszköz nem menti el a kulcsaidat, de lĂ©tezik mentĂ©s amit visszaĂĄllĂ­thatsz Ă©s folytathatod.", "Connect this device to key backup before signing out to avoid losing any keys that may only be on this device.": "Csatlakozz ezzel az eszközzel a kulcs mentĂ©shez kilĂ©pĂ©s elƑtt, hogy ne veszĂ­ts el kulcsot ami esetleg csak ezen az eszközön van meg.", "Connect this device to Key Backup": "Csatlakozz ezzel az eszközzel a Kulcs MentĂ©shez", @@ -1538,7 +1538,7 @@ "This room doesn't exist. Are you sure you're at the right place?": "Ez a szoba nem lĂ©tezik. Biztos, hogy jĂł helyen vagy?", "Try again later, or ask a room admin to check if you have access.": "PrĂłbĂĄlkozz kĂ©sƑbb vagy kĂ©rd meg a szoba adminisztrĂĄtorĂĄt, hogy nĂ©zze meg van-e hozzĂĄfĂ©rĂ©sed.", "%(errcode)s was returned while trying to access the room. If you think you're seeing this message in error, please submit a bug report.": "Amikor a szobĂĄt prĂłbĂĄltuk elĂ©rni ezt a hibaĂŒzenetet kaptuk: %(errcode)s. Ha Ășgy gondolod, hogy ez egy hiba lĂ©gy szĂ­vesnyiss egy hibajegyet.", - "This room has already been upgraded.": "Ez a szoba mĂĄr frissĂŒlt.", + "This room has already been upgraded.": "Ez a szoba mĂĄr fejlesztve van.", "Rotate Left": "Balra forgat", "Rotate Right": "Jobbra forgat", "View Servers in Room": "Szerverek megjelenĂ­tĂ©se a szobĂĄban", @@ -1690,7 +1690,7 @@ "If you don't want to use to discover and be discoverable by existing contacts you know, enter another identity server below.": "Ha felkutatĂĄsra Ă©s, hogy mĂĄs ismerƑsök megtalĂĄlhassanak, nem akarod hasznĂĄlni ezt a szervert: , akkor adjĂĄl meg mĂĄsik azonosĂ­tĂĄsi szervert alĂĄbb.", "Using an identity server is optional. If you choose not to use an identity server, you won't be discoverable by other users and you won't be able to invite others by email or phone.": "AzonosĂ­tĂĄsi szerver hasznĂĄlata nem kötelezƑ. Ha Ășgy döntesz, hogy az azonosĂ­tĂĄsi szervert nem hasznĂĄlod mĂĄs felhasznĂĄlĂłk nem talĂĄlnak rĂĄd Ă©s mĂĄsokat sem tudsz e-mail cĂ­m vagy telefonszĂĄm alapjĂĄn meghĂ­vni.", "Do not use an identity server": "Az azonosĂ­tĂĄsi szerver mellƑzĂ©se", - "Upgrade the room": "Szoba frissĂ­tĂ©se", + "Upgrade the room": "Szoba fejlesztĂ©se", "Set an email for account recovery. Use email or phone to optionally be discoverable by existing contacts.": "E-mail cĂ­m beĂĄllĂ­tĂĄsa a fiĂłk visszaĂĄllĂ­tĂĄsĂĄhoz. E-mail cĂ­m vagy telefonszĂĄm, hogy ismerƑsök megtalĂĄlhassanak.", "Set an email for account recovery. Use email to optionally be discoverable by existing contacts.": "E-mail cĂ­m beĂĄllĂ­tĂĄsa a fiĂłk visszaĂĄllĂ­tĂĄsĂĄhoz. E-mail cĂ­m, hogy ismerƑsök megtalĂĄlhassanak.", "Enter your custom homeserver URL What does this mean?": "Add meg a matrix szervered URL-jĂ©t Mit jelent ez?", @@ -1930,12 +1930,12 @@ "This message cannot be decrypted": "Ezt az ĂŒzenetet nem lehet visszafejteni", "Unencrypted": "TitkosĂ­tatlan", "Automatically invite users": "FelhasznĂĄlĂłk automatikus meghĂ­vĂĄsa", - "Upgrade private room": "PrivĂĄt szoba frissĂ­tĂ©se", - "Upgrade public room": "NyilvĂĄnos szoba frissĂ­tĂ©se", + "Upgrade private room": "PrivĂĄt szoba fejlesztĂ©se", + "Upgrade public room": "NyilvĂĄnos szoba fejlesztĂ©se", "Upgrading a room is an advanced action and is usually recommended when a room is unstable due to bugs, missing features or security vulnerabilities.": "A szoba frissĂ­tĂ©se nem egyszerƱ mƱvelet, ĂĄltalĂĄban a szoba hibĂĄs mƱködĂ©se, hiĂĄnyzĂł funkciĂł vagy biztonsĂĄgi sĂ©rĂŒlĂ©kenysĂ©g esetĂ©n javasolt.", "This usually only affects how the room is processed on the server. If you're having problems with your Riot, please report a bug.": "Ez ĂĄltalĂĄban a szoba szerver oldali kezelĂ©sĂ©ben jelent vĂĄltozĂĄst. Ha a Riotban van problĂ©mĂĄd, kĂ©rlek kĂŒldj egy hibajelentĂ©st.", - "You'll upgrade this room from to .": " verziĂłrĂłl verziĂłra frissĂ­ted a szobĂĄt.", - "Upgrade": "FrissĂ­tĂ©s", + "You'll upgrade this room from to .": " verziĂłrĂłl verziĂłra fejleszted a szobĂĄt.", + "Upgrade": "FejlesztĂ©s", "Notification settings": "ÉrtesĂ­tĂ©sek beĂĄllĂ­tĂĄsa", "User Status": "FelhasznĂĄlĂł ĂĄllapota", "Reactions": "ReakciĂłk", @@ -2076,5 +2076,35 @@ "Something went wrong trying to invite the users.": "Valami nem sikerĂŒlt a felhasznĂĄlĂłk meghĂ­vĂĄsĂĄval.", "We couldn't invite those users. Please check the users you want to invite and try again.": "Ezeket a felhasznĂĄlĂłkat nem tudtuk meghĂ­vni. EllenƑrizd azokat a felhasznĂĄlĂłkat akiket meg szeretnĂ©l hĂ­vni Ă©s prĂłbĂĄld Ășjra.", "Recently Direct Messaged": "NemrĂ©g kĂŒldött Közvetlen Üzenetek", - "If you can't find someone, ask them for their username (e.g. @user:server.com) or share this room.": "Ha nem talĂĄlsz valakit, akkor kĂ©rdezd meg a felhasznĂĄlĂłi nevĂ©t (pl.: @felhasznĂĄlĂł:szerver.com) vagy oszd meg ezt a szobĂĄt." + "If you can't find someone, ask them for their username (e.g. @user:server.com) or share this room.": "Ha nem talĂĄlsz valakit, akkor kĂ©rdezd meg a felhasznĂĄlĂłi nevĂ©t (pl.: @felhasznĂĄlĂł:szerver.com) vagy oszd meg ezt a szobĂĄt.", + "Verify User": "FelhasznĂĄlĂł ellenƑrzĂ©se", + "For extra security, verify this user by checking a one-time code on both of your devices.": "A biztonsĂĄg fokozĂĄsĂĄĂ©rt ellenƑrizd ezt a felhasznĂĄlĂłt egy egyszeri kĂłd egyeztetĂ©sĂ©vel mindkettƑtök kĂ©szĂŒlĂ©kĂ©n.", + "For maximum security, do this in person.": "A legnagyobb biztonsĂĄg Ă©rdekĂ©ben ezt szemĂ©lyesen tedd meg.", + "Start Verification": "EllenƑrzĂ©s elindĂ­tĂĄsa", + "Encrypted by a deleted device": "Egy mĂĄr törölt eszköz titkosĂ­totta", + "Unknown Command": "Ismeretlen Parancs", + "Unrecognised command: %(commandText)s": "Ismeretlen parancs: %(commandText)s", + "You can use /help to list available commands. Did you mean to send this as a message?": "HasznĂĄlhatod a /help-et az elĂ©rhetƑ parancsok kilistĂĄzĂĄsĂĄhoz. Ezt ĂŒzenetkĂ©nt akartad kĂŒldeni?", + "Hint: Begin your message with // to start it with a slash.": "Tipp: Ez ĂŒzenetedet kezd ezzel: //, ha perjellel szeretnĂ©d kezdeni.", + "Send as message": "Üzenet kĂŒldĂ©se", + "%(senderName)s added %(addedAddresses)s and %(count)s other addresses to this room|other": "%(senderName)s szoba cĂ­mnek, %(count)s mĂĄsikkal egyĂŒtt, hozzĂĄadta: %(addedAddresses)s", + "%(senderName)s removed %(removedAddresses)s and %(count)s other addresses from this room|other": "%(senderName)s %(count)s mĂĄsikkal egyĂŒtt törölte a szoba cĂ­mek közĂŒl: %(removedAddresses)s", + "%(senderName)s removed %(countRemoved)s and added %(countAdded)s addresses to this room": "%(senderName)s %(countRemoved)s darabot törölt Ă©s %(countAdded)s darabot hozzĂĄadott a szoba cĂ­mekhez", + "Someone is using an unknown device": "Valaki ismeretlen eszközt hasznĂĄl", + "This room is end-to-end encrypted": "Ez a szoba vĂ©gpontok közötti titkosĂ­tĂĄst hasznĂĄl", + "Everyone in this room is verified": "A szobĂĄba mindenki ellenƑrizve van", + "Invite only": "Csak meghĂ­vĂłval", + "Send a reply
": "VĂĄlasz kĂŒldĂ©se
", + "Send a message
": "Üzenet kĂŒldĂ©se
", + "Reject & Ignore user": "FelhasznĂĄlĂł elutasĂ­tĂĄsa Ă©s figyelmen kĂ­vĂŒl hagyĂĄsa", + "If you can't find someone, ask them for their username, share your username (%(userId)s) or profile link.": "Ha nem talĂĄlsz valakit, akkor kĂ©rdezd meg a felhasznĂĄlĂłi nevĂ©t, ĂĄruld el neki a felhasznĂĄlĂłi nevedet (%(userId)s) vagy a profil hivatkozĂĄsodat.", + "Enter your account password to confirm the upgrade:": "A fejlesztĂ©s megerƑsĂ­tĂ©sĂ©hez add meg a fiĂłk jelszavadat:", + "You'll need to authenticate with the server to confirm the upgrade.": "AzonosĂ­tanod kell magad a szerveren a fejlesztĂ©s megerƑsĂ­tĂ©sĂ©hez.", + "Enter a passphrase": "Jelmondat bevitele", + "Enter your passphrase a second time to confirm it.": "Add meg a jelmondatot mĂĄsodszor is a biztonsĂĄg kedvĂ©Ă©rt.", + "Verify other users in their profile.": "MĂĄs felhasznĂĄlĂłk ellenƑrzĂ©se a profiljukban.", + "Upgrade your encryption": "TitkosĂ­tĂĄsod fejlesztĂ©se", + "Set up encryption": "TitkosĂ­tĂĄs beĂĄllĂ­tĂĄsa", + "Encryption upgraded": "TitkosĂ­tĂĄs fejlesztve", + "Encryption setup complete": "TitkosĂ­tĂĄs beĂĄllĂ­tĂĄsa kĂ©sz" } diff --git a/src/i18n/strings/it.json b/src/i18n/strings/it.json index bb35bd6d69..c8844fb2bb 100644 --- a/src/i18n/strings/it.json +++ b/src/i18n/strings/it.json @@ -2055,5 +2055,57 @@ "Key Backup is enabled on your account but has not been set up from this session. To set up secret storage, restore your key backup.": "Il Backup Chiavi Ăš attivo sul tuo account ma non Ăš stato impostato da questa sessione. Per impostare un archivio segreto, ripristina il tuo backup chiavi.", "Restore": "Ripristina", "Secret Storage will be set up using your existing key backup details. Your secret storage passphrase and recovery key will be the same as they were for your key backup": "L'archivio segreto verrĂ  impostato usando i dettagli esistenti del backup chiavi. La password dell'archivio segreto e la chiave di recupero saranno le stesse del backup chiavi", - "Restore your Key Backup": "Ripristina il tuo Backup Chiavi" + "Restore your Key Backup": "Ripristina il tuo Backup Chiavi", + "New Session": "Nuova sessione", + "New invite dialog": "Nuova finestra di invito", + "Other users may not trust it": "Altri utenti potrebbero non fidarsi", + "Later": "PiĂč tardi", + "Failed to invite the following users to chat: %(csvUsers)s": "Impossibile invitare i seguenti utenti alla chat: %(csvUsers)s", + "We couldn't create your DM. Please check the users you want to invite and try again.": "Impossibile creare il messaggio diretto. Ricontrolla gli utenti che vuoi invitare e riprova.", + "Something went wrong trying to invite the users.": "Qualcosa Ăš andato storto provando ad invitare gli utenti.", + "We couldn't invite those users. Please check the users you want to invite and try again.": "Impossibile invitare quegli utenti. Ricontrolla gli utenti che vuoi invitare e riprova.", + "Recently Direct Messaged": "Contattati direttamente di recente", + "If you can't find someone, ask them for their username (e.g. @user:server.com) or share this room.": "Se non riesci a trovare qualcuno, chiedi il nome utente (es. @utente:server.it) o condividi questa stanza.", + "Complete security": "Sicurezza completa", + "Verify this session to grant it access to encrypted messages.": "Verifica questa sessione per concederle accesso ai messaggi cifrati.", + "Start": "Inizia", + "Session verified": "Sessione verificata", + "Your new session is now verified. It has access to your encrypted messages, and other users will see it as trusted.": "La tua sessione ora Ăš verificata. Ha accesso ai tuoi messaggi cifrati e gli altri utenti la vedranno come fidata.", + "Done": "Fatto", + "Without completing security on this device, it won’t have access to encrypted messages.": "Se non completi la sicurezza su questo dispositivo, esso non avrĂ  accesso ai messaggi cifrati.", + "Go Back": "Torna", + "Secret Storage will be set up using your existing key backup details. Your secret storage passphrase and recovery key will be the same as they were for your key backup.": "L'archivio segreto verrĂ  impostato usando i dettagli del backup chiavi esistente. La password dell'archivio segreto e la chiave di ripristino saranno le stesse del backup chiavi.", + "Encrypted by a deleted device": "Cifrato da un dispositivo eliminato", + "Verify User": "Verifica utente", + "For extra security, verify this user by checking a one-time code on both of your devices.": "Per maggiore sicurezza, verifica questo utente controllando un codice univoco sui vostri dispositivi.", + "For maximum security, do this in person.": "Per massima sicurezza, fatelo di persona.", + "Start Verification": "Inizia la verifica", + "%(senderName)s added %(addedAddresses)s and %(count)s other addresses to this room|other": "%(senderName)s ha aggiunto %(addedAddresses)s e %(count)s altri indirizzi a questa stanza", + "%(senderName)s removed %(removedAddresses)s and %(count)s other addresses from this room|other": "%(senderName)s ha rimosso %(removedAddresses)s e %(count)s altri indirizzi da questa stanza", + "%(senderName)s removed %(countRemoved)s and added %(countAdded)s addresses to this room": "%(senderName)s ha rimosso %(countRemoved)s e aggiunto %(countAdded)s indirizzi a questa stanza", + "Someone is using an unknown device": "Qualcuno sta usando un dispositivo sconosciuto", + "This room is end-to-end encrypted": "Questa stanza Ăš cifrata end-to-end", + "Everyone in this room is verified": "Tutti in questa stanza sono verificati", + "Invite only": "Solo a invito", + "Send a reply
": "Invia risposta
", + "Send a message
": "Invia un messaggio
", + "Reject & Ignore user": "Rifiuta e ignora l'utente", + "Unknown Command": "Comando sconosciuto", + "Unrecognised command: %(commandText)s": "Comando non riconosciuto: %(commandText)s", + "You can use /help to list available commands. Did you mean to send this as a message?": "Puoi usare /help per elencare i comandi disponibili. Volevo forse inviarlo come messaggio?", + "Hint: Begin your message with // to start it with a slash.": "Suggerimento: anteponi al tuo messaggio // per farlo iniziare con uno slash.", + "Send as message": "Invia come messaggio", + "Enter your account password to confirm the upgrade:": "Inserisci la password del tuo account per confermare l'aggiornamento:", + "You'll need to authenticate with the server to confirm the upgrade.": "Dovrai autenticarti con il server per confermare l'aggiornamento.", + "Upgrade this device to allow it to verify other devices, granting them access to encrypted messages and marking them as trusted for other users.": "Aggiorna il dispositivo per consentirgli di verificare altri dispositivi, dando loro accesso ai messaggi cifrati e contrassegnandoli come fidati per gli altri utenti.", + "Set up encryption on this device to allow it to verify other devices, granting them access to encrypted messages and marking them as trusted for other users.": "Imposta la cifratura sul dispositivo per consentirgli di verificare altri dispositivi, dando loro accesso ai messaggi cifrati e contrassegnandoli come fidati per gli altri utenti.", + "Secure your encryption keys with a passphrase. For maximum security this should be different to your account password:": "Proteggi le chiavi di cifratura con una password. Per massima sicurezza questa dovrebbe essere diversa da quella del tuo account:", + "Enter a passphrase": "Inserisci una password", + "Enter your passphrase a second time to confirm it.": "Inserisci di nuovo la tua password per confermarla.", + "This device can now verify other devices, granting them access to encrypted messages and marking them as trusted for other users.": "Questo dispositivo ora puĂČ verificare altri dispositivi, dando loro accesso ai messaggi cifrati e contrassegnandoli come fidati per gli altri utenti.", + "Verify other users in their profile.": "Verifica gli altri utenti nel loro profilo.", + "Upgrade your encryption": "Aggiorna la tua cifratura", + "Set up encryption": "Imposta la cifratura", + "Encryption upgraded": "Cifratura aggiornata", + "Encryption setup complete": "Impostazione cifratura completata" } diff --git a/src/i18n/strings/ja.json b/src/i18n/strings/ja.json index 55cc8782ef..787dcbc4ca 100644 --- a/src/i18n/strings/ja.json +++ b/src/i18n/strings/ja.json @@ -601,7 +601,7 @@ "Copied!": "ă‚łăƒ”ăƒŒă•ă‚ŒăŸă—ăŸ!", "Failed to copy": "ă‚łăƒ”ăƒŒă«ć€±æ•—ă—ăŸă—ăŸ", "Add an Integration": "ç”±ćˆă‚’èżœćŠ ă™ă‚‹", - "You are about to be taken to a third-party site so you can authenticate your account for use with %(integrationsUrl)s. Do you wish to continue?": "ă‚”ăƒŒăƒ‰ăƒ‘ăƒŒăƒ†ă‚Łăźă‚”ă‚€ăƒˆă«ç§»ć‹•ă—ăŠă€%(integationsUrl)s ă§äœżç”šă™ă‚‹ăŸă‚ă«ă‚ąă‚«ă‚Šăƒłăƒˆă‚’èȘèšŒă§ăă‚‹ă‚ˆă†ă«ăȘă‚ŠăŸă™ă€‚ç¶šèĄŒă—ăŸă™ă‹ïŒŸ", + "You are about to be taken to a third-party site so you can authenticate your account for use with %(integrationsUrl)s. Do you wish to continue?": "ă‚”ăƒŒăƒ‰ăƒ‘ăƒŒăƒ†ă‚Łăźă‚”ă‚€ăƒˆă«ç§»ć‹•ă—ăŠă€%(integrationsUrl)s ă§äœżç”šă™ă‚‹ăŸă‚ă«ă‚ąă‚«ă‚Šăƒłăƒˆă‚’èȘèšŒă§ăă‚‹ă‚ˆă†ă«ăȘă‚ŠăŸă™ă€‚ç¶šèĄŒă—ăŸă™ă‹ïŒŸ", "Removed or unknown message type": "ć‰Šé™€ă•ă‚ŒăŸăŸăŸăŻæœȘçŸ„ăźăƒĄăƒƒă‚»ăƒŒă‚žă‚żă‚€ăƒ—", "Message removed by %(userId)s": "%(userId)s ă«ă‚ˆăŁăŠăƒĄăƒƒă‚»ăƒŒă‚žăŒć‰Šé™€ă•ă‚ŒăŸă—ăŸ", "Message removed": "ăƒĄăƒƒă‚»ăƒŒă‚žăŒć‰Šé™€ă•ă‚ŒăŸ", @@ -630,7 +630,7 @@ "Are you sure you want to remove '%(roomName)s' from %(groupId)s?": "%(roomName)s を %(groupId)s ă‹ă‚‰ć‰Šé™€ă—ăŠă‚‚ă‚ˆă‚ă—ă„ă§ă™ă‹?", "Removing a room from the community will also remove it from the community page.": "ă‚łăƒŸăƒ„ăƒ‹ăƒ†ă‚Łă‹ă‚‰éƒšć±‹ă‚’ć‰Šé™€ă™ă‚‹ăšă€ă‚łăƒŸăƒ„ăƒ‹ăƒ†ă‚ŁăƒšăƒŒă‚žă‹ă‚‰ă‚‚ăăźéƒšć±‹ăŒć‰Šé™€ă•ă‚ŒăŸă™ă€‚", "Failed to remove room from community": "ă‚łăƒŸăƒ„ăƒ‹ăƒ†ă‚Łă‹ă‚‰ăźéƒšć±‹ăźć‰Šé™€ă«ć€±æ•—ă—ăŸă—ăŸ", - "Failed to remove '%(roomName)s' from %(groupId)s": "%(groupName)s から '%(roomName)s' ă‚’ć‰Šé™€ă§ăăŸă›ă‚“ă§ă—ăŸ", + "Failed to remove '%(roomName)s' from %(groupId)s": "%(groupId)s から '%(roomName)s' ă‚’ć‰Šé™€ă§ăăŸă›ă‚“ă§ă—ăŸ", "Something went wrong!": "äœ•ă‹ăŒé–“é•ăŁăŠă„ăŸ!", "The visibility of '%(roomName)s' in %(groupId)s could not be updated.": "%(groupId)s た '%(roomName)s' ăźèĄšç€șă‚’æ›Žæ–°ă§ăăŸă›ă‚“ă§ă—ăŸă€‚", "Visibility in Room List": "ăƒ«ăƒŒăƒ ăƒȘă‚čăƒˆăźćŻèŠ–æ€§", @@ -668,7 +668,7 @@ "%(severalUsers)sjoined %(count)s times|one": "%(severalUsers)s ăŒć‚ćŠ ă—ăŸă—ăŸ", "%(oneUser)sjoined %(count)s times|other": "%(oneUser)s が %(count)s ć›žć‚ćŠ ă—ăŸă—ăŸ", "%(oneUser)sjoined %(count)s times|one": "%(oneUser)s ăŒć‚ćŠ ă—ăŸă—ăŸ", - "%(severalUsers)sleft %(count)s times|other": "%(severalUers)s は %(count)s 曞退ć‡șă—ăŸă—ăŸ", + "%(severalUsers)sleft %(count)s times|other": "%(severalUsers)s は %(count)s 曞退ć‡șă—ăŸă—ăŸ", "%(severalUsers)sleft %(count)s times|one": "%(severalUsers)s は退ć‡șă—ăŸă—ăŸ", "%(oneUser)sleft %(count)s times|other": "%(oneUser)s は %(count)s 曞退ć‡șă—ăŸă—ăŸ", "%(oneUser)sleft %(count)s times|one": "%(oneUser)s は退ć‡șă—ăŸă—ăŸ", diff --git a/src/i18n/strings/sq.json b/src/i18n/strings/sq.json index e833009d59..3c04ff85c0 100644 --- a/src/i18n/strings/sq.json +++ b/src/i18n/strings/sq.json @@ -1917,11 +1917,11 @@ "%(senderName)s placed a voice call. (not supported by this browser)": "%(senderName)s bĂ«ri njĂ« thirrje zanore. (e pambuluar nga ky shfletues)", "%(senderName)s placed a video call.": "%(senderName)s bĂ«ri njĂ« thirrje video.", "%(senderName)s placed a video call. (not supported by this browser)": "%(senderName)s bĂ«ri njĂ« thirrje video. (e pambuluar nga ky shfletues)", - "Enable cross-signing to verify per-user instead of per-device (in development)": "", + "Enable cross-signing to verify per-user instead of per-device (in development)": "Aktivizoni cross-signing pĂ«r tĂ« verifikuar me bazĂ« pĂ«rdorues nĂ« vend se me bazĂ« pajisje (nĂ« zhvillim)", "Enable local event indexing and E2EE search (requires restart)": "Aktivizoni indeksim aktesh vendore dhe kĂ«rkim E2EE (lyp rinisje)", "Match system theme": "PĂ«rputhe me temĂ«n e sistemit", - "Send cross-signing keys to homeserver": "", - "Cross-signing public keys:": "", + "Send cross-signing keys to homeserver": "DĂ«rgo te shĂ«rbyesi Home kyçe cross-signing", + "Cross-signing public keys:": "Kyçe publikĂ« pĂ«r cross-signing:", "on device": "nĂ« pajisje", "not found": "s’u gjet", "in secret storage": "nĂ« depozitĂ« tĂ« fshehtĂ«", @@ -2016,5 +2016,88 @@ "Connected to on ": "Lidhur me nĂ« ", "Connected via %(protocolName)s": "Lidhur pĂ«rmes %(protocolName)s", "Bridge Info": "TĂ« dhĂ«na Ure", - "Below is a list of bridges connected to this room.": "MĂ« poshtĂ« keni njĂ« listĂ« urash tĂ« lidhura nĂ« kĂ«tĂ« dhomĂ«." + "Below is a list of bridges connected to this room.": "MĂ« poshtĂ« keni njĂ« listĂ« urash tĂ« lidhura nĂ« kĂ«tĂ« dhomĂ«.", + "New Session": "Sesion i Ri", + "%(senderName)s added %(addedAddresses)s and %(count)s other addresses to this room|other": "%(senderName)s shtoi %(addedAddresses)s dhe dhe %(count)s adresa tĂ« tjera te kjo dhomĂ«", + "%(senderName)s removed %(removedAddresses)s and %(count)s other addresses from this room|other": "%(senderName)s hoqi %(removedAddresses)s dhe %(count)s adresa tĂ« tjera nga kjo dhomĂ«", + "%(senderName)s removed %(countRemoved)s and added %(countAdded)s addresses to this room": "%(senderName)s hoqi %(countRemoved)s dhe shtoi %(countAdded)s adresa te kjo dhomĂ«", + "%(senderName)s turned on end-to-end encryption.": "%(senderName)s aktivizoi fshehtĂ«zimin skaj-mĂ«-skaj.", + "%(senderName)s turned on end-to-end encryption (unrecognised algorithm %(algorithm)s).": "%(senderName)s aktivizoi fshehtĂ«zimin skaj-mĂ«-skaj (algoritĂ«m jo i pranuar %(algorithm)s).", + "a few seconds ago": "pak sekonda mĂ« parĂ«", + "about a minute ago": "rreth njĂ« minutĂ« mĂ« parĂ«", + "%(num)s minutes ago": "%(num)s minuta mĂ« parĂ«", + "about an hour ago": "rreth njĂ« orĂ« mĂ« parĂ«", + "%(num)s hours ago": "%(num)s orĂ« mĂ« parĂ«", + "about a day ago": "rreth njĂ« ditĂ« mĂ« parĂ«", + "%(num)s days ago": "%(num)s ditĂ« mĂ« parĂ«", + "a few seconds from now": "pak sekonda nga tani", + "about a minute from now": "rreth njĂ« minutĂ« nga tani", + "%(num)s minutes from now": "%(num)s minuta nga tani", + "about an hour from now": "rreth njĂ« orĂ« nga tani", + "%(num)s hours from now": "%(num)s orĂ« nga tani", + "about a day from now": "rreth njĂ« ditĂ« nga tani", + "%(num)s days from now": "%(num)s ditĂ« nga tani", + "Show a presence dot next to DMs in the room list": "Shfaqni njĂ« pikĂ« pranie nĂ« krah DM-sh te lista e dhomave", + "Other users may not trust it": "PĂ«rdorues tĂ« tjerĂ« mund tĂ« mos e besojnĂ«", + "Later": "MĂ« vonĂ«", + "Cross-signing and secret storage are enabled.": "Cross-signing dhe depozitimi i fshehtĂ« janĂ« aktivizuar.", + "Your account has a cross-signing identity in secret storage, but it is not yet trusted by this device.": "Llogaria juaj ka njĂ« identitet cross-signing nĂ« depozitĂ« tĂ« fshehtĂ«, por s’ështĂ« ende i besuar nĂ« kĂ«tĂ« pajisje.", + "Cross-signing and secret storage are not yet set up.": "Cross-signing dhe depozitimi i fshehtĂ« s’janĂ« ujdisur ende.", + "Cross-signing private keys:": "Kyçe privatĂ« pĂ«r cross-signing:", + "Backup key stored in secret storage, but this feature is not enabled on this device. Please enable cross-signing in Labs to modify key backup state.": "Kyçi i kopjeruajtjeve u depozitua nĂ« depozitĂ« tĂ« fshehtĂ«, po kjo veçori s’ështĂ« e aktivizuar nĂ« kĂ«tĂ« pajisje. Ju lutemi, aktivizoni nĂ« Labs cross-signing qĂ« tĂ« modifikoni gjendje kopjeruatjeje kyçesh.", + "Labs": "Labs", + "Complete": "E plotĂ«", + "Someone is using an unknown device": "Dikush po pĂ«rdor njĂ« pajisje tĂ« panjohur", + "This room is end-to-end encrypted": "Kjo dhomĂ« Ă«shtĂ« e fshehtĂ«zuar skaj-mĂ«-skaj", + "Everyone in this room is verified": "Gjithkush nĂ« kĂ«tĂ« dhomĂ« Ă«shtĂ« verifikuar", + "Encrypted by a deleted device": "FshehtĂ«zuar nga njĂ« pajisje e fshirĂ«", + "Invite only": "VetĂ«m me ftesa", + "Send a reply
": "DĂ«rgoni njĂ« pĂ«rgjigje
", + "Send a message
": "DĂ«rgoni njĂ« mesazh
", + "Reject & Ignore user": "Hidhe poshtĂ« & ShpĂ«rfille pĂ«rdoruesin", + "Unknown Command": "UrdhĂ«r i Panjohur", + "Unrecognised command: %(commandText)s": "UrdhĂ«r Jo i Pranuar: %(commandText)s", + "You can use /help to list available commands. Did you mean to send this as a message?": "Mund tĂ« pĂ«rdorni /help qĂ« tĂ« shfaqen urdhrat e gatshĂ«m. Donit vĂ«rtet ta dĂ«rgoni kĂ«tĂ« si njĂ« mesazh?", + "Hint: Begin your message with // to start it with a slash.": "NdihmĂ«z: Fillojeni mesazhin tuaj me // qĂ« tĂ« nisĂ« me njĂ« pjerrake.", + "Send as message": "DĂ«rgoni njĂ« mesazh", + "Verify User": "Verifikoni PĂ«rdoruesin", + "For extra security, verify this user by checking a one-time code on both of your devices.": "PĂ«r siguri ekstra, verifikojeni kĂ«tĂ« pĂ«rdorues duke kontrolluar nĂ« tĂ« dyja pajisjet tuaja njĂ« kod njĂ«pĂ«rdorimsh.", + "For maximum security, do this in person.": "PĂ«r siguri maksimum, bĂ«jeni kĂ«tĂ« ju vetĂ«.", + "Start Verification": "Fillo Verifikimin", + "Failed to invite the following users to chat: %(csvUsers)s": "S’u arrit tĂ« ftoheshin pĂ«r bisedĂ« pĂ«rdoruesit vijues: %(csvUsers)s", + "We couldn't create your DM. Please check the users you want to invite and try again.": "S’e krijuam dot DM-nĂ« tuaj. Ju lutemi, kontrolloni pĂ«rdoruesit qĂ« doni tĂ« ftoni dhe riprovoni.", + "Something went wrong trying to invite the users.": "Diç shkoi ters teksa provohej tĂ« ftoheshin pĂ«rdoruesit.", + "We couldn't invite those users. Please check the users you want to invite and try again.": "S’i ftuam dot kĂ«ta pĂ«rdorues. Ju lutemi, kontrolloni pĂ«rdoruesit qĂ« doni tĂ« ftoni dhe riprovoni.", + "Failed to find the following users": "S’u arrit tĂ« gjendeshin pĂ«rdoruesit vijues", + "The following users might not exist or are invalid, and cannot be invited: %(csvNames)s": "PĂ«rdoruesit vijues mund tĂ« mos ekzistojnĂ« ose janĂ« tĂ« pavlefshĂ«m, dhe s’mund tĂ« ftohen: %(csvNames)s", + "Suggestions": "Sugjerime", + "If you can't find someone, ask them for their username, share your username (%(userId)s) or profile link.": "NĂ«se s’gjeni dot dikĂ«, kĂ«rkojini emrin e tij tĂ« pĂ«rdoruesit, tregojuni emrin tuaj tĂ« pĂ«rdoruesit (%(userId)s) ose lidhjen e profilit.", + "If you can't find someone, ask them for their username (e.g. @user:server.com) or share this room.": "NĂ«se s’gjeni dot dikĂ«, kĂ«rkojini emrin e tij tĂ« pĂ«rdoruesit (p.sh., @pĂ«rdorues:shĂ«rbyes.com) ose tregojuni kĂ«tĂ« dhomĂ«.", + "Access your secure message history and your cross-signing identity for verifying other devices by entering your passphrase.": "PĂ«r verifikim pajisjesh tĂ« tjera pĂ«rmes dhĂ«nies sĂ« frazĂ«kalimit tuaj, hyni te historiku i mesazheve tuaj tĂ« sigurt dhe identiteti juaj pĂ«r cross-signing.", + "Access your secure message history and your cross-signing identity for verifying other devices by entering your recovery key.": "PĂ«r verifikim pajisjesh tĂ« tjera pĂ«rmes dhĂ«nies sĂ« kyçit tuaj tĂ« rimarrjes, hyni te historiku i mesazheve tuaj tĂ« sigurt dhe identiteti juaj pĂ«r cross-signing.", + "Complete security": "Siguri tĂ« plotĂ«", + "Verify this session to grant it access to encrypted messages.": "Verifikojeni kĂ«tĂ« sesion qĂ« t’i akordohet hyrje te mesazhe tĂ« fshehtĂ«zuar.", + "Start": "Nise", + "Session verified": "Sesion i verifikuar", + "Your new session is now verified. It has access to your encrypted messages, and other users will see it as trusted.": "Sesioni juaj i ri tani Ă«shtĂ« i verifikuar. Ka hyrje te mesazhet tuaj tĂ« fshehtĂ«zuar dhe pĂ«rdoruesit e tjerĂ« do ta shohin si tĂ« besuar.", + "Done": "U bĂ«", + "Without completing security on this device, it won’t have access to encrypted messages.": "Pa plotĂ«suar sigurinĂ« nĂ« kĂ«tĂ« pajisje, s’do tĂ« ketĂ« hyrje te mesazhe tĂ« fshehtĂ«zuar.", + "Go Back": "Shko Mbrapsht", + "Key Backup is enabled on your account but has not been set up from this session. To set up secret storage, restore your key backup.": "Kopjeruajtja e Kyçeve Ă«shtĂ« e aktivizuar nĂ« llogarinĂ« tuaj, por nuk Ă«shtĂ« ujdisur qĂ« nga ky sesion. QĂ« tĂ« ujdisni depozitim tĂ« fshehtĂ«, riktheni kopjeruajtjen tuaj tĂ« kyçeve.", + "Restore": "Riktheje", + "Enter your account password to confirm the upgrade:": "QĂ« tĂ« ripohohet pĂ«rmirĂ«simi, jepni fjalĂ«kalimin e llogarisĂ« tuaj:", + "You'll need to authenticate with the server to confirm the upgrade.": "Do t’ju duhet tĂ« bĂ«ni mirĂ«filltĂ«simin me shĂ«rbyesin qĂ« tĂ« ripohohet pĂ«rmirĂ«simi.", + "Upgrade this device to allow it to verify other devices, granting them access to encrypted messages and marking them as trusted for other users.": "PĂ«rmirĂ«sojeni kĂ«tĂ« pajisje pĂ«r ta lejuar tĂ« verifikojĂ« pajisje tĂ« tjera, duke u akorduar hyrje te mesazhe tĂ« fshehtĂ«zuar dhe duke u vĂ«nĂ« shenjĂ« si tĂ« besuara pĂ«r pĂ«rdorues tĂ« tjerĂ«.", + "Set up encryption on this device to allow it to verify other devices, granting them access to encrypted messages and marking them as trusted for other users.": "Ujdisni fshehtĂ«zim nĂ« kĂ«tĂ« pajisje qĂ« ta lejoni tĂ« verifikojĂ« pajisje tĂ« tjera, duke u akorduar atyre hyrje te mesazhe tĂ« fshehtĂ«zuar dhe duke u vĂ«nĂ« shenjĂ« atyre si tĂ« besuara pĂ«r pĂ«rdorues tĂ« tjerĂ«.", + "Secure your encryption keys with a passphrase. For maximum security this should be different to your account password:": "Sigurojini kyçet tuaj tĂ« fshehtĂ«zimit me njĂ« frazĂ«kalim. PĂ«r siguri maksimale, ky do tĂ« duhej tĂ« ishte i ndryshĂ«m nga fjalĂ«kalimi pĂ«r llogarinĂ« tuaj:", + "Enter a passphrase": "Jepni njĂ« frazĂ«kalim", + "Enter your passphrase a second time to confirm it.": "QĂ« tĂ« ripohohet, jepeni edhe njĂ« herĂ« frazĂ«kalimin tuaj.", + "This device can now verify other devices, granting them access to encrypted messages and marking them as trusted for other users.": "Kjo pajisje mund tĂ« verifikojĂ« pajisje tĂ« tjera, duke u akorduar hyrje te mesazhe tĂ« fshehtĂ«zuar dhe duke u vĂ«nĂ« shenjĂ« si tĂ« besuara pĂ«r pĂ«rdorues tĂ« tjerĂ«.", + "Verify other users in their profile.": "Verifikoni pĂ«rdorues tĂ« tjerĂ« nĂ« profilin e tyre.", + "Without setting up secret storage, you won't be able to restore your access to encrypted messages or your cross-signing identity for verifying other devices if you log out or use another device.": "Pa ujdisur depozitim tĂ« fshehtĂ«, s’do tĂ« jeni nĂ« gjendje tĂ« rimerrni hyrje te mesazhe tĂ« fshehtĂ«zuar apo te identiteti juaj cross-signing pĂ«r verifikim pajisjesh tĂ« tjera, nĂ«se dilni nga llogaria juaj ose pĂ«rdorni njĂ« pajisje tjetĂ«r.", + "Restore your Key Backup": "Riktheni Kopjeruajtjen tuaj tĂ« Kyçeve", + "Upgrade your encryption": "PĂ«rmirĂ«soni fshehtĂ«zimin tuaj", + "Set up encryption": "Ujdisni fshehtĂ«zim", + "Encryption upgraded": "U pĂ«rmirĂ«sua fshehtĂ«zimi", + "Encryption setup complete": "Ujdisje fshehtĂ«zimit e plotĂ«suar" } diff --git a/src/i18n/strings/tr.json b/src/i18n/strings/tr.json index 81f0522922..257cb27b42 100644 --- a/src/i18n/strings/tr.json +++ b/src/i18n/strings/tr.json @@ -1422,5 +1422,121 @@ "Enable Community Filter Panel": "Toluluk Filtre Panelini Aç", "Match system theme": "Sistem temasıyla eƟle", "Allow Peer-to-Peer for 1:1 calls": "1:1 çağrılar için eƟten-eƟe izin ver", - "Missing media permissions, click the button below to request.": "Medya izinleri eksik, alttaki butona tıkayarak talep edin." + "Missing media permissions, click the button below to request.": "Medya izinleri eksik, alttaki butona tıkayarak talep edin.", + "Credits": "Katkıda Bulunanlar", + "Clear cache and reload": "Belleği temizle ve yeniden yĂŒkle", + "Customise your experience with experimental labs features. Learn more.": "Deneysel laboratuar özellikler ile deneyiminizi özelleƟtirebilirsiniz. Daha fazla.", + "Ignored/Blocked": "Yoksayılan/Bloklanan", + "Error adding ignored user/server": "Yoksayılan kullanıcı/sunucu eklenirken hata", + "Error subscribing to list": "Listeye abone olunurken hata", + "Error removing ignored user/server": "Yoksayılan kullanıcı/sunucu silinirken hata", + "Error unsubscribing from list": "Listeden abonelikten çıkılırken hata", + "You are not subscribed to any lists": "Herhangi bir listeye aboneliğiniz bulunmuyor", + "⚠ These settings are meant for advanced users.": "⚠ Bu ayarlar ileri dĂŒzey kullanıcılar içindir.", + "Unignore": "Yoksayma", + "This bridge was provisioned by ": "Bu körpĂŒ tarafından provize edildi", + "Connected to on ": " ağındaki kanala bağlandı", + "Below is a list of bridges connected to this room.": "Bu odaya bağlanmÄ±ĆŸ köprĂŒlerin bir listesi alttadır.", + "Change room avatar": "Oda resmini değiƟtir", + "Members only (since the point in time of selecting this option)": "Sadece ĂŒyeler ( bu seçeneği seçtiğinizden itibaren)", + "Unable to revoke sharing for email address": "E-posta adresi paylaĆŸÄ±mı kaldırılamadı", + "Unable to revoke sharing for phone number": "Telefon numarası paylaĆŸÄ±mı kaldırılamıyor", + "Where this page includes identifiable information, such as a room, user or group ID, that data is removed before being sent to the server.": "Bu sayfadaki oda, kullanıcı veya grup ID si gibi betimleyici bilgiler sunucuya gönderilmeden önce silindi.", + "Please ask the administrator of your homeserver (%(homeserverDomain)s) to configure a TURN server in order for calls to work reliably.": "Çağrıların sağlıklı bir Ɵekide yapılabilmesi için lĂŒtfen anasunucunuzun (%(homeserverDomain)s) yöneticisinden bir TURN sunucusu yapılandırmasını isteyin.", + "%(severalUsers)schanged their name %(count)s times|other": "%(severalUsers)s kullanıcıları isimlerini %(count)s kez değiƟtirdiler", + "%(oneUser)schanged their name %(count)s times|other": "%(oneUser)s ismini %(count)s kez değiƟtirdi", + "%(severalUsers)smade no changes %(count)s times|one": "%(severalUsers)s değiƟiklik yapmadı", + "%(oneUser)smade no changes %(count)s times|other": "%(oneUser)s %(count)s kez değiƟiklik yapmadı", + "%(oneUser)smade no changes %(count)s times|one": "%(oneUser)s değiƟiklik yapmadı", + "Room alias": "Oda lakabı", + "Please provide a room alias": "LĂŒtfen bir oda lakabı belirtin", + "This alias is available to use": "Bu lakap kullanmaya uygun", + "This alias is already in use": "Bu lakap zaten kullanımda", + "And %(count)s more...|other": "ve %(count)s kez daha...", + "Alternatively, you can try to use the public server at turn.matrix.org, but this will not be as reliable, and it will share your IP address with that server. You can also manage this in Settings.": "Alternatif olarak,turn.matrix.org adresindeki herkese açık sunucuyu kullanmayı deneyebilirsiniz. Fakat bu gĂŒvenilir olmayabilir. IP adresiniz bu sunucu ile paylaĆŸÄ±lacaktır. Ayarlardan yönetebilirsiniz.", + "An error ocurred whilst trying to remove the widget from the room": "Görsel bileƟen odadan silinmeye çalÄ±ĆŸÄ±lırken bir hata oluƟtu", + "Minimize apps": "Uygulamaları kĂŒĂ§ĂŒlt", + "Maximize apps": "Uygulamaları bĂŒyĂŒlt", + "Popout widget": "Görsel bileƟeni göster", + "Please create a new issue on GitHub so that we can investigate this bug.": "LĂŒtfen GitHub’da Yeni bir talep oluƟturun ki bu hatayı inceleyebilelim.", + "Rotate counter-clockwise": "Saat yönĂŒnĂŒn tersine döndĂŒr", + "Language Dropdown": "Dil Listesi", + "%(severalUsers)sleft %(count)s times|other": "%(severalUsers)s, %(count)s kez ayrıldı", + "%(oneUser)sleft %(count)s times|other": "%(oneUser)s %(count)s kez ayrıldı", + "%(severalUsers)sjoined and left %(count)s times|other": "%(severalUsers)s %(count)s kez katılıp ve ayrıldı", + "%(oneUser)sjoined and left %(count)s times|other": "%(oneUser)s %(count)s kez katıldı ve ayrıldı", + "%(severalUsers)sleft and rejoined %(count)s times|one": "%(severalUsers)s ayrıldı ve yeniden katıldı", + "%(severalUsers)srejected their invitations %(count)s times|other": "%(severalUsers)s %(count)s kez davetlerini reddetti", + "%(severalUsers)srejected their invitations %(count)s times|one": "%(severalUsers)s davetlerini reddetti", + "%(oneUser)srejected their invitation %(count)s times|one": "%(oneUser)s davetlerini reddetti", + "%(severalUsers)shad their invitations withdrawn %(count)s times|one": "%(severalUsers)s davetlerini geri çekti", + "%(oneUser)shad their invitation withdrawn %(count)s times|other": "%(oneUser)s davetini %(count)s kez geri çekti", + "%(oneUser)shad their invitation withdrawn %(count)s times|one": "%(oneUser)s davetini geri çekti", + "were banned %(count)s times|other": "%(count)s kez yasaklandı", + "were banned %(count)s times|one": "yasaklandı", + "was banned %(count)s times|other": "%(count)s kez yasaklandı", + "was banned %(count)s times|one": "yasaklandı", + "were unbanned %(count)s times|other": "%(count)s kez yasak kaldırıldı", + "were unbanned %(count)s times|one": "yasak kaldırıldı", + "was unbanned %(count)s times|other": "%(count)s kez yasak kaldırıldı", + "was unbanned %(count)s times|one": "yasak kaldırıldı", + "%(severalUsers)schanged their avatar %(count)s times|one": "%(severalUsers)s resimlerini değiƟtirdiler", + "%(oneUser)schanged their avatar %(count)s times|other": "%(oneUser)s %(count)s kez resmini değiƟtirdi", + "%(oneUser)schanged their avatar %(count)s times|one": "%(oneUser)s resmini değiƟtirdi", + "%(severalUsers)smade no changes %(count)s times|other": "%(severalUsers)s %(count)s kez hiç bir değiƟiklik yapmadı", + "Try using one of the following valid address types: %(validTypesList)s.": "Takip eden geçerli adres tiplerinden birini kullanmayı deneyin: %(validTypesList)s.", + "Use an identity server to invite by email. Use the default (%(defaultIdentityServerName)s) or manage in Settings.": "E-posta ile davet etmek için bir kimlik sunucusu kullan. Varsayılanı kullan (%(defaultIdentityServerName)s ya da Ayarlar kullanarak yönetin.", + "Use an identity server to invite by email. Manage in Settings.": "E-posta ile davet için bir kimlik sunucu kullan. Ayarlar dan yönet.", + "The following users may not exist": "Belirtilen kullanıcılar mevcut olmayabilir", + "Unable to find profiles for the Matrix IDs listed below - would you like to invite them anyway?": "Altta belirtilen Matrix ID li profiller bulunamıyor - Onları yinede davet etmek ister misiniz?", + "Please tell us what went wrong or, better, create a GitHub issue that describes the problem.": "LĂŒtfen neyin yanlÄ±ĆŸ gittiğini bize bildirin ya da en gĂŒzeli problemi tanımlayan bir GitHub talebi oluƟturun.", + "Before submitting logs, you must create a GitHub issue to describe your problem.": "Logları göndermeden önce, probleminizi betimleyen bir GitHub talebi oluƟturun.", + "Community IDs may only contain characters a-z, 0-9, or '=_-./'": "Topluluk ID leri sadece a-z, 0-9 ya da '=_-./' karakterlerini içerebilir", + "Set a room alias to easily share your room with other people.": "Odanızı diğer kiƟilerle kolayca paylaƟabilmek için bir oda lakabı ayarların.", + "Create a public room": "Halka açık bir oda oluƟturun", + "Make this room public": "Bu odayı halka açık yap", + "To avoid losing your chat history, you must export your room keys before logging out. You will need to go back to the newer version of Riot to do this": "Sohbet tarihçesini kaybetmemek için, çıkmadan önce odanızın anahtarlarını dÄ±ĆŸarıya aktarın. Bunu yapabilmek için Riotun daha yeni sĂŒrĂŒmĂŒ gerekli. UlaƟmak için geri gitmeye ihtiyacınız var", + "Continue With Encryption Disabled": "ƞifreleme Kapalı ƞekilde Devam Et", + "The file '%(fileName)s' exceeds this homeserver's size limit for uploads": "%(fileName)s dosyası anasunucunun yĂŒkleme boyutu limitini aĆŸÄ±yor", + "Double check that your server supports the room version chosen and try again.": "Seçtiğiniz oda sĂŒrĂŒmĂŒnĂŒn sunucunuz tarafından desteklenip desteklenmediğini iki kez kontrol edin ve yeniden deneyin.", + "Changes your avatar in this current room only": "Sadece bu odadaki resminizi değiƟtirin", + "Please supply a https:// or http:// widget URL": "LĂŒtfen bir https:// ya da http:// olarak bir görsel bileƟen URL i belirtin", + "Sends the given emote coloured as a rainbow": "Verilen ifadeyi bir gökkuƟağı gibi renklendirilmiƟ olarak gönderin", + "%(oldDisplayName)s changed their display name to %(displayName)s.": "%(oldDisplayName)s ekran adını %(displayName)s olarak değiƟtirdi.", + "%(senderDisplayName)s made the room public to whoever knows the link.": "%(senderDisplayName)s odayı adresi bilen herkesin girebileceği Ɵekilde halka açık hale getirdi.", + "%(senderDisplayName)s changed the join rule to %(rule)s": "%(senderDisplayName)s katılma kuralını %(rule)s Ɵeklinde değiƟtirdi", + "%(senderDisplayName)s changed guest access to %(rule)s": "%(senderDisplayName)s misafir eriƟim kuralını %(rule)s Ɵeklinde değiƟtirdi", + "%(senderName)s set the main address for this room to %(address)s.": "%(senderName)s bu odanın ana adresini %(address)s olarak ayarladı.", + "%(senderName)s placed a voice call.": "%(senderName)s bir çağrı yaptı.", + "%(senderName)s placed a voice call. (not supported by this browser)": "%(senderName)s bir çağrı baƟlattı. (Bu tarayıcı tarafından desteklenmiyor)", + "%(senderName)s placed a video call.": "%(senderName)s bir görĂŒntĂŒlĂŒ çağrı yaptı.", + "%(senderName)s placed a video call. (not supported by this browser)": "%(senderName)s bir görĂŒntĂŒlĂŒ çağrı yaptı. (bu tarayıcı tarafından desteklenmiyor)", + "Ask your Riot admin to check your config for incorrect or duplicate entries.": "Riot yöneticinize yapılandırmanızın hatalı ve mĂŒkerrer girdilerini kontrol etmesi için talepte bulunun.", + "You can register, but some features will be unavailable until the identity server is back online. If you keep seeing this warning, check your configuration or contact a server admin.": "Kayıt olabilirsiniz, fakat kimlik sunucunuz çevrimiçi olana kadar bazı özellikler mevcut olmayacak. Bu uyarıyı sĂŒrekli görĂŒyorsanız, yapılandırmanızı kontrol edin veya sunucu yöneticinizle iletiƟime geçin.", + "You can reset your password, but some features will be unavailable until the identity server is back online. If you keep seeing this warning, check your configuration or contact a server admin.": "Parolanızı sıfırlayabilirsiniz, fakat kimlik sunucunuz çevrimiçi olana kadar bazı özellikler mevcut olmayacak. Bu uyarıyı sĂŒrekli görĂŒyorsanız, yapılandırmanızı kontrol edin veya sunucu yöneticinizle iletiƟime geçin.", + "You can log in, but some features will be unavailable until the identity server is back online. If you keep seeing this warning, check your configuration or contact a server admin.": "Oturum açabilirsiniz, fakat kimlik sunucunuz çevrimiçi olana kadar bazı özellikler mevcut olmayacak. Bu uyarıyı sĂŒrekli görĂŒyorsanız, yapılandırmanızı kontrol edin veya sunucu yöneticinizle iletiƟime geçin.", + "a few seconds from now": "Ɵu andan itibaren bir kaç saniye", + "about a minute from now": "Ɵu andan itibaren yaklaĆŸÄ±k bir dakika", + "%(num)s minutes from now": "Ɵu andan itibaren %(num)s dakika", + "about an hour from now": "Ɵu andan itibaren yaklaĆŸÄ±k bir saat", + "%(num)s hours from now": "Ɵu andan itibaren %(num)s saat", + "about a day from now": "Ɵu andan itibaren yaklaĆŸÄ±k bir gĂŒn", + "%(num)s days from now": "Ɵu andan itibaren %(num)s gĂŒn", + "The user must be unbanned before they can be invited.": "Kullanıcının davet edilebilmesi için öncesinde yasağının kaldırılması gereklidir.", + "Repeats like \"abcabcabc\" are only slightly harder to guess than \"abc\"": "“abcabcabc” gibi tekrarlar “abc” yi tahmin etmekten çok az daha zor olur", + "Sequences like abc or 6543 are easy to guess": "abc veya 6543 gibi diziler tahmin için oldukça kolaydır", + "Common names and surnames are easy to guess": "Yaygın isimleri ve soyisimleri tahmin etmek oldukça kolay", + "Enable cross-signing to verify per-user instead of per-device (in development)": "Her cihaz yerine her kullanıcıyı doğrulamak için çarpraz-imzalamayı aç (geliƟtiriliyor)", + "Show info about bridges in room settings": "Oda ayarlarındaki köprĂŒlerin bilgilerini göster", + "Show a placeholder for removed messages": "Silinen mesajlar için bir yer tutucu göster", + "Show display name changes": "Ekran isim değiƟikliklerini göster", + "Enable URL previews for this room (only affects you)": "Bu oda için URL önizlemeyi aç (sadece sizi etkiler)", + "Enable URL previews by default for participants in this room": "Bu odadaki katılımcılar için URL önizlemeyi varsayılan olarak açık hale getir", + "Enable widget screenshots on supported widgets": "Desteklenen görsel bileƟenlerde anlık görĂŒntĂŒleri aç", + "Show recently visited rooms above the room list": "En son ziyaret edilen odaları oda listesinin en ĂŒstĂŒnde göster", + "Show hidden events in timeline": "Zaman çizelgesinde gizli olayları göster", + "Encrypted messages in one-to-one chats": "Birebir sohbetlerdeki ƟifrelenmiƟ mesajlar", + "Encrypted messages in group chats": "Grup sohbetlerdeki ƟifrelenmiƟ mesajlar", + "This is your list of users/servers you have blocked - don't leave the room!": "Bu sizin engellediğiniz kullanıcılar/sunucular listeniz - odadan ayrılmayın!", + "Got It": "AnlaĆŸÄ±ldı" } diff --git a/src/i18n/strings/zh_Hant.json b/src/i18n/strings/zh_Hant.json index dbd8319b8a..4a70441317 100644 --- a/src/i18n/strings/zh_Hant.json +++ b/src/i18n/strings/zh_Hant.json @@ -2075,5 +2075,41 @@ "Something went wrong trying to invite the users.": "ćœšć˜—è©Šé‚€è«‹äœżç”šè€…æ™‚ç™Œç”ŸéŒŻèȘ€ă€‚", "We couldn't invite those users. Please check the users you want to invite and try again.": "æˆ‘ć€‘ç„Ąæł•é‚€è«‹é‚Łäș›äœżç”šè€…ă€‚è«‹æȘąæŸ„æ‚šæƒłèŠé‚€è«‹çš„äœżç”šè€…äžŠć†è©Šäž€æŹĄă€‚", "Recently Direct Messaged": "æœ€èż‘ć‚łé€éŽç›ŽæŽ„èšŠæŻ", - "If you can't find someone, ask them for their username (e.g. @user:server.com) or share this room.": "ćŠ‚æžœæ‚šæ‰Ÿäžćˆ°æŸäșșïŒŒè«‹è©ąć•ä»–ć€‘çš„äœżç”šè€…ćçš±ïŒˆçŻ„äŸ‹ïŒš@user:server.comïŒ‰æˆ–ćˆ†äș«æ­€èŠć€©ćź€ă€‚" + "If you can't find someone, ask them for their username (e.g. @user:server.com) or share this room.": "ćŠ‚æžœæ‚šæ‰Ÿäžćˆ°æŸäșșïŒŒè«‹è©ąć•ä»–ć€‘çš„äœżç”šè€…ćçš±ïŒˆçŻ„äŸ‹ïŒš@user:server.comïŒ‰æˆ–ćˆ†äș«æ­€èŠć€©ćź€ă€‚", + "Verify User": "é©—è­‰äœżç”šè€…", + "For extra security, verify this user by checking a one-time code on both of your devices.": "ç‚șäș†æé«˜ćź‰ć…šæ€§ïŒŒè«‹é€éŽæȘąæŸ„æ‚šć…©ć€‹èŁçœźäžŠçš„äž€æŹĄæ€§ä»ŁçąŒäŸ†é©—è­‰æ­€äœżç”šè€…ă€‚", + "For maximum security, do this in person.": "ç‚șäș†ć–ćŸ—æœ€ćŒ·çš„ćź‰ć…šæ€§ïŒŒè«‹èŠȘè‡Șé€ČèĄŒă€‚", + "Start Verification": "é–‹ć§‹é©—è­‰", + "Encrypted by a deleted device": "èą«ć·ČćˆȘé™€çš„èŁçœźćŠ ćŻ†", + "Unknown Command": "æœȘ矄的指什", + "Unrecognised command: %(commandText)s": "ç„Ąæł•è­˜ćˆ„çš„æŒ‡ä»€ïŒš%(commandText)s", + "You can use /help to list available commands. Did you mean to send this as a message?": "æ‚šćŻä»„äœżç”š /help äŸ†ćˆ—ć‡șćŻç”šçš„æŒ‡ä»€ă€‚æ‚šæ˜ŻèŠć‚łé€æ­€èšŠæŻć—ŽïŒŸ", + "Hint: Begin your message with // to start it with a slash.": "提ç€ș仄 // é–‹é ­èź“æ‚šçš„èšŠæŻć‚łé€æ™‚ćŻä»„ç”šæ–œç·šé–‹é ­ă€‚", + "Send as message": "ä»„èšŠæŻć‚łé€", + "%(senderName)s added %(addedAddresses)s and %(count)s other addresses to this room|other": "%(senderName)s ć‘æ­€èŠć€©ćź€æ–°ćąžäș† %(addedAddresses)s èˆ‡ć…¶ä»– %(count)s 怋朰杀", + "%(senderName)s removed %(removedAddresses)s and %(count)s other addresses from this room|other": "%(senderName)s ćŸžæ­€èŠć€©ćź€ç§»é™€äș† %(removedAddresses)s èˆ‡ć…¶ä»– %(count)s 怋朰杀", + "%(senderName)s removed %(countRemoved)s and added %(countAdded)s addresses to this room": "%(senderName)s ć°æ­€èŠć€©ćź€ç§»é™€äș† %(countRemoved)s ć€‹äžŠæ–°ćąžäș† %(countAdded)s ćœ°ć€ćˆ°æ­€èŠć€©ćź€", + "%(senderName)s turned on end-to-end encryption.": "%(senderName)s 開敟äș†ç«Żćˆ°ç«ŻćŠ ćŻ†ă€‚", + "%(senderName)s turned on end-to-end encryption (unrecognised algorithm %(algorithm)s).": "%(senderName)s 開敟äș†ç«Żćˆ°ç«ŻćŠ ćŻ†ïŒˆç„Ąæł•è­˜ćˆ„çš„æŒ”çź—æł• %(algorithm)sïŒ‰ă€‚", + "Someone is using an unknown device": "某äșșæ­Łćœšäœżç”šæœȘçŸ„çš„èŁçœź", + "This room is end-to-end encrypted": "æ­€èŠć€©ćź€ć·Čç«Żćˆ°ç«ŻćŠ ćŻ†", + "Everyone in this room is verified": "æ­€èŠć€©ćź€äž­æŻć€‹äșș郜ć·Č驗證", + "Invite only": "ćƒ…é‚€è«‹", + "Send a reply
": "ć‚łé€ć›žèŠ†â€Šâ€Š", + "Send a message
": "ć‚łé€èšŠæŻâ€Šâ€Š", + "Reject & Ignore user": "ć›žç”•äžŠćżœç•„äœżç”šè€…", + "If you can't find someone, ask them for their username, share your username (%(userId)s) or profile link.": "ćŠ‚æžœæ‚šæ‰Ÿäžćˆ°æŸäșșïŒŒè«‹è©ąć•ä»–ć€‘ä»„ć–ćŸ—ä»–ć€‘çš„äœżç”šè€…ćçš±ïŒŒćˆ†äș«æ‚šçš„äœżç”šè€…ćçš± (%(userId)s) æˆ–ç°Ąä»‹é€Łç”ă€‚", + "Enter your account password to confirm the upgrade:": "èŒžć…„æ‚šçš„ćžłè™ŸćŻ†çąŒä»„çąșèȘć‡çŽšïŒš", + "You'll need to authenticate with the server to confirm the upgrade.": "æ‚šćż…é ˆé€éŽäŒșæœć™šé©—è­‰ä»„çąșèȘć‡çŽšă€‚", + "Upgrade this device to allow it to verify other devices, granting them access to encrypted messages and marking them as trusted for other users.": "ć‡çŽšæ­€èŁçœźä»„ć…èš±ć…¶é©—è­‰ć…¶ä»–èŁçœźïŒŒäžŠć…èš±ć­˜ć–ćŠ ćŻ†èšŠæŻä»„ćŠć°‡ćźƒć€‘æš™èš˜ç‚șć—ć…¶ä»–äœżç”šè€…äżĄä»»ă€‚", + "Set up encryption on this device to allow it to verify other devices, granting them access to encrypted messages and marking them as trusted for other users.": "ćœšæ­€èŁçœźäžŠèš­ćźšćŠ ćŻ†ä»„ć…èš±ć…¶é©—è­‰ć…¶ä»–èŁçœźïŒŒäžŠć…èš±ć­˜ć–ćŠ ćŻ†èšŠæŻä»„ćŠć°‡ćźƒć€‘æš™èš˜ç‚șć—ć…¶ä»–äœżç”šè€…äżĄä»»ă€‚", + "Secure your encryption keys with a passphrase. For maximum security this should be different to your account password:": "äœżç”šé€šé—œćŻ†èȘžäżè­·æ‚šçš„抠毆金鑰。ç‚șäș†ć–ćŸ—æœ€ćŒ·çš„ćź‰ć…šæ€§ïŒŒæ­€é€šé—œćŻ†èȘžæ‡‰èˆ‡æ‚šçš„ćžłè™ŸćŻ†çąŒäžćŒïŒš", + "Enter a passphrase": "èŒžć…„é€šé—œćŻ†èȘž", + "Enter your passphrase a second time to confirm it.": "èŒžć…„æ‚šçš„é€šé—œćŻ†èȘžć…©æŹĄä»„çąșèȘă€‚", + "This device can now verify other devices, granting them access to encrypted messages and marking them as trusted for other users.": "æ­€èŁçœźçŸćœšćŻä»„é©—è­‰ć…¶ä»–èŁçœźïŒŒäžŠć…èš±ć­˜ć–ćŠ ćŻ†èšŠæŻä»„ćŠć°‡ćźƒć€‘æš™èš˜ç‚șć—ć…¶ä»–äœżç”šè€…äżĄä»»ă€‚", + "Verify other users in their profile.": "é€éŽä»–ć€‘çš„ç°Ąä»‹é©—è­‰ć…¶ä»–äœżç”šè€…ă€‚", + "Upgrade your encryption": "ć‡çŽšæ‚šçš„ćŠ ćŻ†", + "Set up encryption": "èš­ćźšćŠ ćŻ†", + "Encryption upgraded": "抠毆ć·Č捇箚", + "Encryption setup complete": "ćŠ ćŻ†èš­ćźšćźŒæˆ" } diff --git a/yarn.lock b/yarn.lock index 576cd019ec..232067a99f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5760,11 +5760,12 @@ mathml-tag-names@^2.0.1: resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.1.tgz#6dff66c99d55ecf739ca53c492e626f1d12a33cc" integrity sha512-pWB896KPGSGkp1XtyzRBftpTzwSOL0Gfk0wLvxt4f2mgzjY19o0LxJ3U25vNWTzsh7da+KTbuXQoQ3lOJZ8WHw== -matrix-js-sdk@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-3.0.0.tgz#97908f9eda9eeb3ba0333b7e474c45f2b258e50c" - integrity sha512-lzUMwJAZHw7Dk0K+rubqe6kEpy4+pJ+qCp8n6lisfdKfMDJXdNCkjiiXRnakM1ZD4PFYK8ju89+NfxlyhAAd4A== +matrix-js-sdk@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-4.0.0.tgz#c81bdc905af2ab1634527e5f542f2f15977d31cf" + integrity sha512-Xbe36xL443qtEBH4xk0k39JabolqZfloK7fwYGMb/PgWO26VOzvw94XWahnIr5w83oxBAF9nFmP+7EnPG6IHnA== dependencies: + "@babel/runtime" "^7.8.3" another-json "^0.2.0" browser-request "^0.3.3" bs58 "^4.0.1"