Merge branches 'develop' and 't3chguy/jest' of https://github.com/matrix-org/matrix-react-sdk into t3chguy/jest

 Conflicts:
	yarn.lock
This commit is contained in:
Michael Telatynski 2019-12-19 10:50:14 +00:00
commit affc8b8459
55 changed files with 2388 additions and 1709 deletions

View file

@ -73,7 +73,7 @@
"file-saver": "^1.3.3",
"filesize": "3.5.6",
"flux": "2.1.1",
"focus-trap-react": "^3.0.5",
"react-focus-lock": "^2.2.1",
"focus-visible": "^5.0.2",
"fuse.js": "^2.2.0",
"gemini-scrollbar": "github:matrix-org/gemini-scrollbar#91e1e566",

View file

@ -175,6 +175,7 @@
@import "./views/rooms/_Stickers.scss";
@import "./views/rooms/_TopUnreadMessagesBar.scss";
@import "./views/rooms/_WhoIsTypingTile.scss";
@import "./views/settings/_AvatarSetting.scss";
@import "./views/settings/_CrossSigningPanel.scss";
@import "./views/settings/_DevicesPanel.scss";
@import "./views/settings/_EmailAddresses.scss";

View file

@ -42,3 +42,11 @@ limitations under the License.
padding-left: 40px;
padding-right: 80px;
}
// show a different AvatarSetting placeholder for RoomProfileSettings which is basically a clone of ProfileSettings
.mx_RoomSettingsDialog .mx_AvatarSetting_avatar .mx_AvatarSetting_avatarPlaceholder::before {
mask: url("$(res)/img/feather-customised/image.svg");
mask-repeat: no-repeat;
mask-size: 36px;
mask-position: center;
}

View file

@ -22,7 +22,9 @@ limitations under the License.
display: block;
}
.mx_E2EIcon_verified::after, .mx_E2EIcon_warning::after {
.mx_E2EIcon_warning::after,
.mx_E2EIcon_normal::after,
.mx_E2EIcon_verified::after {
content: "";
display: block;
position: absolute;
@ -34,10 +36,14 @@ limitations under the License.
background-size: contain;
}
.mx_E2EIcon_verified::after {
background-image: url('$(res)/img/e2e/verified.svg');
}
.mx_E2EIcon_warning::after {
background-image: url('$(res)/img/e2e/warning.svg');
}
.mx_E2EIcon_normal::after {
background-image: url('$(res)/img/e2e/normal.svg');
}
.mx_E2EIcon_verified::after {
background-image: url('$(res)/img/e2e/verified.svg');
}

View file

@ -52,12 +52,18 @@ limitations under the License.
}
.mx_LinkPreviewWidget_cancel {
visibility: hidden;
cursor: pointer;
flex: 0 0 40px;
width: 18px;
height: 18px;
img {
flex: 0 0 40px;
visibility: hidden;
}
}
.mx_LinkPreviewWidget:hover .mx_LinkPreviewWidget_cancel {
.mx_LinkPreviewWidget:hover .mx_LinkPreviewWidget_cancel img,
.mx_LinkPreviewWidget_cancel.focus-visible:focus img {
visibility: visible;
}

View file

@ -0,0 +1,87 @@
/*
Copyright 2019 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.
*/
.mx_AvatarSetting_avatar {
width: 88px;
height: 88px;
margin-left: 13px;
position: relative;
& > * {
width: 88px;
box-sizing: border-box;
}
.mx_AccessibleButton.mx_AccessibleButton_kind_primary {
margin-top: 8px;
div {
position: relative;
height: 12px;
width: 12px;
display: inline;
padding-right: 6px; // 0.5 * 12px
left: -6px; // 0.5 * 12px
top: 3px;
}
div::before {
content: '';
position: absolute;
height: 12px;
width: 12px;
background-color: $button-primary-fg-color;
mask-repeat: no-repeat;
mask-size: contain;
mask-image: url('$(res)/img/feather-customised/upload.svg');
}
}
.mx_AccessibleButton.mx_AccessibleButton_kind_link_sm {
color: $button-danger-bg-color;
}
& > img {
cursor: pointer;
object-fit: cover;
}
& > img,
.mx_AvatarSetting_avatarPlaceholder {
display: block;
height: 88px;
border-radius: 4px;
}
.mx_AvatarSetting_avatarPlaceholder::before {
background-color: $settings-profile-overlay-placeholder-fg-color;
mask: url("$(res)/img/feather-customised/user.svg");
mask-repeat: no-repeat;
mask-size: 36px;
mask-position: center;
content: '';
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
}
.mx_AvatarSetting_avatar .mx_AvatarSetting_avatarPlaceholder {
background-color: $settings-profile-placeholder-bg-color;
}

View file

@ -38,91 +38,6 @@ limitations under the License.
}
}
.mx_ProfileSettings_avatar {
width: 88px;
height: 88px;
margin-left: 13px;
position: relative;
}
.mx_ProfileSettings_avatar > * {
display: block;
width: 88px;
height: 88px;
border-radius: 4px;
}
.mx_ProfileSettings_avatar .mx_ProfileSettings_avatarOverlay_disabled {
cursor: default;
}
.mx_ProfileSettings_avatar .mx_ProfileSettings_avatarPlaceholder {
background-color: $settings-profile-placeholder-bg-color;
}
.mx_ProfileSettings_avatarOverlay {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
display: none;
text-align: center;
vertical-align: middle;
font-size: 10px;
cursor: pointer;
}
.mx_ProfileSettings_avatar:hover .mx_ProfileSettings_avatarOverlay:not(.mx_ProfileSettings_avatarOverlay_disabled) {
display: inline-block;
opacity: 0.5 !important;
color: $settings-profile-overlay-fg-color !important;
background-color: $settings-profile-overlay-bg-color !important;
}
.mx_ProfileSettings_avatarOverlay_show {
display: inline-block;
opacity: 1;
color: $settings-profile-overlay-placeholder-fg-color;
background-color: $settings-profile-overlay-placeholder-bg-color;
}
.mx_ProfileSettings_avatarOverlayText {
display: block;
margin-top: 17px;
margin-bottom: 8px;
}
.mx_ProfileSettings_noAvatarText {
display: block;
margin: 34px auto auto;
}
.mx_ProfileSettings_avatarOverlayImgContainer {
position: relative;
width: 14px;
height: 14px;
margin: auto;
}
.mx_ProfileSettings_avatarOverlayImg::before {
background-color: $settings-profile-overlay-placeholder-fg-color;
mask: url("$(res)/img/feather-customised/upload.svg");
mask-repeat: no-repeat;
mask-size: 14px;
mask-position: center;
content: '';
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.mx_ProfileSettings_avatar:hover .mx_ProfileSettings_avatarOverlayImg::before {
background-color: $settings-profile-overlay-fg-color !important;
}
.mx_ProfileSettings_avatarUpload {
display: none;
}

View file

@ -0,0 +1,5 @@
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6 8C6 6.89543 6.89543 6 8 6H40C41.1046 6 42 6.89543 42 8V40C42 41.1046 41.1046 42 40 42H8C6.89543 42 6 41.1046 6 40V8Z" stroke="#61708B" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M17 20C18.6569 20 20 18.6569 20 17C20 15.3431 18.6569 14 17 14C15.3431 14 14 15.3431 14 17C14 18.6569 15.3431 20 17 20Z" stroke="#61708B" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M42 30L32 20L10 42" stroke="#61708B" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 721 B

View file

@ -1,6 +1,7 @@
/*
Copyright 2016 OpenMarket Ltd
Copyright 2017 New Vector Ltd
Copyright 2019 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.
@ -15,52 +16,6 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
/* a selection of key codes, as used in KeyboardEvent.keyCode */
export const KeyCode = {
BACKSPACE: 8,
TAB: 9,
ENTER: 13,
SHIFT: 16,
ESCAPE: 27,
SPACE: 32,
PAGE_UP: 33,
PAGE_DOWN: 34,
END: 35,
HOME: 36,
LEFT: 37,
UP: 38,
RIGHT: 39,
DOWN: 40,
DELETE: 46,
KEY_A: 65,
KEY_B: 66,
KEY_C: 67,
KEY_D: 68,
KEY_E: 69,
KEY_F: 70,
KEY_G: 71,
KEY_H: 72,
KEY_I: 73,
KEY_J: 74,
KEY_K: 75,
KEY_L: 76,
KEY_M: 77,
KEY_N: 78,
KEY_O: 79,
KEY_P: 80,
KEY_Q: 81,
KEY_R: 82,
KEY_S: 83,
KEY_T: 84,
KEY_U: 85,
KEY_V: 86,
KEY_W: 87,
KEY_X: 88,
KEY_Y: 89,
KEY_Z: 90,
KEY_BACKTICK: 223, // DO NOT USE THIS: browsers disagree on backtick 192 vs 223
};
export const Key = {
HOME: "Home",
END: "End",
@ -80,13 +35,35 @@ export const Key = {
SHIFT: "Shift",
CONTEXT_MENU: "ContextMenu",
COMMA: ",",
LESS_THAN: "<",
GREATER_THAN: ">",
BACKTICK: "`",
SPACE: " ",
A: "a",
B: "b",
C: "c",
D: "d",
E: "e",
F: "f",
G: "g",
H: "h",
I: "i",
J: "j",
K: "k",
L: "l",
M: "m",
N: "n",
O: "o",
P: "p",
Q: "q",
R: "r",
S: "s",
T: "t",
U: "u",
V: "v",
W: "w",
X: "x",
Y: "y",
Z: "z",
};

View file

@ -14,6 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import {Key} from "../../../Keyboard";
const React = require("react");
import createReactClass from 'create-react-class';
import PropTypes from 'prop-types';
@ -83,7 +85,7 @@ module.exports = createReactClass({
},
onKeyDown: function(e) {
if (e.keyCode === 27) { // escape
if (e.key === Key.ESCAPE) {
e.stopPropagation();
e.preventDefault();
this.props.onFinished(false);

View file

@ -1492,7 +1492,7 @@ export default createReactClass({
const IncomingSasDialog = sdk.getComponent("views.dialogs.IncomingSasDialog");
Modal.createTrackedDialog('Incoming Verification', '', IncomingSasDialog, {
verifier,
});
}, null, /* priority = */ false, /* static = */ true);
});
}
// Fire the tinter right on startup to ensure the default theme is applied

View file

@ -270,6 +270,7 @@ module.exports = createReactClass({
roomServer: server,
instanceId: instanceId,
includeAll: includeAll,
error: null,
}, this.refreshRoomList);
// We also refresh the room list each time even though this
// filtering is client-side. It hopefully won't be client side

View file

@ -25,7 +25,7 @@ import Unread from '../../Unread';
import * as RoomNotifs from '../../RoomNotifs';
import * as FormattingUtils from '../../utils/FormattingUtils';
import IndicatorScrollbar from './IndicatorScrollbar';
import {Key, KeyCode} from '../../Keyboard';
import {Key} from '../../Keyboard';
import { Group } from 'matrix-js-sdk';
import PropTypes from 'prop-types';
import RoomTile from "../views/rooms/RoomTile";
@ -186,7 +186,7 @@ export default class RoomSubList extends React.PureComponent {
dis.dispatch({
action: 'view_room',
room_id: roomId,
clear_search: (ev && (ev.keyCode === KeyCode.ENTER || ev.keyCode === KeyCode.SPACE)),
clear_search: (ev && (ev.key === Key.ENTER || ev.key === Key.SPACE)),
});
};

View file

@ -44,7 +44,7 @@ import ObjectUtils from '../../ObjectUtils';
import * as Rooms from '../../Rooms';
import eventSearch from '../../Searching';
import { KeyCode, isOnlyCtrlOrCmdKeyEvent } from '../../Keyboard';
import {isOnlyCtrlOrCmdKeyEvent, Key} from '../../Keyboard';
import MainSplit from './MainSplit';
import RightPanel from './RightPanel';
@ -561,15 +561,15 @@ module.exports = createReactClass({
let handled = false;
const ctrlCmdOnly = isOnlyCtrlOrCmdKeyEvent(ev);
switch (ev.keyCode) {
case KeyCode.KEY_D:
switch (ev.key) {
case Key.D:
if (ctrlCmdOnly) {
this.onMuteAudioClick();
handled = true;
}
break;
case KeyCode.KEY_E:
case Key.E:
if (ctrlCmdOnly) {
this.onMuteVideoClick();
handled = true;
@ -792,11 +792,12 @@ module.exports = createReactClass({
this._updateE2EStatus(room);
},
_updateE2EStatus: function(room) {
if (!MatrixClientPeg.get().isRoomEncrypted(room.roomId)) {
_updateE2EStatus: async function(room) {
const cli = MatrixClientPeg.get();
if (!cli.isRoomEncrypted(room.roomId)) {
return;
}
if (!MatrixClientPeg.get().isCryptoEnabled()) {
if (!cli.isCryptoEnabled()) {
// If crypto is not currently enabled, we aren't tracking devices at all,
// so we don't know what the answer is. Let's error on the safe side and show
// a warning for this case.
@ -805,10 +806,38 @@ module.exports = createReactClass({
});
return;
}
room.hasUnverifiedDevices().then((hasUnverifiedDevices) => {
this.setState({
e2eStatus: hasUnverifiedDevices ? "warning" : "verified",
if (!SettingsStore.isFeatureEnabled("feature_cross_signing")) {
room.hasUnverifiedDevices().then((hasUnverifiedDevices) => {
this.setState({
e2eStatus: hasUnverifiedDevices ? "warning" : "verified",
});
});
return;
}
const e2eMembers = await room.getEncryptionTargetMembers();
for (const member of e2eMembers) {
const { userId } = member;
const userVerified = cli.checkUserTrust(userId).isCrossSigningVerified();
if (!userVerified) {
this.setState({
e2eStatus: "warning",
});
return;
}
const devices = await cli.getStoredDevicesForUser(userId);
const allDevicesVerified = devices.every(device => {
const { deviceId } = device;
return cli.checkDeviceTrust(userId, deviceId).isCrossSigningVerified();
});
if (!allDevicesVerified) {
this.setState({
e2eStatus: "warning",
});
return;
}
}
this.setState({
e2eStatus: "verified",
});
},

View file

@ -17,7 +17,7 @@ limitations under the License.
import React, {createRef} from "react";
import createReactClass from 'create-react-class';
import PropTypes from 'prop-types';
import { KeyCode } from '../../Keyboard';
import { Key } from '../../Keyboard';
import Timer from '../../utils/Timer';
import AutoHideScrollbar from "./AutoHideScrollbar";
@ -532,26 +532,26 @@ module.exports = createReactClass({
* @param {object} ev the keyboard event
*/
handleScrollKey: function(ev) {
switch (ev.keyCode) {
case KeyCode.PAGE_UP:
switch (ev.key) {
case Key.PAGE_UP:
if (!ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey) {
this.scrollRelative(-1);
}
break;
case KeyCode.PAGE_DOWN:
case Key.PAGE_DOWN:
if (!ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey) {
this.scrollRelative(1);
}
break;
case KeyCode.HOME:
case Key.HOME:
if (ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey) {
this.scrollToTop();
}
break;
case KeyCode.END:
case Key.END:
if (ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey) {
this.scrollToBottom();
}

View file

@ -18,7 +18,7 @@ limitations under the License.
import React, {createRef} from 'react';
import createReactClass from 'create-react-class';
import PropTypes from 'prop-types';
import { KeyCode } from '../../Keyboard';
import { Key } from '../../Keyboard';
import dis from '../../dispatcher';
import { throttle } from 'lodash';
import AccessibleButton from '../../components/views/elements/AccessibleButton';
@ -93,8 +93,8 @@ module.exports = createReactClass({
}, 200, {trailing: true, leading: true}),
_onKeyDown: function(ev) {
switch (ev.keyCode) {
case KeyCode.ESCAPE:
switch (ev.key) {
case Key.ESCAPE:
this._clearSearch("keyboard");
break;
}

View file

@ -34,7 +34,7 @@ const dis = require("../../dispatcher");
const ObjectUtils = require('../../ObjectUtils');
const Modal = require("../../Modal");
const UserActivity = require("../../UserActivity");
import { KeyCode } from '../../Keyboard';
import {Key} from '../../Keyboard';
import Timer from '../../utils/Timer';
import shouldHideEvent from '../../shouldHideEvent';
import EditorStateTransfer from '../../utils/EditorStateTransfer';
@ -942,8 +942,7 @@ const TimelinePanel = createReactClass({
// jump to the live timeline on ctrl-end, rather than the end of the
// timeline window.
if (ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey &&
ev.keyCode == KeyCode.END) {
if (ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey && ev.key === Key.END) {
this.jumpToLiveTimeline();
} else {
this._messagePanel.current.handleScrollKey(ev);

View file

@ -21,6 +21,7 @@ import sdk from '../../../index';
import { COUNTRIES } from '../../../phonenumber';
import SdkConfig from "../../../SdkConfig";
import { _t } from "../../../languageHandler";
const COUNTRIES_BY_ISO2 = {};
for (const c of COUNTRIES) {
@ -130,10 +131,17 @@ export default class CountryDropdown extends React.Component {
// values between mounting and the initial value propgating
const value = this.props.value || this.state.defaultCountry.iso2;
return <Dropdown className={this.props.className + " mx_CountryDropdown"}
onOptionChange={this._onOptionChange} onSearchChange={this._onSearchChange}
menuWidth={298} getShortOption={this._getShortOption}
value={value} searchEnabled={true} disabled={this.props.disabled}
return <Dropdown
id="mx_CountryDropdown"
className={this.props.className + " mx_CountryDropdown"}
onOptionChange={this._onOptionChange}
onSearchChange={this._onSearchChange}
menuWidth={298}
getShortOption={this._getShortOption}
value={value}
searchEnabled={true}
disabled={this.props.disabled}
label={_t("Country Dropdown")}
>
{ options }
</Dropdown>;

View file

@ -32,6 +32,7 @@ import IdentityAuthClient from '../../../IdentityAuthClient';
import { getDefaultIdentityServerUrl, useDefaultIdentityServer } from '../../../utils/IdentityServerUtils';
import { abbreviateUrl } from '../../../utils/UrlUtils';
import {sleep} from "../../../utils/promise";
import {Key} from "../../../Keyboard";
const TRUNCATE_QUERY_LIST = 40;
const QUERY_USER_DIRECTORY_DEBOUNCE_MS = 200;
@ -142,39 +143,41 @@ module.exports = createReactClass({
},
onKeyDown: function(e) {
if (e.keyCode === 27) { // escape
const textInput = this._textinput.current ? this._textinput.current.value : undefined;
if (e.key === Key.ESCAPE) {
e.stopPropagation();
e.preventDefault();
this.props.onFinished(false);
} else if (e.keyCode === 38) { // up arrow
} else if (e.key === Key.ARROW_UP) {
e.stopPropagation();
e.preventDefault();
if (this.addressSelector) this.addressSelector.moveSelectionUp();
} else if (e.keyCode === 40) { // down arrow
} else if (e.key === Key.ARROW_DOWN) {
e.stopPropagation();
e.preventDefault();
if (this.addressSelector) this.addressSelector.moveSelectionDown();
} else if (this.state.suggestedList.length > 0 && (e.keyCode === 188 || e.keyCode === 13 || e.keyCode === 9)) { // comma or enter or tab
} else if (this.state.suggestedList.length > 0 && [Key.COMMA, Key.ENTER, Key.TAB].includes(e.key)) {
e.stopPropagation();
e.preventDefault();
if (this.addressSelector) this.addressSelector.chooseSelection();
} else if (this._textinput.current.value.length === 0 && this.state.selectedList.length && e.keyCode === 8) { // backspace
} else if (textInput.length === 0 && this.state.selectedList.length && e.key === Key.BACKSPACE) {
e.stopPropagation();
e.preventDefault();
this.onDismissed(this.state.selectedList.length - 1)();
} else if (e.keyCode === 13) { // enter
} else if (e.key === Key.ENTER) {
e.stopPropagation();
e.preventDefault();
if (this._textinput.current.value === '') {
if (textInput === '') {
// if there's nothing in the input box, submit the form
this.onButtonClick();
} else {
this._addAddressesToList([this._textinput.current.value]);
this._addAddressesToList([textInput]);
}
} else if (e.keyCode === 188 || e.keyCode === 9) { // comma or tab
} else if (textInput && (e.key === Key.COMMA || e.key === Key.TAB)) {
e.stopPropagation();
e.preventDefault();
this._addAddressesToList([this._textinput.current.value]);
this._addAddressesToList([textInput]);
}
},

View file

@ -1,6 +1,7 @@
/*
Copyright 2017 Vector Creations Ltd
Copyright 2018, 2019 New Vector Ltd
Copyright 2019 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.
@ -17,13 +18,13 @@ limitations under the License.
import React from 'react';
import createReactClass from 'create-react-class';
import FocusTrap from 'focus-trap-react';
import FocusLock from 'react-focus-lock';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { MatrixClient } from 'matrix-js-sdk';
import { KeyCode } from '../../../Keyboard';
import { Key } from '../../../Keyboard';
import AccessibleButton from '../elements/AccessibleButton';
import MatrixClientPeg from '../../../MatrixClientPeg';
import { _t } from "../../../languageHandler";
@ -101,7 +102,7 @@ export default createReactClass({
if (this.props.onKeyDown) {
this.props.onKeyDown(e);
}
if (this.props.hasCancel && e.keyCode === KeyCode.ESCAPE) {
if (this.props.hasCancel && e.key === Key.ESCAPE) {
e.stopPropagation();
e.preventDefault();
this.props.onFinished(false);
@ -121,20 +122,24 @@ export default createReactClass({
}
return (
<FocusTrap onKeyDown={this._onKeyDown}
<FocusLock
returnFocus={true}
lockProps={{
onKeyDown: this._onKeyDown,
role: "dialog",
["aria-labelledby"]: "mx_BaseDialog_title",
// This should point to a node describing the dialog.
// If we were about to completely follow this recommendation we'd need to
// make all the components relying on BaseDialog to be aware of it.
// So instead we will use the whole content as the description.
// Description comes first and if the content contains more text,
// AT users can skip its presentation.
["aria-describedby"]: this.props.contentId,
}}
className={classNames({
[this.props.className]: true,
'mx_Dialog_fixedWidth': this.props.fixedWidth,
})}
role="dialog"
aria-labelledby='mx_BaseDialog_title'
// This should point to a node describing the dialog.
// If we were about to completely follow this recommendation we'd need to
// make all the components relying on BaseDialog to be aware of it.
// So instead we will use the whole content as the description.
// Description comes first and if the content contains more text,
// AT users can skip its presentation.
aria-describedby={this.props.contentId}
>
<div className={classNames('mx_Dialog_header', {
'mx_Dialog_headerWithButton': !!this.props.headerButton,
@ -146,7 +151,7 @@ export default createReactClass({
{ cancelButton }
</div>
{ this.props.children }
</FocusTrap>
</FocusLock>
);
},
});

View file

@ -99,7 +99,7 @@ export default createReactClass({
this.props.onFinished(true);
}
},
});
}, null, /* priority = */ false, /* static = */ true);
},
_onShareClicked: function() {

View file

@ -21,7 +21,7 @@ import PropTypes from 'prop-types';
import sdk from '../../../index';
import MatrixClientPeg from '../../../MatrixClientPeg';
import classnames from 'classnames';
import { KeyCode } from '../../../Keyboard';
import { Key } from '../../../Keyboard';
import { _t } from '../../../languageHandler';
import { SAFE_LOCALPART_REGEX } from '../../../Registration';
@ -101,7 +101,7 @@ export default createReactClass({
},
onKeyUp: function(ev) {
if (ev.keyCode === KeyCode.ENTER) {
if (ev.key === Key.ENTER) {
this.onSubmit();
}
},

View file

@ -17,7 +17,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { KeyCode } from '../../../Keyboard';
import {Key} from '../../../Keyboard';
/**
* AccessibleButton is a generic wrapper for any element that should be treated
@ -40,23 +40,23 @@ export default function AccessibleButton(props) {
// Browsers handle space and enter keypresses differently and we are only adjusting to the
// inconsistencies here
restProps.onKeyDown = function(e) {
if (e.keyCode === KeyCode.ENTER) {
if (e.key === Key.ENTER) {
e.stopPropagation();
e.preventDefault();
return onClick(e);
}
if (e.keyCode === KeyCode.SPACE) {
if (e.key === Key.SPACE) {
e.stopPropagation();
e.preventDefault();
}
};
restProps.onKeyUp = function(e) {
if (e.keyCode === KeyCode.SPACE) {
if (e.key === Key.SPACE) {
e.stopPropagation();
e.preventDefault();
return onClick(e);
}
if (e.keyCode === KeyCode.ENTER) {
if (e.key === Key.ENTER) {
e.stopPropagation();
e.preventDefault();
}

View file

@ -59,7 +59,7 @@ export default createReactClass({
Modal.createTrackedDialog('Device Verify Dialog', '', DeviceVerifyDialog, {
userId: this.props.userId,
device: this.state.device,
});
}, null, /* priority = */ false, /* static = */ true);
},
onUnverifyClick: function() {

View file

@ -1,6 +1,7 @@
/*
Copyright 2017 Vector Creations Ltd
Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
Copyright 2019 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.
@ -15,11 +16,12 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import React, {createRef} from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import AccessibleButton from './AccessibleButton';
import { _t } from '../../../languageHandler';
import {Key} from "../../../Keyboard";
class MenuOption extends React.Component {
constructor(props) {
@ -48,9 +50,14 @@ class MenuOption extends React.Component {
mx_Dropdown_option_highlight: this.props.highlighted,
});
return <div className={optClasses}
return <div
id={this.props.id}
className={optClasses}
onClick={this._onClick}
onMouseEnter={this._onMouseEnter}
role="option"
aria-selected={this.props.highlighted}
ref={this.props.inputRef}
>
{ this.props.children }
</div>;
@ -66,6 +73,7 @@ MenuOption.propTypes = {
dropdownKey: PropTypes.string,
onClick: PropTypes.func.isRequired,
onMouseEnter: PropTypes.func.isRequired,
inputRef: PropTypes.any,
};
/*
@ -86,8 +94,6 @@ export default class Dropdown extends React.Component {
this._onRootClick = this._onRootClick.bind(this);
this._onDocumentClick = this._onDocumentClick.bind(this);
this._onMenuOptionClick = this._onMenuOptionClick.bind(this);
this._onInputKeyPress = this._onInputKeyPress.bind(this);
this._onInputKeyUp = this._onInputKeyUp.bind(this);
this._onInputChange = this._onInputChange.bind(this);
this._collectRoot = this._collectRoot.bind(this);
this._collectInputTextBox = this._collectInputTextBox.bind(this);
@ -111,6 +117,7 @@ export default class Dropdown extends React.Component {
}
componentWillMount() {
this._button = createRef();
// Listen for all clicks on the document so we can close the
// menu when the user clicks somewhere else
document.addEventListener('click', this._onDocumentClick, false);
@ -169,40 +176,49 @@ export default class Dropdown extends React.Component {
}
}
_onMenuOptionClick(dropdownKey) {
_close() {
this.setState({
expanded: false,
});
this.props.onOptionChange(dropdownKey);
}
_onInputKeyPress(e) {
// This needs to be on the keypress event because otherwise
// it can't cancel the form submission
if (e.key == 'Enter') {
this.setState({
expanded: false,
});
this.props.onOptionChange(this.state.highlightedOption);
e.preventDefault();
// their focus was on the input, its getting unmounted, move it to the button
if (this._button.current) {
this._button.current.focus();
}
}
_onInputKeyUp(e) {
// These keys don't generate keypress events and so needs to
// be on keyup
if (e.key == 'Escape') {
this.setState({
expanded: false,
});
} else if (e.key == 'ArrowDown') {
this.setState({
highlightedOption: this._nextOption(this.state.highlightedOption),
});
} else if (e.key == 'ArrowUp') {
this.setState({
highlightedOption: this._prevOption(this.state.highlightedOption),
});
_onMenuOptionClick(dropdownKey) {
this._close();
this.props.onOptionChange(dropdownKey);
}
_onInputKeyDown = (e) => {
let handled = true;
// These keys don't generate keypress events and so needs to be on keyup
switch (e.key) {
case Key.ENTER:
this.props.onOptionChange(this.state.highlightedOption);
// fallthrough
case Key.ESCAPE:
this._close();
break;
case Key.ARROW_DOWN:
this.setState({
highlightedOption: this._nextOption(this.state.highlightedOption),
});
break;
case Key.ARROW_UP:
this.setState({
highlightedOption: this._prevOption(this.state.highlightedOption),
});
break;
default:
handled = false;
}
if (handled) {
e.preventDefault();
e.stopPropagation();
}
}
@ -250,20 +266,34 @@ export default class Dropdown extends React.Component {
return keys[(index - 1) % keys.length];
}
_scrollIntoView(node) {
if (node) {
node.scrollIntoView({
block: "nearest",
behavior: "auto",
});
}
}
_getMenuOptions() {
const options = React.Children.map(this.props.children, (child) => {
const highlighted = this.state.highlightedOption === child.key;
return (
<MenuOption key={child.key} dropdownKey={child.key}
highlighted={this.state.highlightedOption == child.key}
<MenuOption
id={`${this.props.id}__${child.key}`}
key={child.key}
dropdownKey={child.key}
highlighted={highlighted}
onMouseEnter={this._setHighlightedOption}
onClick={this._onMenuOptionClick}
inputRef={highlighted ? this._scrollIntoView : undefined}
>
{ child }
</MenuOption>
);
});
if (options.length === 0) {
return [<div key="0" className="mx_Dropdown_option">
return [<div key="0" className="mx_Dropdown_option" role="option">
{ _t("No results") }
</div>];
}
@ -279,23 +309,35 @@ export default class Dropdown extends React.Component {
let menu;
if (this.state.expanded) {
if (this.props.searchEnabled) {
currentValue = <input type="text" className="mx_Dropdown_option"
ref={this._collectInputTextBox} onKeyPress={this._onInputKeyPress}
onKeyUp={this._onInputKeyUp}
onChange={this._onInputChange}
value={this.state.searchQuery}
/>;
currentValue = (
<input
type="text"
className="mx_Dropdown_option"
ref={this._collectInputTextBox}
onKeyDown={this._onInputKeyDown}
onChange={this._onInputChange}
value={this.state.searchQuery}
role="combobox"
aria-autocomplete="list"
aria-activedescendant={`${this.props.id}__${this.state.highlightedOption}`}
aria-owns={`${this.props.id}_listbox`}
aria-disabled={this.props.disabled}
aria-label={this.props.label}
/>
);
}
menu = <div className="mx_Dropdown_menu" style={menuStyle}>
{ this._getMenuOptions() }
</div>;
menu = (
<div className="mx_Dropdown_menu" style={menuStyle} role="listbox" id={`${this.props.id}_listbox`}>
{ this._getMenuOptions() }
</div>
);
}
if (!currentValue) {
const selectedChild = this.props.getShortOption ?
this.props.getShortOption(this.props.value) :
this.childrenByKey[this.props.value];
currentValue = <div className="mx_Dropdown_option">
currentValue = <div className="mx_Dropdown_option" id={`${this.props.id}_value`}>
{ selectedChild }
</div>;
}
@ -311,9 +353,18 @@ export default class Dropdown extends React.Component {
// Note the menu sits inside the AccessibleButton div so it's anchored
// to the input, but overflows below it. The root contains both.
return <div className={classnames(dropdownClasses)} ref={this._collectRoot}>
<AccessibleButton className="mx_Dropdown_input mx_no_textinput" onClick={this._onInputClick}>
<AccessibleButton
className="mx_Dropdown_input mx_no_textinput"
onClick={this._onInputClick}
aria-haspopup="listbox"
aria-expanded={this.state.expanded}
disabled={this.props.disabled}
inputRef={this._button}
aria-label={this.props.label}
aria-describedby={`${this.props.id}_value`}
>
{ currentValue }
<span className="mx_Dropdown_arrow"></span>
<span className="mx_Dropdown_arrow" />
{ menu }
</AccessibleButton>
</div>;
@ -321,6 +372,7 @@ export default class Dropdown extends React.Component {
}
Dropdown.propTypes = {
id: PropTypes.string.isRequired,
// The width that the dropdown should be. If specified,
// the dropped-down part of the menu will be set to this
// width.
@ -340,4 +392,6 @@ Dropdown.propTypes = {
value: PropTypes.string,
// negative for consistency with HTML
disabled: PropTypes.bool,
// ARIA label
label: PropTypes.string.isRequired,
};

View file

@ -66,10 +66,14 @@ export default class Field extends React.PureComponent {
this.state = {
valid: undefined,
feedback: undefined,
focused: false,
};
}
onFocus = (ev) => {
this.setState({
focused: true,
});
this.validate({
focused: true,
});
@ -88,6 +92,9 @@ export default class Field extends React.PureComponent {
};
onBlur = (ev) => {
this.setState({
focused: false,
});
this.validate({
focused: false,
});
@ -112,7 +119,9 @@ export default class Field extends React.PureComponent {
allowEmpty,
});
if (feedback) {
// this method is async and so we may have been blurred since the method was called
// if we have then hide the feedback as withValidation does
if (this.state.focused && feedback) {
this.setState({
valid,
feedback,

View file

@ -28,6 +28,7 @@ const AccessibleButton = require('../../../components/views/elements/AccessibleB
const Modal = require('../../../Modal');
const sdk = require('../../../index');
import { _t } from '../../../languageHandler';
import {Key} from "../../../Keyboard";
export default class ImageView extends React.Component {
static propTypes = {
@ -62,7 +63,7 @@ export default class ImageView extends React.Component {
}
onKeyDown = (ev) => {
if (ev.keyCode === 27) { // escape
if (ev.key === Key.ESCAPE) {
ev.stopPropagation();
ev.preventDefault();
this.props.onFinished();

View file

@ -21,6 +21,7 @@ import PropTypes from 'prop-types';
import sdk from '../../../index';
import * as languageHandler from '../../../languageHandler';
import SettingsStore from "../../../settings/SettingsStore";
import { _t } from "../../../languageHandler";
function languageMatchesSearchQuery(query, language) {
if (language.label.toUpperCase().indexOf(query.toUpperCase()) == 0) return true;
@ -105,9 +106,14 @@ export default class LanguageDropdown extends React.Component {
value = this.props.value || language;
}
return <Dropdown className={this.props.className}
onOptionChange={this.props.onOptionChange} onSearchChange={this._onSearchChange}
searchEnabled={true} value={value}
return <Dropdown
id="mx_LanguageDropdown"
className={this.props.className}
onOptionChange={this.props.onOptionChange}
onSearchChange={this._onSearchChange}
searchEnabled={true}
value={value}
label={_t("Language Dropdown")}
>
{ options }
</Dropdown>;

View file

@ -19,46 +19,32 @@ import React from "react";
import PropTypes from "prop-types";
import classNames from "classnames";
import {KeyCode} from "../../../Keyboard";
import sdk from "../../../index";
// Controlled Toggle Switch element
// Controlled Toggle Switch element, written with Accessibility in mind
const ToggleSwitch = ({checked, disabled=false, onChange, ...props}) => {
const _onClick = (e) => {
e.stopPropagation();
e.preventDefault();
if (disabled) return;
onChange(!checked);
};
const _onKeyDown = (e) => {
e.stopPropagation();
e.preventDefault();
if (disabled) return;
if (e.keyCode === KeyCode.ENTER || e.keyCode === KeyCode.SPACE) {
onChange(!checked);
}
};
const classes = classNames({
"mx_ToggleSwitch": true,
"mx_ToggleSwitch_on": checked,
"mx_ToggleSwitch_enabled": !disabled,
});
const AccessibleButton = sdk.getComponent("elements.AccessibleButton");
return (
<div {...props}
<AccessibleButton {...props}
className={classes}
onClick={_onClick}
onKeyDown={_onKeyDown}
role="checkbox"
role="switch"
aria-checked={checked}
aria-disabled={disabled}
tabIndex={0}
>
<div className="mx_ToggleSwitch_ball" />
</div>
</AccessibleButton>
);
};

View file

@ -52,7 +52,7 @@ export default class MKeyVerificationRequest extends React.Component {
const verifier = MatrixClientPeg.get().acceptVerificationDM(this.props.mxEvent, verificationMethods.SAS);
Modal.createTrackedDialog('Incoming Verification', '', IncomingSasDialog, {
verifier,
});
}, null, /* priority = */ false, /* static = */ true);
};
_onRejectClicked = () => {

View file

@ -58,9 +58,20 @@ const _disambiguateDevices = (devices) => {
}
};
const _getE2EStatus = (devices) => {
const hasUnverifiedDevice = devices.some((device) => device.isUnverified());
return hasUnverifiedDevice ? "warning" : "verified";
const _getE2EStatus = (cli, userId, devices) => {
if (!SettingsStore.isFeatureEnabled("feature_cross_signing")) {
const hasUnverifiedDevice = devices.some((device) => device.isUnverified());
return hasUnverifiedDevice ? "warning" : "verified";
}
const userVerified = cli.checkUserTrust(userId).isCrossSigningVerified();
const allDevicesVerified = devices.every(device => {
const { deviceId } = device;
return cli.checkDeviceTrust(userId, deviceId).isCrossSigningVerified();
});
if (allDevicesVerified) {
return userVerified ? "verified" : "normal";
}
return "warning";
};
async function unverifyUser(matrixClient, userId) {
@ -98,14 +109,14 @@ function openDMForUser(matrixClient, userId) {
}
function useIsEncrypted(cli, room) {
const [isEncrypted, setIsEncrypted] = useState(cli.isRoomEncrypted(room.roomId));
const [isEncrypted, setIsEncrypted] = useState(room ? cli.isRoomEncrypted(room.roomId) : undefined);
const update = useCallback((event) => {
if (event.getType() === "m.room.encryption") {
setIsEncrypted(cli.isRoomEncrypted(room.roomId));
}
}, [cli, room]);
useEventEmitter(room.currentState, "RoomState.events", update);
useEventEmitter(room ? room.currentState : undefined, "RoomState.events", update);
return isEncrypted;
}
@ -114,7 +125,7 @@ function verifyDevice(userId, device) {
Modal.createTrackedDialog('Device Verify Dialog', '', DeviceVerifyDialog, {
userId: userId,
device: device,
});
}, null, /* priority = */ false, /* static = */ true);
}
function DeviceItem({userId, device}) {
@ -1264,7 +1275,8 @@ const UserInfo = withLegacyMatrixClient(({matrixClient: cli, user, groupId, room
let e2eIcon;
if (isRoomEncrypted && devices) {
e2eIcon = <E2EIcon size={18} status={_getE2EStatus(devices)} isUser={true} />;
const e2eStatus = _getE2EStatus(cli, user.userId, devices);
e2eIcon = <E2EIcon size={18} status={e2eStatus} isUser={true} />;
}
return (

View file

@ -19,8 +19,7 @@ import PropTypes from 'prop-types';
import {_t} from "../../../languageHandler";
import MatrixClientPeg from "../../../MatrixClientPeg";
import Field from "../elements/Field";
import AccessibleButton from "../elements/AccessibleButton";
import classNames from 'classnames';
import sdk from "../../../index";
// TODO: Merge with ProfileSettings?
export default class RoomProfileSettings extends React.Component {
@ -62,13 +61,20 @@ export default class RoomProfileSettings extends React.Component {
this._avatarUpload = createRef();
}
_uploadAvatar = (e) => {
e.stopPropagation();
e.preventDefault();
_uploadAvatar = () => {
this._avatarUpload.current.click();
};
_removeAvatar = () => {
// clear file upload field so same file can be selected
this._avatarUpload.current.value = "";
this.setState({
avatarUrl: undefined,
avatarFile: undefined,
enableProfileSave: true,
});
};
_saveProfile = async (e) => {
e.stopPropagation();
e.preventDefault();
@ -139,45 +145,8 @@ export default class RoomProfileSettings extends React.Component {
};
render() {
// TODO: Why is rendering a box with an overlay so complicated? Can the DOM be reduced?
let showOverlayAnyways = true;
let avatarElement = <div className="mx_ProfileSettings_avatarPlaceholder" />;
if (this.state.avatarUrl) {
showOverlayAnyways = false;
avatarElement = <img src={this.state.avatarUrl}
alt={_t("Room avatar")} />;
}
const avatarOverlayClasses = classNames({
"mx_ProfileSettings_avatarOverlay": true,
"mx_ProfileSettings_avatarOverlay_show": showOverlayAnyways,
});
let avatarHoverElement = (
<div className={avatarOverlayClasses} onClick={this._uploadAvatar}>
<span className="mx_ProfileSettings_avatarOverlayText">{_t("Upload room avatar")}</span>
<div className="mx_ProfileSettings_avatarOverlayImgContainer">
<div className="mx_ProfileSettings_avatarOverlayImg" />
</div>
</div>
);
if (!this.state.canSetAvatar) {
if (!showOverlayAnyways) {
avatarHoverElement = null;
} else {
const disabledOverlayClasses = classNames({
"mx_ProfileSettings_avatarOverlay": true,
"mx_ProfileSettings_avatarOverlay_show": true,
"mx_ProfileSettings_avatarOverlay_disabled": true,
});
avatarHoverElement = (
<div className={disabledOverlayClasses}>
<span className="mx_ProfileSettings_noAvatarText">{_t("No room avatar")}</span>
</div>
);
}
}
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
const AvatarSetting = sdk.getComponent('settings.AvatarSetting');
return (
<form onSubmit={this._saveProfile} autoComplete="off" noValidate={true}>
<input type="file" ref={this._avatarUpload} className="mx_ProfileSettings_avatarUpload"
@ -191,10 +160,12 @@ export default class RoomProfileSettings extends React.Component {
type="text" value={this.state.topic} autoComplete="off"
onChange={this._onTopicChanged} element="textarea" />
</div>
<div className="mx_ProfileSettings_avatar">
{avatarElement}
{avatarHoverElement}
</div>
<AvatarSetting
avatarUrl={this.state.avatarUrl}
avatarName={this.state.displayName || this.props.roomId}
avatarAltText={_t("Room avatar")}
uploadAvatar={this.state.canSetAvatar ? this._uploadAvatar : undefined}
removeAvatar={this.state.canSetAvatar ? this._removeAvatar : undefined} />
</div>
<AccessibleButton onClick={this._saveProfile} kind="primary"
disabled={!this.state.enableProfileSave}>

View file

@ -17,24 +17,62 @@ limitations under the License.
import classNames from 'classnames';
import { _t } from '../../../languageHandler';
import AccessibleButton from '../elements/AccessibleButton';
import SettingsStore from '../../../settings/SettingsStore';
export default function(props) {
const { isUser } = props;
const isNormal = props.status === "normal";
const isWarning = props.status === "warning";
const isVerified = props.status === "verified";
const e2eIconClasses = classNames({
mx_E2EIcon: true,
mx_E2EIcon_warning: isWarning,
mx_E2EIcon_normal: isNormal,
mx_E2EIcon_verified: isVerified,
}, props.className);
let e2eTitle;
if (isWarning) {
e2eTitle = props.isUser ?
_t("Some devices for this user are not trusted") :
_t("Some devices in this encrypted room are not trusted");
} else if (isVerified) {
e2eTitle = props.isUser ?
_t("All devices for this user are trusted") :
_t("All devices in this encrypted room are trusted");
const crossSigning = SettingsStore.isFeatureEnabled("feature_cross_signing");
if (crossSigning && isUser) {
if (isWarning) {
e2eTitle = _t(
"This user has not verified all of their devices.",
);
} else if (isNormal) {
e2eTitle = _t(
"You have not verified this user. " +
"This user has verified all of their devices.",
);
} else if (isVerified) {
e2eTitle = _t(
"You have verified this user. " +
"This user has verified all of their devices.",
);
}
} else if (crossSigning && !isUser) {
if (isWarning) {
e2eTitle = _t(
"Some users in this encrypted room are not verified by you or " +
"they have not verified their own devices.",
);
} else if (isVerified) {
e2eTitle = _t(
"All users in this encrypted room are verified by you and " +
"they have verified their own devices.",
);
}
} else if (!crossSigning && isUser) {
if (isWarning) {
e2eTitle = _t("Some devices for this user are not trusted");
} else if (isVerified) {
e2eTitle = _t("All devices for this user are trusted");
}
} else if (!crossSigning && !isUser) {
if (isWarning) {
e2eTitle = _t("Some devices in this encrypted room are not trusted");
} else if (isVerified) {
e2eTitle = _t("All devices in this encrypted room are trusted");
}
}
let style = null;

View file

@ -20,7 +20,7 @@ import PropTypes from 'prop-types';
import createReactClass from 'create-react-class';
import { _t } from '../../../languageHandler';
import dis from '../../../dispatcher';
import { KeyCode } from '../../../Keyboard';
import {Key} from '../../../Keyboard';
module.exports = createReactClass({
@ -52,8 +52,8 @@ module.exports = createReactClass({
},
_onKeyDown: function(ev) {
switch (ev.keyCode) {
case KeyCode.ESCAPE:
switch (ev.key) {
case Key.ESCAPE:
this.props.onCancelClick();
break;
}

View file

@ -1,5 +1,6 @@
/*
Copyright 2016 OpenMarket Ltd
Copyright 2019 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.
@ -19,6 +20,7 @@ import PropTypes from 'prop-types';
import createReactClass from 'create-react-class';
import { linkifyElement } from '../../../HtmlUtils';
import SettingsStore from "../../../settings/SettingsStore";
import { _t } from "../../../languageHandler";
const sdk = require('../../../index');
const MatrixClientPeg = require('../../../MatrixClientPeg');
@ -125,6 +127,7 @@ module.exports = createReactClass({
</div>;
}
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
return (
<div className="mx_LinkPreviewWidget" >
{ img }
@ -135,9 +138,10 @@ module.exports = createReactClass({
{ p["og:description"] }
</div>
</div>
<img className="mx_LinkPreviewWidget_cancel mx_filterFlipColor"
src={require("../../../../res/img/cancel.svg")} width="18" height="18"
onClick={this.props.onCancelClick} />
<AccessibleButton className="mx_LinkPreviewWidget_cancel" onClick={this.props.onCancelClick} aria-label={_t("Close preview")}>
<img className="mx_filterFlipColor" alt="" role="presentation"
src={require("../../../../res/img/cancel.svg")} width="18" height="18" />
</AccessibleButton>
</div>
);
},

View file

@ -33,7 +33,7 @@ import classNames from 'classnames';
import MatrixClientPeg from '../../../MatrixClientPeg';
import type {MatrixClient} from 'matrix-js-sdk/lib/matrix';
import {processCommandInput} from '../../../SlashCommands';
import { KeyCode, isOnlyCtrlOrCmdKeyEvent } from '../../../Keyboard';
import { isOnlyCtrlOrCmdKeyEvent, Key} from '../../../Keyboard';
import Modal from '../../../Modal';
import sdk from '../../../index';
import { _t } from '../../../languageHandler';
@ -608,12 +608,12 @@ export default class MessageComposerInput extends React.Component {
// Navigate autocomplete list with arrow keys
if (this.autocomplete.countCompletions() > 0) {
if (!(ev.ctrlKey || ev.shiftKey || ev.altKey || ev.metaKey)) {
switch (ev.keyCode) {
case KeyCode.UP:
switch (ev.key) {
case Key.ARROW_UP:
this.autocomplete.moveSelection(-1);
ev.preventDefault();
return true;
case KeyCode.DOWN:
case Key.ARROW_DOWN:
this.autocomplete.moveSelection(+1);
ev.preventDefault();
return true;
@ -623,38 +623,38 @@ export default class MessageComposerInput extends React.Component {
// skip void nodes - see
// https://github.com/ianstormtaylor/slate/issues/762#issuecomment-304855095
if (ev.keyCode === KeyCode.LEFT) {
if (ev.key === Key.ARROW_LEFT) {
this.direction = 'Previous';
} else if (ev.keyCode === KeyCode.RIGHT) {
} else if (ev.key === Key.ARROW_RIGHT) {
this.direction = 'Next';
}
switch (ev.keyCode) {
case KeyCode.ENTER:
switch (ev.key) {
case Key.ENTER:
return this.handleReturn(ev, change);
case KeyCode.BACKSPACE:
case Key.BACKSPACE:
return this.onBackspace(ev, change);
case KeyCode.UP:
case Key.ARROW_UP:
return this.onVerticalArrow(ev, true);
case KeyCode.DOWN:
case Key.ARROW_DOWN:
return this.onVerticalArrow(ev, false);
case KeyCode.TAB:
case Key.TAB:
return this.onTab(ev);
case KeyCode.ESCAPE:
case Key.ESCAPE:
return this.onEscape(ev);
case KeyCode.SPACE:
case Key.SPACE:
return this.onSpace(ev, change);
}
if (isOnlyCtrlOrCmdKeyEvent(ev)) {
const ctrlCmdCommand = {
// C-m => Toggles between rich text and markdown modes
[KeyCode.KEY_M]: 'toggle-mode',
[KeyCode.KEY_B]: 'bold',
[KeyCode.KEY_I]: 'italic',
[KeyCode.KEY_U]: 'underlined',
[KeyCode.KEY_J]: 'inline-code',
}[ev.keyCode];
[Key.M]: 'toggle-mode',
[Key.B]: 'bold',
[Key.I]: 'italic',
[Key.U]: 'underlined',
[Key.J]: 'inline-code',
}[ev.key];
if (ctrlCmdCommand) {
ev.preventDefault(); // to prevent clashing with Mac's minimize window

View file

@ -19,6 +19,7 @@ import createReactClass from 'create-react-class';
const classNames = require('classnames');
const AccessibleButton = require('../../../components/views/elements/AccessibleButton');
import { _t } from '../../../languageHandler';
import {Key} from "../../../Keyboard";
module.exports = createReactClass({
displayName: 'SearchBar',
@ -42,11 +43,13 @@ module.exports = createReactClass({
},
onSearchChange: function(e) {
if (e.keyCode === 13) { // on enter...
this.onSearch();
}
if (e.keyCode === 27) { // escape...
this.props.onCancelClick();
switch (e.key) {
case Key.ENTER:
this.onSearch();
break;
case Key.ESCAPE:
this.props.onCancelClick();
break;
}
},

View file

@ -0,0 +1,78 @@
/*
Copyright 2019 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, {useCallback} from "react";
import PropTypes from "prop-types";
import sdk from "../../../index";
import {_t} from "../../../languageHandler";
import Modal from "../../../Modal";
const AvatarSetting = ({avatarUrl, avatarAltText, avatarName, uploadAvatar, removeAvatar}) => {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
const openImageView = useCallback(() => {
const ImageView = sdk.getComponent("elements.ImageView");
Modal.createDialog(ImageView, {
src: avatarUrl,
name: avatarName,
}, "mx_Dialog_lightbox");
}, [avatarUrl, avatarName]);
let avatarElement = <div className="mx_AvatarSetting_avatarPlaceholder" />;
if (avatarUrl) {
avatarElement = (
<AccessibleButton
element="img"
src={avatarUrl}
alt={avatarAltText}
aria-label={avatarAltText}
onClick={openImageView} />
);
}
let uploadAvatarBtn;
if (uploadAvatar) {
// insert an empty div to be the host for a css mask containing the upload.svg
uploadAvatarBtn = <AccessibleButton onClick={uploadAvatar} kind="primary">
<div>&nbsp;</div>
{_t("Upload")}
</AccessibleButton>;
}
let removeAvatarBtn;
if (avatarUrl && removeAvatar) {
removeAvatarBtn = <AccessibleButton onClick={removeAvatar} kind="link_sm">
{_t("Remove")}
</AccessibleButton>;
}
return <div className="mx_AvatarSetting_avatar">
{ avatarElement }
{ uploadAvatarBtn }
{ removeAvatarBtn }
</div>;
};
AvatarSetting.propTypes = {
avatarUrl: PropTypes.string,
avatarName: PropTypes.string.isRequired, // name of user/room the avatar belongs to
uploadAvatar: PropTypes.func,
removeAvatar: PropTypes.func,
avatarAltText: PropTypes.string.isRequired,
};
export default AvatarSetting;

View file

@ -20,6 +20,7 @@ import PropTypes from 'prop-types';
import sdk from '../../../index';
import { _t } from '../../../languageHandler';
import dis from '../../../dispatcher';
import {Key} from "../../../Keyboard";
export default class IntegrationManager extends React.Component {
static propTypes = {
@ -52,7 +53,7 @@ export default class IntegrationManager extends React.Component {
}
onKeyDown = (ev) => {
if (ev.keyCode === 27) { // escape
if (ev.key === Key.ESCAPE) {
ev.stopPropagation();
ev.preventDefault();
this.props.onFinished();

View file

@ -18,10 +18,9 @@ import React, {createRef} from 'react';
import {_t} from "../../../languageHandler";
import MatrixClientPeg from "../../../MatrixClientPeg";
import Field from "../elements/Field";
import AccessibleButton from "../elements/AccessibleButton";
import classNames from 'classnames';
import {User} from "matrix-js-sdk";
import { getHostingLink } from '../../../utils/HostingLink';
import sdk from "../../../index";
export default class ProfileSettings extends React.Component {
constructor() {
@ -52,13 +51,20 @@ export default class ProfileSettings extends React.Component {
this._avatarUpload = createRef();
}
_uploadAvatar = (e) => {
e.stopPropagation();
e.preventDefault();
_uploadAvatar = () => {
this._avatarUpload.current.click();
};
_removeAvatar = () => {
// clear file upload field so same file can be selected
this._avatarUpload.current.value = "";
this.setState({
avatarUrl: undefined,
avatarFile: undefined,
enableProfileSave: true,
});
};
_saveProfile = async (e) => {
e.stopPropagation();
e.preventDefault();
@ -117,29 +123,6 @@ export default class ProfileSettings extends React.Component {
};
render() {
// TODO: Why is rendering a box with an overlay so complicated? Can the DOM be reduced?
let showOverlayAnyways = true;
let avatarElement = <div className="mx_ProfileSettings_avatarPlaceholder" />;
if (this.state.avatarUrl) {
showOverlayAnyways = false;
avatarElement = <img src={this.state.avatarUrl}
alt={_t("Profile picture")} />;
}
const avatarOverlayClasses = classNames({
"mx_ProfileSettings_avatarOverlay": true,
"mx_ProfileSettings_avatarOverlay_show": showOverlayAnyways,
});
const avatarHoverElement = (
<div className={avatarOverlayClasses} onClick={this._uploadAvatar}>
<span className="mx_ProfileSettings_avatarOverlayText">{_t("Upload profile picture")}</span>
<div className="mx_ProfileSettings_avatarOverlayImgContainer">
<div className="mx_ProfileSettings_avatarOverlayImg" />
</div>
</div>
);
const hostingSignupLink = getHostingLink('user-settings');
let hostingSignup = null;
if (hostingSignupLink) {
@ -156,6 +139,8 @@ export default class ProfileSettings extends React.Component {
</span>;
}
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
const AvatarSetting = sdk.getComponent('settings.AvatarSetting');
return (
<form onSubmit={this._saveProfile} autoComplete="off" noValidate={true}>
<input type="file" ref={this._avatarUpload} className="mx_ProfileSettings_avatarUpload"
@ -170,10 +155,12 @@ export default class ProfileSettings extends React.Component {
type="text" value={this.state.displayName} autoComplete="off"
onChange={this._onDisplayNameChanged} />
</div>
<div className="mx_ProfileSettings_avatar">
{avatarElement}
{avatarHoverElement}
</div>
<AvatarSetting
avatarUrl={this.state.avatarUrl}
avatarName={this.state.displayName || this.state.userId}
avatarAltText={_t("Profile picture")}
uploadAvatar={this._uploadAvatar}
removeAvatar={this._removeAvatar} />
</div>
<AccessibleButton onClick={this._saveProfile} kind="primary"
disabled={!this.state.enableProfileSave}>

View file

@ -37,12 +37,13 @@ export class IgnoredUser extends React.Component {
};
render() {
const id = `mx_SecurityUserSettingsTab_ignoredUser_${this.props.userId}`;
return (
<div className='mx_SecurityUserSettingsTab_ignoredUser'>
<AccessibleButton onClick={this._onUnignoreClicked} kind='primary_sm'>
{_t('Unignore')}
<AccessibleButton onClick={this._onUnignoreClicked} kind='primary_sm' aria-describedby={id}>
{ _t('Unignore') }
</AccessibleButton>
<span>{this.props.userId}</span>
<span id={id}>{ this.props.userId }</span>
</div>
);
}

View file

@ -90,7 +90,9 @@ export default class VerificationRequestToast extends React.PureComponent {
const verifier = this.props.request.beginKeyVerification(verificationMethods.SAS);
const IncomingSasDialog = sdk.getComponent('views.dialogs.IncomingSasDialog');
Modal.createTrackedDialog('Incoming Verification', '', IncomingSasDialog, {verifier});
Modal.createTrackedDialog('Incoming Verification', '', IncomingSasDialog, {
verifier,
}, null, /* priority = */ false, /* static = */ true);
};
render() {

View file

@ -28,6 +28,9 @@ export const useEventEmitter = (emitter, eventName, handler) => {
useEffect(
() => {
// allow disabling this hook by passing a falsy emitter
if (!emitter) return;
// Create event listener that calls handler function stored in ref
const eventListener = event => savedHandler.current(event);

View file

@ -510,8 +510,8 @@
"Flair": "Vztah ke komunitě",
"Showing flair for these communities:": "Místnost má vztah k těmto komunitám:",
"This room is not showing flair for any communities": "Tato místnost nemá vztah k žádné komunitě",
"URL previews are enabled by default for participants in this room.": "Náhledy URL adres jsou defaultně nastavené jako povolené pro členy této místnosti.",
"URL previews are disabled by default for participants in this room.": "Náhledy URL adres jsou defaultně nastavené jako zakázané pro členy této místnosti.",
"URL previews are enabled by default for participants in this room.": "Ve výchozím nastavení jsou náhledy URL adres povolené pro členy této místnosti.",
"URL previews are disabled by default for participants in this room.": "Ve výchozím nastavení jsou náhledy URL adres zakázané pro členy této místnosti.",
"Invalid file%(extra)s": "Neplatný soubor%(extra)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?": "Budete přesměrováni na stránku třetí strany k ověření svého účtu pro používání s %(integrationsUrl)s. Chcete pokračovat?",
"To continue, please enter your password.": "Aby jste mohli pokračovat, zadejte prosím své heslo.",
@ -587,10 +587,10 @@
"%(severalUsers)schanged their name %(count)s times|one": "%(severalUsers)ssi změnili jméno",
"%(oneUser)schanged their name %(count)s times|other": "%(oneUser)ssi %(count)s krát změnili jméno",
"%(oneUser)schanged their name %(count)s times|one": "%(oneUser)ssi změnili jméno",
"%(severalUsers)schanged their avatar %(count)s times|other": "%(severalUsers)ssi %(count)s krát změnili avatara",
"%(severalUsers)schanged their avatar %(count)s times|one": "%(severalUsers)ssi změnili avatara",
"%(oneUser)schanged their avatar %(count)s times|other": "%(oneUser)ssi %(count)s krát změnil avatara",
"%(oneUser)schanged their avatar %(count)s times|one": "%(oneUser)ssi změnil avatara",
"%(severalUsers)schanged their avatar %(count)s times|other": "%(severalUsers)ssi %(count)s krát změnili avatary",
"%(severalUsers)schanged their avatar %(count)s times|one": "%(severalUsers)ssi změnili avatary",
"%(oneUser)schanged their avatar %(count)s times|other": "%(oneUser)ssi %(count)s krát změnil avatar",
"%(oneUser)schanged their avatar %(count)s times|one": "%(oneUser)ssi změnil avatar",
"%(items)s and %(count)s others|other": "%(items)s a %(count)s další",
"%(items)s and %(count)s others|one": "%(items)s a jeden další",
"%(items)s and %(lastItem)s": "%(items)s a také %(lastItem)s",
@ -604,8 +604,8 @@
"You have entered an invalid address.": "Zadali jste neplatnou adresu.",
"Confirm Removal": "Potvrdit odstranění",
"Are you sure you wish to remove (delete) this event? Note that if you delete a room name or topic change, it could undo the change.": "Opravdu chcete odstranit (smazat) tuto událost? V případě, že smažete název místnosti anebo změníte téma, je možné, že se změny neprovedou.",
"Community IDs may only contain characters a-z, 0-9, or '=_-./'": "ID skupiny může obsahovat pouze znaky a-z, 0-9, or '=_-./'",
"Something went wrong whilst creating your community": "Něco se pokazilo v během vytváření vaší skupiny",
"Community IDs may only contain characters a-z, 0-9, or '=_-./'": "ID skupiny může obsahovat pouze znaky a-z, 0-9, nebo '=_-./'",
"Something went wrong whilst creating your community": "Něco se pokazilo během vytváření vaší skupiny",
"Unknown error": "Neznámá chyba",
"Incorrect password": "Nesprávné heslo",
"To verify that this device can be trusted, please contact its owner using some other means (e.g. in person or a phone call) and ask them whether the key they see in their User Settings for this device matches the key below:": "Pokud si chcete ověřit, zda je zařízení skutečně důvěryhodné, kontaktujte vlastníka jiným způsobem (např. osobně anebo telefonicky) a zeptejte se ho na klíč, který má pro toto zařízení zobrazený v nastavení a zda se shoduje s klíčem zobrazeným níže:",
@ -1019,7 +1019,7 @@
"Room Topic": "Téma místnosti",
"No room avatar": "Žádný avatar místnosti",
"Room avatar": "Avatar místnosti",
"Upload room avatar": "Nahrát avatara místnosti",
"Upload room avatar": "Nahrát avatar místnosti",
"Changes to who can read history will only apply to future messages in this room. The visibility of existing history will be unchanged.": "Změny toho kdo smí číst historické zprávy se aplikují jenom na další zprávy v této místosti. Viditelnost už poslaných zpráv zůstane jaká byla.",
"To link to this room, please add an alias.": "K vytvoření odkazu je potřeba vyrobit místnosti alias.",
"Roles & Permissions": "Funkce & Práva",
@ -1047,7 +1047,7 @@
"Enable big emoji in chat": "Povolit velké emotikony v chatu",
"Show avatars in user and room mentions": "Zobrazovat ikony uživatelů ve zmínkách o nich",
"Prompt before sending invites to potentially invalid matrix IDs": "Zeptat před odesláním pozvánky potenciálně neplatným Matrixovým identifikátorům",
"Show avatar changes": "Zobrazovat změny ikony",
"Show avatar changes": "Zobrazovat změny avatarů",
"Show join/leave messages (invites/kicks/bans unaffected)": "Zobrazovat zprávy o připojení/opuštění (netýká se pozvánek/vykopnutí/vykázání)",
"Show a placeholder for removed messages": "Zobrazovat zamazání místo smazané zprávy",
"Show display name changes": "Zobrazovat změny jména",
@ -1406,7 +1406,7 @@
"Order rooms in the room list by most important first instead of most recent": "Seřadit místosti v seznamu podle důležitosti místo podle posledního použití",
"Scissors": "Nůžky",
"Accept all %(invitedRooms)s invites": "Přijmout všechny pozvánky: %(invitedRooms)s",
"Change room avatar": "Změnit avatara místnosti",
"Change room avatar": "Změnit avatar místnosti",
"Change room name": "Změnit jméno místnosti",
"Change main address for the room": "Změnit hlavní adresu místnosti",
"Change history visibility": "Změnit viditelnost historie",
@ -1451,7 +1451,7 @@
"Room upgrades usually only affect <i>server-side</i> processing of the room. If you're having problems with your Riot client, please file an issue with <issueLink />.": "Upgrade místnosti se většinou týká zpracování <i>serverovem</i>. Pokud máte problém s klientem Riot, nahlašte nám prosím chybu na GitHub: <issueLink />.",
"<b>Warning</b>: Upgrading a room will <i>not automatically migrate room members to the new version of the room.</i> We'll post a link to the new room in the old version of the room - room members will have to click this link to join the new room.": "<b>Varování</b>: Upgrade místnosti <i>automaticky převede všechny členy na novou verzi místnosti.</i> Do staré místnosti pošleme odkaz na novou místnost - všichni členové na něj budou muset kliknout, aby se přidali do nové místnosti.",
"Please confirm that you'd like to go forward with upgrading this room from <oldVersion /> to <newVersion />.": "Potvrďte prosím, že chcete pokračovat a opravdu provést upgrade z verze <oldVersion /> na verzi <newVersion />.",
"Changes your avatar in this current room only": "Změní vaší ikonu jen v této místnosti",
"Changes your avatar in this current room only": "Změní váš avatar jen v této místnosti",
"Unbans user with given ID": "Přijmout zpět uživatele s daným identifikátorem",
"Adds a custom widget by URL to the room": "Přidá do místnosti vlastní widget podle adresy URL",
"Please supply a https:// or http:// widget URL": "Zadejte webovou adresu widgetu (začínající na https:// nebo http://)",
@ -1500,7 +1500,7 @@
"Do you want to join %(roomName)s?": "Chcete se přidat do místnosti %(roomName)s?",
"<userName/> invited you": "<userName/> vás pozval",
"You're previewing %(roomName)s. Want to join it?": "Prohlížíte si místnost %(roomName)s. Chcete se do ní přidat?",
"%(roomName)s can't be previewed. Do you want to join it?": "Místnost %(roomName)s si nelze jen tak prohlížet. Chcete se do ní přidat?",
"%(roomName)s can't be previewed. Do you want to join it?": "%(roomName)s si nelze jen tak prohlížet. Chcete se do ní přidat?",
"This room doesn't exist. Are you sure you're at the right place?": "Tato místnost neexistuje. Jste si jistí, že jste na správném místě?",
"Try again later, or ask a room admin to check if you have access.": "Zkuste to znovu nebo se zeptejte administrátora aby zkontrolovat jestli máte přístup.",
"%(errcode)s was returned while trying to access the room. If you think you're seeing this message in error, please <issueLink>submit a bug report</issueLink>.": "Při pokusu o připojení došlo k chybě: %(errcode)s. Pokud si myslíte, že je to bug, můžete ho <issueLink>nahlásit</issueLink>.",
@ -1602,8 +1602,8 @@
"Actions": "Akce",
"Sends a message as plain text, without interpreting it as markdown": "Pošle zprávu jako prostý text, neinterpretuje jí jako Markdown",
"You do not have the required permissions to use this command.": "Na provedení tohoto příkazu nemáte dostatečná oprávnění.",
"Changes the avatar of the current room": "Změní vašeho avatara pro tuto místnost",
"Changes your avatar in all rooms": "Změní vašeho avatara pro všechny místnosti",
"Changes the avatar of the current room": "Změní váš avatar pro tuto místnost",
"Changes your avatar in all rooms": "Změní váš avatar pro všechny místnosti",
"Use an identity server": "Používat server identit",
"Use an identity server to invite by email. Click continue to use the default identity server (%(defaultIdentityServerName)s) or manage in Settings.": "Použít server identit na odeslání emailové pozvánky. Pokračováním použijete výchozí server identit (%(defaultIdentityServerName)s) nebo ho můžete změnit v Nastavení.",
"Use an identity server to invite by email. Manage in Settings.": "Použít server identit na odeslání emailové pozvánky. Můžete spravovat v Nastavení.",
@ -1807,7 +1807,7 @@
"View": "Zobrazit",
"Find a room…": "Najít místnost…",
"Find a room… (e.g. %(exampleRoom)s)": "Najít místnost… (například %(exampleRoom)s)",
"If you can't find the room you're looking for, ask for an invite or <a>Create a new room</a>.": "Pokud nemůžete nelézt místnost, kterou hledáte, napište o pozvánku nebo si jí <a>Vytvořte</a>.",
"If you can't find the room you're looking for, ask for an invite or <a>Create a new room</a>.": "Pokud nemůžete nelézt místnost, kterou hledáte, napište si o pozvánku nebo <a>Vytvořte novou</a>.",
"Explore rooms": "Prohlížet místnosti",
"Jump to first unread room.": "Skočit na první nepřečtenou místnost.",
"Jump to first invite.": "Skočit na první pozvánku.",
@ -1834,5 +1834,147 @@
"Emoji Autocomplete": "Automatické doplňování Emodži",
"Notification Autocomplete": "Automatické doplňování upozornění",
"Room Autocomplete": "Automatické doplňování místností",
"User Autocomplete": "Automatické doplňování uživatelů"
"User Autocomplete": "Automatické doplňování uživatelů",
"Custom (%(level)s)": "Vlastní (%(level)s)",
"Error upgrading room": "Chyba při upgrade místnosti",
"Double check that your server supports the room version chosen and try again.": "Zkontrolujte, že váš server opravdu podporuje zvolenou verzi místnosti.",
"%(senderName)s placed a voice call.": "%(senderName)s spustil hovor.",
"%(senderName)s placed a voice call. (not supported by this browser)": "%(senderName)s spustil hovor. (není podporováno tímto prohlížečem)",
"%(senderName)s placed a video call.": "%(senderName)s spustil videohovor.",
"%(senderName)s placed a video call. (not supported by this browser)": "%(senderName)s spustil videohovor. (není podporováno tímto prohlížečem)",
"%(senderName)s removed the rule banning users matching %(glob)s": "%(senderName)s odstranit pravidlo blokující uživatele odpovídající %(glob)s",
"%(senderName)s removed the rule banning rooms matching %(glob)s": "%(senderName)s odstranil pravidlo blokující místnosti odpovídající %(glob)s",
"%(senderName)s removed the rule banning servers matching %(glob)s": "%(senderName)s odstranil pravidlo blokující servery odpovídající %(glob)s",
"%(senderName)s removed a ban rule matching %(glob)s": "%(senderName)s odstranil blokující pravidlo %(glob)s",
"%(senderName)s updated an invalid ban rule": "%(senderName)s aktualizoval neplatné pravidlo blokování",
"%(senderName)s updated the rule banning users matching %(glob)s for %(reason)s": "%(senderName)s aktualizoval pravidlo blokující uživatele odpovídající %(glob)s z důvodu %(reason)s",
"%(senderName)s updated the rule banning rooms matching %(glob)s for %(reason)s": "%(senderName)s aktualizoval pravidlo blokující místnosti odpovídající %(glob)s z důvodu %(reason)s",
"%(senderName)s updated the rule banning servers matching %(glob)s for %(reason)s": "%(senderName)s aktualizoval pravidlo blokující servery odpovídající %(glob)s z důvodu %(reason)s",
"%(senderName)s updated a ban rule matching %(glob)s for %(reason)s": "%(senderName)s aktualizoval blokovací pravidlo odpovídající %(glob)s z důvodu %(reason)s",
"%(senderName)s created a rule banning users matching %(glob)s for %(reason)s": "%(senderName)s vytvořil pravidlo blokující uživatele odpovídající %(glob)s z důvodu %(reason)s",
"%(senderName)s created a rule banning rooms matching %(glob)s for %(reason)s": "%(senderName)s vytvořil pravidlo blokující místnosti odpovídající %(glob)s z důvodu %(reason)s",
"%(senderName)s created a rule banning servers matching %(glob)s for %(reason)s": "%(senderName)s vytvořil pravidlo blokující servery odpovídající %(glob)s z důvodu %(reason)s",
"%(senderName)s created a ban rule matching %(glob)s for %(reason)s": "%(senderName)s vytvořil blokovací pravidlo odpovídající %(glob)s z důvodu %(reason)s",
"%(senderName)s changed a rule that was banning users matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s změnil pravidlo blokující uživatele odpovídající %(oldGlob)s na uživatele odpovídající %(newGlob)s z důvodu %(reason)s.",
"%(senderName)s changed a rule that was banning rooms matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s změnil pravidlo blokující místnosti odpovídající %(oldGlob)s na místnosti odpovídající %(newGlob)s z důvodu %(reason)s",
"%(senderName)s changed a rule that was banning servers matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s změnil pravidlo blokující servery odpovídající %(oldGlob)s na servery odpovídající %(newGlob)s z důvodu %(reason)s",
"%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s změnil blokovací pravidlo odpovídající %(oldGlob)s na odpovídající %(newGlob)s z důvodu %(reason)s",
"Try out new ways to ignore people (experimental)": "Vyzkošejte nové metody ignorování lidí (experimentální)",
"Send verification requests in direct message, including a new verification UX in the member panel.": "Poslat požadavek na ověření v přímé zprávě včetně nového verifikačního rozhraní v panelu.",
"Enable local event indexing and E2EE search (requires restart)": "Povolit lokální indexování a vyhledávání v E2E šifrovaných zprávách (vyžaduje restart)",
"Match system theme": "Přizpůsobit se systémovému vzhledu",
"My Ban List": "Můj seznam zablokovaných",
"This is your list of users/servers you have blocked - don't leave the room!": "Toto je váš seznam blokovaných uživatelů/serverů - neopouštějte tuto místnost!",
"Decline (%(counter)s)": "Odmítnout (%(counter)s)",
"on device": "na zařízení",
"Connecting to integration manager...": "Připojuji se ke správci integrací...",
"Cannot connect to integration manager": "Nepovedlo se připojení ke správci integrací",
"The integration manager is offline or it cannot reach your homeserver.": "Správce integrací neběží nebo se nemůže připojit k vašemu domovskému serveru.",
"Clear notifications": "Odstranit notifikace",
"Use an Integration Manager <b>(%(serverName)s)</b> to manage bots, widgets, and sticker packs.": "Použít správce integrací <b>(%(serverName)s)</b> na správu botů, widgetů a samolepek.",
"Use an Integration Manager to manage bots, widgets, and sticker packs.": "Použít správce integrací na správu botů, widgetů a samolepek.",
"Manage integrations": "Spravovat integrace",
"Integration Managers receive configuration data, and can modify widgets, send room invites, and set power levels on your behalf.": "Správce integrací dostává konfigurační data a může za vás modifikovat widgety, posílat pozvánky a nastavovat úrovně oprávnění.",
"Customise your experience with experimental labs features. <a>Learn more</a>.": "Přizpůsobte si aplikaci s experimentálními funkcemi. <a>Více informací</a>.",
"Ignored/Blocked": "Ignorováno/Blokováno",
"Error adding ignored user/server": "Chyba při přidávání ignorovaného uživatele/serveru",
"Something went wrong. Please try again or view your console for hints.": "Něco se nepovedlo. Zkuste pro prosím znovu nebo se podívejte na detaily do konzole.",
"Error subscribing to list": "Nepovedlo se založit odběr",
"Please verify the room ID or alias and try again.": "Zkontrolujte prosím ID místnosti a zkuste to znovu.",
"Error removing ignored user/server": "Ignorovaný uživatel/server nejde odebrat",
"Error unsubscribing from list": "Nepovedlo se zrušit odběr",
"Please try again or view your console for hints.": "Zkuste to prosím znovu a nebo se podívejte na detailní chybu do konzole.",
"None": "Žádné",
"Ban list rules - %(roomName)s": "Pravidla blokování - %(roomName)s",
"Server rules": "Pravidla serveru",
"User rules": "Pravidla uživatele",
"You have not ignored anyone.": "Nikoho neignorujete.",
"You are currently ignoring:": "Ignorujete:",
"You are not subscribed to any lists": "Neodebíráte žádné seznamy",
"Unsubscribe": "Přestat odebírat",
"View rules": "Zobrazit pravidla",
"You are currently subscribed to:": "Odebíráte:",
"⚠ These settings are meant for advanced users.": "⚠ Tato nastavení jsou pro pokročilé uživatele.",
"Add users and servers you want to ignore here. Use asterisks to have Riot match any characters. For example, <code>@bot:*</code> would ignore all users that have the name 'bot' on any server.": "Sem přidejte uživatele a servery, které chcete ignorovat. Můžete použít hvězdičku místo libovolných znaků. Například pravidlo <code>@bot:*</code> bude blokovat všechny uživatele se jménem 'bot' na libovolném serveru.",
"Ignoring people is done through ban lists which contain rules for who to ban. Subscribing to a ban list means the users/servers blocked by that list will be hidden from you.": "Lidé a servery jsou blokováni pomocí seznamů obsahující pravidla koho blokovat. Odebírání blokovacího seznamu znamená, že neuvidíte uživatele a servery na něm uvedené.",
"Personal ban list": "Osobní seznam blokací",
"Your personal ban list holds all the users/servers you personally don't want to see messages from. After ignoring your first user/server, a new room will show up in your room list named 'My Ban List' - stay in this room to keep the ban list in effect.": "Váš osobní seznam blokací obsahuje všechny uživatele a server, které nechcete vidět. Po ignorování prvního uživatele/server se vytvoří nová místnost 'Můj seznam blokací' - zůstaňte v ní aby seznam platil.",
"Server or user ID to ignore": "Server nebo ID uživatele",
"eg: @bot:* or example.org": "např.: @bot:* nebo example.org",
"Subscribed lists": "Odebírané seznamy",
"Room ID or alias of ban list": "ID místnosti nebo alias seznamu blokování",
"Subscribe": "Odebírat",
"This message cannot be decrypted": "Zprávu nelze rozšifrovat",
"Unencrypted": "Nešifrované",
"<userName/> wants to chat": "<userName/> chce chatovat",
"Start chatting": "Začít chatovat",
"Failed to connect to integration manager": "Nepovedlo se připojit ke správci integrací",
"Trusted": "Důvěryhodné",
"Not trusted": "Nedůvěryhodné",
"Hide verified Sign-In's": "Skrýt důvěryhodná přihlášení",
"%(count)s verified Sign-In's|other": "%(count)s důvěryhodných přihlášení",
"%(count)s verified Sign-In's|one": "1 důvěryhodné přihlášení",
"Direct message": "Přímá zpráva",
"Unverify user": "Nedůvěřovat uživateli",
"<strong>%(role)s</strong> in %(roomName)s": "<strong>%(role)s</strong> v %(roomName)s",
"Messages in this room are end-to-end encrypted.": "V této místosti jsou zprávy E2E šifrované.",
"Security": "Bezpečnost",
"Verify": "Ověřit",
"You have ignored this user, so their message is hidden. <a>Show anyways.</a>": "Tohoto uživatele ignorujete, takže jsou jeho/její zprávy skryté. <a>Přesto zobrazit.</a>",
"Reactions": "Reakce",
"<reactors/><reactedWith> reacted with %(content)s</reactedWith>": "<reactors/><reactedWith> reagoval %(content)s</reactedWith>",
"Any of the following data may be shared:": "Následující data můžou být sdílena:",
"Your display name": "Vaše zobrazované jméno",
"Your avatar URL": "URL vašeho avataru",
"Your user ID": "Vaše ID",
"Your theme": "Váš motiv",
"Riot URL": "URL Riotu",
"Room ID": "ID místnosti",
"Widget ID": "ID widgetu",
"Using this widget may share data <helpIcon /> with %(widgetDomain)s & your Integration Manager.": "Použití tohoto widgetu může sdílet data <helpIcon /> s %(widgetDomain)s a vaším správcem integrací.",
"Using this widget may share data <helpIcon /> with %(widgetDomain)s.": "Použití tohoto widgetu může sdílet data <helpIcon /> s %(widgetDomain)s.",
"Widgets do not use message encryption.": "Widgety nepoužívají šifrování zpráv.",
"Widget added by": "Widget přidal",
"This widget may use cookies.": "Widget může používat cookies.",
"More options": "Více možností",
"Integrations are disabled": "Integrace jsou zakázané",
"Enable 'Manage Integrations' in Settings to do this.": "Abyste mohli akci provést, povolte 'Spravovat integrace' v Nastavení.",
"Integrations not allowed": "Integrace nejsou povolené",
"Your Riot doesn't allow you to use an Integration Manager to do this. Please contact an admin.": "Váš Riot neumožňuje použít správce integrací. Kontaktujte prosím administrátora.",
"Automatically invite users": "Automaticky zvát uživatele",
"Upgrade private room": "Upgradovat soukromou místnost",
"Upgrade public room": "Upgradovat veřejnou místnost",
"Upgrading a room is an advanced action and is usually recommended when a room is unstable due to bugs, missing features or security vulnerabilities.": "Upgradování místnosti je pokročilá operace a je doporučeno jí provést pokud je místnost nestabilní kvůli chybám, chybějícím funkcím nebo zranitelnostem.",
"This usually only affects how the room is processed on the server. If you're having problems with your Riot, please <a>report a bug</a>.": "Toto běžně ovlivňuje jak je místnost zpracovávána na serveru. Pokud máte problém s Riotem, <a>nahlaste nám prosím bug</a>.",
"You'll upgrade this room from <oldVersion /> to <newVersion />.": "Upgradujeme tuto místnost z <oldVersion /> na <newVersion />.",
"Upgrade": "Upgradovat",
"Enter secret storage passphrase": "Zadejte tajné heslo k úložišti",
"Unable to access secret storage. Please verify that you entered the correct passphrase.": "Nepovedlo se přistoupit k bezpečnému úložišti. Zkontrolujte prosím, že je zadané správné heslo.",
"<b>Warning</b>: You should only access secret storage from a trusted computer.": "<b>Varování</b>: Přistupujte k bezpečnému úložišti pouze z důvěryhodných počítačů.",
"If you've forgotten your passphrase you can <button1>use your recovery key</button1> or <button2>set up new recovery options</button2>.": "Pokud si nepamatujete heslo, můžete použít <button1>váš obnovovací klíč</button1> nebo <button2>si nastavte nové možnosti obnovení</button2>.",
"Enter secret storage recovery key": "Zadejte klíč k bezpečnému úložišti",
"Unable to access secret storage. Please verify that you entered the correct recovery key.": "Nepovedlo se dostat k bezpečnému úložišti. Ověřte prosím, že je zadaný správný klíč.",
"If you've forgotten your recovery key you can <button>set up new recovery options</button>.": "Pokud si nepamatujete obnovovací klíč, můžete si <button>nastavit nové možnosti obnovení</button>.",
"<b>Warning</b>: You should only set up key backup from a trusted computer.": "<b>Varování</b>: Nastavujte zálohu jen z důvěryhodných počítačů.",
"If you've forgotten your recovery key you can <button>set up new recovery options</button>": "Pokud si nepamatujete obnovovací klíč, můžete si <button>nastavit nové možnosti obnovení</button>",
"Notification settings": "Nastavení notifikací",
"Reload": "Načíst znovu",
"Take picture": "Udělat fotku",
"Remove for everyone": "Odstranit pro všechny",
"Remove for me": "Odstranit pro mě",
"User Status": "Stav uživatele",
"Verification Request": "Požadavek na ověření",
" (1/%(totalCount)s)": " (1/%(totalCount)s)",
"<b>Warning</b>: You should only set up secret storage from a trusted computer.": "<b>Varování</b>: Nastavujte bezpečné úložiště pouze z důvěryhodného počítače.",
"Set up with a recovery key": "Nastavit obnovovací klíč",
"As a safety net, you can use it to restore your access to encrypted messages if you forget your passphrase.": "Můžete jej použít jako záchranou síť na obnovení šifrovaných zpráv když zapomenete heslo.",
"As a safety net, you can use it to restore your access to encrypted messages.": "Můžete jej použít jako záchranou síť na obnovení šifrovaných zpráv.",
"Keep your recovery key somewhere very secure, like a password manager (or a safe).": "Uschovejte svůj klíč na velmi bezpečném místě, například ve správci hesel (nebo v trezoru).",
"Your recovery key has been <b>copied to your clipboard</b>, paste it to:": "Váš obnovovací klíč byl <b>zkopírován do schránky</b>, vložte jej:",
"Your recovery key is in your <b>Downloads</b> folder.": "Váš obnovací klíč je ve složce <b>Stažené</b>.",
"Your access to encrypted messages is now protected.": "Přístup k šifrovaným zprávám je teď chráněn.",
"Set up secret storage": "Nastavit bezpečné úložiště",
"Secure your encrypted messages with a passphrase": "Zabezpečte vaše šifrované zprávy heslem",
"Storing secrets...": "Ukládám tajná data...",
"Unable to set up secret storage": "Nepovedlo se nastavit bezpečné úložiště"
}

View file

@ -1471,7 +1471,7 @@
"Please supply a https:// or http:// widget URL": "Bitte gib eine https:// oder http:// Widget-URL an",
"Sends the given emote coloured as a rainbow": "Sended das Emoji in Regenbogenfarben",
"%(senderName)s made no change.": "%(senderName)s hat keine Änderung vorgenommen.",
"%(senderName)s revoked the invitation for %(targetDisplayName)s to join the room.": "%(senderName)s hat die Einladung zum Betreten des Raumes für %(targetDisplayName)s zurückgezogen.",
"%(senderName)s revoked the invitation for %(targetDisplayName)s to join the room.": "%(senderName)s hat die Einladung zum Raumbeitritt für %(targetDisplayName)s zurückgezogen.",
"Cannot reach homeserver": "Der Heimserver ist nicht erreichbar",
"Ensure you have a stable internet connection, or get in touch with the server admin": "Stelle sicher, dass du eine stabile Internetverbindung hast oder wende dich an deinen Server-Administrator",
"Ask your Riot admin to check <a>your config</a> for incorrect or duplicate entries.": "Wende dich an deinen Riot Admin um <a>deine Konfiguration</a> auf ungültige oder doppelte Einträge zu überprüfen.",
@ -1579,5 +1579,11 @@
"Change identity server": "Wechsle den Identitätsserver",
"You should <b>remove your personal data</b> from identity server <idserver /> before disconnecting. Unfortunately, identity server <idserver /> is currently offline or cannot be reached.": "Du solltest deine <b>persönlichen Daten</b> vom Identitätsserver <idserver /> entfernen, bevor du die Verbindung trennst. Leider ist der Identitätsserver <idserver /> derzeit offline oder kann nicht erreicht werden.",
"You should:": "Du solltest:",
"check your browser plugins for anything that might block the identity server (such as Privacy Badger)": "Überprüfe deinen Browser auf Erweiterungen, die den Identitätsserver blockieren könnten (z.B. Privacy Badger)"
"check your browser plugins for anything that might block the identity server (such as Privacy Badger)": "Überprüfe deinen Browser auf Erweiterungen, die den Identitätsserver blockieren könnten (z.B. Privacy Badger)",
"Error upgrading room": "Fehler beim Raum-Aufrüsten",
"Double check that your server supports the room version chosen and try again.": "Überprüfe nochmal ob dein Server die ausgewählte Raumversion unterstützt und versuche es nochmal.",
"%(senderName)s placed a voice call.": "%(senderName)s tätigte einen Sprachanruf.",
"%(senderName)s placed a voice call. (not supported by this browser)": "%(senderName)s tätigte einen Sprachanruf (Nicht von diesem Browser unterstützt)",
"%(senderName)s placed a video call.": "%(senderName)s tätigte einen Videoanruf.",
"%(senderName)s placed a video call. (not supported by this browser)": "%(senderName)s tätigte einen Videoanruf (Nicht von diesem Browser unterstützt)"
}

View file

@ -499,6 +499,8 @@
"Pin": "Pin",
"Decline (%(counter)s)": "Decline (%(counter)s)",
"Accept <policyLink /> to continue:": "Accept <policyLink /> to continue:",
"Upload": "Upload",
"Remove": "Remove",
"Failed to upload profile picture!": "Failed to upload profile picture!",
"Upload new:": "Upload new:",
"No display name": "No display name",
@ -597,10 +599,9 @@
"Off": "Off",
"On": "On",
"Noisy": "Noisy",
"Profile picture": "Profile picture",
"Upload profile picture": "Upload profile picture",
"<a>Upgrade</a> to your own domain": "<a>Upgrade</a> to your own domain",
"Display Name": "Display Name",
"Profile picture": "Profile picture",
"Save": "Save",
"Identity Server URL must be HTTPS": "Identity Server URL must be HTTPS",
"Not a valid Identity Server (status code %(code)s)": "Not a valid Identity Server (status code %(code)s)",
@ -691,7 +692,6 @@
"User rules": "User rules",
"Close": "Close",
"You have not ignored anyone.": "You have not ignored anyone.",
"Remove": "Remove",
"You are currently ignoring:": "You are currently ignoring:",
"You are not subscribed to any lists": "You are not subscribed to any lists",
"Unsubscribe": "Unsubscribe",
@ -857,9 +857,14 @@
" (unsupported)": " (unsupported)",
"Join as <voiceText>voice</voiceText> or <videoText>video</videoText>.": "Join as <voiceText>voice</voiceText> or <videoText>video</videoText>.",
"Ongoing conference call%(supportedText)s.": "Ongoing conference call%(supportedText)s.",
"This user has not verified all of their devices.": "This user has not verified all of their devices.",
"You have not verified this user. This user has verified all of their devices.": "You have not verified this user. This user has verified all of their devices.",
"You have verified this user. This user has verified all of their devices.": "You have verified this user. This user has verified all of their devices.",
"Some users in this encrypted room are not verified by you or they have not verified their own devices.": "Some users in this encrypted room are not verified by you or they have not verified their own devices.",
"All users in this encrypted room are verified by you and they have verified their own devices.": "All users in this encrypted room are verified by you and they have verified their own devices.",
"Some devices for this user are not trusted": "Some devices for this user are not trusted",
"Some devices in this encrypted room are not trusted": "Some devices in this encrypted room are not trusted",
"All devices for this user are trusted": "All devices for this user are trusted",
"Some devices in this encrypted room are not trusted": "Some devices in this encrypted room are not trusted",
"All devices in this encrypted room are trusted": "All devices in this encrypted room are trusted",
"Edit message": "Edit message",
"This event could not be displayed": "This event could not be displayed",
@ -876,6 +881,7 @@
"Unencrypted": "Unencrypted",
"Please select the destination room for this message": "Please select the destination room for this message",
"Scroll to bottom of page": "Scroll to bottom of page",
"Close preview": "Close preview",
"device id: ": "device id: ",
"Disinvite": "Disinvite",
"Kick": "Kick",
@ -1091,11 +1097,9 @@
"Showing flair for these communities:": "Showing flair for these communities:",
"This room is not showing flair for any communities": "This room is not showing flair for any communities",
"New community ID (e.g. +foo:%(localDomain)s)": "New community ID (e.g. +foo:%(localDomain)s)",
"Room avatar": "Room avatar",
"Upload room avatar": "Upload room avatar",
"No room avatar": "No room avatar",
"Room Name": "Room Name",
"Room Topic": "Room Topic",
"Room avatar": "Room avatar",
"You have <a>enabled</a> URL previews by default.": "You have <a>enabled</a> URL previews by default.",
"You have <a>disabled</a> URL previews by default.": "You have <a>disabled</a> URL previews by default.",
"URL previews are enabled by default for participants in this room.": "URL previews are enabled by default for participants in this room.",
@ -1262,6 +1266,7 @@
"Rotate Right": "Rotate Right",
"Rotate clockwise": "Rotate clockwise",
"Download this file": "Download this file",
"Language Dropdown": "Language Dropdown",
"Manage Integrations": "Manage Integrations",
"%(nameList)s %(transitionList)s": "%(nameList)s %(transitionList)s",
"%(severalUsers)sjoined %(count)s times|other": "%(severalUsers)sjoined %(count)s times",
@ -1538,7 +1543,6 @@
"Upload files (%(current)s of %(total)s)": "Upload files (%(current)s of %(total)s)",
"Upload files": "Upload files",
"Upload all": "Upload all",
"Upload": "Upload",
"This file is <b>too large</b> to upload. The file size limit is %(limit)s but this file is %(sizeOfThisFile)s.": "This file is <b>too large</b> to upload. The file size limit is %(limit)s but this file is %(sizeOfThisFile)s.",
"These files are <b>too large</b> to upload. The file size limit is %(limit)s.": "These files are <b>too large</b> to upload. The file size limit is %(limit)s.",
"Some files are <b>too large</b> to be uploaded. The file size limit is %(limit)s.": "Some files are <b>too large</b> to be uploaded. The file size limit is %(limit)s.",
@ -1627,6 +1631,7 @@
"User Status": "User Status",
"powered by Matrix": "powered by Matrix",
"This homeserver would like to make sure you are not a robot.": "This homeserver would like to make sure you are not a robot.",
"Country Dropdown": "Country Dropdown",
"Custom Server Options": "Custom Server Options",
"You can use the custom server options to sign into other Matrix servers by specifying a different homeserver URL. This allows you to use this app with an existing Matrix account on a different homeserver.": "You can use the custom server options to sign into other Matrix servers by specifying a different homeserver URL. This allows you to use this app with an existing Matrix account on a different homeserver.",
"To continue, please enter your password.": "To continue, please enter your password.",

View file

@ -1842,7 +1842,7 @@
"%(senderName)s placed a video call. (not supported by this browser)": "%(senderName)s erabiltzaileak bideo-dei bat abiatu du. (Nabigatzaile honek ez du onartzen)",
"Try out new ways to ignore people (experimental)": "Probatu jendea ez entzuteko modu berriak (esperimentala)",
"Send verification requests in direct message, including a new verification UX in the member panel.": "Bidali egiaztatze eskariak mezu zuzenetan, kide paneleko egiaztatze interfaze berria barne.",
"Enable cross-signing to verify per-user instead of per-device (in development)": "Gaitu sinatze gurutzatua erabiltzaileko eta ez gailuko egiaztatzeko (garapenean)",
"Enable cross-signing to verify per-user instead of per-device (in development)": "Gaitu zeharkako sinadura erabiltzaileko eta ez gailuko egiaztatzeko (garapenean)",
"Enable local event indexing and E2EE search (requires restart)": "Gaitu gertaera lokalen indexazioa eta E2EE bilaketa (berrabiarazi behar da)",
"Match system theme": "Bat egin sistemako gaiarekin",
"My Ban List": "Nire debeku-zerrenda",
@ -1923,5 +1923,89 @@
"Remove for everyone": "Kendu denentzat",
"Remove for me": "Kendu niretzat",
"Verification Request": "Egiaztaketa eskaria",
" (1/%(totalCount)s)": " (1/%(totalCount)s)"
" (1/%(totalCount)s)": " (1/%(totalCount)s)",
"Send cross-signing keys to homeserver": "Bidali zeharkako sinaduraren gakoak hasiera-zerbitzarira",
"Error upgrading room": "Errorea gela eguneratzean",
"Double check that your server supports the room version chosen and try again.": "Egiaztatu zure zerbitzariak aukeratutako gela bertsioa onartzen duela eta saiatu berriro.",
"%(senderName)s removed the rule banning users matching %(glob)s": "%(senderName)s erabiltzaileak %(glob)s adierazpenarekin bat datozen erabiltzaileak debekatzen zituen araua kendu du",
"%(senderName)s removed the rule banning rooms matching %(glob)s": "%(senderName)s erabiltzaileak %(glob)s adierazpenarekin bat datozen gelak debekatzen zituen araua kendu du",
"%(senderName)s removed the rule banning servers matching %(glob)s": "%(senderName)s erabiltzaileak %(glob)s adierazpenarekin bat datozen zerbitzariak debekatzen zituen araua kendu du",
"%(senderName)s removed a ban rule matching %(glob)s": "%(senderName)s erabiltzaileak %(glob)s adierazpenarekin bat datorren debeku arau bat kendu du",
"%(senderName)s updated an invalid ban rule": "%(senderName)s erabiltzaileak baliogabeko debeku arau bat eguneratu du",
"%(senderName)s updated the rule banning users matching %(glob)s for %(reason)s": "%(senderName)s erabiltzaileak %(glob)s adierazpenarekin bat datozen erabiltzaileak debekatzen dituen araua eguneratu du, arrazoia: %(reason)s",
"%(senderName)s updated the rule banning rooms matching %(glob)s for %(reason)s": "%(senderName)s erabiltzaileak %(glob)s adierazpenarekin bat datozen gelak debekatzen dituen araua eguneratu du, arrazoia: %(reason)s",
"%(senderName)s updated the rule banning servers matching %(glob)s for %(reason)s": "%(senderName)s erabiltzaileak %(glob)s adierazpenarekin bat datozen zerbitzariak debekatzen dituen araua eguneratu du, arrazoia: %(reason)s",
"%(senderName)s updated a ban rule matching %(glob)s for %(reason)s": "%(senderName)s erabiltzaileak %(glob)s adierazpenarekin bat datorren debeku arau bat eguneratu du, arrazoia: %(reason)s",
"%(senderName)s created a rule banning users matching %(glob)s for %(reason)s": "%(senderName)s erabiltzaileak %(glob)s adierazpenarekin bat datozen erabiltzaileak debekatzen dituen araua sortu du, arrazoia: %(reason)s",
"%(senderName)s created a rule banning rooms matching %(glob)s for %(reason)s": "%(senderName)s erabiltzaileak %(glob)s adierazpenarekin bat datozen gelak debekatzen dituen araua sortu du, arrazoia: %(reason)s",
"%(senderName)s created a rule banning servers matching %(glob)s for %(reason)s": "%(senderName)s erabiltzaileak %(glob)s adierazpenarekin bat datozen zerbitzariak debekatzen dituen araua sortu du, arrazoia: %(reason)s",
"%(senderName)s created a ban rule matching %(glob)s for %(reason)s": "%(senderName)s erabiltzaileak %(glob)s adierazpenarekin bat datorren debeku arau bat sortu du, arrazoia: %(reason)s",
"%(senderName)s changed a rule that was banning users matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s erabiltzaileak erabiltzaileak debekatzen dituen araua aldatu du %(oldGlob)s adierazpenetik %(newGlob)s adierazpenera, arrazoia: %(reason)s",
"%(senderName)s changed a rule that was banning rooms matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s erabiltzaileak gelak debekatzen dituen araua aldatu du %(oldGlob)s adierazpenetik %(newGlob)s adierazpenera, arrazoia: %(reason)s",
"%(senderName)s changed a rule that was banning servers matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s erabiltzaileak zerbitzariak debekatzen dituen araua aldatu du %(oldGlob)s adierazpenetik %(newGlob)s adierazpenera, arrazoia: %(reason)s",
"%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s erabiltzaileak debeku arau bat aldatu du %(oldGlob)s adierazpenetik %(newGlob)s adierazpenera, arrazoia: %(reason)s",
"Cross-signing and secret storage are enabled.": "Zeharkako sinadura eta biltegi sekretua gaituta daude.",
"Your account has a cross-signing identity in secret storage, but it is not yet trusted by this device.": "Zure kontuak zeharkako sinaduraren identitatea biltegi sekretuan du, baina gailu honek oraindik ez du fidagarritzat.",
"Cross-signing and secret storage are not yet set up.": "Zeharkako sinadura eta biltegi sekretua ez daude oraindik ezarrita.",
"Bootstrap cross-signing and secret storage": "Abiatu zeharkako sinadura eta biltegi sekretua",
"Cross-signing public keys:": "Zeharkako sinaduraren gako publikoak:",
"on device": "gailuan",
"not found": "ez da aurkitu",
"Cross-signing private keys:": "Zeharkako sinaduraren gako pribatuak:",
"in secret storage": "biltegi sekretuan",
"Secret storage public key:": "Biltegi sekretuko gako publikoa:",
"in account data": "kontuaren datuetan",
"not stored": "gorde gabe",
"Backup has a <validity>valid</validity> signature from this user": "Babes-kopiak erabiltzaile honen <validity>baliozko</validity> sinadura bat du",
"Backup has a <validity>invalid</validity> signature from this user": "Babes-kopiak erabiltzaile honen <validity>baliogabeko</validity> sinadura bat du",
"Backup has a signature from <verify>unknown</verify> user with ID %(deviceId)s": "Babes-kopiak %(deviceId)s ID-a duen erabiltzaile <verify>ezezagun</verify> baten sinadura du",
"Backup has a signature from <verify>unknown</verify> device with ID %(deviceId)s": "Babes-kopiak %(deviceId)s ID-a duen gailu <verify>ezezagun</verify> baten sinadura du",
"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.": "Babes-kopiaren gakoa biltegi sekretuan gorde da, gaina ezaugarri hau ez dago aktibatuta gailu honetan. Gaitu zeharkako sinadura laborategian babes-kopiaren egoera aldatzeko.",
"Backup key stored: ": "Babes-kopiaren gakoa gordeta: ",
"Start using Key Backup with Secure Secret Storage": "Hasi gakoen babes-kopia erabiltzen biltegi sekretu seguruarekin",
"Cross-signing": "Zeharkako sinadura",
"This message cannot be decrypted": "Mezu hau ezin da deszifratu",
"Unencrypted": "Zifratu gabe",
"Close preview": "Itxi aurrebista",
"<userName/> wants to chat": "<userName/> erabiltzaileak txateatu nahi du",
"Start chatting": "Hasi txateatzen",
"Hide verified sessions": "Ezkutatu egiaztatutako saioak",
"%(count)s verified sessions|other": "%(count)s egiaztatutako saio",
"%(count)s verified sessions|one": "Egiaztatutako saio 1",
"Reactions": "Erreakzioak",
"<reactors/><reactedWith> reacted with %(content)s</reactedWith>": "<reactors/> erabiltzaileak <reactedWith>%(content)s batekin erreakzionatu du</reactedWith>",
"Automatically invite users": "Gonbidatu erabiltzaileak automatikoki",
"Upgrade private room": "Eguneratu gela pribatua",
"Upgrade public room": "Eguneratu gela publikoa",
"Upgrading a room is an advanced action and is usually recommended when a room is unstable due to bugs, missing features or security vulnerabilities.": "Gela eguneratzea ekintza aurreratu bat da eta akatsen, falta diren ezaugarrien, edo segurtasun arazoen erruz gela ezegonkorra denean aholkatzen da.",
"This usually only affects how the room is processed on the server. If you're having problems with your Riot, please <a>report a bug</a>.": "Orokorrean honek zerbitzariak gela nola prozesatzen duen da duen eragin bakarra. RIot-ekin arazoak badituzu, <a>eman akats baten berri</a>.",
"You'll upgrade this room from <oldVersion /> to <newVersion />.": "Gela hau <oldVersion /> bertsiotik <newVersion /> bertsiora eguneratuko duzu.",
"Upgrade": "Eguneratu",
"Enter secret storage passphrase": "Sartu biltegi sekretuko pasaesaldia",
"Unable to access secret storage. Please verify that you entered the correct passphrase.": "Ezin izan da biltegi sekretura sartu. Egiaztatu pasaesaldi zuzena idatzi duzula.",
"<b>Warning</b>: You should only access secret storage from a trusted computer.": "<b>Abisua</b>: Biltegi sekretura ordenagailu fidagarri batetik konektatu beharko zinateke beti.",
"Access your secure message history and your cross-signing identity for verifying other devices by entering your passphrase.": "Atzitu zure mezu seguruen historiala eta zeharkako sinaduraren identitatea beste gailuak egiaztatzeko zure pasa-esaldia sartuz.",
"If you've forgotten your passphrase you can <button1>use your recovery key</button1> or <button2>set up new recovery options</button2>.": "Zure pasa-esaldia ahaztu baduzu <button1>berreskuratze gakoa erabili</button1> dezakezu edo <button2>berreskuratze aukera berriak ezarri</button2> ditzakezu.",
"Enter secret storage recovery key": "Sartu biltegi sekretuko berreskuratze-gakoa",
"Unable to access secret storage. Please verify that you entered the correct recovery key.": "Ezin izan da biltegi sekretura sartu. Egiaztatu berreskuratze-gako zuzena sartu duzula.",
"Access your secure message history and your cross-signing identity for verifying other devices by entering your recovery key.": "Atzitu zure mezu seguruen historiala eta zeharkako sinaduraren identitatea beste gailuak egiaztatzeko zure pasa-esaldia sartuz.",
"If you've forgotten your recovery key you can <button>set up new recovery options</button>.": "Zure berreskuratze-gakoa ahaztu baduzu <button>berreskuratze aukera berriak ezarri</button> ditzakezu.",
"<b>Warning</b>: You should only set up key backup from a trusted computer.": "<b>Abisua:</b>: Gakoen babes-kopia fidagarria den gailu batetik egin beharko zenuke beti.",
"If you've forgotten your recovery key you can <button>set up new recovery options</button>": "Zure berreskuratze-gakoa ahaztu baduzu <button>berreskuratze aukera berriak ezarri</button> ditzakezu",
"Notification settings": "Jakinarazpenen ezarpenak",
"User Status": "Erabiltzaile-egoera",
"<b>Warning</b>: You should only set up secret storage from a trusted computer.": "<b>Abisua</b>: Biltegi sekretura ordenagailu fidagarri batetik konektatu beharko zinateke beti.",
"We'll use secret storage to optionally store an encrypted copy of your cross-signing identity for verifying other devices and message keys on our server. Protect your access to encrypted messages with a passphrase to keep it secure.": "Biltegi sekretua erabiliko dugu, aukeran, beste gailuak egiaztatzeko zure zeharkako sinaduraren identitatearen eta mezuen gakoen kopia zifratu bat zure zerbitzarian gordetzeko. Babestu zure mezu zifratuetara sarbidea pasa.esaldi batekin seguru mantentzeko.",
"Set up with a recovery key": "Ezarri berreskuratze gakoarekin",
"As a safety net, you can use it to restore your access to encrypted messages if you forget your passphrase.": "Aukeran, berreskuratze pasa-esaldia ahazten baduzu, zure zifratutako mezuak berreskuratzeko erabili dezakezu.",
"As a safety net, you can use it to restore your access to encrypted messages.": "Badaezpada, zure zifratutako mezuen historiala berreskuratzeko erabili dezakezu.",
"Keep your recovery key somewhere very secure, like a password manager (or a safe).": "Gorde zure berreskuratze gakoa toki oso seguruan, esaterako pasahitz kudeatzaile batean (edo gordailu kutxan).",
"Your recovery key has been <b>copied to your clipboard</b>, paste it to:": "Zure berreskuratze gakoa <b>arbelera kopiatu da</b>, itsatsi hemen:",
"Your recovery key is in your <b>Downloads</b> folder.": "Zure berreskuratze gakoa zure <b>Deskargak</b> karpetan dago.",
"Your access to encrypted messages is now protected.": "Zure zifratutako mezuetara sarbidea babestuta dago.",
"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.": "Mezu seguruen berreskuratzea ezartzen ez bada, ezin izango duzu zure zifratutako mezuen historiala edo beste gailuak egiaztatzeko zeharkako sinadura berreskuratu saioa amaitzen baduzu edo beste gailu bat erabiltzen baduzu.",
"Set up secret storage": "Ezarri biltegi sekretua",
"Secure your encrypted messages with a passphrase": "Babestu zure zifratutako mezuak pasa-esaldi batekin",
"Storing secrets...": "Sekretuak gordetzen...",
"Unable to set up secret storage": "Ezin izan da biltegi sekretua ezarri"
}

View file

@ -122,7 +122,7 @@
"%(senderName)s kicked %(targetName)s.": "%(senderName)s a expulsé %(targetName)s.",
"Kick": "Expulser",
"Kicks user with given id": "Expulse l'utilisateur à partir de son identifiant",
"Labs": "Laboratoire",
"Labs": "Labo",
"Leave room": "Quitter le salon",
"%(targetName)s left the room.": "%(targetName)s a quitté le salon.",
"Local addresses for this room:": "Adresses locales pour ce salon :",
@ -1938,5 +1938,75 @@
"Notification settings": "Paramètres de notification",
"User Status": "Statut de lutilisateur",
"Reactions": "Réactions",
"<reactors/><reactedWith> reacted with %(content)s</reactedWith>": "<reactors/><reactedWith> ont réagi avec %(content)s</reactedWith>"
"<reactors/><reactedWith> reacted with %(content)s</reactedWith>": "<reactors/><reactedWith> ont réagi avec %(content)s</reactedWith>",
"<userName/> wants to chat": "<userName/> veut discuter",
"Start chatting": "Commencer à discuter",
"Send cross-signing keys to homeserver": "Envoyer les clés de signature croisée au serveur daccueil",
"Cross-signing public keys:": "Clés publiques de signature croisée :",
"on device": "sur lappareil",
"not found": "non trouvé",
"Cross-signing private keys:": "Clés privées de signature croisée :",
"%(senderName)s removed the rule banning users matching %(glob)s": "%(senderName)s a supprimé la règle qui bannit les utilisateurs correspondant à %(glob)s",
"%(senderName)s removed the rule banning rooms matching %(glob)s": "%(senderName)s a supprimé la règle qui bannit les salons correspondant à %(glob)s",
"%(senderName)s removed the rule banning servers matching %(glob)s": "%(senderName)s a supprimé la règle qui bannit les serveurs correspondant à %(glob)s",
"%(senderName)s removed a ban rule matching %(glob)s": "%(senderName)s a supprimé une règle de bannissement correspondant à %(glob)s",
"%(senderName)s updated an invalid ban rule": "%(senderName)s a mis à jour une règle de bannissement non valide",
"%(senderName)s updated the rule banning users matching %(glob)s for %(reason)s": "%(senderName)s a mis à jour la règle qui bannit les utilisateurs correspondant à %(glob)s pour %(reason)s",
"%(senderName)s updated the rule banning rooms matching %(glob)s for %(reason)s": "%(senderName)s a supprimé la règle qui bannit les salons correspondant à %(glob)s pour %(reason)s",
"%(senderName)s updated the rule banning servers matching %(glob)s for %(reason)s": "%(senderName)s a supprimé la règle qui bannit les serveurs correspondant à %(glob)s pour %(reason)s",
"%(senderName)s updated a ban rule matching %(glob)s for %(reason)s": "%(senderName)s a mis à jour la règle de bannissement correspondant à %(glob)s pour %(reason)s",
"%(senderName)s created a rule banning users matching %(glob)s for %(reason)s": "%(senderName)s a créé une règle qui bannit les utilisateurs correspondant à %(glob)s pour %(reason)s",
"%(senderName)s created a rule banning rooms matching %(glob)s for %(reason)s": "%(senderName)s a créé une règle qui bannit les salons correspondant à %(glob)s pour %(reason)s",
"%(senderName)s created a rule banning servers matching %(glob)s for %(reason)s": "%(senderName)s a créé une règle qui bannit les serveurs correspondant à %(glob)s pour %(reason)s",
"%(senderName)s created a ban rule matching %(glob)s for %(reason)s": "%(senderName)s a créé une règle de bannissement correspondant à %(glob)s pour %(reason)s",
"%(senderName)s changed a rule that was banning users matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s a changé une règle qui bannit les utilisateurs correspondant à %(oldGlob)s vers une règle correspondant à %(newGlob)s pour %(reason)s",
"%(senderName)s changed a rule that was banning rooms matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s a changé une règle qui bannit les salons correspondant à %(oldGlob)s vers une règle correspondant à %(newGlob)s pour %(reason)s",
"%(senderName)s changed a rule that was banning servers matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s a changé une règle qui bannit les serveurs correspondant à %(oldGlob)s vers une règle correspondant à %(newGlob)s pour %(reason)s",
"%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s a mis à jour une règle de bannissement correspondant à %(oldGlob)s vers une règle correspondant à %(newGlob)s pour %(reason)s",
"in secret storage": "dans le coffre secret",
"Secret storage public key:": "Clé publique du coffre secret :",
"in account data": "dans les données du compte",
"Bootstrap Secure Secret Storage": "Créer le coffre secret sécurisé",
"Cross-signing": "Signature croisée",
"Enter secret storage passphrase": "Saisir la phrase de passe du coffre secret",
"Unable to access secret storage. Please verify that you entered the correct passphrase.": "Impossible daccéder au coffre secret. Vérifiez que vous avez saisi la bonne phrase de passe.",
"<b>Warning</b>: You should only access secret storage from a trusted computer.": "<b>Attention</b> : Vous devriez uniquement accéder au coffre secret depuis un ordinateur de confiance.",
"Access your secure message history and your cross-signing identity for verifying other devices by entering your passphrase.": "Accédez à lhistorique de vos messages sécurisés et votre identité de signature croisée pour vérifier dautres appareils en saisissant votre phrase de passe.",
"If you've forgotten your passphrase you can <button1>use your recovery key</button1> or <button2>set up new recovery options</button2>.": "Si vous avez oublié votre phrase de passe, vous pouvez <button1>utiliser votre clé de récupération</button1> ou <button2>définir de nouvelles options de récupération</button2>.",
"Enter secret storage recovery key": "Saisir la clé de récupération du coffre secret",
"Unable to access secret storage. Please verify that you entered the correct recovery key.": "Impossible daccéder au coffre secret. Vérifiez que vous avez saisi la bonne clé de récupération.",
"Access your secure message history and your cross-signing identity for verifying other devices by entering your recovery key.": "Accédez à lhistorique de vos messages secrets et à votre identité de signature croisée pour vérifier dautres appareils en saisissant votre clé de récupération.",
"If you've forgotten your recovery key you can <button>set up new recovery options</button>.": "Si vous avez oublié votre clé de récupération vous pouvez <button>définir de nouvelles options de récupération</button>.",
"<b>Warning</b>: You should only set up key backup from a trusted computer.": "<b>Attention</b> : Vous devriez uniquement configurer une sauvegarde de clés depuis un ordinateur de confiance.",
"If you've forgotten your recovery key you can <button>set up new recovery options</button>": "Si vous avez oublié votre clé de récupération, vous pouvez <button>définir de nouvelles options de récupération</button>",
"<b>Warning</b>: You should only set up secret storage from a trusted computer.": "<b>Attention</b> : Vous devriez uniquement configurer le coffre secret depuis un ordinateur de confiance.",
"We'll use secret storage to optionally store an encrypted copy of your cross-signing identity for verifying other devices and message keys on our server. Protect your access to encrypted messages with a passphrase to keep it secure.": "Nous utiliserons le coffre secret pour conserver optionnellement une copie chiffrée de votre identité de signature croisée pour vérifier dautres appareils et des clés de messages sur notre serveur. Protégez votre accès aux messages chiffrés avec une phrase de passe pour la sécuriser.",
"Set up with a recovery key": "Configurer avec une clé de récupération",
"As a safety net, you can use it to restore your access to encrypted messages if you forget your passphrase.": "Par mesure de sécurité, vous pouvez lutiliser pour récupérer laccès aux messages chiffrés si vous oubliez votre phrase de passe.",
"As a safety net, you can use it to restore your access to encrypted messages.": "Par mesure de sécurité, vous pouvez lutiliser pour récupérer laccès à vos messages chiffrés.",
"Keep your recovery key somewhere very secure, like a password manager (or a safe).": "Conservez votre clé de récupération dans un endroit très sécurisé, comme un gestionnaire de mots de passe (ou un coffre-fort).",
"Your recovery key has been <b>copied to your clipboard</b>, paste it to:": "Votre clé de récupération a été <b>copiée dans votre presse-papiers</b>, collez-la pour :",
"Your recovery key is in your <b>Downloads</b> folder.": "Votre clé de récupération est dans votre dossier de <b>Téléchargements</b>.",
"Your access to encrypted messages is now protected.": "Votre accès aux messages chiffrés est maintenant protégé.",
"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.": "Si vous ne configurez pas le coffre secret, vous ne pourrez pas récupérer laccès à vos messages chiffrés ou à votre identité de signature croisée pour vérifier dautres appareils si vous vous déconnectez ou si vous utilisez un autre appareil.",
"Set up secret storage": "Configurer le coffre secret",
"Secure your encrypted messages with a passphrase": "Sécuriser vos messages chiffrés avec une phrase de passe",
"Storing secrets...": "Sauvegarde des secrets…",
"Unable to set up secret storage": "Impossible de configurer le coffre secret",
"Cross-signing and secret storage are enabled.": "La signature croisée et le coffre secret sont activés.",
"Your account has a cross-signing identity in secret storage, but it is not yet trusted by this device.": "Votre compte a une identité de signature croisée dans le coffre secret, mais cet appareil ne lui fait pas encore confiance.",
"Cross-signing and secret storage are not yet set up.": "La signature croisée et le coffre secret ne sont pas encore configurés.",
"Bootstrap cross-signing and secret storage": "Initialiser la signature croisée et le coffre secret",
"not stored": "non sauvegardé",
"Backup has a <validity>valid</validity> signature from this user": "La sauvegarde a une signature <validity>valide</validity> de cet utilisateur",
"Backup has a <validity>invalid</validity> signature from this user": "La sauvegarde a une signature <validity>non valide</validity> de cet utilisateur",
"Backup has a signature from <verify>unknown</verify> user with ID %(deviceId)s": "La sauvegarde a une signature de lutilisateur <verify>inconnu</verify> ayant pour identifiant %(deviceId)s",
"Backup has a signature from <verify>unknown</verify> device with ID %(deviceId)s": "La sauvegarde a une signature de lappareil <verify>inconnu</verify> ayant pour identifiant %(deviceId)s",
"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.": "La clé de sauvegarde est stockée dans le coffre secret, mais cette fonctionnalité nest pas activée sur cet appareil. Activez la signature croisée dans le Labo pour modifier létat de la sauvegarde de clé.",
"Backup key stored: ": "Clé de sauvegarde stockée : ",
"Start using Key Backup with Secure Secret Storage": "Commencer à utiliser la sauvegarde de clés avec le coffre secret sécurisé",
"Hide verified sessions": "Masquer les sessions vérifiées",
"%(count)s verified sessions|other": "%(count)s sessions vérifiées",
"%(count)s verified sessions|one": "1 session vérifiée",
"Close preview": "Fermer laperçu"
}

View file

@ -1939,5 +1939,75 @@
"Notification settings": "Értesítések beállítása",
"User Status": "Felhasználó állapota",
"Reactions": "Reakciók",
"<reactors/><reactedWith> reacted with %(content)s</reactedWith>": "<reactors/><reactedWith> ezzel reagáltak: %(content)s</reactedWith>"
"<reactors/><reactedWith> reacted with %(content)s</reactedWith>": "<reactors/><reactedWith> ezzel reagáltak: %(content)s</reactedWith>",
"<userName/> wants to chat": "<userName/> csevegni szeretne",
"Start chatting": "Beszélgetés elkezdése",
"Send cross-signing keys to homeserver": "Kereszt-aláírás kulcsok küldése a matrix szervernek",
"Cross-signing public keys:": "Kereszt-aláírás nyilvános kulcsok:",
"on device": "eszközön",
"not found": "nem található",
"Cross-signing private keys:": "Kereszt-aláírás privát kulcsok:",
"in secret storage": "biztonsági tárolóban",
"Secret storage public key:": "Biztonsági tároló nyilvános kulcs:",
"in account data": "fiók adatokban",
"Bootstrap Secure Secret Storage": "Biztonsági Titok Tároló megnyitása",
"Cross-signing": "Kereszt-aláírás",
"Enter secret storage passphrase": "Add meg a jelmondatot a biztonsági tárolóhoz",
"Unable to access secret storage. Please verify that you entered the correct passphrase.": "A biztonsági tárolóhoz nem lehet hozzáférni. Kérlek ellenőrizd, hogy jó jelmondatot adtál-e meg.",
"<b>Warning</b>: You should only access secret storage from a trusted computer.": "<b>Figyelem</b>: Csak biztonságos eszközről férj hozzá a biztonságos tárolóhoz.",
"If you've forgotten your passphrase you can <button1>use your recovery key</button1> or <button2>set up new recovery options</button2>.": "Ha elfelejtetted a jelmondatodat <button1>használd a visszaállítási kulcsod</button1> vagy <button2>állíts be új visszaállítási lehetőséget</button2>.",
"Enter secret storage recovery key": "Add meg a visszaállítási kulcsot a biztonsági tárolóhoz",
"Unable to access secret storage. Please verify that you entered the correct recovery key.": "A biztonsági tárolóhoz nem lehet hozzáférni. Kérlek ellenőrizd, hogy jó visszaállítási kulcsot adtál-e meg.",
"If you've forgotten your recovery key you can <button>set up new recovery options</button>.": "Ha elfelejtetted a visszaállítási kulcsot <button>állíts be új visszaállítási lehetőséget</button>.",
"<b>Warning</b>: You should only set up key backup from a trusted computer.": "<b>Figyelmeztetés</b>: Csak biztonságos számítógépről állíts be kulcs mentést.",
"If you've forgotten your recovery key you can <button>set up new recovery options</button>": "Ha elfelejtetted a visszaállítási kulcsot <button>állíts be új visszaállítási lehetőséget</button>",
"<b>Warning</b>: You should only set up secret storage from a trusted computer.": "<b>Figyelem</b>: Csak biztonságos eszközről állíts be biztonságos tárolót.",
"Set up with a recovery key": "Beállítás visszaállítási kulccsal",
"As a safety net, you can use it to restore your access to encrypted messages if you forget your passphrase.": "Mint egy biztonsági háló, ha elfelejted a jelmondatot akkor felhasználhatod ahhoz, hogy hozzáférj a titkosított üzeneteidhez.",
"As a safety net, you can use it to restore your access to encrypted messages.": "Használhatod egy biztonsági hálóként a titkosított üzenetekhez való hozzáférés visszaállításához.",
"Keep your recovery key somewhere very secure, like a password manager (or a safe).": "A Visszaállítási Kulcsot tartsd biztonságos helyen, mint pl. egy jelszókezelő (vagy széf).",
"Your recovery key has been <b>copied to your clipboard</b>, paste it to:": "A visszaállítási kulcsod <b>a vágólapra lett másolva</b>, illeszd be ide:",
"Your recovery key is in your <b>Downloads</b> folder.": "A visszaállítási kulcsod a <b>Letöltések</b> mappában van.",
"Your access to encrypted messages is now protected.": "A titkosított üzenetekhez való hozzáférésed védve van.",
"Set up secret storage": "Biztonságos tároló beállítása",
"Secure your encrypted messages with a passphrase": "Biztosítsd a titkosított üzeneteidet jelmondattal",
"Storing secrets...": "Titkok tárolása...",
"Unable to set up secret storage": "A biztonsági tárolót nem sikerült beállítani",
"%(senderName)s removed the rule banning users matching %(glob)s": "%(senderName)s törölte azt a szabályt amivel ilyen felhasználók voltak kitiltva: %(glob)s",
"%(senderName)s removed the rule banning rooms matching %(glob)s": "%(senderName)s törölte azt a szabályt amivel ilyen szobák voltak kitiltva: %(glob)s",
"%(senderName)s removed the rule banning servers matching %(glob)s": "%(senderName)s törölte azt a szabályt amivel ilyen szerverek voltak kitiltva: %(glob)s",
"%(senderName)s removed a ban rule matching %(glob)s": "%(senderName)s törölte ezt a kitiltó szabályt: %(glob)s",
"%(senderName)s updated an invalid ban rule": "%(senderName)s frissített egy érvénytelen kitiltó szabályt",
"%(senderName)s updated the rule banning users matching %(glob)s for %(reason)s": "%(senderName)s frissítette azt a szabályt amivel ilyen felhasználók voltak kitiltva: %(glob)s ezért: %(reason)s",
"%(senderName)s updated the rule banning rooms matching %(glob)s for %(reason)s": "%(senderName)s frissítette azt a szabályt amivel ilyen szobák voltak kitiltva: %(glob)s ezért: %(reason)s",
"%(senderName)s updated the rule banning servers matching %(glob)s for %(reason)s": "%(senderName)s frissítette azt a szabályt amivel ilyen szerverek voltak kitiltva: %(glob)s ezért: %(reason)s",
"%(senderName)s updated a ban rule matching %(glob)s for %(reason)s": "%(senderName)s frissítette ezt a kitiltó szabályt: %(glob)s ezért: %(reason)s",
"%(senderName)s created a rule banning users matching %(glob)s for %(reason)s": "%(senderName)s hozzáadta azt a szabályt amivel ilyen felhasználók lesznek kitiltva: %(glob)s ezért: %(reason)s",
"%(senderName)s created a rule banning rooms matching %(glob)s for %(reason)s": "%(senderName)s hozzáadta azt a szabályt amivel ilyen szobák lesznek kitiltva: %(glob)s ezért: %(reason)s",
"%(senderName)s created a rule banning servers matching %(glob)s for %(reason)s": "%(senderName)s hozzáadta azt a szabályt amivel ilyen szerverek lesznek kitiltva: %(glob)s ezért: %(reason)s",
"%(senderName)s created a ban rule matching %(glob)s for %(reason)s": "%(senderName)s hozzáadta ezt a kitiltó szabályt: %(glob)s ezért: %(reason)s",
"%(senderName)s changed a rule that was banning users matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s megváltoztatta a szabályt amivel felhasználók voltak kitiltva erről: %(oldGlob)s erre: %(newGlob)s ezért: %(reason)s",
"%(senderName)s changed a rule that was banning rooms matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s megváltoztatta a szabályt amivel szobák voltak kitiltva erről: %(oldGlob)s erre: %(newGlob)s ezért: %(reason)s",
"%(senderName)s changed a rule that was banning servers matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s megváltoztatta a szabályt amivel szerverek voltak kitiltva erről: %(oldGlob)s erre: %(newGlob)s ezért: %(reason)s",
"%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s megváltoztatta a kitiltó szabályt erről: %(oldGlob)s erre: %(newGlob)s ezért: %(reason)s",
"Cross-signing and secret storage are enabled.": "Kereszt-aláírás és a biztonsági tároló engedélyezve van.",
"Your account has a cross-signing identity in secret storage, but it is not yet trusted by this device.": "A fiókod a biztonsági tárolóban tartalmaz egy személyazonosságot a kereszt-aláíráshoz de egyenlőre nincs megbízhatónak jelölve ezen az eszközön.",
"Cross-signing and secret storage are not yet set up.": "Kereszt-aláírás és a biztonsági tároló egyenlőre nincs beállítva.",
"Bootstrap cross-signing and secret storage": "Kereszt-aláírás és biztonsági tároló beállítása",
"not stored": "nincs mentve",
"Backup has a <validity>valid</validity> signature from this user": "A mentés <validity>érvényes</validity> aláírást tartalmaz a felhasználótól",
"Backup has a <validity>invalid</validity> signature from this user": "A mentés <validity>érvénytelen</validity> aláírást tartalmaz a felhasználótól",
"Backup has a signature from <verify>unknown</verify> user with ID %(deviceId)s": "A mentésnek <verify>ismeretlen</verify> felhasználótól származó aláírása van ezzel az azonosítóval: %(deviceId)s",
"Backup has a signature from <verify>unknown</verify> device with ID %(deviceId)s": "A mentésnek <verify>ismeretlen</verify> eszköztől származó aláírása van ezzel az azonosítóval: %(deviceId)s",
"Backup key stored: ": "Visszaállítási kulcs tárolva: ",
"Start using Key Backup with Secure Secret Storage": "Kulcs Mentés és Biztonsági Titok Tároló használatának megkezdése",
"Hide verified sessions": "Ellenőrzött munkamenetek eltakarása",
"%(count)s verified sessions|other": "%(count)s ellenőrzött munkamenet",
"%(count)s verified sessions|one": "1 ellenőrzött munkamenet",
"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.": "Visszaállítási kulcs a biztonsági tárolóban van elmentve, de ezen az eszközön ez a lehetőség nincs engedélyezve. Engedélyezd a kulcs mentés állapotának módosításához a kereszt-aláírást a Laborban.",
"Close preview": "Előnézet bezárása",
"Access your secure message history and your cross-signing identity for verifying other devices by entering your passphrase.": "A jelmondat megadásával hozzáférhetsz a titkosított üzeneteidhez és a kereszt-aláíráshoz tartozó azonosítódhoz amivel más eszközöket ellenőrizhetsz.",
"Access your secure message history and your cross-signing identity for verifying other devices by entering your recovery key.": "A visszaállítási kulcs megadásával hozzáférhetsz a titkosított üzeneteidhez és a kereszt-aláíráshoz tartozó azonosítódhoz amivel más eszközöket ellenőrizhetsz.",
"We'll use secret storage to optionally store an encrypted copy of your cross-signing identity for verifying other devices and message keys on our server. Protect your access to encrypted messages with a passphrase to keep it secure.": "Biztonsági tárolót fogunk használni, hogy tárolhassuk a kereszt-aláíráshoz tartozó azonosítót titkosított formában, amivel más eszközöket és üzenet kulcsokat lehet ellenőrizni. Védd a titkosított üzenetekhez való hozzáférést jelmondattal és azt tartsd titokban.",
"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.": "A biztonsági tároló beállítása nélkül ha kijelentkezel és egy másik eszközön lépsz be nem fogsz hozzáférni a titkosított üzeneteidhez és a kereszt-aláíráshoz tartozó azonosítódhoz amivel más eszközöket ellenőrizhetsz."
}

View file

@ -858,7 +858,7 @@
"All messages": "Tutti i messaggi",
"Call invitation": "Invito ad una chiamata",
"Downloading update...": "Scaricamento aggiornamento...",
"State Key": "Chiave dello Stato",
"State Key": "Chiave dello stato",
"Failed to send custom event.": "Impossibile inviare evento personalizzato.",
"What's new?": "Cosa c'è di nuovo?",
"Notify me for anything else": "Notificami per qualsiasi altra cosa",
@ -1923,5 +1923,88 @@
"%(senderName)s placed a video call.": "%(senderName)s ha effettuato una videochiamata.",
"%(senderName)s placed a video call. (not supported by this browser)": "%(senderName)s ha effettuato una videochiamata. (non supportata da questo browser)",
"Clear notifications": "Cancella le notifiche",
"Customise your experience with experimental labs features. <a>Learn more</a>.": "Personalizza la tua esperienza con funzionalità sperimentali. <a>Maggiori informazioni</a>."
"Customise your experience with experimental labs features. <a>Learn more</a>.": "Personalizza la tua esperienza con funzionalità sperimentali. <a>Maggiori informazioni</a>.",
"Error upgrading room": "Errore di aggiornamento stanza",
"Double check that your server supports the room version chosen and try again.": "Controlla che il tuo server supporti la versione di stanza scelta e riprova.",
"This message cannot be decrypted": "Questo messaggio non può essere decifrato",
"Unencrypted": "Non criptato",
"Reactions": "Reazioni",
"<reactors/><reactedWith> reacted with %(content)s</reactedWith>": "<reactors/><reactedWith> ha reagito con %(content)s</reactedWith>",
"Automatically invite users": "Invita utenti automaticamente",
"Upgrade private room": "Aggiorna stanza privata",
"Upgrade public room": "Aggiorna stanza pubblica",
"Upgrading a room is an advanced action and is usually recommended when a room is unstable due to bugs, missing features or security vulnerabilities.": "Aggiornare una stanza è un'azione avanzata ed è consigliabile quando una stanza non è stabile a causa di errori, funzioni mancanti o vulnerabilità di sicurezza.",
"This usually only affects how the room is processed on the server. If you're having problems with your Riot, please <a>report a bug</a>.": "Solitamente ciò influisce solo come la stanza viene elaborata sul server. Se stai riscontrando problemi con il tuo Riot, <a>segnala un errore</a>.",
"You'll upgrade this room from <oldVersion /> to <newVersion />.": "Aggiornerai questa stanza dalla <oldVersion /> alla <newVersion />.",
"Upgrade": "Aggiorna",
"Notification settings": "Impostazioni di notifica",
"User Status": "Stato utente",
"%(senderName)s removed the rule banning users matching %(glob)s": "%(senderName)s ha rimosso la regola che bandisce utenti corrispondenti a %(glob)s",
"%(senderName)s removed the rule banning rooms matching %(glob)s": "%(senderName)s ha rimosso la regola che bandisce stanze corrispondenti a %(glob)s",
"%(senderName)s removed the rule banning servers matching %(glob)s": "%(senderName)s ha rimosso la regola che bandisce server corrispondenti a %(glob)s",
"%(senderName)s removed a ban rule matching %(glob)s": "%(senderName)s ha rimosso una regola di ban corrispondente a %(glob)s",
"%(senderName)s updated an invalid ban rule": "%(senderName)s ha aggiornato una regola di ban non valida",
"%(senderName)s updated the rule banning users matching %(glob)s for %(reason)s": "%(senderName)s ha aggiornato la regola che bandisce utenti corrispondenti a %(glob)s perchè %(reason)s",
"%(senderName)s updated the rule banning rooms matching %(glob)s for %(reason)s": "%(senderName)s ha aggiornato la regola che bandisce stanze corrispondenti a %(glob)s perchè %(reason)s",
"%(senderName)s updated the rule banning servers matching %(glob)s for %(reason)s": "%(senderName)s ha aggiornato la regola che bandisce server corrispondenti a %(glob)s perchè %(reason)s",
"%(senderName)s updated a ban rule matching %(glob)s for %(reason)s": "%(senderName)s ha aggiornato una regola di ban corrispondente a %(glob)s perchè %(reason)s",
"%(senderName)s created a rule banning users matching %(glob)s for %(reason)s": "%(senderName)s ha creato una regola che bandisce utenti corrispondenti a %(glob)s perchè %(reason)s",
"%(senderName)s created a rule banning rooms matching %(glob)s for %(reason)s": "%(senderName)s ha creato una regola che bandisce stanze corrispondenti a %(glob)s perchè %(reason)s",
"%(senderName)s created a rule banning servers matching %(glob)s for %(reason)s": "%(senderName)s ha creato una regola che bandisce server corrispondenti a %(glob)s perchè %(reason)s",
"%(senderName)s created a ban rule matching %(glob)s for %(reason)s": "%(senderName)s ha creato una regola di ban corrispondente a %(glob)s perchè %(reason)s",
"%(senderName)s changed a rule that was banning users matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s ha modificato una regola che bandiva utenti corrispondenti a %(oldGlob)s per corrispondere a %(newGlob)s perchè %(reason)s",
"%(senderName)s changed a rule that was banning rooms matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s ha modificato una regola che bandiva stanze corrispondenti a %(oldGlob)s per corrispondere a %(newGlob)s perchè %(reason)s",
"%(senderName)s changed a rule that was banning servers matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s ha modificato una regola che bandiva server corrispondenti a %(oldGlob)s per corrispondere a %(newGlob)s perchè %(reason)s",
"%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s ha modificato una regola di ban che corrispondeva a %(oldGlob)s per corrispondere a %(newGlob)s perchè %(reason)s",
"Send cross-signing keys to homeserver": "Invia chiavi di firma incrociata all'homeserver",
"Cross-signing public keys:": "Chiavi pubbliche di firma incrociata:",
"on device": "sul dispositivo",
"not found": "non trovato",
"Cross-signing private keys:": "Chiavi private di firma incrociata:",
"in secret storage": "in un archivio segreto",
"Secret storage public key:": "Chiave pubblica dell'archivio segreto:",
"in account data": "nei dati dell'account",
"Cross-signing": "Firma incrociata",
"<userName/> wants to chat": "<userName/> vuole chattare",
"Start chatting": "Inizia a chattare",
"Enter secret storage passphrase": "Inserisci la password dell'archivio segreto",
"Unable to access secret storage. Please verify that you entered the correct passphrase.": "Impossibile accedere all'archivio segreto. Controlla di avere inserito la password corretta.",
"<b>Warning</b>: You should only access secret storage from a trusted computer.": "<b>Attenzione</b>: dovresti accedere all'archivio segreto solo da un computer fidato.",
"Cross-signing and secret storage are enabled.": "La firma incrociata e l'archivio segreto sono attivi.",
"Your account has a cross-signing identity in secret storage, but it is not yet trusted by this device.": "Il tuo account ha un'identità a firma incrociata in archivio segreto, ma non è ancora fidata da questo dispositivo.",
"Cross-signing and secret storage are not yet set up.": "La firma incrociata e l'archivio segreto non sono ancora impostati.",
"not stored": "non salvato",
"Backup has a <validity>valid</validity> signature from this user": "Il backup ha una firma <validity>valida</validity> da questo utente",
"Backup has a <validity>invalid</validity> signature from this user": "Il backup ha una firma <validity>non valida</validity> da questo utente",
"Backup has a signature from <verify>unknown</verify> user with ID %(deviceId)s": "Il backup ha una firma dall'utente <verify>sconosciuto</verify> con ID %(deviceId)s",
"Backup has a signature from <verify>unknown</verify> device with ID %(deviceId)s": "Il backup ha una firma dal dispositivo <verify>sconosciuto</verify> con ID %(deviceId)s",
"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.": "Backup chiavi presente nell'archivio segreto, ma questa funzione non è attiva sul dispositivo. Attiva la firma incrociata in Labs per modificare lo stato del backup.",
"Backup key stored: ": "Backup chiavi salvato: ",
"Start using Key Backup with Secure Secret Storage": "Inizia ad usare il Backup Chiavi con l'Archivio Segreto",
"Hide verified sessions": "Nascondi sessioni verificate",
"%(count)s verified sessions|other": "%(count)s sessioni verificate",
"%(count)s verified sessions|one": "1 sessione verificata",
"Access your secure message history and your cross-signing identity for verifying other devices by entering your passphrase.": "Accedi alla cronologia sicura dei tuoi messaggi e all'identità a firma incrociata per verificare altri dispositivi inserendo la tua password.",
"If you've forgotten your passphrase you can <button1>use your recovery key</button1> or <button2>set up new recovery options</button2>.": "Se hai dimenticato la password puoi <button1>usare la tua chiave di recupero</button1> o <button2>impostare nuove opzioni di recupero</button2>.",
"Enter secret storage recovery key": "Inserisci la chiave di recupero dell'archivio segreto",
"Unable to access secret storage. Please verify that you entered the correct recovery key.": "Impossibile accedere all'archivio segreto. Controlla di avere inserito la chiave di recupero corretta.",
"Access your secure message history and your cross-signing identity for verifying other devices by entering your recovery key.": "Accedi alla cronologia sicura dei tuoi messaggi e all'identità a firma incrociata per verificare altri dispositivi inserendo la tua chiave di recupero.",
"If you've forgotten your recovery key you can <button>set up new recovery options</button>.": "Se hai dimenticato la tua chiave di recupero puoi <button>impostare nuove opzioni di recupero</button>.",
"<b>Warning</b>: You should only set up key backup from a trusted computer.": "<b>Attenzione</b>: dovresti impostare il backup chiavi solo da un computer fidato.",
"If you've forgotten your recovery key you can <button>set up new recovery options</button>": "Se hai dimenticato la tua chiave di recupero puoi <button>impostare nuove opzioni di recupero</button>",
"<b>Warning</b>: You should only set up secret storage from a trusted computer.": "<b>Attenzione</b>: dovresti impostare l'archivio segreto solo da un computer fidato.",
"We'll use secret storage to optionally store an encrypted copy of your cross-signing identity for verifying other devices and message keys on our server. Protect your access to encrypted messages with a passphrase to keep it secure.": "Utilizzeremo l'archivio segreto per memorizzare facoltativamente una copia criptata della tua identità a firma incrociata per verificare altri dispositivi e chiavi dei messaggi sul nostro server. Proteggi il tuo accesso ai messaggi cifrati con una password per tenerlo al sicuro.",
"Set up with a recovery key": "Imposta con una chiave di recupero",
"As a safety net, you can use it to restore your access to encrypted messages if you forget your passphrase.": "Come àncora di salvezza, puoi usarla per recuperare l'accesso ai tuoi messaggi cifrati se dimentichi la password.",
"As a safety net, you can use it to restore your access to encrypted messages.": "Come àncora di salvezza, puoi usarla per recuperare l'accesso ai tuoi messaggi cifrati.",
"Keep your recovery key somewhere very secure, like a password manager (or a safe).": "Tieni la chiave di recupero in un posto molto sicuro, come un gestore di password (o una cassaforte).",
"Your recovery key has been <b>copied to your clipboard</b>, paste it to:": "La tua chiave di recupero è stata <b>copiata negli appunti</b>, incollala in:",
"Your recovery key is in your <b>Downloads</b> folder.": "La chiave di recupero è nella tua cartella <b>Scaricati</b>.",
"Your access to encrypted messages is now protected.": "L'accesso ai tuoi messaggi cifrati è ora protetto.",
"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.": "Senza l'impostazione dell'archivio segreto, non sarà possibile recuperare l'accesso ai messaggi cifrati o l'identità a firma incrociata per verificare altri dispositivi se ti disconnetti o utilizzi un altro dispositivo.",
"Set up secret storage": "Imposta l'archivio segreto",
"Secure your encrypted messages with a passphrase": "Proteggi i tuoi messaggi cifrati con una password",
"Storing secrets...": "Memorizzo i segreti...",
"Unable to set up secret storage": "Impossibile impostare un archivio segreto",
"Close preview": "Chiudi anteprima"
}

1
src/i18n/strings/mn.json Normal file
View file

@ -0,0 +1 @@
{}

View file

@ -865,7 +865,7 @@
"%(oneUser)shad their invitation withdrawn %(count)s times|other": "Për %(oneUser)s përdorues ftesa u tërhoq mbrapsht %(count)s herë",
"%(oneUser)shad their invitation withdrawn %(count)s times|one": "U tërhoq mbrapsht ftesa për %(oneUser)s",
"Community IDs cannot be empty.": "ID-të e bashkësisë smund të jenë të zbrazëta.",
"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. <b>This action is irreversible.</b>": "Kjo do ta bëjë llogarinë tuaj përgjithmonë të papërdorshme. Sdo të jeni në gjendje të hyni në llogarinë tuaj, dhe askush sdo të jetë në gjendje të riregjistrojë të njëjtën ID përdoruesi. Kjo do të shkaktojë daljen e llogarisë tuaj nga krejt dhomat ku merrni pjesë, dhe do të heqë hollësitë e llogarisë tuaj nga shërbyesi juaj i identiteteve. <b>Ky veprim është i paprapakthyeshëm</b>.",
"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. <b>This action is irreversible.</b>": "Kjo do ta bëjë llogarinë tuaj përgjithmonë të papërdorshme. Sdo të jeni në gjendje të hyni në llogarinë tuaj, dhe askush sdo të jetë në gjendje të riregjistrojë të njëjtën ID përdoruesi. Kjo do të shkaktojë daljen e llogarisë tuaj nga krejt dhomat ku merrni pjesë, dhe do të heqë hollësitë e llogarisë tuaj nga shërbyesi juaj i identiteteve. <b>Ky veprim është i paprapakthyeshëm.</b>",
"Deactivating your account <b>does not by default cause us to forget messages you have sent.</b> If you would like us to forget your messages, please tick the box below.": "Çaktivizimi i llogarisë tuaj <b>nuk shkakton, si parazgjedhje, harrimin nga ne të mesazheve që keni dërguar</b>. Nëse do të donit të harrojmë mesazhet tuaja, ju lutemi, i vini shenjë kutizës më poshtë.",
"Upgrade this room to version %(version)s": "Përmirësojeni këtë dhomë me versionin %(version)s",
"Share Room": "Ndani Dhomë Me të Tjerë",
@ -1037,7 +1037,7 @@
"That doesn't match.": "Spërputhen.",
"Go back to set it again.": "Shkoni mbrapsht që ta ricaktoni.",
"Repeat your passphrase...": "Përsëritni frazëkalimin tuaj…",
"As a safety net, you can use it to restore your encrypted message history if you forget your Recovery Passphrase.": "Si rrjet i parrezikuar, mund ta përdoreni për të rikthyer historikun e mesazheve tuaj të fshehtëzuar, nëse harroni Frazëkalimin e Rimarrjeve.",
"As a safety net, you can use it to restore your encrypted message history if you forget your Recovery Passphrase.": "Si masë sigurie, mund ta përdoreni për të rikthyer historikun e mesazheve tuaj të fshehtëzuar, nëse harroni Frazëkalimin e Rimarrjeve.",
"Your Recovery Key": "Kyçi Juaj i Rimarrjeve",
"Copy to clipboard": "Kopjoje në të papastër",
"Download": "Shkarkoje",
@ -1046,8 +1046,8 @@
"<b>Print it</b> and store it somewhere safe": "<b>Shtypeni</b> dhe ruajeni diku pa rrezik",
"<b>Save it</b> on a USB key or backup drive": "<b>Ruajeni</b> në një diskth USB ose disk kopjeruajtjesh",
"<b>Copy it</b> to your personal cloud storage": "<b>Kopjojeni</b> te depoja juaj personale në re",
"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.": "Pa rregulluar Rikthim Mesazhesh të Sigurt, sdo të jeni në gjendje të riktheni historikun e mesazheve tuaj të fshehtëzuar, nëse bëni daljen ose përdorni një pajisje tjetër.",
"Set up Secure Message Recovery": "Rregulloni Rikthim Mesazhesh të Sigurt",
"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.": "Pa ujdisur Rimarrje të Sigurt Mesazhesh, sdo të jeni në gjendje të riktheni historikun e mesazheve tuaj të fshehtëzuar, nëse bëni daljen ose përdorni një pajisje tjetër.",
"Set up Secure Message Recovery": "Rregulloni Rimarrje të Sigurt Mesazhesh",
"Keep it safe": "Mbajeni të parrezikuar",
"Create Key Backup": "Krijo Kopjeruajtje Kyçesh",
"Unable to create key backup": "Sarrihet të krijojhet kopjeruajtje kyçesh",
@ -1059,12 +1059,12 @@
"Failed to decrypt %(failedCount)s sessions!": "Su arrit të shfshehtëzohet sesioni %(failedCount)s!",
"Restored %(sessionCount)s session keys": "U rikthyen kyçet e sesionit %(sessionCount)s",
"Enter Recovery Passphrase": "Jepni Frazëkalim Rimarrjeje",
"Access your secure message history and set up secure messaging by entering your recovery passphrase.": "Hyni te historiku i mesazheve tuaj të siguruar dhe rregulloni shkëmbim mesazhesh të sigurt duke dhënë frazëkalimin tuaj të rikthimeve.",
"If you've forgotten your recovery passphrase you can <button1>use your recovery key</button1> or <button2>set up new recovery options</button2>": "Nëse keni harruar frazëkalimin tuaj të rikthimeve, mund të <button1>përdorni kyçin tuaj të rikthimeve</button1> ose <button2>rregulloni mundësi të reja rikthimesh</button2>",
"Access your secure message history and set up secure messaging by entering your recovery passphrase.": "Hyni te historiku i mesazheve tuaj të siguruar dhe rregulloni shkëmbim mesazhesh të sigurt duke dhënë frazëkalimin tuaj të rimarrjeve.",
"If you've forgotten your recovery passphrase you can <button1>use your recovery key</button1> or <button2>set up new recovery options</button2>": "Nëse keni harruar frazëkalimin tuaj të rimarrjeve, mund të <button1>përdorni kyçin tuaj të rimarrjeve</button1> ose <button2>rregulloni mundësi të reja rimarrjesh</button2>",
"Enter Recovery Key": "Jepni Kyç Rimarrjeje",
"This looks like a valid recovery key!": "Ky duket si kyç i vlefshëm rikthimesh!",
"Not a valid recovery key": "Kyç rikthimesh jo i vlefshëm",
"Access your secure message history and set up secure messaging by entering your recovery key.": "Hyni te historiku i mesazheve tuaj të siguruar dhe rregulloni shkëmbim mesazhesh të sigurt duke dhënë kyçin tuaj të rikthimeve.",
"This looks like a valid recovery key!": "Ky duket si kyç i vlefshëm rimarrjesh!",
"Not a valid recovery key": "Kyç rimarrjesh jo i vlefshëm",
"Access your secure message history and set up secure messaging by entering your recovery key.": "Hyni te historiku i mesazheve tuaj të siguruar dhe rregulloni shkëmbim mesazhesh të sigurt duke dhënë kyçin tuaj të rimarrjeve.",
"If you've forgotten your recovery passphrase you can <button>set up new recovery options</button>": "Nëse keni harruar frazëkalimin tuaj të rikthimeve, mund të <button>rregulloni mundësi të reja rikthimesh</button>",
"Sign in with single sign-on": "Bëni hyrjen me hyrje njëshe",
"Failed to perform homeserver discovery": "Su arrit të kryhej zbulim shërbyesi Home",
@ -1096,16 +1096,16 @@
"Common names and surnames are easy to guess": "Emra dhe mbiemra të rëndomtë janë të kollajtë për tu hamendësuar",
"Great! This passphrase looks strong enough.": "Bukur! Ky frazëkalim duket goxha i fuqishëm.",
"Failed to load group members": "S'u arrit të ngarkoheshin anëtarë grupi",
"As a safety net, you can use it to restore your encrypted message history.": "Si një rrjet sigurie, mund ta përdorni për të rikthyer historikun e mesazheve tuaj të fshehtëzuar.",
"As a safety net, you can use it to restore your encrypted message history.": "Si masë sigurie, mund ta përdorni për të rikthyer historikun e mesazheve tuaj të fshehtëzuar.",
"Failed to invite users to the room:": "Su arrit të ftohen përdorues te dhoma:",
"You do not have permission to invite people to this room.": "Skeni leje të ftoni njerëz në këtë dhomë.",
"User %(user_id)s does not exist": "Përdoruesi %(user_id)s nuk ekziston",
"Unknown server error": "Gabim i panjohur shërbyesi",
"There was an error joining the room": "Pati një gabim ardhjeje në dhomë",
"Show a reminder to enable Secure Message Recovery in encrypted rooms": "Shfaq një kujtues për aktivizim Rikthimi Mesazhesh të Sigurt në dhoma të fshehtëzuara",
"Show a reminder to enable Secure Message Recovery in encrypted rooms": "Shfaq një kujtues për aktivizim Rimarrjeje Mesazhesh të Sigurt në dhoma të fshehtëzuara",
"Don't ask again": "Mos pyet sërish",
"Set up": "Rregulloje",
"Without setting up Secure Message Recovery, you'll lose your secure message history when you log out.": "Po srregulluat Rikthim Mesazhesh të Sigurt, do të humbni historikun e mesazheve të parrezik, kur të dilni nga llogaria.",
"Without setting up Secure Message Recovery, you'll lose your secure message history when you log out.": "Pa ujdisur Rimarrje të Sigurt Mesazhesh, do të humbni historikun e mesazheve tuaj të fshehtëzuar, nëse bëni daljen nga llogaria.",
"If you don't want to set this up now, you can later in Settings.": "Nëse sdoni ta rregulloni tani këtë, mund ta bëni më vonë që nga Rregullimet.",
"Messages containing @room": "Mesazhe që përmbajnë @room",
"Encrypted messages in one-to-one chats": "Mesazhe të fshehtëzuar në fjalosje tek-për-tek",
@ -1115,7 +1115,7 @@
"Invalid identity server discovery response": "Përgjigje e pavlefshme zbulimi identiteti shërbyesi",
"Backup has a <validity>valid</validity> signature from <verify>verified</verify> device <device></device>": "Kopjeruajtja ka një nënshkrim <validity>të vlefshëm</validity> prej pajisjes së <verify>verifikuar</verify> <device></device>",
"New Recovery Method": "Metodë e Re Rimarrjesh",
"If you didn't set the new recovery method, an attacker may be trying to access your account. Change your account password and set a new recovery method immediately in Settings.": "Nëse metodën e re të rikthimeve se keni caktuar ju, dikush mund të jetë duke u rrekur të hyjë në llogarinë tuaj. Ndryshoni menjëherë fjalëkalimin e llogarisë tuaj, te Rregullimet, dhe caktoni një metodë të re rikthimesh.",
"If you didn't set the new recovery method, an attacker may be trying to access your account. Change your account password and set a new recovery method immediately in Settings.": "Nëse metodën e re të rimarrjeve se keni caktuar ju, dikush mund të jetë duke u rrekur të hyjë në llogarinë tuaj. Ndryshoni menjëherë fjalëkalimin e llogarisë tuaj, te Rregullimet, dhe caktoni një metodë të re rimarrjesh.",
"Set up Secure Messages": "Rregulloni Mesazhi të Sigurt",
"Go to Settings": "Kalo te Rregullimet",
"Straight rows of keys are easy to guess": "Rreshta uniformë tastesh janë lehtësisht të hamendësueshëm",
@ -1230,7 +1230,7 @@
"To help avoid duplicate issues, please <existingIssuesLink>view existing issues</existingIssuesLink> first (and add a +1) or <newIssueLink>create a new issue</newIssueLink> if you can't find it.": "Për të na ndihmuar të shmangim çështje të përsëdytura, ju lutemi, së pari <existingIssuesLink>shihni çështjet ekzistuese</existingIssuesLink> (dhe shtoni një +1) ose <newIssueLink>krijoni një çështje të re</newIssueLink>, nëse nuk gjeni gjë.",
"Report bugs & give feedback": "Njoftoni të meta & jepni përshtypjet",
"Go back": "Kthehu mbrapsht",
"Backup could not be decrypted with this key: please verify that you entered the correct recovery key.": "Nuk u shfshehtëzua dot kopjeruajtja me këtë kyç: ju lutemi, verifikoni që dhatë kyçin e duhur të rikthimeve.",
"Backup could not be decrypted with this key: please verify that you entered the correct recovery key.": "Nuk u shfshehtëzua dot kopjeruajtja me këtë kyç: ju lutemi, verifikoni që dhatë kyçin e duhur të rimarrjeve.",
"Update status": "Përditëso gendjen",
"Set status": "Caktojini gjendjen",
"You can use the custom server options to sign into other Matrix servers by specifying a different homeserver URL. This allows you to use this app with an existing Matrix account on a different homeserver.": "Mund të përdorni mundësitë mbi shërbyes vetjak, për të bërë hyrjen në shërbyes të tjerë Matrix, duke dhënë URL-në e një tjetër shërbyesi Home. Kjo ju lejon ta përdorni këtë aplikacion në një tjetër shërbyes Home, me një llogari ekzistuese Matrix.",
@ -1260,12 +1260,12 @@
"Create account": "Krijoni llogari",
"Keep going...": "Vazhdoni kështu…",
"Starting backup...": "Po fillohet kopjeruajtje…",
"A new recovery passphrase and key for Secure Messages have been detected.": "Janë pikasur një frazëkalim dhe kyç i ri rikthimesh për Mesazhe të Sigurt.",
"This device is encrypting history using the new recovery method.": "Kjo pajisje e fshehtëzon historikun duke përdorur metodë të re rikthimesh.",
"A new recovery passphrase and key for Secure Messages have been detected.": "Janë pikasur një frazëkalim dhe kyç i ri rimarrjesh për Mesazhe të Sigurt.",
"This device is encrypting history using the new recovery method.": "Kjo pajisje e fshehtëzon historikun duke përdorur metodë të re rimarrjesh.",
"Recovery Method Removed": "U hoq Metodë Rimarrje",
"This device has detected that your recovery passphrase and key for Secure Messages have been removed.": "Kjo pajisje ka pikasur se frazëkalimi dhe kyçi juaj i rikthimeve për Mesazhe të Sigurt janë hequr.",
"If you did this accidentally, you can setup Secure Messages on this device which will re-encrypt this device's message history with a new recovery method.": "Nëse këtë e keni bërë pa dashje, mund të ujdisni Mesazhe të Sigurt në këtë pajisje, gjë që do të sjellë rifshehtëzimin e historikut të mesazheve të pajisjes me një metodë të re rikthimesh.",
"If you didn't remove the recovery method, an attacker may be trying to access your account. Change your account password and set a new recovery method immediately in Settings.": "Nëse metodën e re të rikthimeve se keni hequr ju, dikush mund të jetë duke u rrekur të hyjë në llogarinë tuaj. Ndryshoni menjëherë fjalëkalimin e llogarisë tuaj, te Rregullimet, dhe caktoni një metodë të re rikthimesh.",
"This device has detected that your recovery passphrase and key for Secure Messages have been removed.": "Kjo pajisje ka pikasur se frazëkalimi dhe kyçi juaj i rimarrjeve për Mesazhe të Sigurt janë hequr.",
"If you did this accidentally, you can setup Secure Messages on this device which will re-encrypt this device's message history with a new recovery method.": "Nëse këtë e keni bërë pa dashje, mund të ujdisni Mesazhe të Sigurt në këtë pajisje, gjë që do të sjellë rifshehtëzimin e historikut të mesazheve të pajisjes me një metodë të re rimarrjesh.",
"If you didn't remove the recovery method, an attacker may be trying to access your account. Change your account password and set a new recovery method immediately in Settings.": "Nëse metodën e re të rimarrjeve se keni hequr ju, dikush mund të jetë duke u rrekur të hyjë në llogarinë tuaj. Ndryshoni menjëherë fjalëkalimin e llogarisë tuaj, te Rregullimet, dhe caktoni një metodë të re rimarrjesh.",
"Disinvite this user?": "Ti hiqet ftesa këtij përdoruesi?",
"The file '%(fileName)s' exceeds this homeserver's size limit for uploads": "Kartela '%(fileName)s' tejkalon kufirin e këtij shërbyesi Home për madhësinë e ngarkimeve",
"Gets or sets the room topic": "Merr ose cakton temën e dhomës",
@ -1332,9 +1332,9 @@
"Chat with Riot Bot": "Fjalosuni me Robotin Riot",
"Some devices for this user are not trusted": "Disa pajisje për këtë përdorues nuk janë të besuara",
"All devices for this user are trusted": "Krejt pajisjet për këtë përdorues janë të besuara",
"Recovery Key Mismatch": "Mospërputhje Kyçesh",
"Recovery Key Mismatch": "Mospërputhje Kyçesh Rimarrjeje",
"Incorrect Recovery Passphrase": "Frazëkalim Rimarrjeje i Pasaktë",
"Backup could not be decrypted with this passphrase: please verify that you entered the correct recovery passphrase.": "Su shfshehtëzua dot kopjeruajtja me këtë frazëkalim: ju lutemi, verifikoni që dhatë frazëkalimin e duhur të rikthimeve.",
"Backup could not be decrypted with this passphrase: please verify that you entered the correct recovery passphrase.": "Su shfshehtëzua dot kopjeruajtja me këtë frazëkalim: ju lutemi, verifikoni që dhatë frazëkalimin e duhur të rimarrjeve.",
"This homeserver would like to make sure you are not a robot.": "Ky Shërbyes Home do të donte të sigurohej se sjeni robot.",
"Change": "Ndërroje",
"Couldn't load page": "Su ngarkua dot faqja",
@ -1382,14 +1382,14 @@
"Hide": "Fshihe",
"We'll store an encrypted copy of your keys on our server. Protect your backup with a passphrase to keep it secure.": "Do të depozitojmë në shërbyesin tonë një kopje të fshehtëzuar të kyçeve tuaj. Mbrojeni kopjeruajtjen tuaj me një frazëkalim, për ta mbajtur të parrezikuar.",
"For maximum security, this should be different from your account password.": "Për maksimumin e sigurisë, ky do të duhej të ishte i ndryshëm nga fjalëkalimi juaj për llogarinë.",
"Set up with a Recovery Key": "Rregullojeni me një Kyç Rikthimesh",
"Set up with a Recovery Key": "Rregullojeni me një Kyç Rimarrjesh",
"Please enter your passphrase a second time to confirm.": "Ju lutemi, që të ripohohet, rijepeni frazëkalimin tuaj.",
"Your recovery key is a safety net - you can use it to restore access to your encrypted messages if you forget your passphrase.": "Kyçi juaj i rikthimeve është një rrjet sigurie - mund ta përdorni për rikthim hyrjeje te mesazhet tuaj të fshehtëzuar, nëse harroni frazëkalimin tuaj.",
"Your recovery key is a safety net - you can use it to restore access to your encrypted messages if you forget your passphrase.": "Kyçi juaj i rimarrjeve është një masë sigurie - mund ta përdorni për rimarrje hyrjeje te mesazhet tuaj të fshehtëzuar, nëse harroni frazëkalimin tuaj.",
"Keep your recovery key somewhere very secure, like a password manager (or a safe)": "Mbajeni kyçin tuaj të rikthimeve diku në një vend shumë të sigurt, bie fjala, nën një përgjegjës fjalëkalimesh (ose në një kasafortë)",
"Your keys are being backed up (the first backup could take a few minutes).": "Kyçet tuaj po kopjeruhen (kopjeruajtja e parë mund të hajë disa minuta).",
"Secure your backup with a passphrase": "Sigurojeni kopjeruajtjen tuaj me një frazëkalim",
"Confirm your passphrase": "Ripohoni frazëkalimin tuaj",
"Recovery key": "Kyç rikthimesh",
"Recovery key": "Kyç rimarrjesh",
"Success!": "Sukses!",
"Allow Peer-to-Peer for 1:1 calls": "Lejo Peer-to-Peer për thirrje tek për tek",
"Credits": "Kredite",
@ -1910,5 +1910,59 @@
"Remove for everyone": "Hiqe për këdo",
"Remove for me": "Hiqe për mua",
"Verification Request": "Kërkesë Verifikimi",
" (1/%(totalCount)s)": " (1/%(totalCount)s)"
" (1/%(totalCount)s)": " (1/%(totalCount)s)",
"Error upgrading room": "Gabim në përditësim dhome",
"Double check that your server supports the room version chosen and try again.": "Rikontrolloni që shërbyesi juaj e mbulon versionin e zgjedhur për dhomën dhe riprovoni.",
"%(senderName)s placed a voice call.": "%(senderName)s bëri një thirrje zanore.",
"%(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 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:": "",
"on device": "në pajisje",
"not found": "su gjet",
"in secret storage": "në depozitë të fshehtë",
"Secret storage public key:": "Kyç publik depozite të fshehtë:",
"in account data": "në të dhëna llogarie",
"Clear notifications": "Spastro njoftimet",
"Customise your experience with experimental labs features. <a>Learn more</a>.": "Përshtateni punimin tuaj me veçori eksperimentale. <a>Mësoni më tepër</a>.",
"This message cannot be decrypted": "Ky mesazh s'mund të shfshehtëzohet",
"Unencrypted": "Të pafshehtëzuara",
"<userName/> wants to chat": "<userName/> dëshiron të bisedojë",
"Start chatting": "Filloni të bisedoni",
"Reactions": "Reagime",
"<reactors/><reactedWith> reacted with %(content)s</reactedWith>": "<reactors/><reactedWith> reagoi me %(content)s</reactedWith>",
"Automatically invite users": "Fto përdorues automatikisht",
"Upgrade private room": "Përmirëso dhomë private",
"Upgrade public room": "Përmirëso dhomë publike",
"Upgrading a room is an advanced action and is usually recommended when a room is unstable due to bugs, missing features or security vulnerabilities.": "Përmirësimi i një dhome është një veprim i thelluar dhe zakonisht rekomandohet kur një dhomë është e papërdorshme, për shkak të metash, veçorish që i mungojnë ose cenueshmëri sigurie.",
"This usually only affects how the room is processed on the server. If you're having problems with your Riot, please <a>report a bug</a>.": "Kjo zakonisht prek vetëm mënyrën se si përpunohet dhoma te shërbyesi. Nëse keni probleme me Riot-in, ju lutemi, <a>njoftoni një të metë</a>.",
"You'll upgrade this room from <oldVersion /> to <newVersion />.": "Do ta përmirësoni këtë dhomë nga <oldVersion /> në <newVersion />.",
"Upgrade": "Përmirësoje",
"Enter secret storage passphrase": "Jepni frazëkalim për te depozitë e fshehtë",
"Unable to access secret storage. Please verify that you entered the correct passphrase.": "Sarrihet të hyhet te depozitë e fshehtë. Ju lutemi, verifikoni se dhatë frazëkalimin e saktë.",
"<b>Warning</b>: You should only access secret storage from a trusted computer.": "<b>Kujdes</b>: Duhet të hyni në depozitën e fshehtë vetëm nga një kompjuter i besuar.",
"If you've forgotten your passphrase you can <button1>use your recovery key</button1> or <button2>set up new recovery options</button2>.": "Nëse keni harruar frazëkalimin tuaj, mund të <button1>përdorni kyçin tuaj të rimarrjes</button1> ose <button2>të ujdisni mundësi të reja rimarrjeje</button2>.",
"Enter secret storage recovery key": "Jepni kyç rimarrjeje për depozitë të fshehtë",
"Unable to access secret storage. Please verify that you entered the correct recovery key.": "Sarrihet të hyhet te depozitë e fshehtë. Ju lutemi, verifikoni se dhatë kyç të saktë rimarrjeje.",
"If you've forgotten your recovery key you can <button>set up new recovery options</button>.": "Nëse keni harruar kyçin tuaj të rimarrjeve, mund të <button>ujdisni mundësi të reja rimarrjeje</button>.",
"<b>Warning</b>: You should only set up key backup from a trusted computer.": "<b>Kujdes</b>: duhet të ujdisni kopjeruajtje kyçesh vetëm nga një kompjuter i besuar.",
"If you've forgotten your recovery key you can <button>set up new recovery options</button>": "Nëse keni harruar kyçin tuaj të rimarrjeve, mund të <button>ujdisni mundësi të reja rimarrjeje</button>",
"Notification settings": "Rregullime njoftimesh",
"User Status": "Gjendje Përdoruesi",
"<b>Warning</b>: You should only set up secret storage from a trusted computer.": "<b>Kujdes</b>: Duhet të ujdisni një depozitë të fshehtë vetëm nga një kompjuter i besuar.",
"Set up with a recovery key": "Rregullojeni me një kyç rimarrjesh",
"As a safety net, you can use it to restore your access to encrypted messages if you forget your passphrase.": "Si masë sigurie, mund ta përdorni për të rifituar hyrjen tuaj te mesazhe të fshehtëzuar, nëse harroni frazëkalimin tuaj.",
"As a safety net, you can use it to restore your access to encrypted messages.": "Si një masë sigurie, mund ta përdorni për të rifituar hyrjen tuaj te mesazhe të fshehtëzuar.",
"Keep your recovery key somewhere very secure, like a password manager (or a safe).": "Mbajeni kyçin tuaj të rimarrjeve diku në një vend shumë të sigurt, bie fjala, nën një përgjegjës fjalëkalimesh (ose në një kasafortë).",
"Your recovery key has been <b>copied to your clipboard</b>, paste it to:": "Kyçi juaj i rimarrjeve është <b>kopjuar te e papastra juaj</b>, ngjiteni te:",
"Your recovery key is in your <b>Downloads</b> folder.": "Kyçi juaj i rimarrjeve gjendet te dosja juaj <b>Shkarkime</b>.",
"Your access to encrypted messages is now protected.": "Hyrja juaj te mesazhe të fshehtëzuar tani është e mbrojtur.",
"Set up secret storage": "Ujdisni depozitë të fshehtë",
"Secure your encrypted messages with a passphrase": "Sigurojini mesazhet tuaj të fshehtëzuar me një frazëkalim",
"Storing secrets...": "Po depozitohen të fshehta…",
"Unable to set up secret storage": "Su arrit të ujdiset depozitë e fshehtë"
}

View file

@ -1938,5 +1938,75 @@
"Notification settings": "通知設定",
"User Status": "使用者狀態",
"Reactions": "反應",
"<reactors/><reactedWith> reacted with %(content)s</reactedWith>": "<reactors/><reactedWith> 反應了 %(content)s</reactedWith>"
"<reactors/><reactedWith> reacted with %(content)s</reactedWith>": "<reactors/><reactedWith> 反應了 %(content)s</reactedWith>",
"<userName/> wants to chat": "<userName/> 想要聊天",
"Start chatting": "開始聊天",
"%(senderName)s removed the rule banning users matching %(glob)s": "%(senderName)s 移除了封鎖符合 %(glob)s 使用者的規則",
"%(senderName)s removed the rule banning rooms matching %(glob)s": "%(senderName)s 移除了封鎖符合 %(glob)s 聊天室的規則",
"%(senderName)s removed the rule banning servers matching %(glob)s": "%(senderName)s 移除了封鎖符合 %(glob)s 伺服器的規則",
"%(senderName)s removed a ban rule matching %(glob)s": "%(senderName)s 移除了封鎖符合 %(glob)s 的規則",
"%(senderName)s updated an invalid ban rule": "%(senderName)s 更新無效的封鎖的規則",
"%(senderName)s updated the rule banning users matching %(glob)s for %(reason)s": "%(senderName)s 更新了封鎖符合 %(glob)s 使用者的規則,因為 %(reason)s",
"%(senderName)s updated the rule banning rooms matching %(glob)s for %(reason)s": "%(senderName)s 更新了封鎖符合 %(glob)s 聊天室的規則,因為 %(reason)s",
"%(senderName)s updated the rule banning servers matching %(glob)s for %(reason)s": "%(senderName)s 更新了封鎖符合 %(glob)s 伺服器的規則,因為 %(reason)s",
"%(senderName)s updated a ban rule matching %(glob)s for %(reason)s": "%(senderName)s 更新了封鎖符合 %(glob)s 的規則,因為 %(reason)s",
"%(senderName)s created a rule banning users matching %(glob)s for %(reason)s": "%(senderName)s 建立了封鎖符合 %(glob)s 使用者的規則,因為 %(reason)s",
"%(senderName)s created a rule banning rooms matching %(glob)s for %(reason)s": "%(senderName)s 建立了封鎖符合 %(glob)s 聊天室的規則,因為 %(reason)s",
"%(senderName)s created a rule banning servers matching %(glob)s for %(reason)s": "%(senderName)s 建立了封鎖符合 %(glob)s 伺服器的規則,因為 %(reason)s",
"%(senderName)s created a ban rule matching %(glob)s for %(reason)s": "%(senderName)s 建立了封鎖符合 %(glob)s 的規則,因為 %(reason)s",
"%(senderName)s changed a rule that was banning users matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s 將封鎖符合 %(oldGlob)s 使用者的規則變更為 %(newGlob)s因為 %(reason)s",
"%(senderName)s changed a rule that was banning rooms matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s 將封鎖符合 %(oldGlob)s 聊天室的規則變更為 %(newGlob)s因為 %(reason)s",
"%(senderName)s changed a rule that was banning servers matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s 將封鎖符合 %(oldGlob)s 伺服器的規則變更為 %(newGlob)s因為 %(reason)s",
"%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s 將封鎖符合 %(oldGlob)s 的規則更新為 %(newGlob)s因為 %(reason)s",
"Send cross-signing keys to homeserver": "將交叉簽章的金鑰傳送到家伺服器",
"Cross-signing public keys:": "交叉簽章的公開金鑰:",
"on device": "在裝置上",
"not found": "找不到",
"Cross-signing private keys:": "交叉簽章的私密金鑰:",
"in secret storage": "在秘密儲存空間中",
"Secret storage public key:": "秘密儲存空間公開金鑰:",
"in account data": "在帳號資料中",
"Bootstrap Secure Secret Storage": "Bootstrap 安全秘密儲存空間",
"Cross-signing": "交叉簽章",
"Enter secret storage passphrase": "輸入秘密儲存空間密碼",
"Unable to access secret storage. Please verify that you entered the correct passphrase.": "無法存取秘密儲存空間。請驗證您是否輸入了正確的密碼。",
"<b>Warning</b>: You should only access secret storage from a trusted computer.": "<b>警告</b>:您應該僅從信任的電腦存取秘密儲存空間。",
"Cross-signing and secret storage are enabled.": "已啟用交叉簽章與秘密儲存空間。",
"Your account has a cross-signing identity in secret storage, but it is not yet trusted by this device.": "您的帳號在秘密儲存空間中有交叉簽章的身份,但尚未被此裝置信任。",
"Cross-signing and secret storage are not yet set up.": "尚未設定交叉簽章與秘密儲存空間。",
"Bootstrap cross-signing and secret storage": "啟動交叉簽章與秘密儲存空間",
"not stored": "未儲存",
"Backup has a <validity>valid</validity> signature from this user": "備份有從此使用者而來的<validity>有效</validity>簽章",
"Backup has a <validity>invalid</validity> signature from this user": "備份有從此使用者而來的<validity>無效</validity>簽章",
"Backup has a signature from <verify>unknown</verify> user with ID %(deviceId)s": "備份有從<verify>未知的</verify>使用者而來ID 為 %(deviceId)s 的簽章",
"Backup has a signature from <verify>unknown</verify> device with ID %(deviceId)s": "備份有從<verify>未知的</verify>裝置而來ID 為 %(deviceId)s 的簽章",
"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.": "備份金鑰儲存於秘密儲存空間中,但此功能未在此裝置上啟用。請在實驗室中啟用交叉簽章以修改金鑰備份狀態。",
"Backup key stored: ": "備份金鑰已儲存: ",
"Start using Key Backup with Secure Secret Storage": "開始將金鑰備份與安全秘密儲存空間一起使用",
"Hide verified sessions": "隱藏已驗證的工作階段",
"%(count)s verified sessions|other": "%(count)s 個已驗證的工作階段",
"%(count)s verified sessions|one": "1 個已驗證的工作階段",
"Access your secure message history and your cross-signing identity for verifying other devices by entering your passphrase.": "透過輸入您的密碼來存取您的安全訊息歷史與您的交叉簽章身份並驗證其他裝置。",
"If you've forgotten your passphrase you can <button1>use your recovery key</button1> or <button2>set up new recovery options</button2>.": "如果您忘記您的密碼,您可以<button1>使用您的復原金鑰</button1>或<button2>設定新的復原選項</button2>。",
"Enter secret storage recovery key": "輸入秘密儲存空間復原金鑰",
"Unable to access secret storage. Please verify that you entered the correct recovery key.": "無法存取秘密儲存空間。請驗證您是否輸入了正確的復原金鑰。",
"Access your secure message history and your cross-signing identity for verifying other devices by entering your recovery key.": "透過輸入您的復原金鑰來存取您的安全訊息歷史與您的交叉簽章身份並驗證其他裝置。",
"If you've forgotten your recovery key you can <button>set up new recovery options</button>.": "如果您忘記您的復原金鑰,您可以<button>設定新的復原選項</button>。",
"<b>Warning</b>: You should only set up key backup from a trusted computer.": "<b>警告</b>:您應該只從信任的電腦設定金鑰備份。",
"If you've forgotten your recovery key you can <button>set up new recovery options</button>": "如果您忘記您的復原金鑰,您可以<button>設定新的復原選項</button>",
"<b>Warning</b>: You should only set up secret storage from a trusted computer.": "<b>警告</b>:您應該只從信任的電腦設定秘密儲存空間。",
"We'll use secret storage to optionally store an encrypted copy of your cross-signing identity for verifying other devices and message keys on our server. Protect your access to encrypted messages with a passphrase to keep it secure.": "我們將會使用秘密儲存空間來選擇性儲存您用來驗證其他裝置與訊息金鑰的交叉簽章加密副本在我們的伺服器上。使用密碼來保護您對加密訊息的存取權以使其更安全。",
"Set up with a recovery key": "設定復原金鑰",
"As a safety net, you can use it to restore your access to encrypted messages if you forget your passphrase.": "作為安全網,如果您忘記您的密碼的話,您可以使用它來恢復您對加密訊息的存取。",
"As a safety net, you can use it to restore your access to encrypted messages.": "作為安全網,您可以使用它來恢復您對加密訊息的存取。",
"Keep your recovery key somewhere very secure, like a password manager (or a safe).": "將您的復原金鑰保留在某個非常安全的地方,如密碼管理員(或保險櫃)中。",
"Your recovery key has been <b>copied to your clipboard</b>, paste it to:": "您的復原金鑰已被<b>複製到您的剪貼簿</b>,請將其貼到:",
"Your recovery key is in your <b>Downloads</b> folder.": "您的復原金鑰在您的<b>下載</b>資料夾中。",
"Your access to encrypted messages is now protected.": "您對加密訊息的存取權已被保護。",
"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.": "沒有設定秘密儲存空間,您將無法恢復您的加密訊息的存取權,或是您在登出或使用其他裝置時,用以驗證其他裝置的交叉簽章身份。",
"Set up secret storage": "設定秘密儲存空間",
"Secure your encrypted messages with a passphrase": "使用密碼保護您的加密訊息",
"Storing secrets...": "正在儲存秘密……",
"Unable to set up secret storage": "無法設定秘密儲存空間",
"Close preview": "關閉預覽"
}

View file

@ -154,7 +154,7 @@ export default class RightPanelStore extends Store {
});
}
} else {
if (targetPhase === this._state.lastRoomPhase) {
if (targetPhase === this._state.lastRoomPhase && !payload.refireParams) {
this._setState({
showRoomPanel: !this._state.showRoomPanel,
});

2364
yarn.lock

File diff suppressed because it is too large Load diff