Merge remote-tracking branch 'origin/develop' into jryans/4s-new-key-backup

This commit is contained in:
J. Ryan Stinnett 2019-12-11 10:05:20 +00:00
commit fae819dfe5
149 changed files with 3358 additions and 12421 deletions

View file

@ -78,6 +78,7 @@ export const Key = {
CONTROL: "Control",
META: "Meta",
SHIFT: "Shift",
CONTEXT_MENU: "ContextMenu",
LESS_THAN: "<",
GREATER_THAN: ">",

View file

@ -153,13 +153,8 @@ function _onStartDmFinished(shouldInvite, addrs) {
}
}
function _onRoomInviteFinished(roomId, shouldInvite, addrs) {
if (!shouldInvite) return;
const addrTexts = addrs.map((addr) => addr.address);
// Invite new users to a room
inviteMultipleToRoom(roomId, addrTexts).then((result) => {
export function inviteUsersToRoom(roomId, userIds) {
return inviteMultipleToRoom(roomId, userIds).then((result) => {
const room = MatrixClientPeg.get().getRoom(roomId);
return _showAnyInviteErrors(result.states, room, result.inviter);
}).catch((err) => {
@ -172,6 +167,15 @@ function _onRoomInviteFinished(roomId, shouldInvite, addrs) {
});
}
function _onRoomInviteFinished(roomId, shouldInvite, addrs) {
if (!shouldInvite) return;
const addrTexts = addrs.map((addr) => addr.address);
// Invite new users to a room
inviteUsersToRoom(roomId, addrTexts);
}
// TODO: Immutable DMs replaces this
function _isDmChat(addrTexts) {
if (addrTexts.length === 1 && getAddressType(addrTexts[0]) === 'mx-user-id') {

View file

@ -32,6 +32,7 @@ import { getAddressType } from './UserAddress';
import { abbreviateUrl } from './utils/UrlUtils';
import { getDefaultIdentityServerUrl, useDefaultIdentityServer } from './utils/IdentityServerUtils';
import {isPermalinkHost, parsePermalink} from "./utils/permalinks/Permalinks";
import {inviteUsersToRoom} from "./RoomInvite";
const singleMxcUpload = async () => {
return new Promise((resolve) => {
@ -154,70 +155,58 @@ export const CommandMap = {
return reject(_t("You do not have the required permissions to use this command."));
}
const RoomUpgradeWarningDialog = sdk.getComponent("dialogs.RoomUpgradeWarningDialog");
const {finished} = Modal.createTrackedDialog('Slash Commands', 'upgrade room confirmation',
QuestionDialog, {
title: _t('Room upgrade confirmation'),
description: (
<div>
<p>{_t("Upgrading a room can be destructive and isn't always necessary.")}</p>
<p>
{_t(
"Room upgrades are usually recommended when a room version is considered " +
"<i>unstable</i>. Unstable room versions might have bugs, missing features, or " +
"security vulnerabilities.",
{}, {
"i": (sub) => <i>{sub}</i>,
},
)}
</p>
<p>
{_t(
"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 />.",
{}, {
"i": (sub) => <i>{sub}</i>,
"issueLink": () => {
return <a href="https://github.com/vector-im/riot-web/issues/new/choose"
target="_blank" rel="noopener">
https://github.com/vector-im/riot-web/issues/new/choose
</a>;
},
},
)}
</p>
<p>
{_t(
"<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": (sub) => <b>{sub}</b>,
"i": (sub) => <i>{sub}</i>,
},
)}
</p>
<p>
{_t(
"Please confirm that you'd like to go forward with upgrading this room " +
"from <oldVersion /> to <newVersion />.",
{},
{
oldVersion: () => <code>{room ? room.getVersion() : "1"}</code>,
newVersion: () => <code>{args}</code>,
},
)}
</p>
</div>
),
button: _t("Upgrade"),
});
RoomUpgradeWarningDialog, {roomId: roomId, targetVersion: args}, /*className=*/null,
/*isPriority=*/false, /*isStatic=*/true);
return success(finished.then(([confirm]) => {
if (!confirm) return;
return success(finished.then(async ([resp]) => {
if (!resp.continue) return;
return cli.upgradeRoom(roomId, args);
let checkForUpgradeFn;
try {
const upgradePromise = cli.upgradeRoom(roomId, args);
// We have to wait for the js-sdk to give us the room back so
// we can more effectively abuse the MultiInviter behaviour
// which heavily relies on the Room object being available.
if (resp.invite) {
checkForUpgradeFn = async (newRoom) => {
// The upgradePromise should be done by the time we await it here.
const {replacement_room: newRoomId} = await upgradePromise;
if (newRoom.roomId !== newRoomId) return;
const toInvite = [
...room.getMembersWithMembership("join"),
...room.getMembersWithMembership("invite"),
].map(m => m.userId).filter(m => m !== cli.getUserId());
if (toInvite.length > 0) {
// Errors are handled internally to this function
await inviteUsersToRoom(newRoomId, toInvite);
}
cli.removeListener('Room', checkForUpgradeFn);
};
cli.on('Room', checkForUpgradeFn);
}
// We have to await after so that the checkForUpgradesFn has a proper reference
// to the new room's ID.
await upgradePromise;
} catch (e) {
console.error(e);
if (checkForUpgradeFn) cli.removeListener('Room', checkForUpgradeFn);
const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog');
Modal.createTrackedDialog('Slash Commands', 'room upgrade error', ErrorDialog, {
title: _t('Error upgrading room'),
description: _t(
'Double check that your server supports the room version chosen and try again.'),
});
}
}));
}
return reject(this.getUsage());

View file

@ -36,6 +36,8 @@ module.exports = {
return false;
} else if (ev.getType() == 'm.room.aliases' || ev.getType() == 'm.room.canonical_alias') {
return false;
} else if (ev.getType() == 'm.room.server_acl') {
return false;
}
const EventTile = sdk.getComponent('rooms.EventTile');
return EventTile.haveTileForEvent(ev);

View file

@ -1,7 +1,6 @@
const React = require('react');
const ReactDom = require('react-dom');
import PropTypes from 'prop-types';
import createReactClass from 'create-react-class';
const Velocity = require('velocity-animate');
/**
@ -11,10 +10,8 @@ const Velocity = require('velocity-animate');
* from DOM order. This makes it a lot simpler and lighter: if you need fully
* automatic positional animation, look at react-shuffle or similar libraries.
*/
module.exports = createReactClass({
displayName: 'Velociraptor',
propTypes: {
export default class Velociraptor extends React.Component {
static propTypes = {
// either a list of child nodes, or a single child.
children: PropTypes.any,
@ -26,82 +23,71 @@ module.exports = createReactClass({
// a list of transition options from the corresponding startStyle
enterTransitionOpts: PropTypes.array,
},
};
getDefaultProps: function() {
return {
startStyles: [],
enterTransitionOpts: [],
};
},
static defaultProps = {
startStyles: [],
enterTransitionOpts: [],
};
constructor(props) {
super(props);
componentWillMount: function() {
this.nodes = {};
this._updateChildren(this.props.children);
},
}
componentWillReceiveProps: function(nextProps) {
this._updateChildren(nextProps.children);
},
componentDidUpdate() {
this._updateChildren(this.props.children);
}
/**
* update `this.children` according to the new list of children given
*/
_updateChildren: function(newChildren) {
const self = this;
_updateChildren(newChildren) {
const oldChildren = this.children || {};
this.children = {};
React.Children.toArray(newChildren).forEach(function(c) {
React.Children.toArray(newChildren).forEach((c) => {
if (oldChildren[c.key]) {
const old = oldChildren[c.key];
const oldNode = ReactDom.findDOMNode(self.nodes[old.key]);
const oldNode = ReactDom.findDOMNode(this.nodes[old.key]);
if (oldNode && oldNode.style.left != c.props.style.left) {
Velocity(oldNode, { left: c.props.style.left }, self.props.transition).then(function() {
if (oldNode && oldNode.style.left !== c.props.style.left) {
Velocity(oldNode, { left: c.props.style.left }, this.props.transition).then(() => {
// special case visibility because it's nonsensical to animate an invisible element
// so we always hidden->visible pre-transition and visible->hidden after
if (oldNode.style.visibility == 'visible' && c.props.style.visibility == 'hidden') {
if (oldNode.style.visibility === 'visible' && c.props.style.visibility === 'hidden') {
oldNode.style.visibility = c.props.style.visibility;
}
});
//console.log("translation: "+oldNode.style.left+" -> "+c.props.style.left);
}
if (oldNode && oldNode.style.visibility == 'hidden' && c.props.style.visibility == 'visible') {
if (oldNode && oldNode.style.visibility === 'hidden' && c.props.style.visibility === 'visible') {
oldNode.style.visibility = c.props.style.visibility;
}
// clone the old element with the props (and children) of the new element
// so prop updates are still received by the children.
self.children[c.key] = React.cloneElement(old, c.props, c.props.children);
this.children[c.key] = React.cloneElement(old, c.props, c.props.children);
} else {
// new element. If we have a startStyle, use that as the style and go through
// the enter animations
const newProps = {};
const restingStyle = c.props.style;
const startStyles = self.props.startStyles;
const startStyles = this.props.startStyles;
if (startStyles.length > 0) {
const startStyle = startStyles[0];
newProps.style = startStyle;
// console.log("mounted@startstyle0: "+JSON.stringify(startStyle));
}
newProps.ref = ((n) => self._collectNode(
newProps.ref = ((n) => this._collectNode(
c.key, n, restingStyle,
));
self.children[c.key] = React.cloneElement(c, newProps);
this.children[c.key] = React.cloneElement(c, newProps);
}
});
},
}
/**
* called when a child element is mounted/unmounted
*
* @param {string} k key of the child
* @param {null|Object} node On mount: React node. On unmount: null
* @param {Object} restingStyle final style
*/
_collectNode: function(k, node, restingStyle) {
_collectNode(k, node, restingStyle) {
if (
node &&
this.nodes[k] === undefined &&
@ -125,12 +111,12 @@ module.exports = createReactClass({
// and then we animate to the resting state
Velocity(domNode, restingStyle,
transitionOpts[i-1])
.then(() => {
// once we've reached the resting state, hide the element if
// appropriate
domNode.style.visibility = restingStyle.visibility;
});
transitionOpts[i-1])
.then(() => {
// once we've reached the resting state, hide the element if
// appropriate
domNode.style.visibility = restingStyle.visibility;
});
/*
console.log("enter:",
@ -153,13 +139,13 @@ module.exports = createReactClass({
if (domNode) Velocity.Utilities.removeData(domNode);
}
this.nodes[k] = node;
},
}
render: function() {
render() {
return (
<span>
{ Object.values(this.children) }
</span>
);
},
});
}
}

View file

@ -15,7 +15,7 @@ limitations under the License.
*/
import FileSaver from 'file-saver';
import React from 'react';
import React, {createRef} from 'react';
import PropTypes from 'prop-types';
import createReactClass from 'create-react-class';
import { _t } from '../../../languageHandler';
@ -44,6 +44,9 @@ export default createReactClass({
componentWillMount: function() {
this._unmounted = false;
this._passphrase1 = createRef();
this._passphrase2 = createRef();
},
componentWillUnmount: function() {
@ -53,8 +56,8 @@ export default createReactClass({
_onPassphraseFormSubmit: function(ev) {
ev.preventDefault();
const passphrase = this.refs.passphrase1.value;
if (passphrase !== this.refs.passphrase2.value) {
const passphrase = this._passphrase1.current.value;
if (passphrase !== this._passphrase2.current.value) {
this.setState({errStr: _t('Passphrases must match')});
return false;
}
@ -148,7 +151,7 @@ export default createReactClass({
</label>
</div>
<div className='mx_E2eKeysDialog_inputCell'>
<input ref='passphrase1' id='passphrase1'
<input ref={this._passphrase1} id='passphrase1'
autoFocus={true} size='64' type='password'
disabled={disableForm}
/>
@ -161,7 +164,7 @@ export default createReactClass({
</label>
</div>
<div className='mx_E2eKeysDialog_inputCell'>
<input ref='passphrase2' id='passphrase2'
<input ref={this._passphrase2} id='passphrase2'
size='64' type='password'
disabled={disableForm}
/>

View file

@ -14,7 +14,7 @@ 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 createReactClass from 'create-react-class';
@ -56,6 +56,9 @@ export default createReactClass({
componentWillMount: function() {
this._unmounted = false;
this._file = createRef();
this._passphrase = createRef();
},
componentWillUnmount: function() {
@ -63,15 +66,15 @@ export default createReactClass({
},
_onFormChange: function(ev) {
const files = this.refs.file.files || [];
const files = this._file.current.files || [];
this.setState({
enableSubmit: (this.refs.passphrase.value !== "" && files.length > 0),
enableSubmit: (this._passphrase.current.value !== "" && files.length > 0),
});
},
_onFormSubmit: function(ev) {
ev.preventDefault();
this._startImport(this.refs.file.files[0], this.refs.passphrase.value);
this._startImport(this._file.current.files[0], this._passphrase.current.value);
return false;
},
@ -146,7 +149,10 @@ export default createReactClass({
</label>
</div>
<div className='mx_E2eKeysDialog_inputCell'>
<input ref='file' id='importFile' type='file'
<input
ref={this._file}
id='importFile'
type='file'
autoFocus={true}
onChange={this._onFormChange}
disabled={disableForm} />
@ -159,8 +165,11 @@ export default createReactClass({
</label>
</div>
<div className='mx_E2eKeysDialog_inputCell'>
<input ref='passphrase' id='passphrase'
size='64' type='password'
<input
ref={this._passphrase}
id='passphrase'
size='64'
type='password'
onChange={this._onFormChange}
disabled={disableForm} />
</div>

View file

@ -0,0 +1,484 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
Copyright 2018 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.
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, {useRef, useState} from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import {Key} from "../../Keyboard";
import sdk from "../../index";
import AccessibleButton from "../views/elements/AccessibleButton";
// Shamelessly ripped off Modal.js. There's probably a better way
// of doing reusable widgets like dialog boxes & menus where we go and
// pass in a custom control as the actual body.
const ContextualMenuContainerId = "mx_ContextualMenu_Container";
function getOrCreateContainer() {
let container = document.getElementById(ContextualMenuContainerId);
if (!container) {
container = document.createElement("div");
container.id = ContextualMenuContainerId;
document.body.appendChild(container);
}
return container;
}
const ARIA_MENU_ITEM_ROLES = new Set(["menuitem", "menuitemcheckbox", "menuitemradio"]);
// Generic ContextMenu Portal wrapper
// all options inside the menu should be of role=menuitem/menuitemcheckbox/menuitemradiobutton and have tabIndex={-1}
// this will allow the ContextMenu to manage its own focus using arrow keys as per the ARIA guidelines.
export class ContextMenu extends React.Component {
static propTypes = {
top: PropTypes.number,
bottom: PropTypes.number,
left: PropTypes.number,
right: PropTypes.number,
menuWidth: PropTypes.number,
menuHeight: PropTypes.number,
chevronOffset: PropTypes.number,
chevronFace: PropTypes.string, // top, bottom, left, right or none
// Function to be called on menu close
onFinished: PropTypes.func.isRequired,
menuPaddingTop: PropTypes.number,
menuPaddingRight: PropTypes.number,
menuPaddingBottom: PropTypes.number,
menuPaddingLeft: PropTypes.number,
zIndex: PropTypes.number,
// If true, insert an invisible screen-sized element behind the
// menu that when clicked will close it.
hasBackground: PropTypes.bool,
// on resize callback
windowResize: PropTypes.func,
catchTab: PropTypes.bool, // whether to close the ContextMenu on TAB (default=true)
};
static defaultProps = {
hasBackground: true,
catchTab: true,
};
constructor() {
super();
this.state = {
contextMenuElem: null,
};
// persist what had focus when we got initialized so we can return it after
this.initialFocus = document.activeElement;
}
componentWillUnmount() {
// return focus to the thing which had it before us
this.initialFocus.focus();
}
collectContextMenuRect = (element) => {
// We don't need to clean up when unmounting, so ignore
if (!element) return;
let first = element.querySelector('[role^="menuitem"]');
if (!first) {
first = element.querySelector('[tab-index]');
}
if (first) {
first.focus();
}
this.setState({
contextMenuElem: element,
});
};
onContextMenu = (e) => {
if (this.props.onFinished) {
this.props.onFinished();
e.preventDefault();
const x = e.clientX;
const y = e.clientY;
// XXX: This isn't pretty but the only way to allow opening a different context menu on right click whilst
// a context menu and its click-guard are up without completely rewriting how the context menus work.
setImmediate(() => {
const clickEvent = document.createEvent('MouseEvents');
clickEvent.initMouseEvent(
'contextmenu', true, true, window, 0,
0, 0, x, y, false, false,
false, false, 0, null,
);
document.elementFromPoint(x, y).dispatchEvent(clickEvent);
});
}
};
_onMoveFocus = (element, up) => {
let descending = false; // are we currently descending or ascending through the DOM tree?
do {
const child = up ? element.lastElementChild : element.firstElementChild;
const sibling = up ? element.previousElementSibling : element.nextElementSibling;
if (descending) {
if (child) {
element = child;
} else if (sibling) {
element = sibling;
} else {
descending = false;
element = element.parentElement;
}
} else {
if (sibling) {
element = sibling;
descending = true;
} else {
element = element.parentElement;
}
}
if (element) {
if (element.classList.contains("mx_ContextualMenu")) { // we hit the top
element = up ? element.lastElementChild : element.firstElementChild;
descending = true;
}
}
} while (element && !ARIA_MENU_ITEM_ROLES.has(element.getAttribute("role")));
if (element) {
element.focus();
}
};
_onMoveFocusHomeEnd = (element, up) => {
let results = element.querySelectorAll('[role^="menuitem"]');
if (!results) {
results = element.querySelectorAll('[tab-index]');
}
if (results && results.length) {
if (up) {
results[0].focus();
} else {
results[results.length - 1].focus();
}
}
};
_onKeyDown = (ev) => {
let handled = true;
switch (ev.key) {
case Key.TAB:
if (!this.props.catchTab) {
handled = false;
break;
}
// fallthrough
case Key.ESCAPE:
this.props.onFinished();
break;
case Key.ARROW_UP:
this._onMoveFocus(ev.target, true);
break;
case Key.ARROW_DOWN:
this._onMoveFocus(ev.target, false);
break;
case Key.HOME:
this._onMoveFocusHomeEnd(this.state.contextMenuElem, true);
break;
case Key.END:
this._onMoveFocusHomeEnd(this.state.contextMenuElem, false);
break;
default:
handled = false;
}
if (handled) {
// consume all other keys in context menu
ev.stopPropagation();
ev.preventDefault();
}
};
renderMenu(hasBackground=this.props.hasBackground) {
const position = {};
let chevronFace = null;
const props = this.props;
if (props.top) {
position.top = props.top;
} else {
position.bottom = props.bottom;
}
if (props.left) {
position.left = props.left;
chevronFace = 'left';
} else {
position.right = props.right;
chevronFace = 'right';
}
const contextMenuRect = this.state.contextMenuElem ? this.state.contextMenuElem.getBoundingClientRect() : null;
const padding = 10;
const chevronOffset = {};
if (props.chevronFace) {
chevronFace = props.chevronFace;
}
const hasChevron = chevronFace && chevronFace !== "none";
if (chevronFace === 'top' || chevronFace === 'bottom') {
chevronOffset.left = props.chevronOffset;
} else {
const target = position.top;
// By default, no adjustment is made
let adjusted = target;
// If we know the dimensions of the context menu, adjust its position
// such that it does not leave the (padded) window.
if (contextMenuRect) {
adjusted = Math.min(position.top, document.body.clientHeight - contextMenuRect.height - padding);
}
position.top = adjusted;
chevronOffset.top = Math.max(props.chevronOffset, props.chevronOffset + target - adjusted);
}
let chevron;
if (hasChevron) {
chevron = <div style={chevronOffset} className={"mx_ContextualMenu_chevron_" + chevronFace} />;
}
const menuClasses = classNames({
'mx_ContextualMenu': true,
'mx_ContextualMenu_left': !hasChevron && position.left,
'mx_ContextualMenu_right': !hasChevron && position.right,
'mx_ContextualMenu_top': !hasChevron && position.top,
'mx_ContextualMenu_bottom': !hasChevron && position.bottom,
'mx_ContextualMenu_withChevron_left': chevronFace === 'left',
'mx_ContextualMenu_withChevron_right': chevronFace === 'right',
'mx_ContextualMenu_withChevron_top': chevronFace === 'top',
'mx_ContextualMenu_withChevron_bottom': chevronFace === 'bottom',
});
const menuStyle = {};
if (props.menuWidth) {
menuStyle.width = props.menuWidth;
}
if (props.menuHeight) {
menuStyle.height = props.menuHeight;
}
if (!isNaN(Number(props.menuPaddingTop))) {
menuStyle["paddingTop"] = props.menuPaddingTop;
}
if (!isNaN(Number(props.menuPaddingLeft))) {
menuStyle["paddingLeft"] = props.menuPaddingLeft;
}
if (!isNaN(Number(props.menuPaddingBottom))) {
menuStyle["paddingBottom"] = props.menuPaddingBottom;
}
if (!isNaN(Number(props.menuPaddingRight))) {
menuStyle["paddingRight"] = props.menuPaddingRight;
}
const wrapperStyle = {};
if (!isNaN(Number(props.zIndex))) {
menuStyle["zIndex"] = props.zIndex + 1;
wrapperStyle["zIndex"] = props.zIndex;
}
let background;
if (hasBackground) {
background = (
<div className="mx_ContextualMenu_background" style={wrapperStyle} onClick={props.onFinished} onContextMenu={this.onContextMenu} />
);
}
return (
<div className="mx_ContextualMenu_wrapper" style={{...position, ...wrapperStyle}} onKeyDown={this._onKeyDown}>
<div className={menuClasses} style={menuStyle} ref={this.collectContextMenuRect} role="menu">
{ chevron }
{ props.children }
</div>
{ background }
</div>
);
}
render() {
return ReactDOM.createPortal(this.renderMenu(), getOrCreateContainer());
}
}
// Semantic component for representing the AccessibleButton which launches a <ContextMenu />
export const ContextMenuButton = ({ label, isExpanded, children, ...props }) => {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
return (
<AccessibleButton {...props} title={label} aria-label={label} aria-haspopup={true} aria-expanded={isExpanded}>
{ children }
</AccessibleButton>
);
};
ContextMenuButton.propTypes = {
...AccessibleButton.propTypes,
label: PropTypes.string.isRequired,
isExpanded: PropTypes.bool.isRequired, // whether or not the context menu is currently open
};
// Semantic component for representing a role=menuitem
export const MenuItem = ({children, label, ...props}) => {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
return (
<AccessibleButton {...props} role="menuitem" tabIndex={-1} aria-label={label}>
{ children }
</AccessibleButton>
);
};
MenuItem.propTypes = {
...AccessibleButton.propTypes,
label: PropTypes.string, // optional
className: PropTypes.string, // optional
onClick: PropTypes.func.isRequired,
};
// Semantic component for representing a role=group for grouping menu radios/checkboxes
export const MenuGroup = ({children, label, ...props}) => {
return <div {...props} role="group" aria-label={label}>
{ children }
</div>;
};
MenuGroup.propTypes = {
...AccessibleButton.propTypes,
label: PropTypes.string.isRequired,
className: PropTypes.string, // optional
};
// Semantic component for representing a role=menuitemcheckbox
export const MenuItemCheckbox = ({children, label, active=false, disabled=false, ...props}) => {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
return (
<AccessibleButton {...props} role="menuitemcheckbox" aria-checked={active} aria-disabled={disabled} tabIndex={-1} aria-label={label}>
{ children }
</AccessibleButton>
);
};
MenuItemCheckbox.propTypes = {
...AccessibleButton.propTypes,
label: PropTypes.string, // optional
active: PropTypes.bool.isRequired,
disabled: PropTypes.bool, // optional
className: PropTypes.string, // optional
onClick: PropTypes.func.isRequired,
};
// Semantic component for representing a role=menuitemradio
export const MenuItemRadio = ({children, label, active=false, disabled=false, ...props}) => {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
return (
<AccessibleButton {...props} role="menuitemradio" aria-checked={active} aria-disabled={disabled} tabIndex={-1} aria-label={label}>
{ children }
</AccessibleButton>
);
};
MenuItemRadio.propTypes = {
...AccessibleButton.propTypes,
label: PropTypes.string, // optional
active: PropTypes.bool.isRequired,
disabled: PropTypes.bool, // optional
className: PropTypes.string, // optional
onClick: PropTypes.func.isRequired,
};
// Placement method for <ContextMenu /> to position context menu to right of elementRect with chevronOffset
export const toRightOf = (elementRect, chevronOffset=12) => {
const left = elementRect.right + window.pageXOffset + 3;
let top = elementRect.top + (elementRect.height / 2) + window.pageYOffset;
top -= chevronOffset + 8; // where 8 is half the height of the chevron
return {left, top, chevronOffset};
};
// Placement method for <ContextMenu /> to position context menu right-aligned and flowing to the left of elementRect
export const aboveLeftOf = (elementRect, chevronFace="none") => {
const menuOptions = { chevronFace };
const buttonRight = elementRect.right + window.pageXOffset;
const buttonBottom = elementRect.bottom + window.pageYOffset;
const buttonTop = elementRect.top + window.pageYOffset;
// Align the right edge of the menu to the right edge of the button
menuOptions.right = window.innerWidth - buttonRight;
// Align the menu vertically on whichever side of the button has more space available.
if (buttonBottom < window.innerHeight / 2) {
menuOptions.top = buttonBottom;
} else {
menuOptions.bottom = window.innerHeight - buttonTop;
}
return menuOptions;
};
export const useContextMenu = () => {
const button = useRef(null);
const [isOpen, setIsOpen] = useState(false);
const open = () => {
setIsOpen(true);
};
const close = () => {
setIsOpen(false);
};
return [isOpen, button, open, close, setIsOpen];
};
export default class LegacyContextMenu extends ContextMenu {
render() {
return this.renderMenu(false);
}
}
// XXX: Deprecated, used only for dynamic Tooltips. Avoid using at all costs.
export function createMenu(ElementClass, props) {
const onFinished = function(...args) {
ReactDOM.unmountComponentAtNode(getOrCreateContainer());
if (props && props.onFinished) {
props.onFinished.apply(null, args);
}
};
const menu = <LegacyContextMenu
{...props}
onFinished={onFinished} // eslint-disable-line react/jsx-no-bind
windowResize={onFinished} // eslint-disable-line react/jsx-no-bind
>
<ElementClass {...props} onFinished={onFinished} />
</LegacyContextMenu>;
ReactDOM.render(menu, getOrCreateContainer());
return {close: onFinished};
}

View file

@ -1,253 +0,0 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
Copyright 2018 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.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import {focusCapturedRef} from "../../utils/Accessibility";
import {KeyCode} from "../../Keyboard";
// Shamelessly ripped off Modal.js. There's probably a better way
// of doing reusable widgets like dialog boxes & menus where we go and
// pass in a custom control as the actual body.
const ContextualMenuContainerId = "mx_ContextualMenu_Container";
function getOrCreateContainer() {
let container = document.getElementById(ContextualMenuContainerId);
if (!container) {
container = document.createElement("div");
container.id = ContextualMenuContainerId;
document.body.appendChild(container);
}
return container;
}
export default class ContextualMenu extends React.Component {
propTypes: {
top: PropTypes.number,
bottom: PropTypes.number,
left: PropTypes.number,
right: PropTypes.number,
menuWidth: PropTypes.number,
menuHeight: PropTypes.number,
chevronOffset: PropTypes.number,
chevronFace: PropTypes.string, // top, bottom, left, right or none
// Function to be called on menu close
onFinished: PropTypes.func,
menuPaddingTop: PropTypes.number,
menuPaddingRight: PropTypes.number,
menuPaddingBottom: PropTypes.number,
menuPaddingLeft: PropTypes.number,
zIndex: PropTypes.number,
// If true, insert an invisible screen-sized element behind the
// menu that when clicked will close it.
hasBackground: PropTypes.bool,
// The component to render as the context menu
elementClass: PropTypes.element.isRequired,
// on resize callback
windowResize: PropTypes.func,
// method to close menu
closeMenu: PropTypes.func.isRequired,
};
constructor() {
super();
this.state = {
contextMenuRect: null,
};
this.onContextMenu = this.onContextMenu.bind(this);
this.collectContextMenuRect = this.collectContextMenuRect.bind(this);
}
collectContextMenuRect(element) {
// We don't need to clean up when unmounting, so ignore
if (!element) return;
// For screen readers to find the thing
focusCapturedRef(element);
this.setState({
contextMenuRect: element.getBoundingClientRect(),
});
}
onContextMenu(e) {
if (this.props.closeMenu) {
this.props.closeMenu();
e.preventDefault();
const x = e.clientX;
const y = e.clientY;
// XXX: This isn't pretty but the only way to allow opening a different context menu on right click whilst
// a context menu and its click-guard are up without completely rewriting how the context menus work.
setImmediate(() => {
const clickEvent = document.createEvent('MouseEvents');
clickEvent.initMouseEvent(
'contextmenu', true, true, window, 0,
0, 0, x, y, false, false,
false, false, 0, null,
);
document.elementFromPoint(x, y).dispatchEvent(clickEvent);
});
}
}
_onKeyDown = (ev) => {
if (ev.keyCode === KeyCode.ESCAPE) {
ev.stopPropagation();
ev.preventDefault();
this.props.closeMenu();
}
};
render() {
const position = {};
let chevronFace = null;
const props = this.props;
if (props.top) {
position.top = props.top;
} else {
position.bottom = props.bottom;
}
if (props.left) {
position.left = props.left;
chevronFace = 'left';
} else {
position.right = props.right;
chevronFace = 'right';
}
const contextMenuRect = this.state.contextMenuRect || null;
const padding = 10;
const chevronOffset = {};
if (props.chevronFace) {
chevronFace = props.chevronFace;
}
const hasChevron = chevronFace && chevronFace !== "none";
if (chevronFace === 'top' || chevronFace === 'bottom') {
chevronOffset.left = props.chevronOffset;
} else {
const target = position.top;
// By default, no adjustment is made
let adjusted = target;
// If we know the dimensions of the context menu, adjust its position
// such that it does not leave the (padded) window.
if (contextMenuRect) {
adjusted = Math.min(position.top, document.body.clientHeight - contextMenuRect.height - padding);
}
position.top = adjusted;
chevronOffset.top = Math.max(props.chevronOffset, props.chevronOffset + target - adjusted);
}
const chevron = hasChevron ?
<div style={chevronOffset} className={"mx_ContextualMenu_chevron_" + chevronFace} /> :
undefined;
const className = 'mx_ContextualMenu_wrapper';
const menuClasses = classNames({
'mx_ContextualMenu': true,
'mx_ContextualMenu_left': !hasChevron && position.left,
'mx_ContextualMenu_right': !hasChevron && position.right,
'mx_ContextualMenu_top': !hasChevron && position.top,
'mx_ContextualMenu_bottom': !hasChevron && position.bottom,
'mx_ContextualMenu_withChevron_left': chevronFace === 'left',
'mx_ContextualMenu_withChevron_right': chevronFace === 'right',
'mx_ContextualMenu_withChevron_top': chevronFace === 'top',
'mx_ContextualMenu_withChevron_bottom': chevronFace === 'bottom',
});
const menuStyle = {};
if (props.menuWidth) {
menuStyle.width = props.menuWidth;
}
if (props.menuHeight) {
menuStyle.height = props.menuHeight;
}
if (!isNaN(Number(props.menuPaddingTop))) {
menuStyle["paddingTop"] = props.menuPaddingTop;
}
if (!isNaN(Number(props.menuPaddingLeft))) {
menuStyle["paddingLeft"] = props.menuPaddingLeft;
}
if (!isNaN(Number(props.menuPaddingBottom))) {
menuStyle["paddingBottom"] = props.menuPaddingBottom;
}
if (!isNaN(Number(props.menuPaddingRight))) {
menuStyle["paddingRight"] = props.menuPaddingRight;
}
const wrapperStyle = {};
if (!isNaN(Number(props.zIndex))) {
menuStyle["zIndex"] = props.zIndex + 1;
wrapperStyle["zIndex"] = props.zIndex;
}
const ElementClass = props.elementClass;
// FIXME: If a menu uses getDefaultProps it clobbers the onFinished
// property set here so you can't close the menu from a button click!
return <div className={className} style={{...position, ...wrapperStyle}} onKeyDown={this._onKeyDown}>
<div className={menuClasses} style={menuStyle} ref={this.collectContextMenuRect} tabIndex={0}>
{ chevron }
<ElementClass {...props} onFinished={props.closeMenu} onResize={props.windowResize} />
</div>
{ props.hasBackground && <div className="mx_ContextualMenu_background" style={wrapperStyle}
onClick={props.closeMenu} onContextMenu={this.onContextMenu} /> }
</div>;
}
}
export function createMenu(ElementClass, props, hasBackground=true) {
const closeMenu = function(...args) {
ReactDOM.unmountComponentAtNode(getOrCreateContainer());
if (props && props.onFinished) {
props.onFinished.apply(null, args);
}
};
// We only reference closeMenu once per call to createMenu
const menu = <ContextualMenu
hasBackground={hasBackground}
{...props}
elementClass={ElementClass}
closeMenu={closeMenu} // eslint-disable-line react/jsx-no-bind
windowResize={closeMenu} // eslint-disable-line react/jsx-no-bind
/>;
ReactDOM.render(menu, getOrCreateContainer());
return {close: closeMenu};
}

View file

@ -1214,25 +1214,25 @@ export default createReactClass({
const EditableText = sdk.getComponent("elements.EditableText");
nameNode = <EditableText ref="nameEditor"
className="mx_GroupView_editable"
placeholderClassName="mx_GroupView_placeholder"
placeholder={_t('Community Name')}
blurToCancel={false}
initialValue={this.state.profileForm.name}
onValueChanged={this._onNameChange}
tabIndex="0"
dir="auto" />;
nameNode = <EditableText
className="mx_GroupView_editable"
placeholderClassName="mx_GroupView_placeholder"
placeholder={_t('Community Name')}
blurToCancel={false}
initialValue={this.state.profileForm.name}
onValueChanged={this._onNameChange}
tabIndex="0"
dir="auto" />;
shortDescNode = <EditableText ref="descriptionEditor"
className="mx_GroupView_editable"
placeholderClassName="mx_GroupView_placeholder"
placeholder={_t("Description")}
blurToCancel={false}
initialValue={this.state.profileForm.short_description}
onValueChanged={this._onShortDescChange}
tabIndex="0"
dir="auto" />;
shortDescNode = <EditableText
className="mx_GroupView_editable"
placeholderClassName="mx_GroupView_placeholder"
placeholder={_t("Description")}
blurToCancel={false}
initialValue={this.state.profileForm.short_description}
onValueChanged={this._onShortDescChange}
tabIndex="0"
dir="auto" />;
} else {
const onGroupHeaderItemClick = this.state.isUserMember ? this._onEditClick : null;
const groupAvatarUrl = summary.profile ? summary.profile.avatar_url : null;

View file

@ -18,7 +18,7 @@ limitations under the License.
import Matrix from 'matrix-js-sdk';
const InteractiveAuth = Matrix.InteractiveAuth;
import React from 'react';
import React, {createRef} from 'react';
import createReactClass from 'create-react-class';
import PropTypes from 'prop-types';
@ -129,6 +129,8 @@ export default createReactClass({
this._authLogic.poll();
}, 2000);
}
this._stageComponent = createRef();
},
componentWillUnmount: function() {
@ -153,8 +155,8 @@ export default createReactClass({
},
tryContinue: function() {
if (this.refs.stageComponent && this.refs.stageComponent.tryContinue) {
this.refs.stageComponent.tryContinue();
if (this._stageComponent.current && this._stageComponent.current.tryContinue) {
this._stageComponent.current.tryContinue();
}
},
@ -192,8 +194,8 @@ export default createReactClass({
},
_setFocus: function() {
if (this.refs.stageComponent && this.refs.stageComponent.focus) {
this.refs.stageComponent.focus();
if (this._stageComponent.current && this._stageComponent.current.focus) {
this._stageComponent.current.focus();
}
},
@ -214,7 +216,8 @@ export default createReactClass({
const StageComponent = getEntryComponentForLoginType(stage);
return (
<StageComponent ref="stageComponent"
<StageComponent
ref={this._stageComponent}
loginType={stage}
matrixClient={this.props.matrixClient}
authSessionId={this._authLogic.getSessionId()}

View file

@ -17,7 +17,7 @@ limitations under the License.
*/
import { MatrixClient } from 'matrix-js-sdk';
import React from 'react';
import React, {createRef} from 'react';
import createReactClass from 'create-react-class';
import PropTypes from 'prop-types';
import { DragDropContext } from 'react-beautiful-dnd';
@ -129,6 +129,8 @@ const LoggedInView = createReactClass({
this._matrixClient.on("RoomState.events", this.onRoomStateEvents);
fixupColorFonts();
this._roomView = createRef();
},
componentDidUpdate(prevProps) {
@ -165,10 +167,10 @@ const LoggedInView = createReactClass({
},
canResetTimelineInRoom: function(roomId) {
if (!this.refs.roomView) {
if (!this._roomView.current) {
return true;
}
return this.refs.roomView.canResetTimeline();
return this._roomView.current.canResetTimeline();
},
_setStateFromSessionStore() {
@ -401,6 +403,11 @@ const LoggedInView = createReactClass({
const isClickShortcut = ev.target !== document.body &&
(ev.key === Key.SPACE || ev.key === Key.ENTER);
// Do not capture the context menu key to improve keyboard accessibility
if (ev.key === Key.CONTEXT_MENU) {
return;
}
// XXX: Remove after CIDER replaces Slate completely: https://github.com/vector-im/riot-web/issues/11036
// If using Slate, consume the Backspace without first focusing as it causes an implosion
if (ev.key === Key.BACKSPACE && !SettingsStore.getValue("useCiderComposer")) {
@ -423,8 +430,8 @@ const LoggedInView = createReactClass({
* @param {Object} ev The key event
*/
_onScrollKeyPressed: function(ev) {
if (this.refs.roomView) {
this.refs.roomView.handleScrollKey(ev);
if (this._roomView.current) {
this._roomView.current.handleScrollKey(ev);
}
},
@ -538,7 +545,7 @@ const LoggedInView = createReactClass({
switch (this.props.page_type) {
case PageTypes.RoomView:
pageElement = <RoomView
ref='roomView'
ref={this._roomView}
autoJoin={this.props.autoJoin}
onRegistered={this.props.onRegistered}
thirdPartyInvite={this.props.thirdPartyInvite}

View file

@ -24,6 +24,8 @@ import Matrix from "matrix-js-sdk";
// focus-visible is a Polyfill for the :focus-visible CSS pseudo-attribute used by _AccessibleButton.scss
import 'focus-visible';
// what-input helps improve keyboard accessibility
import 'what-input';
import Analytics from "../../Analytics";
import { DecryptionFailureTracker } from "../../DecryptionFailureTracker";

View file

@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import React, {createRef} from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import classNames from 'classnames';
@ -159,6 +159,10 @@ export default class MessagePanel extends React.Component {
SettingsStore.getValue("showHiddenEventsInTimeline");
this._isMounted = false;
this._readMarkerNode = createRef();
this._whoIsTyping = createRef();
this._scrollPanel = createRef();
}
componentDidMount() {
@ -191,8 +195,7 @@ export default class MessagePanel extends React.Component {
/* return true if the content is fully scrolled down right now; else false.
*/
isAtBottom() {
return this.refs.scrollPanel
&& this.refs.scrollPanel.isAtBottom();
return this._scrollPanel.current && this._scrollPanel.current.isAtBottom();
}
/* get the current scroll state. See ScrollPanel.getScrollState for
@ -201,8 +204,7 @@ export default class MessagePanel extends React.Component {
* returns null if we are not mounted.
*/
getScrollState() {
if (!this.refs.scrollPanel) { return null; }
return this.refs.scrollPanel.getScrollState();
return this._scrollPanel.current ? this._scrollPanel.current.getScrollState() : null;
}
// returns one of:
@ -212,8 +214,8 @@ export default class MessagePanel extends React.Component {
// 0: read marker is within the window
// +1: read marker is below the window
getReadMarkerPosition() {
const readMarker = this.refs.readMarkerNode;
const messageWrapper = this.refs.scrollPanel;
const readMarker = this._readMarkerNode.current;
const messageWrapper = this._scrollPanel.current;
if (!readMarker || !messageWrapper) {
return null;
@ -236,16 +238,16 @@ export default class MessagePanel extends React.Component {
/* jump to the top of the content.
*/
scrollToTop() {
if (this.refs.scrollPanel) {
this.refs.scrollPanel.scrollToTop();
if (this._scrollPanel.current) {
this._scrollPanel.current.scrollToTop();
}
}
/* jump to the bottom of the content.
*/
scrollToBottom() {
if (this.refs.scrollPanel) {
this.refs.scrollPanel.scrollToBottom();
if (this._scrollPanel.current) {
this._scrollPanel.current.scrollToBottom();
}
}
@ -255,8 +257,8 @@ export default class MessagePanel extends React.Component {
* @param {number} mult: -1 to page up, +1 to page down
*/
scrollRelative(mult) {
if (this.refs.scrollPanel) {
this.refs.scrollPanel.scrollRelative(mult);
if (this._scrollPanel.current) {
this._scrollPanel.current.scrollRelative(mult);
}
}
@ -266,8 +268,8 @@ export default class MessagePanel extends React.Component {
* @param {KeyboardEvent} ev: the keyboard event to handle
*/
handleScrollKey(ev) {
if (this.refs.scrollPanel) {
this.refs.scrollPanel.handleScrollKey(ev);
if (this._scrollPanel.current) {
this._scrollPanel.current.handleScrollKey(ev);
}
}
@ -282,8 +284,8 @@ export default class MessagePanel extends React.Component {
* defaults to 0.
*/
scrollToEvent(eventId, pixelOffset, offsetBase) {
if (this.refs.scrollPanel) {
this.refs.scrollPanel.scrollToToken(eventId, pixelOffset, offsetBase);
if (this._scrollPanel.current) {
this._scrollPanel.current.scrollToToken(eventId, pixelOffset, offsetBase);
}
}
@ -297,8 +299,8 @@ export default class MessagePanel extends React.Component {
/* check the scroll state and send out pagination requests if necessary.
*/
checkFillState() {
if (this.refs.scrollPanel) {
this.refs.scrollPanel.checkFillState();
if (this._scrollPanel.current) {
this._scrollPanel.current.checkFillState();
}
}
@ -345,7 +347,7 @@ export default class MessagePanel extends React.Component {
}
return (
<li key={"readMarker_"+eventId} ref="readMarkerNode"
<li key={"readMarker_"+eventId} ref={this._readMarkerNode}
className="mx_RoomView_myReadMarker_container">
{ hr }
</li>
@ -693,6 +695,10 @@ export default class MessagePanel extends React.Component {
const readReceipts = this._readReceiptsByEvent[eventId];
// Dev note: `this._isUnmounting.bind(this)` is important - it ensures that
// the function is run in the context of this class and not EventTile, therefore
// ensuring the right `this._mounted` variable is used by read receipts (which
// don't update their position if we, the MessagePanel, is unmounting).
ret.push(
<li key={eventId}
ref={this._collectEventNode.bind(this, eventId)}
@ -707,7 +713,7 @@ export default class MessagePanel extends React.Component {
readReceipts={readReceipts}
readReceiptMap={this._readReceiptMap}
showUrlPreview={this.props.showUrlPreview}
checkUnmounting={this._isUnmounting}
checkUnmounting={this._isUnmounting.bind(this)}
eventSendStatus={mxEv.getAssociatedStatus()}
tileShape={this.props.tileShape}
isTwelveHour={this.props.isTwelveHour}
@ -825,14 +831,14 @@ export default class MessagePanel extends React.Component {
// once dynamic content in the events load, make the scrollPanel check the
// scroll offsets.
_onHeightChanged = () => {
const scrollPanel = this.refs.scrollPanel;
const scrollPanel = this._scrollPanel.current;
if (scrollPanel) {
scrollPanel.checkScroll();
}
};
_onTypingShown = () => {
const scrollPanel = this.refs.scrollPanel;
const scrollPanel = this._scrollPanel.current;
// this will make the timeline grow, so checkScroll
scrollPanel.checkScroll();
if (scrollPanel && scrollPanel.getScrollState().stuckAtBottom) {
@ -841,7 +847,7 @@ export default class MessagePanel extends React.Component {
};
_onTypingHidden = () => {
const scrollPanel = this.refs.scrollPanel;
const scrollPanel = this._scrollPanel.current;
if (scrollPanel) {
// as hiding the typing notifications doesn't
// update the scrollPanel, we tell it to apply
@ -854,11 +860,11 @@ export default class MessagePanel extends React.Component {
};
updateTimelineMinHeight() {
const scrollPanel = this.refs.scrollPanel;
const scrollPanel = this._scrollPanel.current;
if (scrollPanel) {
const isAtBottom = scrollPanel.isAtBottom();
const whoIsTyping = this.refs.whoIsTyping;
const whoIsTyping = this._whoIsTyping.current;
const isTypingVisible = whoIsTyping && whoIsTyping.isVisible();
// when messages get added to the timeline,
// but somebody else is still typing,
@ -871,7 +877,7 @@ export default class MessagePanel extends React.Component {
}
onTimelineReset() {
const scrollPanel = this.refs.scrollPanel;
const scrollPanel = this._scrollPanel.current;
if (scrollPanel) {
scrollPanel.clearPreventShrinking();
}
@ -905,19 +911,22 @@ export default class MessagePanel extends React.Component {
room={this.props.room}
onShown={this._onTypingShown}
onHidden={this._onTypingHidden}
ref="whoIsTyping" />
ref={this._whoIsTyping} />
);
}
return (
<ScrollPanel ref="scrollPanel" className={className}
onScroll={this.props.onScroll}
onResize={this.onResize}
onFillRequest={this.props.onFillRequest}
onUnfillRequest={this.props.onUnfillRequest}
style={style}
stickyBottom={this.props.stickyBottom}
resizeNotifier={this.props.resizeNotifier}>
<ScrollPanel
ref={this._scrollPanel}
className={className}
onScroll={this.props.onScroll}
onResize={this.onResize}
onFillRequest={this.props.onFillRequest}
onUnfillRequest={this.props.onUnfillRequest}
style={style}
stickyBottom={this.props.stickyBottom}
resizeNotifier={this.props.resizeNotifier}
>
{ topSpinner }
{ this._getEventTiles() }
{ whoIsTyping }

View file

@ -572,7 +572,7 @@ module.exports = createReactClass({
if (rows.length === 0 && !this.state.loading) {
scrollpanel_content = <i>{ _t('No rooms to show') }</i>;
} else {
scrollpanel_content = <table ref="directory_table" className="mx_RoomDirectory_table">
scrollpanel_content = <table className="mx_RoomDirectory_table">
<tbody>
{ rows }
</tbody>

View file

@ -18,7 +18,6 @@ limitations under the License.
*/
import React, {createRef} from 'react';
import createReactClass from 'create-react-class';
import classNames from 'classnames';
import sdk from '../../index';
import dis from '../../dispatcher';
@ -36,12 +35,11 @@ import {_t} from "../../languageHandler";
// turn this on for drop & drag console debugging galore
const debug = false;
const RoomSubList = createReactClass({
displayName: 'RoomSubList',
export default class RoomSubList extends React.PureComponent {
static displayName = 'RoomSubList';
static debug = debug;
debug: debug,
propTypes: {
static propTypes = {
list: PropTypes.arrayOf(PropTypes.object).isRequired,
label: PropTypes.string.isRequired,
tagName: PropTypes.string,
@ -59,10 +57,26 @@ const RoomSubList = createReactClass({
incomingCall: PropTypes.object,
extraTiles: PropTypes.arrayOf(PropTypes.node), // extra elements added beneath tiles
forceExpand: PropTypes.bool,
},
};
getInitialState: function() {
static defaultProps = {
onHeaderClick: function() {
}, // NOP
extraTiles: [],
isInvite: false,
};
static getDerivedStateFromProps(props, state) {
return {
listLength: props.list.length,
scrollTop: props.list.length === state.listLength ? state.scrollTop : 0,
};
}
constructor(props) {
super(props);
this.state = {
hidden: this.props.startAsHidden || false,
// some values to get LazyRenderList starting
scrollerHeight: 800,
@ -71,47 +85,33 @@ const RoomSubList = createReactClass({
// we have to store the length of the list here so we can see if it's changed or not...
listLength: null,
};
},
getDefaultProps: function() {
return {
onHeaderClick: function() {
}, // NOP
extraTiles: [],
isInvite: false,
};
},
componentDidMount: function() {
this._header = createRef();
this._subList = createRef();
this._scroller = createRef();
this._headerButton = createRef();
}
componentDidMount() {
this.dispatcherRef = dis.register(this.onAction);
},
}
statics: {
getDerivedStateFromProps: function(props, state) {
return {
listLength: props.list.length,
scrollTop: props.list.length === state.listLength ? state.scrollTop : 0,
};
},
},
componentWillUnmount: function() {
componentWillUnmount() {
dis.unregister(this.dispatcherRef);
},
}
// The header is collapsible if it is hidden or not stuck
// The dataset elements are added in the RoomList _initAndPositionStickyHeaders method
isCollapsibleOnClick: function() {
const stuck = this.refs.header.dataset.stuck;
isCollapsibleOnClick() {
const stuck = this._header.current.dataset.stuck;
if (!this.props.forceExpand && (this.state.hidden || stuck === undefined || stuck === "none")) {
return true;
} else {
return false;
}
},
}
onAction: function(payload) {
onAction = (payload) => {
// XXX: Previously RoomList would forceUpdate whenever on_room_read is dispatched,
// but this is no longer true, so we must do it here (and can apply the small
// optimisation of checking that we care about the room being read).
@ -124,9 +124,9 @@ const RoomSubList = createReactClass({
) {
this.forceUpdate();
}
},
};
onClick: function(ev) {
onClick = (ev) => {
if (this.isCollapsibleOnClick()) {
// The header isCollapsible, so the click is to be interpreted as collapse and truncation logic
const isHidden = !this.state.hidden;
@ -135,11 +135,11 @@ const RoomSubList = createReactClass({
});
} else {
// The header is stuck, so the click is to be interpreted as a scroll to the header
this.props.onHeaderClick(this.state.hidden, this.refs.header.dataset.originalPosition);
this.props.onHeaderClick(this.state.hidden, this._header.current.dataset.originalPosition);
}
},
};
onHeaderKeyDown: function(ev) {
onHeaderKeyDown = (ev) => {
switch (ev.key) {
case Key.TAB:
// Prevent LeftPanel handling Tab if focus is on the sublist header itself
@ -159,7 +159,7 @@ const RoomSubList = createReactClass({
this.onClick();
} else if (!this.props.forceExpand) {
// sublist is expanded, go to first room
const element = this.refs.subList && this.refs.subList.querySelector(".mx_RoomTile");
const element = this._subList.current && this._subList.current.querySelector(".mx_RoomTile");
if (element) {
element.focus();
}
@ -167,9 +167,9 @@ const RoomSubList = createReactClass({
break;
}
}
},
};
onKeyDown: function(ev) {
onKeyDown = (ev) => {
switch (ev.key) {
// On ARROW_LEFT go to the sublist header
case Key.ARROW_LEFT:
@ -180,24 +180,24 @@ const RoomSubList = createReactClass({
case Key.ARROW_RIGHT:
ev.stopPropagation();
}
},
};
onRoomTileClick(roomId, ev) {
onRoomTileClick = (roomId, ev) => {
dis.dispatch({
action: 'view_room',
room_id: roomId,
clear_search: (ev && (ev.keyCode === KeyCode.ENTER || ev.keyCode === KeyCode.SPACE)),
});
},
};
_updateSubListCount: function() {
_updateSubListCount = () => {
// Force an update by setting the state to the current state
// Doing it this way rather than using forceUpdate(), so that the shouldComponentUpdate()
// method is honoured
this.setState(this.state);
},
};
makeRoomTile: function(room) {
makeRoomTile = (room) => {
return <RoomTile
room={room}
roomSubList={this}
@ -212,9 +212,9 @@ const RoomSubList = createReactClass({
incomingCall={null}
onClick={this.onRoomTileClick}
/>;
},
};
_onNotifBadgeClick: function(e) {
_onNotifBadgeClick = (e) => {
// prevent the roomsublist collapsing
e.preventDefault();
e.stopPropagation();
@ -225,9 +225,9 @@ const RoomSubList = createReactClass({
room_id: room.roomId,
});
}
},
};
_onInviteBadgeClick: function(e) {
_onInviteBadgeClick = (e) => {
// prevent the roomsublist collapsing
e.preventDefault();
e.stopPropagation();
@ -247,14 +247,14 @@ const RoomSubList = createReactClass({
});
}
}
},
};
onAddRoom: function(e) {
onAddRoom = (e) => {
e.stopPropagation();
if (this.props.onAddRoom) this.props.onAddRoom();
},
};
_getHeaderJsx: function(isCollapsed) {
_getHeaderJsx(isCollapsed) {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
const AccessibleTooltipButton = sdk.getComponent('elements.AccessibleTooltipButton');
const subListNotifications = !this.props.isInvite ?
@ -328,7 +328,7 @@ const RoomSubList = createReactClass({
}
return (
<div className="mx_RoomSubList_labelContainer" title={title} ref="header" onKeyDown={this.onHeaderKeyDown}>
<div className="mx_RoomSubList_labelContainer" title={title} ref={this._header} onKeyDown={this.onHeaderKeyDown}>
<AccessibleButton
onClick={this.onClick}
className="mx_RoomSubList_label"
@ -346,36 +346,36 @@ const RoomSubList = createReactClass({
{ addRoomButton }
</div>
);
},
}
checkOverflow: function() {
if (this.refs.scroller) {
this.refs.scroller.checkOverflow();
checkOverflow = () => {
if (this._scroller.current) {
this._scroller.current.checkOverflow();
}
},
};
setHeight: function(height) {
if (this.refs.subList) {
this.refs.subList.style.height = `${height}px`;
setHeight = (height) => {
if (this._subList.current) {
this._subList.current.style.height = `${height}px`;
}
this._updateLazyRenderHeight(height);
},
};
_updateLazyRenderHeight: function(height) {
_updateLazyRenderHeight(height) {
this.setState({scrollerHeight: height});
},
}
_onScroll: function() {
this.setState({scrollTop: this.refs.scroller.getScrollTop()});
},
_onScroll = () => {
this.setState({scrollTop: this._scroller.current.getScrollTop()});
};
_canUseLazyListRendering() {
// for now disable lazy rendering as they are already rendered tiles
// not rooms like props.list we pass to LazyRenderList
return !this.props.extraTiles || !this.props.extraTiles.length;
},
}
render: function() {
render() {
const len = this.props.list.length + this.props.extraTiles.length;
const isCollapsed = this.state.hidden && !this.props.forceExpand;
@ -391,7 +391,7 @@ const RoomSubList = createReactClass({
// no body
} else if (this._canUseLazyListRendering()) {
content = (
<IndicatorScrollbar ref="scroller" className="mx_RoomSubList_scroll" onScroll={this._onScroll}>
<IndicatorScrollbar ref={this._scroller} className="mx_RoomSubList_scroll" onScroll={this._onScroll}>
<LazyRenderList
scrollTop={this.state.scrollTop }
height={ this.state.scrollerHeight }
@ -404,7 +404,7 @@ const RoomSubList = createReactClass({
const roomTiles = this.props.list.map(r => this.makeRoomTile(r));
const tiles = roomTiles.concat(this.props.extraTiles);
content = (
<IndicatorScrollbar ref="scroller" className="mx_RoomSubList_scroll" onScroll={this._onScroll}>
<IndicatorScrollbar ref={this._scroller} className="mx_RoomSubList_scroll" onScroll={this._onScroll}>
{ tiles }
</IndicatorScrollbar>
);
@ -418,7 +418,7 @@ const RoomSubList = createReactClass({
return (
<div
ref="subList"
ref={this._subList}
className={subListClasses}
role="group"
aria-label={this.props.label}
@ -428,7 +428,5 @@ const RoomSubList = createReactClass({
{ content }
</div>
);
},
});
module.exports = RoomSubList;
}
}

View file

@ -23,7 +23,7 @@ limitations under the License.
import shouldHideEvent from '../../shouldHideEvent';
import React from 'react';
import React, {createRef} from 'react';
import createReactClass from 'create-react-class';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
@ -207,6 +207,9 @@ module.exports = createReactClass({
this._onCiderUpdated();
this._ciderWatcherRef = SettingsStore.watchSetting(
"useCiderComposer", null, this._onCiderUpdated);
this._roomView = createRef();
this._searchResultsPanel = createRef();
},
_onCiderUpdated: function() {
@ -459,8 +462,8 @@ module.exports = createReactClass({
},
componentDidUpdate: function() {
if (this.refs.roomView) {
const roomView = ReactDOM.findDOMNode(this.refs.roomView);
if (this._roomView.current) {
const roomView = ReactDOM.findDOMNode(this._roomView.current);
if (!roomView.ondrop) {
roomView.addEventListener('drop', this.onDrop);
roomView.addEventListener('dragover', this.onDragOver);
@ -474,10 +477,10 @@ module.exports = createReactClass({
// in render() prevents the ref from being set on first mount, so we try and
// catch the messagePanel when it does mount. Because we only want the ref once,
// we use a boolean flag to avoid duplicate work.
if (this.refs.messagePanel && !this.state.atEndOfLiveTimelineInit) {
if (this._messagePanel && !this.state.atEndOfLiveTimelineInit) {
this.setState({
atEndOfLiveTimelineInit: true,
atEndOfLiveTimeline: this.refs.messagePanel.isAtEndOfLiveTimeline(),
atEndOfLiveTimeline: this._messagePanel.isAtEndOfLiveTimeline(),
});
}
},
@ -499,12 +502,12 @@ module.exports = createReactClass({
// stop tracking room changes to format permalinks
this._stopAllPermalinkCreators();
if (this.refs.roomView) {
if (this._roomView.current) {
// disconnect the D&D event listeners from the room view. This
// is really just for hygiene - we're going to be
// deleted anyway, so it doesn't matter if the event listeners
// don't get cleaned up.
const roomView = ReactDOM.findDOMNode(this.refs.roomView);
const roomView = ReactDOM.findDOMNode(this._roomView.current);
roomView.removeEventListener('drop', this.onDrop);
roomView.removeEventListener('dragover', this.onDragOver);
roomView.removeEventListener('dragleave', this.onDragLeaveOrEnd);
@ -701,10 +704,10 @@ module.exports = createReactClass({
},
canResetTimeline: function() {
if (!this.refs.messagePanel) {
if (!this._messagePanel) {
return true;
}
return this.refs.messagePanel.canResetTimeline();
return this._messagePanel.canResetTimeline();
},
// called when state.room is first initialised (either at initial load,
@ -1046,7 +1049,7 @@ module.exports = createReactClass({
},
onMessageListScroll: function(ev) {
if (this.refs.messagePanel.isAtEndOfLiveTimeline()) {
if (this._messagePanel.isAtEndOfLiveTimeline()) {
this.setState({
numUnreadMessages: 0,
atEndOfLiveTimeline: true,
@ -1119,8 +1122,8 @@ module.exports = createReactClass({
// if we already have a search panel, we need to tell it to forget
// about its scroll state.
if (this.refs.searchResultsPanel) {
this.refs.searchResultsPanel.resetScrollState();
if (this._searchResultsPanel.current) {
this._searchResultsPanel.current.resetScrollState();
}
// make sure that we don't end up showing results from
@ -1225,7 +1228,7 @@ module.exports = createReactClass({
// once dynamic content in the search results load, make the scrollPanel check
// the scroll offsets.
const onHeightChanged = () => {
const scrollPanel = this.refs.searchResultsPanel;
const scrollPanel = this._searchResultsPanel.current;
if (scrollPanel) {
scrollPanel.checkScroll();
}
@ -1370,28 +1373,28 @@ module.exports = createReactClass({
// jump down to the bottom of this room, where new events are arriving
jumpToLiveTimeline: function() {
this.refs.messagePanel.jumpToLiveTimeline();
this._messagePanel.jumpToLiveTimeline();
dis.dispatch({action: 'focus_composer'});
},
// jump up to wherever our read marker is
jumpToReadMarker: function() {
this.refs.messagePanel.jumpToReadMarker();
this._messagePanel.jumpToReadMarker();
},
// update the read marker to match the read-receipt
forgetReadMarker: function(ev) {
ev.stopPropagation();
this.refs.messagePanel.forgetReadMarker();
this._messagePanel.forgetReadMarker();
},
// decide whether or not the top 'unread messages' bar should be shown
_updateTopUnreadMessagesBar: function() {
if (!this.refs.messagePanel) {
if (!this._messagePanel) {
return;
}
const showBar = this.refs.messagePanel.canJumpToReadMarker();
const showBar = this._messagePanel.canJumpToReadMarker();
if (this.state.showTopUnreadMessagesBar != showBar) {
this.setState({showTopUnreadMessagesBar: showBar});
}
@ -1401,7 +1404,7 @@ module.exports = createReactClass({
// restored when we switch back to it.
//
_getScrollState: function() {
const messagePanel = this.refs.messagePanel;
const messagePanel = this._messagePanel;
if (!messagePanel) return null;
// if we're following the live timeline, we want to return null; that
@ -1506,10 +1509,10 @@ module.exports = createReactClass({
*/
handleScrollKey: function(ev) {
let panel;
if (this.refs.searchResultsPanel) {
panel = this.refs.searchResultsPanel;
} else if (this.refs.messagePanel) {
panel = this.refs.messagePanel;
if (this._searchResultsPanel.current) {
panel = this._searchResultsPanel.current;
} else if (this._messagePanel) {
panel = this._messagePanel;
}
if (panel) {
@ -1530,7 +1533,7 @@ module.exports = createReactClass({
// this has to be a proper method rather than an unnamed function,
// otherwise react calls it with null on each update.
_gatherTimelinePanelRef: function(r) {
this.refs.messagePanel = r;
this._messagePanel = r;
if (r) {
console.log("updateTint from RoomView._gatherTimelinePanelRef");
this.updateTint();
@ -1719,7 +1722,7 @@ module.exports = createReactClass({
aux = <ForwardMessage onCancelClick={this.onCancelClick} />;
} else if (this.state.searching) {
hideCancel = true; // has own cancel
aux = <SearchBar ref="search_bar" searchInProgress={this.state.searchInProgress} onCancelClick={this.onCancelSearchClick} onSearch={this.onSearch} />;
aux = <SearchBar searchInProgress={this.state.searchInProgress} onCancelClick={this.onCancelSearchClick} onSearch={this.onSearch} />;
} else if (showRoomUpgradeBar) {
aux = <RoomUpgradeWarningBar room={this.state.room} recommendation={roomVersionRecommendation} />;
hideCancel = true;
@ -1775,7 +1778,7 @@ module.exports = createReactClass({
}
const auxPanel = (
<AuxPanel ref="auxPanel" room={this.state.room}
<AuxPanel room={this.state.room}
fullHeight={false}
userId={MatrixClientPeg.get().credentials.userId}
conferenceHandler={this.props.ConferenceHandler}
@ -1875,7 +1878,7 @@ module.exports = createReactClass({
searchResultsPanel = (<div className="mx_RoomView_messagePanel mx_RoomView_messagePanelSearchSpinner" />);
} else {
searchResultsPanel = (
<ScrollPanel ref="searchResultsPanel"
<ScrollPanel ref={this._searchResultsPanel}
className="mx_RoomView_messagePanel mx_RoomView_searchResultsPanel"
onFillRequest={this.onSearchResultsFillRequest}
resizeNotifier={this.props.resizeNotifier}
@ -1898,7 +1901,8 @@ module.exports = createReactClass({
// console.info("ShowUrlPreview for %s is %s", this.state.room.roomId, this.state.showUrlPreview);
const messagePanel = (
<TimelinePanel ref={this._gatherTimelinePanelRef}
<TimelinePanel
ref={this._gatherTimelinePanelRef}
timelineSet={this.state.room.getUnfilteredTimelineSet()}
showReadReceipts={SettingsStore.getValue('showReadReceipts')}
manageReadReceipts={!this.state.isPeeking}
@ -1952,9 +1956,11 @@ module.exports = createReactClass({
const collapsedRhs = hideRightPanel || this.props.collapsedRhs;
return (
<main className={"mx_RoomView" + (inCall ? " mx_RoomView_inCall" : "")} ref="roomView">
<main className={"mx_RoomView" + (inCall ? " mx_RoomView_inCall" : "")} ref={this._roomView}>
<ErrorBoundary>
<RoomHeader ref="header" room={this.state.room} searchInfo={searchInfo}
<RoomHeader
room={this.state.room}
searchInfo={searchInfo}
oobData={this.props.oobData}
inRoom={myMembership === 'join'}
collapsedRhs={collapsedRhs}

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from "react";
import React, {createRef} from "react";
import createReactClass from 'create-react-class';
import PropTypes from 'prop-types';
import { KeyCode } from '../../Keyboard';
@ -166,6 +166,8 @@ module.exports = createReactClass({
}
this.resetScrollState();
this._itemlist = createRef();
},
componentDidMount: function() {
@ -328,7 +330,7 @@ module.exports = createReactClass({
this._isFilling = true;
}
const itemlist = this.refs.itemlist;
const itemlist = this._itemlist.current;
const firstTile = itemlist && itemlist.firstElementChild;
const contentTop = firstTile && firstTile.offsetTop;
const fillPromises = [];
@ -373,7 +375,7 @@ module.exports = createReactClass({
const origExcessHeight = excessHeight;
const tiles = this.refs.itemlist.children;
const tiles = this._itemlist.current.children;
// The scroll token of the first/last tile to be unpaginated
let markerScrollToken = null;
@ -602,7 +604,7 @@ module.exports = createReactClass({
const scrollNode = this._getScrollNode();
const viewportBottom = scrollNode.scrollHeight - (scrollNode.scrollTop + scrollNode.clientHeight);
const itemlist = this.refs.itemlist;
const itemlist = this._itemlist.current;
const messages = itemlist.children;
let node = null;
@ -644,7 +646,7 @@ module.exports = createReactClass({
const sn = this._getScrollNode();
sn.scrollTop = sn.scrollHeight;
} else if (scrollState.trackedScrollToken) {
const itemlist = this.refs.itemlist;
const itemlist = this._itemlist.current;
const trackedNode = this._getTrackedNode();
if (trackedNode) {
const newBottomOffset = this._topFromBottom(trackedNode);
@ -682,7 +684,7 @@ module.exports = createReactClass({
}
const sn = this._getScrollNode();
const itemlist = this.refs.itemlist;
const itemlist = this._itemlist.current;
const contentHeight = this._getMessagesHeight();
const minHeight = sn.clientHeight;
const height = Math.max(minHeight, contentHeight);
@ -724,7 +726,7 @@ module.exports = createReactClass({
if (!trackedNode || !trackedNode.parentElement) {
let node;
const messages = this.refs.itemlist.children;
const messages = this._itemlist.current.children;
const scrollToken = scrollState.trackedScrollToken;
for (let i = messages.length-1; i >= 0; --i) {
@ -756,7 +758,7 @@ module.exports = createReactClass({
},
_getMessagesHeight() {
const itemlist = this.refs.itemlist;
const itemlist = this._itemlist.current;
const lastNode = itemlist.lastElementChild;
const lastNodeBottom = lastNode ? lastNode.offsetTop + lastNode.clientHeight : 0;
const firstNodeTop = itemlist.firstElementChild ? itemlist.firstElementChild.offsetTop : 0;
@ -765,7 +767,7 @@ module.exports = createReactClass({
},
_topFromBottom(node) {
return this.refs.itemlist.clientHeight - node.offsetTop;
return this._itemlist.current.clientHeight - node.offsetTop;
},
/* get the DOM node which has the scrollTop property we care about for our
@ -797,7 +799,7 @@ module.exports = createReactClass({
the same minimum bottom offset, effectively preventing the timeline to shrink.
*/
preventShrinking: function() {
const messageList = this.refs.itemlist;
const messageList = this._itemlist.current;
const tiles = messageList && messageList.children;
if (!messageList) {
return;
@ -824,7 +826,7 @@ module.exports = createReactClass({
/** Clear shrinking prevention. Used internally, and when the timeline is reloaded. */
clearPreventShrinking: function() {
const messageList = this.refs.itemlist;
const messageList = this._itemlist.current;
const balanceElement = messageList && messageList.parentElement;
if (balanceElement) balanceElement.style.paddingBottom = null;
this.preventShrinkingState = null;
@ -843,7 +845,7 @@ module.exports = createReactClass({
if (this.preventShrinkingState) {
const sn = this._getScrollNode();
const scrollState = this.scrollState;
const messageList = this.refs.itemlist;
const messageList = this._itemlist.current;
const {offsetNode, offsetFromBottom} = this.preventShrinkingState;
// element used to set paddingBottom to balance the typing notifs disappearing
const balanceElement = messageList.parentElement;
@ -879,7 +881,7 @@ module.exports = createReactClass({
onScroll={this.onScroll}
className={`mx_ScrollPanel ${this.props.className}`} style={this.props.style}>
<div className="mx_RoomView_messageListWrapper">
<ol ref="itemlist" className="mx_RoomView_MessageList" aria-live="polite">
<ol ref={this._itemlist} className="mx_RoomView_MessageList" aria-live="polite">
{ this.props.children }
</ol>
</div>

View file

@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import React, {createRef} from 'react';
import createReactClass from 'create-react-class';
import PropTypes from 'prop-types';
import { KeyCode } from '../../Keyboard';
@ -53,6 +53,10 @@ module.exports = createReactClass({
};
},
UNSAFE_componentWillMount: function() {
this._search = createRef();
},
componentDidMount: function() {
this.dispatcherRef = dis.register(this.onAction);
},
@ -66,26 +70,26 @@ module.exports = createReactClass({
switch (payload.action) {
case 'view_room':
if (this.refs.search && payload.clear_search) {
if (this._search.current && payload.clear_search) {
this._clearSearch();
}
break;
case 'focus_room_filter':
if (this.refs.search) {
this.refs.search.focus();
if (this._search.current) {
this._search.current.focus();
}
break;
}
},
onChange: function() {
if (!this.refs.search) return;
this.setState({ searchTerm: this.refs.search.value });
if (!this._search.current) return;
this.setState({ searchTerm: this._search.current.value });
this.onSearch();
},
onSearch: throttle(function() {
this.props.onSearch(this.refs.search.value);
this.props.onSearch(this._search.current.value);
}, 200, {trailing: true, leading: true}),
_onKeyDown: function(ev) {
@ -113,7 +117,7 @@ module.exports = createReactClass({
},
_clearSearch: function(source) {
this.refs.search.value = "";
this._search.current.value = "";
this.onChange();
if (this.props.onCleared) {
this.props.onCleared(source);
@ -146,7 +150,7 @@ module.exports = createReactClass({
<input
key="searchfield"
type="text"
ref="search"
ref={this._search}
className={"mx_textinput_icon mx_textinput_search " + className}
value={ this.state.searchTerm }
onFocus={ this._onFocus }

View file

@ -19,7 +19,7 @@ limitations under the License.
import SettingsStore from "../../settings/SettingsStore";
import React from 'react';
import React, {createRef} from 'react';
import createReactClass from 'create-react-class';
import ReactDOM from "react-dom";
import PropTypes from 'prop-types';
@ -203,6 +203,8 @@ const TimelinePanel = createReactClass({
this.lastRRSentEventId = undefined;
this.lastRMSentEventId = undefined;
this._messagePanel = createRef();
if (this.props.manageReadReceipts) {
this.updateReadReceiptOnUserActivity();
}
@ -425,8 +427,8 @@ const TimelinePanel = createReactClass({
if (payload.action === "edit_event") {
const editState = payload.event ? new EditorStateTransfer(payload.event) : null;
this.setState({editState}, () => {
if (payload.event && this.refs.messagePanel) {
this.refs.messagePanel.scrollToEventIfNeeded(
if (payload.event && this._messagePanel.current) {
this._messagePanel.current.scrollToEventIfNeeded(
payload.event.getId(),
);
}
@ -442,9 +444,9 @@ const TimelinePanel = createReactClass({
// updates from pagination will happen when the paginate completes.
if (toStartOfTimeline || !data || !data.liveEvent) return;
if (!this.refs.messagePanel) return;
if (!this._messagePanel.current) return;
if (!this.refs.messagePanel.getScrollState().stuckAtBottom) {
if (!this._messagePanel.current.getScrollState().stuckAtBottom) {
// we won't load this event now, because we don't want to push any
// events off the other end of the timeline. But we need to note
// that we can now paginate.
@ -499,7 +501,7 @@ const TimelinePanel = createReactClass({
}
this.setState(updatedState, () => {
this.refs.messagePanel.updateTimelineMinHeight();
this._messagePanel.current.updateTimelineMinHeight();
if (callRMUpdated) {
this.props.onReadMarkerUpdated();
}
@ -510,13 +512,13 @@ const TimelinePanel = createReactClass({
onRoomTimelineReset: function(room, timelineSet) {
if (timelineSet !== this.props.timelineSet) return;
if (this.refs.messagePanel && this.refs.messagePanel.isAtBottom()) {
if (this._messagePanel.current && this._messagePanel.current.isAtBottom()) {
this._loadTimeline();
}
},
canResetTimeline: function() {
return this.refs.messagePanel && this.refs.messagePanel.isAtBottom();
return this._messagePanel.current && this._messagePanel.current.isAtBottom();
},
onRoomRedaction: function(ev, room) {
@ -629,7 +631,7 @@ const TimelinePanel = createReactClass({
sendReadReceipt: function() {
if (SettingsStore.getValue("lowBandwidth")) return;
if (!this.refs.messagePanel) return;
if (!this._messagePanel.current) return;
if (!this.props.manageReadReceipts) return;
// This happens on user_activity_end which is delayed, and it's
// very possible have logged out within that timeframe, so check
@ -815,8 +817,8 @@ const TimelinePanel = createReactClass({
if (this._timelineWindow.canPaginate(EventTimeline.FORWARDS)) {
this._loadTimeline();
} else {
if (this.refs.messagePanel) {
this.refs.messagePanel.scrollToBottom();
if (this._messagePanel.current) {
this._messagePanel.current.scrollToBottom();
}
}
},
@ -826,7 +828,7 @@ const TimelinePanel = createReactClass({
*/
jumpToReadMarker: function() {
if (!this.props.manageReadMarkers) return;
if (!this.refs.messagePanel) return;
if (!this._messagePanel.current) return;
if (!this.state.readMarkerEventId) return;
// we may not have loaded the event corresponding to the read-marker
@ -835,11 +837,11 @@ const TimelinePanel = createReactClass({
//
// a quick way to figure out if we've loaded the relevant event is
// simply to check if the messagepanel knows where the read-marker is.
const ret = this.refs.messagePanel.getReadMarkerPosition();
const ret = this._messagePanel.current.getReadMarkerPosition();
if (ret !== null) {
// The messagepanel knows where the RM is, so we must have loaded
// the relevant event.
this.refs.messagePanel.scrollToEvent(this.state.readMarkerEventId,
this._messagePanel.current.scrollToEvent(this.state.readMarkerEventId,
0, 1/3);
return;
}
@ -874,8 +876,8 @@ const TimelinePanel = createReactClass({
* at the end of the live timeline.
*/
isAtEndOfLiveTimeline: function() {
return this.refs.messagePanel
&& this.refs.messagePanel.isAtBottom()
return this._messagePanel.current
&& this._messagePanel.current.isAtBottom()
&& this._timelineWindow
&& !this._timelineWindow.canPaginate(EventTimeline.FORWARDS);
},
@ -887,8 +889,8 @@ const TimelinePanel = createReactClass({
* returns null if we are not mounted.
*/
getScrollState: function() {
if (!this.refs.messagePanel) { return null; }
return this.refs.messagePanel.getScrollState();
if (!this._messagePanel.current) { return null; }
return this._messagePanel.current.getScrollState();
},
// returns one of:
@ -899,9 +901,9 @@ const TimelinePanel = createReactClass({
// +1: read marker is below the window
getReadMarkerPosition: function() {
if (!this.props.manageReadMarkers) return null;
if (!this.refs.messagePanel) return null;
if (!this._messagePanel.current) return null;
const ret = this.refs.messagePanel.getReadMarkerPosition();
const ret = this._messagePanel.current.getReadMarkerPosition();
if (ret !== null) {
return ret;
}
@ -936,7 +938,7 @@ const TimelinePanel = createReactClass({
* We pass it down to the scroll panel.
*/
handleScrollKey: function(ev) {
if (!this.refs.messagePanel) { return; }
if (!this._messagePanel.current) { return; }
// jump to the live timeline on ctrl-end, rather than the end of the
// timeline window.
@ -944,7 +946,7 @@ const TimelinePanel = createReactClass({
ev.keyCode == KeyCode.END) {
this.jumpToLiveTimeline();
} else {
this.refs.messagePanel.handleScrollKey(ev);
this._messagePanel.current.handleScrollKey(ev);
}
},
@ -986,8 +988,8 @@ const TimelinePanel = createReactClass({
const onLoaded = () => {
// clear the timeline min-height when
// (re)loading the timeline
if (this.refs.messagePanel) {
this.refs.messagePanel.onTimelineReset();
if (this._messagePanel.current) {
this._messagePanel.current.onTimelineReset();
}
this._reloadEvents();
@ -1002,7 +1004,7 @@ const TimelinePanel = createReactClass({
timelineLoading: false,
}, () => {
// initialise the scroll state of the message panel
if (!this.refs.messagePanel) {
if (!this._messagePanel.current) {
// this shouldn't happen - we know we're mounted because
// we're in a setState callback, and we know
// timelineLoading is now false, so render() should have
@ -1012,10 +1014,10 @@ const TimelinePanel = createReactClass({
return;
}
if (eventId) {
this.refs.messagePanel.scrollToEvent(eventId, pixelOffset,
this._messagePanel.current.scrollToEvent(eventId, pixelOffset,
offsetBase);
} else {
this.refs.messagePanel.scrollToBottom();
this._messagePanel.current.scrollToBottom();
}
this.sendReadReceipt();
@ -1134,7 +1136,7 @@ const TimelinePanel = createReactClass({
const ignoreOwn = opts.ignoreOwn || false;
const allowPartial = opts.allowPartial || false;
const messagePanel = this.refs.messagePanel;
const messagePanel = this._messagePanel.current;
if (messagePanel === undefined) return null;
const EventTile = sdk.getComponent('rooms.EventTile');
@ -1313,7 +1315,8 @@ const TimelinePanel = createReactClass({
['PREPARED', 'CATCHUP'].includes(this.state.clientSyncState)
);
return (
<MessagePanel ref="messagePanel"
<MessagePanel
ref={this._messagePanel}
room={this.props.timelineSet.room}
permalinkCreator={this.props.permalinkCreator}
hidden={this.props.hidden}

View file

@ -17,15 +17,13 @@ limitations under the License.
import React from 'react';
import PropTypes from 'prop-types';
import * as ContextualMenu from './ContextualMenu';
import {TopLeftMenu} from '../views/context_menus/TopLeftMenu';
import AccessibleButton from '../views/elements/AccessibleButton';
import BaseAvatar from '../views/avatars/BaseAvatar';
import MatrixClientPeg from '../../MatrixClientPeg';
import Avatar from '../../Avatar';
import { _t } from '../../languageHandler';
import dis from "../../dispatcher";
import {focusCapturedRef} from "../../utils/Accessibility";
import {ContextMenu, ContextMenuButton} from "./ContextMenu";
const AVATAR_SIZE = 28;
@ -40,11 +38,8 @@ export default class TopLeftMenuButton extends React.Component {
super();
this.state = {
menuDisplayed: false,
menuFunctions: null, // should be { close: fn }
profileInfo: null,
};
this.onToggleMenu = this.onToggleMenu.bind(this);
}
async _getProfileInfo() {
@ -95,7 +90,21 @@ export default class TopLeftMenuButton extends React.Component {
}
}
openMenu = (e) => {
e.preventDefault();
e.stopPropagation();
this.setState({ menuDisplayed: true });
};
closeMenu = () => {
this.setState({
menuDisplayed: false,
});
};
render() {
const cli = MatrixClientPeg.get().getUserId();
const name = this._getDisplayName();
let nameElement;
let chevronElement;
@ -106,14 +115,29 @@ export default class TopLeftMenuButton extends React.Component {
chevronElement = <span className="mx_TopLeftMenuButton_chevron" />;
}
return (
<AccessibleButton
let contextMenu;
if (this.state.menuDisplayed) {
const elementRect = this._buttonRef.getBoundingClientRect();
contextMenu = (
<ContextMenu
chevronFace="none"
left={elementRect.left}
top={elementRect.top + elementRect.height}
onFinished={this.closeMenu}
>
<TopLeftMenu displayName={name} userId={cli} onFinished={this.closeMenu} />
</ContextMenu>
);
}
return <React.Fragment>
<ContextMenuButton
className="mx_TopLeftMenuButton"
onClick={this.onToggleMenu}
onClick={this.openMenu}
inputRef={(r) => this._buttonRef = r}
aria-label={_t("Your profile")}
aria-haspopup={true}
aria-expanded={this.state.menuDisplayed}
label={_t("Your profile")}
isExpanded={this.state.menuDisplayed}
>
<BaseAvatar
idName={MatrixClientPeg.get().getUserId()}
@ -125,34 +149,9 @@ export default class TopLeftMenuButton extends React.Component {
/>
{ nameElement }
{ chevronElement }
</AccessibleButton>
);
}
</ContextMenuButton>
onToggleMenu(e) {
e.preventDefault();
e.stopPropagation();
if (this.state.menuDisplayed && this.state.menuFunctions) {
this.state.menuFunctions.close();
return;
}
const elementRect = e.currentTarget.getBoundingClientRect();
const x = elementRect.left;
const y = elementRect.top + elementRect.height;
const menuFunctions = ContextualMenu.createMenu(TopLeftMenu, {
chevronFace: "none",
left: x,
top: y,
userId: MatrixClientPeg.get().getUserId(),
displayName: this._getDisplayName(),
containerRef: focusCapturedRef, // Focus the TopLeftMenu on first render
onFinished: () => {
this.setState({ menuDisplayed: false, menuFunctions: null });
},
});
this.setState({ menuDisplayed: true, menuFunctions });
{ contextMenu }
</React.Fragment>;
}
}

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import React, {createRef} from 'react';
import createReactClass from 'create-react-class';
import PropTypes from 'prop-types';
import { _t } from '../../../languageHandler';
@ -48,6 +48,8 @@ module.exports = createReactClass({
componentWillMount: function() {
this._captchaWidgetId = null;
this._recaptchaContainer = createRef();
},
componentDidMount: function() {
@ -67,7 +69,7 @@ module.exports = createReactClass({
scriptTag.setAttribute(
'src', `${protocol}//www.recaptcha.net/recaptcha/api.js?onload=mx_on_recaptcha_loaded&render=explicit`,
);
this.refs.recaptchaContainer.appendChild(scriptTag);
this._recaptchaContainer.current.appendChild(scriptTag);
}
},
@ -124,11 +126,11 @@ module.exports = createReactClass({
}
return (
<div ref="recaptchaContainer">
<div ref={this._recaptchaContainer}>
<p>{_t(
"This homeserver would like to make sure you are not a robot.",
)}</p>
<div id={DIV_ID}></div>
<div id={DIV_ID} />
{ error }
</div>
);

View file

@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import React, {createRef} from 'react';
import createReactClass from 'create-react-class';
import PropTypes from 'prop-types';
import url from 'url';
@ -581,6 +581,8 @@ export const FallbackAuthEntry = createReactClass({
// the popup if we open it immediately.
this._popupWindow = null;
window.addEventListener("message", this._onReceiveMessage);
this._fallbackButton = createRef();
},
componentWillUnmount: function() {
@ -591,8 +593,8 @@ export const FallbackAuthEntry = createReactClass({
},
focus: function() {
if (this.refs.fallbackButton) {
this.refs.fallbackButton.focus();
if (this._fallbackButton.current) {
this._fallbackButton.current.focus();
}
},
@ -624,7 +626,7 @@ export const FallbackAuthEntry = createReactClass({
}
return (
<div>
<a ref="fallbackButton" onClick={this._onShowFallbackClick}>{ _t("Start authentication") }</a>
<a ref={this._fallbackButton} onClick={this._onShowFallbackClick}>{ _t("Start authentication") }</a>
{errorSection}
</div>
);

View file

@ -14,15 +14,15 @@ 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 MatrixClientPeg from '../../../MatrixClientPeg';
import AccessibleButton from '../elements/AccessibleButton';
import {_t} from "../../../languageHandler";
import MemberAvatar from '../avatars/MemberAvatar';
import classNames from 'classnames';
import * as ContextualMenu from "../../structures/ContextualMenu";
import StatusMessageContextMenu from "../context_menus/StatusMessageContextMenu";
import SettingsStore from "../../../settings/SettingsStore";
import {ContextMenu, ContextMenuButton} from "../../structures/ContextMenu";
export default class MemberStatusMessageAvatar extends React.Component {
static propTypes = {
@ -43,7 +43,10 @@ export default class MemberStatusMessageAvatar extends React.Component {
this.state = {
hasStatus: this.hasStatus,
menuDisplayed: false,
};
this._button = createRef();
}
componentWillMount() {
@ -86,25 +89,12 @@ export default class MemberStatusMessageAvatar extends React.Component {
});
};
_onClick = (e) => {
e.stopPropagation();
openMenu = () => {
this.setState({ menuDisplayed: true });
};
const elementRect = e.target.getBoundingClientRect();
const x = (elementRect.left + window.pageXOffset);
const chevronWidth = 16; // See .mx_ContextualMenu_chevron_bottom
const chevronOffset = (elementRect.width - chevronWidth) / 2;
const chevronMargin = 1; // Add some spacing away from target
const y = elementRect.top + window.pageYOffset - chevronMargin;
ContextualMenu.createMenu(StatusMessageContextMenu, {
chevronOffset: chevronOffset,
chevronFace: 'bottom',
left: x,
top: y,
menuWidth: 226,
user: this.props.member.user,
});
closeMenu = () => {
this.setState({ menuDisplayed: false });
};
render() {
@ -124,10 +114,39 @@ export default class MemberStatusMessageAvatar extends React.Component {
"mx_MemberStatusMessageAvatar_hasStatus": this.state.hasStatus,
});
return <AccessibleButton className={classes}
element="div" onClick={this._onClick}
>
{avatar}
</AccessibleButton>;
let contextMenu;
if (this.state.menuDisplayed) {
const elementRect = this._button.current.getBoundingClientRect();
const chevronWidth = 16; // See .mx_ContextualMenu_chevron_bottom
const chevronMargin = 1; // Add some spacing away from target
contextMenu = (
<ContextMenu
chevronOffset={(elementRect.width - chevronWidth) / 2}
chevronFace="bottom"
left={elementRect.left + window.pageXOffset}
top={elementRect.top + window.pageYOffset - chevronMargin}
menuWidth={226}
onFinished={this.closeMenu}
>
<StatusMessageContextMenu user={this.props.member.user} onFinished={this.closeMenu} />
</ContextMenu>
);
}
return <React.Fragment>
<ContextMenuButton
className={classes}
inputRef={this._button}
onClick={this.openMenu}
isExpanded={this.state.menuDisplayed}
label={_t("User Status")}
>
{avatar}
</ContextMenuButton>
{ contextMenu }
</React.Fragment>;
}
}

View file

@ -22,6 +22,7 @@ import { _t } from '../../../languageHandler';
import Modal from '../../../Modal';
import {Group} from 'matrix-js-sdk';
import GroupStore from "../../../stores/GroupStore";
import {MenuItem} from "../../structures/ContextMenu";
export default class GroupInviteTileContextMenu extends React.Component {
static propTypes = {
@ -36,7 +37,7 @@ export default class GroupInviteTileContextMenu extends React.Component {
this._onClickReject = this._onClickReject.bind(this);
}
componentWillMount() {
componentDidMount() {
this._unmounted = false;
}
@ -78,12 +79,11 @@ export default class GroupInviteTileContextMenu extends React.Component {
}
render() {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
return <div>
<AccessibleButton className="mx_RoomTileContextMenu_leave" onClick={this._onClickReject} >
<img className="mx_RoomTileContextMenu_tag_icon" src={require("../../../../res/img/icon_context_delete.svg")} width="15" height="15" />
<MenuItem className="mx_RoomTileContextMenu_leave" onClick={this._onClickReject}>
<img className="mx_RoomTileContextMenu_tag_icon" src={require("../../../../res/img/icon_context_delete.svg")} width="15" height="15" alt="" />
{ _t('Reject') }
</AccessibleButton>
</MenuItem>
</div>;
}
}

View file

@ -31,6 +31,7 @@ import Resend from '../../../Resend';
import SettingsStore from '../../../settings/SettingsStore';
import { isUrlPermitted } from '../../../HtmlUtils';
import { isContentActionable } from '../../../utils/EventUtils';
import {MenuItem} from "../../structures/ContextMenu";
function canCancel(eventStatus) {
return eventStatus === EventStatus.QUEUED || eventStatus === EventStatus.NOT_SENT;
@ -289,8 +290,6 @@ module.exports = createReactClass({
},
render: function() {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
const cli = MatrixClientPeg.get();
const me = cli.getUserId();
const mxEvent = this.props.mxEvent;
@ -322,89 +321,89 @@ module.exports = createReactClass({
if (!mxEvent.isRedacted()) {
if (eventStatus === EventStatus.NOT_SENT) {
resendButton = (
<AccessibleButton className="mx_MessageContextMenu_field" onClick={this.onResendClick}>
<MenuItem className="mx_MessageContextMenu_field" onClick={this.onResendClick}>
{ _t('Resend') }
</AccessibleButton>
</MenuItem>
);
}
if (editStatus === EventStatus.NOT_SENT) {
resendEditButton = (
<AccessibleButton className="mx_MessageContextMenu_field" onClick={this.onResendEditClick}>
<MenuItem className="mx_MessageContextMenu_field" onClick={this.onResendEditClick}>
{ _t('Resend edit') }
</AccessibleButton>
</MenuItem>
);
}
if (unsentReactionsCount !== 0) {
resendReactionsButton = (
<AccessibleButton className="mx_MessageContextMenu_field" onClick={this.onResendReactionsClick}>
<MenuItem className="mx_MessageContextMenu_field" onClick={this.onResendReactionsClick}>
{ _t('Resend %(unsentCount)s reaction(s)', {unsentCount: unsentReactionsCount}) }
</AccessibleButton>
</MenuItem>
);
}
}
if (redactStatus === EventStatus.NOT_SENT) {
resendRedactionButton = (
<AccessibleButton className="mx_MessageContextMenu_field" onClick={this.onResendRedactionClick}>
<MenuItem className="mx_MessageContextMenu_field" onClick={this.onResendRedactionClick}>
{ _t('Resend removal') }
</AccessibleButton>
</MenuItem>
);
}
if (isSent && this.state.canRedact) {
redactButton = (
<AccessibleButton className="mx_MessageContextMenu_field" onClick={this.onRedactClick}>
<MenuItem className="mx_MessageContextMenu_field" onClick={this.onRedactClick}>
{ _t('Remove') }
</AccessibleButton>
</MenuItem>
);
}
if (allowCancel) {
cancelButton = (
<AccessibleButton className="mx_MessageContextMenu_field" onClick={this.onCancelSendClick}>
<MenuItem className="mx_MessageContextMenu_field" onClick={this.onCancelSendClick}>
{ _t('Cancel Sending') }
</AccessibleButton>
</MenuItem>
);
}
if (isContentActionable(mxEvent)) {
forwardButton = (
<AccessibleButton className="mx_MessageContextMenu_field" onClick={this.onForwardClick}>
<MenuItem className="mx_MessageContextMenu_field" onClick={this.onForwardClick}>
{ _t('Forward Message') }
</AccessibleButton>
</MenuItem>
);
if (this.state.canPin) {
pinButton = (
<AccessibleButton className="mx_MessageContextMenu_field" onClick={this.onPinClick}>
<MenuItem className="mx_MessageContextMenu_field" onClick={this.onPinClick}>
{ this._isPinned() ? _t('Unpin Message') : _t('Pin Message') }
</AccessibleButton>
</MenuItem>
);
}
}
const viewSourceButton = (
<AccessibleButton className="mx_MessageContextMenu_field" onClick={this.onViewSourceClick}>
<MenuItem className="mx_MessageContextMenu_field" onClick={this.onViewSourceClick}>
{ _t('View Source') }
</AccessibleButton>
</MenuItem>
);
if (mxEvent.getType() !== mxEvent.getWireType()) {
viewClearSourceButton = (
<AccessibleButton className="mx_MessageContextMenu_field" onClick={this.onViewClearSourceClick}>
<MenuItem className="mx_MessageContextMenu_field" onClick={this.onViewClearSourceClick}>
{ _t('View Decrypted Source') }
</AccessibleButton>
</MenuItem>
);
}
if (this.props.eventTileOps) {
if (this.props.eventTileOps.isWidgetHidden()) {
unhidePreviewButton = (
<AccessibleButton className="mx_MessageContextMenu_field" onClick={this.onUnhidePreviewClick}>
<MenuItem className="mx_MessageContextMenu_field" onClick={this.onUnhidePreviewClick}>
{ _t('Unhide Preview') }
</AccessibleButton>
</MenuItem>
);
}
}
@ -415,19 +414,19 @@ module.exports = createReactClass({
}
// XXX: if we use room ID, we should also include a server where the event can be found (other than in the domain of the event ID)
const permalinkButton = (
<AccessibleButton className="mx_MessageContextMenu_field">
<MenuItem className="mx_MessageContextMenu_field">
<a href={permalink} target="_blank" rel="noopener" onClick={this.onPermalinkClick} tabIndex={-1}>
{ mxEvent.isRedacted() || mxEvent.getType() !== 'm.room.message'
? _t('Share Permalink') : _t('Share Message') }
</a>
</AccessibleButton>
</MenuItem>
);
if (this.props.eventTileOps && this.props.eventTileOps.getInnerText) {
quoteButton = (
<AccessibleButton className="mx_MessageContextMenu_field" onClick={this.onQuoteClick}>
<MenuItem className="mx_MessageContextMenu_field" onClick={this.onQuoteClick}>
{ _t('Quote') }
</AccessibleButton>
</MenuItem>
);
}
@ -437,7 +436,7 @@ module.exports = createReactClass({
isUrlPermitted(mxEvent.event.content.external_url)
) {
externalURLButton = (
<AccessibleButton className="mx_MessageContextMenu_field">
<MenuItem className="mx_MessageContextMenu_field">
<a
href={mxEvent.event.content.external_url}
target="_blank"
@ -447,33 +446,33 @@ module.exports = createReactClass({
>
{ _t('Source URL') }
</a>
</AccessibleButton>
</MenuItem>
);
}
if (this.props.collapseReplyThread) {
collapseReplyThread = (
<AccessibleButton className="mx_MessageContextMenu_field" onClick={this.onCollapseReplyThreadClick}>
<MenuItem className="mx_MessageContextMenu_field" onClick={this.onCollapseReplyThreadClick}>
{ _t('Collapse Reply Thread') }
</AccessibleButton>
</MenuItem>
);
}
let e2eInfo;
if (this.props.e2eInfoCallback) {
e2eInfo = (
<AccessibleButton className="mx_MessageContextMenu_field" onClick={this.e2eInfoClicked}>
<MenuItem className="mx_MessageContextMenu_field" onClick={this.e2eInfoClicked}>
{ _t('End-to-end encryption information') }
</AccessibleButton>
</MenuItem>
);
}
let reportEventButton;
if (mxEvent.getSender() !== me) {
reportEventButton = (
<AccessibleButton className="mx_MessageContextMenu_field" onClick={this.onReportEventClick}>
<MenuItem className="mx_MessageContextMenu_field" onClick={this.onReportEventClick}>
{ _t('Report Content') }
</AccessibleButton>
</MenuItem>
);
}

View file

@ -32,6 +32,36 @@ import Modal from '../../../Modal';
import RoomListActions from '../../../actions/RoomListActions';
import RoomViewStore from '../../../stores/RoomViewStore';
import {sleep} from "../../../utils/promise";
import {MenuItem, MenuItemCheckbox, MenuItemRadio} from "../../structures/ContextMenu";
const RoomTagOption = ({active, onClick, src, srcSet, label}) => {
const classes = classNames('mx_RoomTileContextMenu_tag_field', {
'mx_RoomTileContextMenu_tag_fieldSet': active,
'mx_RoomTileContextMenu_tag_fieldDisabled': false,
});
return (
<MenuItemCheckbox className={classes} onClick={onClick} active={active} label={label}>
<img className="mx_RoomTileContextMenu_tag_icon" src={src} width="15" height="15" alt="" />
<img className="mx_RoomTileContextMenu_tag_icon_set" src={srcSet} width="15" height="15" alt="" />
{ label }
</MenuItemCheckbox>
);
};
const NotifOption = ({active, onClick, src, label}) => {
const classes = classNames('mx_RoomTileContextMenu_notif_field', {
'mx_RoomTileContextMenu_notif_fieldSet': active,
});
return (
<MenuItemRadio className={classes} onClick={onClick} active={active} label={label}>
<img className="mx_RoomTileContextMenu_notif_activeIcon" src={require("../../../../res/img/notif-active.svg")} width="12" height="12" alt="" />
<img className="mx_RoomTileContextMenu_notif_icon mx_filterFlipColor" src={src} width="16" height="12" alt="" />
{ label }
</MenuItemRadio>
);
};
module.exports = createReactClass({
displayName: 'RoomTileContextMenu',
@ -228,53 +258,36 @@ module.exports = createReactClass({
},
_renderNotifMenu: function() {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
const alertMeClasses = classNames({
'mx_RoomTileContextMenu_notif_field': true,
'mx_RoomTileContextMenu_notif_fieldSet': this.state.roomNotifState == RoomNotifs.ALL_MESSAGES_LOUD,
});
const allNotifsClasses = classNames({
'mx_RoomTileContextMenu_notif_field': true,
'mx_RoomTileContextMenu_notif_fieldSet': this.state.roomNotifState == RoomNotifs.ALL_MESSAGES,
});
const mentionsClasses = classNames({
'mx_RoomTileContextMenu_notif_field': true,
'mx_RoomTileContextMenu_notif_fieldSet': this.state.roomNotifState == RoomNotifs.MENTIONS_ONLY,
});
const muteNotifsClasses = classNames({
'mx_RoomTileContextMenu_notif_field': true,
'mx_RoomTileContextMenu_notif_fieldSet': this.state.roomNotifState == RoomNotifs.MUTE,
});
return (
<div className="mx_RoomTileContextMenu">
<div className="mx_RoomTileContextMenu_notif_picker">
<img src={require("../../../../res/img/notif-slider.svg")} width="20" height="107" />
<div className="mx_RoomTileContextMenu" role="group" aria-label={_t("Notification settings")}>
<div className="mx_RoomTileContextMenu_notif_picker" role="presentation">
<img src={require("../../../../res/img/notif-slider.svg")} width="20" height="107" alt="" />
</div>
<AccessibleButton className={alertMeClasses} onClick={this._onClickAlertMe}>
<img className="mx_RoomTileContextMenu_notif_activeIcon" src={require("../../../../res/img/notif-active.svg")} width="12" height="12" />
<img className="mx_RoomTileContextMenu_notif_icon mx_filterFlipColor" src={require("../../../../res/img/icon-context-mute-off-copy.svg")} width="16" height="12" />
{ _t('All messages (noisy)') }
</AccessibleButton>
<AccessibleButton className={allNotifsClasses} onClick={this._onClickAllNotifs}>
<img className="mx_RoomTileContextMenu_notif_activeIcon" src={require("../../../../res/img/notif-active.svg")} width="12" height="12" />
<img className="mx_RoomTileContextMenu_notif_icon mx_filterFlipColor" src={require("../../../../res/img/icon-context-mute-off.svg")} width="16" height="12" />
{ _t('All messages') }
</AccessibleButton>
<AccessibleButton className={mentionsClasses} onClick={this._onClickMentions}>
<img className="mx_RoomTileContextMenu_notif_activeIcon" src={require("../../../../res/img/notif-active.svg")} width="12" height="12" />
<img className="mx_RoomTileContextMenu_notif_icon mx_filterFlipColor" src={require("../../../../res/img/icon-context-mute-mentions.svg")} width="16" height="12" />
{ _t('Mentions only') }
</AccessibleButton>
<AccessibleButton className={muteNotifsClasses} onClick={this._onClickMute}>
<img className="mx_RoomTileContextMenu_notif_activeIcon" src={require("../../../../res/img/notif-active.svg")} width="12" height="12" />
<img className="mx_RoomTileContextMenu_notif_icon mx_filterFlipColor" src={require("../../../../res/img/icon-context-mute.svg")} width="16" height="12" />
{ _t('Mute') }
</AccessibleButton>
<NotifOption
active={this.state.roomNotifState === RoomNotifs.ALL_MESSAGES_LOUD}
label={_t('All messages (noisy)')}
onClick={this._onClickAlertMe}
src={require("../../../../res/img/icon-context-mute-off-copy.svg")}
/>
<NotifOption
active={this.state.roomNotifState === RoomNotifs.ALL_MESSAGES}
label={_t('All messages')}
onClick={this._onClickAllNotifs}
src={require("../../../../res/img/icon-context-mute-off.svg")}
/>
<NotifOption
active={this.state.roomNotifState === RoomNotifs.MENTIONS_ONLY}
label={_t('Mentions only')}
onClick={this._onClickMentions}
src={require("../../../../res/img/icon-context-mute-mentions.svg")}
/>
<NotifOption
active={this.state.roomNotifState === RoomNotifs.MUTE}
label={_t('Mute')}
onClick={this._onClickMute}
src={require("../../../../res/img/icon-context-mute.svg")}
/>
</div>
);
},
@ -290,13 +303,12 @@ module.exports = createReactClass({
},
_renderSettingsMenu: function() {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
return (
<div>
<AccessibleButton className="mx_RoomTileContextMenu_tag_field" onClick={this._onClickSettings} >
<img className="mx_RoomTileContextMenu_tag_icon" src={require("../../../../res/img/icons-settings-room.svg")} width="15" height="15" />
<MenuItem className="mx_RoomTileContextMenu_tag_field" onClick={this._onClickSettings}>
<img className="mx_RoomTileContextMenu_tag_icon" src={require("../../../../res/img/icons-settings-room.svg")} width="15" height="15" alt="" />
{ _t('Settings') }
</AccessibleButton>
</MenuItem>
</div>
);
},
@ -306,8 +318,6 @@ module.exports = createReactClass({
return null;
}
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
let leaveClickHandler = null;
let leaveText = null;
@ -329,52 +339,38 @@ module.exports = createReactClass({
return (
<div>
<AccessibleButton className="mx_RoomTileContextMenu_leave" onClick={leaveClickHandler} >
<img className="mx_RoomTileContextMenu_tag_icon" src={require("../../../../res/img/icon_context_delete.svg")} width="15" height="15" />
<MenuItem className="mx_RoomTileContextMenu_leave" onClick={leaveClickHandler}>
<img className="mx_RoomTileContextMenu_tag_icon" src={require("../../../../res/img/icon_context_delete.svg")} width="15" height="15" alt="" />
{ leaveText }
</AccessibleButton>
</MenuItem>
</div>
);
},
_renderRoomTagMenu: function() {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
const favouriteClasses = classNames({
'mx_RoomTileContextMenu_tag_field': true,
'mx_RoomTileContextMenu_tag_fieldSet': this.state.isFavourite,
'mx_RoomTileContextMenu_tag_fieldDisabled': false,
});
const lowPriorityClasses = classNames({
'mx_RoomTileContextMenu_tag_field': true,
'mx_RoomTileContextMenu_tag_fieldSet': this.state.isLowPriority,
'mx_RoomTileContextMenu_tag_fieldDisabled': false,
});
const dmClasses = classNames({
'mx_RoomTileContextMenu_tag_field': true,
'mx_RoomTileContextMenu_tag_fieldSet': this.state.isDirectMessage,
'mx_RoomTileContextMenu_tag_fieldDisabled': false,
});
return (
<div>
<AccessibleButton className={favouriteClasses} onClick={this._onClickFavourite} >
<img className="mx_RoomTileContextMenu_tag_icon" src={require("../../../../res/img/icon_context_fave.svg")} width="15" height="15" />
<img className="mx_RoomTileContextMenu_tag_icon_set" src={require("../../../../res/img/icon_context_fave_on.svg")} width="15" height="15" />
{ _t('Favourite') }
</AccessibleButton>
<AccessibleButton className={lowPriorityClasses} onClick={this._onClickLowPriority} >
<img className="mx_RoomTileContextMenu_tag_icon" src={require("../../../../res/img/icon_context_low.svg")} width="15" height="15" />
<img className="mx_RoomTileContextMenu_tag_icon_set" src={require("../../../../res/img/icon_context_low_on.svg")} width="15" height="15" />
{ _t('Low Priority') }
</AccessibleButton>
<AccessibleButton className={dmClasses} onClick={this._onClickDM} >
<img className="mx_RoomTileContextMenu_tag_icon" src={require("../../../../res/img/icon_context_person.svg")} width="15" height="15" />
<img className="mx_RoomTileContextMenu_tag_icon_set" src={require("../../../../res/img/icon_context_person_on.svg")} width="15" height="15" />
{ _t('Direct Chat') }
</AccessibleButton>
<RoomTagOption
active={this.state.isFavourite}
label={_t('Favourite')}
onClick={this._onClickFavourite}
src={require("../../../../res/img/icon_context_fave.svg")}
srcSet={require("../../../../res/img/icon_context_fave_on.svg")}
/>
<RoomTagOption
active={this.state.isLowPriority}
label={_t('Low Priority')}
onClick={this._onClickLowPriority}
src={require("../../../../res/img/icon_context_low.svg")}
srcSet={require("../../../../res/img/icon_context_low_on.svg")}
/>
<RoomTagOption
active={this.state.isDirectMessage}
label={_t('Direct Chat')}
onClick={this._onClickDM}
src={require("../../../../res/img/icon_context_person.svg")}
srcSet={require("../../../../res/img/icon_context_person_on.svg")}
/>
</div>
);
},
@ -386,11 +382,11 @@ module.exports = createReactClass({
case 'join':
return <div>
{ this._renderNotifMenu() }
<hr className="mx_RoomTileContextMenu_separator" />
<hr className="mx_RoomTileContextMenu_separator" role="separator" />
{ this._renderLeaveMenu(myMembership) }
<hr className="mx_RoomTileContextMenu_separator" />
<hr className="mx_RoomTileContextMenu_separator" role="separator" />
{ this._renderRoomTagMenu() }
<hr className="mx_RoomTileContextMenu_separator" />
<hr className="mx_RoomTileContextMenu_separator" role="separator" />
{ this._renderSettingsMenu() }
</div>;
case 'invite':
@ -400,7 +396,7 @@ module.exports = createReactClass({
default:
return <div>
{ this._renderLeaveMenu(myMembership) }
<hr className="mx_RoomTileContextMenu_separator" />
<hr className="mx_RoomTileContextMenu_separator" role="separator" />
{ this._renderSettingsMenu() }
</div>;
}

View file

@ -1,5 +1,6 @@
/*
Copyright 2018 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.
@ -16,11 +17,12 @@ limitations under the License.
import React from 'react';
import PropTypes from 'prop-types';
import { MatrixClient } from 'matrix-js-sdk';
import { _t } from '../../../languageHandler';
import dis from '../../../dispatcher';
import TagOrderActions from '../../../actions/TagOrderActions';
import MatrixClientPeg from '../../../MatrixClientPeg';
import sdk from '../../../index';
import {MenuItem} from "../../structures/ContextMenu";
export default class TagTileContextMenu extends React.Component {
static propTypes = {
@ -29,6 +31,10 @@ export default class TagTileContextMenu extends React.Component {
onFinished: PropTypes.func.isRequired,
};
static contextTypes = {
matrixClient: PropTypes.instanceOf(MatrixClient),
};
constructor() {
super();
@ -45,18 +51,15 @@ export default class TagTileContextMenu extends React.Component {
}
_onRemoveClick() {
dis.dispatch(TagOrderActions.removeTag(
// XXX: Context menus don't have a MatrixClient context
MatrixClientPeg.get(),
this.props.tag,
));
dis.dispatch(TagOrderActions.removeTag(this.context.matrixClient, this.props.tag));
this.props.onFinished();
}
render() {
const TintableSvg = sdk.getComponent("elements.TintableSvg");
return <div>
<div className="mx_TagTileContextMenu_item" onClick={this._onViewCommunityClick} >
<MenuItem className="mx_TagTileContextMenu_item" onClick={this._onViewCommunityClick}>
<TintableSvg
className="mx_TagTileContextMenu_item_icon"
src={require("../../../../res/img/icons-groups.svg")}
@ -64,12 +67,12 @@ export default class TagTileContextMenu extends React.Component {
height="15"
/>
{ _t('View Community') }
</div>
<hr className="mx_TagTileContextMenu_separator" />
<div className="mx_TagTileContextMenu_item" onClick={this._onRemoveClick} >
<img className="mx_TagTileContextMenu_item_icon" src={require("../../../../res/img/icon_context_delete.svg")} width="15" height="15" />
</MenuItem>
<hr className="mx_TagTileContextMenu_separator" role="separator" />
<MenuItem className="mx_TagTileContextMenu_item" onClick={this._onRemoveClick}>
<img className="mx_TagTileContextMenu_item_icon" src={require("../../../../res/img/icon_context_delete.svg")} width="15" height="15" alt="" />
{ _t('Hide') }
</div>
</MenuItem>
</div>;
}
}

View file

@ -24,7 +24,7 @@ import Modal from "../../../Modal";
import SdkConfig from '../../../SdkConfig';
import { getHostingLink } from '../../../utils/HostingLink';
import MatrixClientPeg from '../../../MatrixClientPeg';
import sdk from "../../../index";
import {MenuItem} from "../../structures/ContextMenu";
export class TopLeftMenu extends React.Component {
static propTypes = {
@ -58,8 +58,6 @@ export class TopLeftMenu extends React.Component {
}
render() {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
const isGuest = MatrixClientPeg.get().isGuest();
const hostingSignupLink = getHostingLink('user-context-menu');
@ -69,10 +67,10 @@ export class TopLeftMenu extends React.Component {
{_t(
"<a>Upgrade</a> to your own domain", {},
{
a: sub => <a href={hostingSignupLink} target="_blank" rel="noopener" tabIndex="0">{sub}</a>,
a: sub => <a href={hostingSignupLink} target="_blank" rel="noopener" tabIndex={-1}>{sub}</a>,
},
)}
<a href={hostingSignupLink} target="_blank" rel="noopener" aria-hidden={true}>
<a href={hostingSignupLink} target="_blank" rel="noopener" role="presentation" aria-hidden={true} tabIndex={-1}>
<img src={require("../../../../res/img/external-link.svg")} width="11" height="10" alt='' />
</a>
</div>;
@ -81,40 +79,40 @@ export class TopLeftMenu extends React.Component {
let homePageItem = null;
if (this.hasHomePage()) {
homePageItem = (
<AccessibleButton element="li" className="mx_TopLeftMenu_icon_home" onClick={this.viewHomePage}>
<MenuItem className="mx_TopLeftMenu_icon_home" onClick={this.viewHomePage}>
{_t("Home")}
</AccessibleButton>
</MenuItem>
);
}
let signInOutItem;
if (isGuest) {
signInOutItem = (
<AccessibleButton element="li" className="mx_TopLeftMenu_icon_signin" onClick={this.signIn}>
<MenuItem className="mx_TopLeftMenu_icon_signin" onClick={this.signIn}>
{_t("Sign in")}
</AccessibleButton>
</MenuItem>
);
} else {
signInOutItem = (
<AccessibleButton element="li" className="mx_TopLeftMenu_icon_signout" onClick={this.signOut}>
<MenuItem className="mx_TopLeftMenu_icon_signout" onClick={this.signOut}>
{_t("Sign out")}
</AccessibleButton>
</MenuItem>
);
}
const settingsItem = (
<AccessibleButton element="li" className="mx_TopLeftMenu_icon_settings" onClick={this.openSettings}>
<MenuItem className="mx_TopLeftMenu_icon_settings" onClick={this.openSettings}>
{_t("Settings")}
</AccessibleButton>
</MenuItem>
);
return <div className="mx_TopLeftMenu" ref={this.props.containerRef}>
<div className="mx_TopLeftMenu_section_noIcon" aria-readonly={true}>
return <div className="mx_TopLeftMenu" ref={this.props.containerRef} role="menu">
<div className="mx_TopLeftMenu_section_noIcon" aria-readonly={true} tabIndex={-1}>
<div>{this.props.displayName}</div>
<div className="mx_TopLeftMenu_greyedText" aria-hidden={true}>{this.props.userId}</div>
{hostingSignup}
</div>
<ul className="mx_TopLeftMenu_section_withIcon">
<ul className="mx_TopLeftMenu_section_withIcon" role="none">
{homePageItem}
{settingsItem}
{signInOutItem}

View file

@ -16,8 +16,8 @@ limitations under the License.
import React from 'react';
import PropTypes from 'prop-types';
import sdk from '../../../index';
import {_t} from '../../../languageHandler';
import {MenuItem} from "../../structures/ContextMenu";
export default class WidgetContextMenu extends React.Component {
static propTypes = {
@ -71,50 +71,45 @@ export default class WidgetContextMenu extends React.Component {
};
render() {
const AccessibleButton = sdk.getComponent("views.elements.AccessibleButton");
const options = [];
if (this.props.onEditClicked) {
options.push(
<AccessibleButton className='mx_WidgetContextMenu_option' onClick={this.onEditClicked} key='edit'>
<MenuItem className='mx_WidgetContextMenu_option' onClick={this.onEditClicked} key='edit'>
{_t("Edit")}
</AccessibleButton>,
</MenuItem>,
);
}
if (this.props.onReloadClicked) {
options.push(
<AccessibleButton className='mx_WidgetContextMenu_option' onClick={this.onReloadClicked}
key='reload'>
<MenuItem className='mx_WidgetContextMenu_option' onClick={this.onReloadClicked} key='reload'>
{_t("Reload")}
</AccessibleButton>,
</MenuItem>,
);
}
if (this.props.onSnapshotClicked) {
options.push(
<AccessibleButton className='mx_WidgetContextMenu_option' onClick={this.onSnapshotClicked}
key='snap'>
<MenuItem className='mx_WidgetContextMenu_option' onClick={this.onSnapshotClicked} key='snap'>
{_t("Take picture")}
</AccessibleButton>,
</MenuItem>,
);
}
if (this.props.onDeleteClicked) {
options.push(
<AccessibleButton className='mx_WidgetContextMenu_option' onClick={this.onDeleteClicked}
key='delete'>
<MenuItem className='mx_WidgetContextMenu_option' onClick={this.onDeleteClicked} key='delete'>
{_t("Remove for everyone")}
</AccessibleButton>,
</MenuItem>,
);
}
// Push this last so it appears last. It's always present.
options.push(
<AccessibleButton className='mx_WidgetContextMenu_option' onClick={this.onRevokeClicked} key='revoke'>
<MenuItem className='mx_WidgetContextMenu_option' onClick={this.onRevokeClicked} key='revoke'>
{_t("Remove for me")}
</AccessibleButton>,
</MenuItem>,
);
// Put separators between the options

View file

@ -17,7 +17,7 @@ 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 createReactClass from 'create-react-class';
@ -106,10 +106,14 @@ module.exports = createReactClass({
};
},
UNSAFE_componentWillMount: function() {
this._textinput = createRef();
},
componentDidMount: function() {
if (this.props.focus) {
// Set the cursor at the end of the text input
this.refs.textinput.value = this.props.value;
this._textinput.current.value = this.props.value;
}
},
@ -126,8 +130,8 @@ module.exports = createReactClass({
let selectedList = this.state.selectedList.slice();
// Check the text input field to see if user has an unconverted address
// If there is and it's valid add it to the local selectedList
if (this.refs.textinput.value !== '') {
selectedList = this._addAddressesToList([this.refs.textinput.value]);
if (this._textinput.current.value !== '') {
selectedList = this._addAddressesToList([this._textinput.current.value]);
if (selectedList === null) return;
}
this.props.onFinished(true, selectedList);
@ -154,23 +158,23 @@ module.exports = createReactClass({
e.stopPropagation();
e.preventDefault();
if (this.addressSelector) this.addressSelector.chooseSelection();
} else if (this.refs.textinput.value.length === 0 && this.state.selectedList.length && e.keyCode === 8) { // backspace
} else if (this._textinput.current.value.length === 0 && this.state.selectedList.length && e.keyCode === 8) { // backspace
e.stopPropagation();
e.preventDefault();
this.onDismissed(this.state.selectedList.length - 1)();
} else if (e.keyCode === 13) { // enter
e.stopPropagation();
e.preventDefault();
if (this.refs.textinput.value === '') {
if (this._textinput.current.value === '') {
// if there's nothing in the input box, submit the form
this.onButtonClick();
} else {
this._addAddressesToList([this.refs.textinput.value]);
this._addAddressesToList([this._textinput.current.value]);
}
} else if (e.keyCode === 188 || e.keyCode === 9) { // comma or tab
e.stopPropagation();
e.preventDefault();
this._addAddressesToList([this.refs.textinput.value]);
this._addAddressesToList([this._textinput.current.value]);
}
},
@ -647,7 +651,7 @@ module.exports = createReactClass({
onPaste={this._onPaste}
rows="1"
id="textinput"
ref="textinput"
ref={this._textinput}
className="mx_AddressPickerDialog_input"
onChange={this.onQueryChanged}
placeholder={this.getPlaceholder()}

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.
@ -21,15 +22,12 @@ import sdk from '../../../index';
import Analytics from '../../../Analytics';
import MatrixClientPeg from '../../../MatrixClientPeg';
import * as Lifecycle from '../../../Lifecycle';
import Velocity from 'velocity-animate';
import { _t } from '../../../languageHandler';
export default class DeactivateAccountDialog extends React.Component {
constructor(props, context) {
super(props, context);
this._passwordField = null;
this._onOk = this._onOk.bind(this);
this._onCancel = this._onCancel.bind(this);
this._onPasswordFieldChange = this._onPasswordFieldChange.bind(this);
@ -78,7 +76,6 @@ export default class DeactivateAccountDialog extends React.Component {
// https://matrix.org/jira/browse/SYN-744
if (err.httpStatus === 401 || err.httpStatus === 403) {
errStr = _t('Incorrect password');
Velocity(this._passwordField, "callout.shake", 300);
}
this.setState({
busy: false,
@ -181,7 +178,6 @@ export default class DeactivateAccountDialog extends React.Component {
label={_t('Password')}
onChange={this._onPasswordFieldChange}
value={this.state.password}
ref={(e) => {this._passwordField = e;}}
className={passwordBoxClass}
/>
</div>

View file

@ -0,0 +1,128 @@
/*
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 from 'react';
import PropTypes from 'prop-types';
import {_t} from "../../../languageHandler";
import sdk from "../../../index";
import LabelledToggleSwitch from "../elements/LabelledToggleSwitch";
import MatrixClientPeg from "../../../MatrixClientPeg";
import Modal from "../../../Modal";
export default class RoomUpgradeWarningDialog extends React.Component {
static propTypes = {
onFinished: PropTypes.func.isRequired,
roomId: PropTypes.string.isRequired,
targetVersion: PropTypes.string.isRequired,
};
constructor(props) {
super(props);
const room = MatrixClientPeg.get().getRoom(this.props.roomId);
const joinRules = room ? room.currentState.getStateEvents("m.room.join_rules", "") : null;
const isPrivate = joinRules ? joinRules.getContent()['join_rule'] !== 'public' : true;
this.state = {
currentVersion: room ? room.getVersion() : "1",
isPrivate,
inviteUsersToNewRoom: true,
};
}
_onContinue = () => {
this.props.onFinished({continue: true, invite: this.state.isPrivate && this.state.inviteUsersToNewRoom});
};
_onCancel = () => {
this.props.onFinished({continue: false, invite: false});
};
_onInviteUsersToggle = (newVal) => {
this.setState({inviteUsersToNewRoom: newVal});
};
_openBugReportDialog = (e) => {
e.preventDefault();
e.stopPropagation();
const BugReportDialog = sdk.getComponent("dialogs.BugReportDialog");
Modal.createTrackedDialog('Bug Report Dialog', '', BugReportDialog, {});
};
render() {
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
let inviteToggle = null;
if (this.state.isPrivate) {
inviteToggle = (
<LabelledToggleSwitch
value={this.state.inviteUsersToNewRoom}
onChange={this._onInviteUsersToggle}
label={_t("Automatically invite users")} />
);
}
const title = this.state.isPrivate ? _t("Upgrade private room") : _t("Upgrade public room");
return (
<BaseDialog
className='mx_RoomUpgradeWarningDialog'
hasCancel={true}
fixedWidth={false}
onFinished={this.props.onFinished}
title={title}
>
<div>
<p>
{_t(
"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>
<p>
{_t(
"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>.",
{}, {
"a": (sub) => {
return <a href='#' onClick={this._openBugReportDialog}>{sub}</a>;
},
},
)}
</p>
<p>
{_t(
"You'll upgrade this room from <oldVersion /> to <newVersion />.",
{},
{
oldVersion: () => <code>{this.state.currentVersion}</code>,
newVersion: () => <code>{this.props.targetVersion}</code>,
},
)}
</p>
{inviteToggle}
</div>
<DialogButtons
primaryButton={_t("Upgrade")}
onPrimaryButtonClick={this._onContinue}
cancelButton={_t("Cancel")}
onCancel={this._onCancel}
/>
</BaseDialog>
);
}
}

View file

@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import React, {createRef} from 'react';
import createReactClass from 'create-react-class';
import PropTypes from 'prop-types';
import sdk from '../../../index';
@ -62,8 +62,13 @@ export default createReactClass({
};
},
UNSAFE_componentWillMount: function() {
this._input_value = createRef();
this._uiAuth = createRef();
},
componentDidMount: function() {
this.refs.input_value.select();
this._input_value.current.select();
this._matrixClient = MatrixClientPeg.get();
},
@ -102,8 +107,8 @@ export default createReactClass({
},
onSubmit: function(ev) {
if (this.refs.uiAuth) {
this.refs.uiAuth.tryContinue();
if (this._uiAuth.current) {
this._uiAuth.current.tryContinue();
}
this.setState({
doingUIAuth: true,
@ -215,7 +220,7 @@ export default createReactClass({
onAuthFinished={this._onUIAuthFinished}
inputs={{}}
poll={true}
ref="uiAuth"
ref={this._uiAuth}
continueIsManaged={true}
/>;
}
@ -257,7 +262,7 @@ export default createReactClass({
>
<div className="mx_Dialog_content" id='mx_Dialog_content'>
<div className="mx_SetMxIdDialog_input_group">
<input type="text" ref="input_value" value={this.state.username}
<input type="text" ref={this._input_value} value={this.state.username}
autoFocus={true}
onChange={this.onValueChange}
onKeyUp={this.onKeyUp}

View file

@ -14,14 +14,15 @@ 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 {Room, User, Group, RoomMember, MatrixEvent} from 'matrix-js-sdk';
import sdk from '../../../index';
import { _t } from '../../../languageHandler';
import QRCode from 'qrcode-react';
import {RoomPermalinkCreator, makeGroupPermalink, makeUserPermalink} from "../../../utils/permalinks/Permalinks";
import * as ContextualMenu from "../../structures/ContextualMenu";
import * as ContextMenu from "../../structures/ContextMenu";
import {toRightOf} from "../../structures/ContextMenu";
const socials = [
{
@ -73,6 +74,8 @@ export default class ShareDialog extends React.Component {
// MatrixEvent defaults to share linkSpecificEvent
linkSpecificEvent: this.props.target instanceof MatrixEvent,
};
this._link = createRef();
}
static _selectText(target) {
@ -93,7 +96,7 @@ export default class ShareDialog extends React.Component {
onCopyClick(e) {
e.preventDefault();
ShareDialog._selectText(this.refs.link);
ShareDialog._selectText(this._link.current);
let successful;
try {
@ -102,18 +105,12 @@ export default class ShareDialog extends React.Component {
console.error('Failed to copy: ', err);
}
const GenericTextContextMenu = sdk.getComponent('context_menus.GenericTextContextMenu');
const buttonRect = e.target.getBoundingClientRect();
// The window X and Y offsets are to adjust position when zoomed in to page
const x = buttonRect.right + window.pageXOffset;
const y = (buttonRect.top + (buttonRect.height / 2) + window.pageYOffset) - 19;
const {close} = ContextualMenu.createMenu(GenericTextContextMenu, {
chevronOffset: 10,
left: x,
top: y,
const GenericTextContextMenu = sdk.getComponent('context_menus.GenericTextContextMenu');
const {close} = ContextMenu.createMenu(GenericTextContextMenu, {
...toRightOf(buttonRect, 2),
message: successful ? _t('Copied!') : _t('Failed to copy'),
}, false);
});
// Drop a reference to this close handler for componentWillUnmount
this.closeCopiedTooltip = e.target.onmouseleave = close;
}
@ -200,7 +197,7 @@ export default class ShareDialog extends React.Component {
>
<div className="mx_ShareDialog_content">
<div className="mx_ShareDialog_matrixto">
<a ref="link"
<a ref={this._link}
href={matrixToUrl}
onClick={ShareDialog.onLinkClick}
className="mx_ShareDialog_matrixto_link"

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import React, {createRef} from 'react';
import createReactClass from 'create-react-class';
import PropTypes from 'prop-types';
import sdk from '../../../index';
@ -42,15 +42,19 @@ export default createReactClass({
};
},
UNSAFE_componentWillMount: function() {
this._textinput = createRef();
},
componentDidMount: function() {
if (this.props.focus) {
// Set the cursor at the end of the text input
this.refs.textinput.value = this.props.value;
this._textinput.current.value = this.props.value;
}
},
onOk: function() {
this.props.onFinished(true, this.refs.textinput.value);
this.props.onFinished(true, this._textinput.current.value);
},
onCancel: function() {
@ -70,7 +74,13 @@ export default createReactClass({
<label htmlFor="textinput"> { this.props.description } </label>
</div>
<div>
<input id="textinput" ref="textinput" className="mx_TextInputDialog_input" defaultValue={this.props.value} autoFocus={this.props.focus} size="64" />
<input
id="textinput"
ref={this._textinput}
className="mx_TextInputDialog_input"
defaultValue={this.props.value}
autoFocus={this.props.focus}
size="64" />
</div>
</div>
</form>

View file

@ -18,7 +18,7 @@ limitations under the License.
import url from 'url';
import qs from 'querystring';
import React from 'react';
import React, {createRef} from 'react';
import PropTypes from 'prop-types';
import MatrixClientPeg from '../../../MatrixClientPeg';
import WidgetMessaging from '../../../WidgetMessaging';
@ -35,7 +35,7 @@ import ActiveWidgetStore from '../../../stores/ActiveWidgetStore';
import classNames from 'classnames';
import {IntegrationManagers} from "../../../integrations/IntegrationManagers";
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
import {createMenu} from "../../structures/ContextualMenu";
import {aboveLeftOf, ContextMenu, ContextMenuButton} from "../../structures/ContextMenu";
import PersistedElement from "./PersistedElement";
const ALLOWED_APP_URL_SCHEMES = ['https:', 'http:'];
@ -62,6 +62,10 @@ export default class AppTile extends React.Component {
this._revokeWidgetPermission = this._revokeWidgetPermission.bind(this);
this._onPopoutWidgetClick = this._onPopoutWidgetClick.bind(this);
this._onReloadWidgetClick = this._onReloadWidgetClick.bind(this);
this._contextMenuButton = createRef();
this._appFrame = createRef();
this._menu_bar = createRef();
}
/**
@ -89,6 +93,7 @@ export default class AppTile extends React.Component {
error: null,
deleting: false,
widgetPageTitle: newProps.widgetPageTitle,
menuDisplayed: false,
};
}
@ -334,14 +339,14 @@ export default class AppTile extends React.Component {
// HACK: This is a really dirty way to ensure that Jitsi cleans up
// its hold on the webcam. Without this, the widget holds a media
// stream open, even after death. See https://github.com/vector-im/riot-web/issues/7351
if (this.refs.appFrame) {
if (this._appFrame.current) {
// In practice we could just do `+= ''` to trick the browser
// into thinking the URL changed, however I can foresee this
// being optimized out by a browser. Instead, we'll just point
// the iframe at a page that is reasonably safe to use in the
// event the iframe doesn't wink away.
// This is relative to where the Riot instance is located.
this.refs.appFrame.src = 'about:blank';
this._appFrame.current.src = 'about:blank';
}
WidgetUtils.setRoomWidget(
@ -386,7 +391,7 @@ export default class AppTile extends React.Component {
// FIXME: There's probably no reason to do this here: it should probably be done entirely
// in ActiveWidgetStore.
const widgetMessaging = new WidgetMessaging(
this.props.id, this.props.url, this.props.userWidget, this.refs.appFrame.contentWindow);
this.props.id, this.props.url, this.props.userWidget, this._appFrame.current.contentWindow);
ActiveWidgetStore.setWidgetMessaging(this.props.id, widgetMessaging);
widgetMessaging.getCapabilities().then((requestedCapabilities) => {
console.log(`Widget ${this.props.id} requested capabilities: ` + requestedCapabilities);
@ -493,7 +498,7 @@ export default class AppTile extends React.Component {
ev.preventDefault();
// Ignore clicks on menu bar children
if (ev.target !== this.refs.menu_bar) {
if (ev.target !== this._menu_bar.current) {
return;
}
@ -552,48 +557,15 @@ export default class AppTile extends React.Component {
_onReloadWidgetClick() {
// Reload iframe in this way to avoid cross-origin restrictions
this.refs.appFrame.src = this.refs.appFrame.src;
this._appFrame.current.src = this._appFrame.current.src;
}
_getMenuOptions(ev) {
// TODO: This block of code gets copy/pasted a lot. We should make that happen less.
const menuOptions = {};
const buttonRect = ev.target.getBoundingClientRect();
// The window X and Y offsets are to adjust position when zoomed in to page
const buttonLeft = buttonRect.left + window.pageXOffset;
const buttonTop = buttonRect.top + window.pageYOffset;
// Align the right edge of the menu to the left edge of the button
menuOptions.right = window.innerWidth - buttonLeft;
// Align the menu vertically on whichever side of the button has more
// space available.
if (buttonTop < window.innerHeight / 2) {
menuOptions.top = buttonTop;
} else {
menuOptions.bottom = window.innerHeight - buttonTop;
}
return menuOptions;
}
_onContextMenuClick = () => {
this.setState({ menuDisplayed: true });
};
_onContextMenuClick = (ev) => {
const WidgetContextMenu = sdk.getComponent('views.context_menus.WidgetContextMenu');
const menuOptions = {
...this._getMenuOptions(ev),
// A revoke handler is always required
onRevokeClicked: this._onRevokeClicked,
};
const canUserModify = this._canUserModify();
const showEditButton = Boolean(this._scalarClient && canUserModify);
const showDeleteButton = (this.props.showDelete === undefined || this.props.showDelete) && canUserModify;
const showPictureSnapshotButton = this._hasCapability('m.capability.screenshot') && this.props.show;
if (showEditButton) menuOptions.onEditClicked = this._onEditClick;
if (showDeleteButton) menuOptions.onDeleteClicked = this._onDeleteClick;
if (showPictureSnapshotButton) menuOptions.onSnapshotClicked = this._onSnapshotClick;
if (this.props.showReload) menuOptions.onReloadClicked = this._onReloadWidgetClick;
createMenu(WidgetContextMenu, menuOptions);
_closeContextMenu = () => {
this.setState({ menuDisplayed: false });
};
render() {
@ -601,7 +573,7 @@ export default class AppTile extends React.Component {
// Don't render widget if it is in the process of being deleted
if (this.state.deleting) {
return <div></div>;
return <div />;
}
// Note that there is advice saying allow-scripts shouldn't be used with allow-same-origin
@ -656,7 +628,7 @@ export default class AppTile extends React.Component {
{ this.state.loading && loadingElement }
<iframe
allow={iframeFeatures}
ref="appFrame"
ref={this._appFrame}
src={this._getSafeUrl()}
allowFullScreen={true}
sandbox={sandboxFlags}
@ -697,10 +669,34 @@ export default class AppTile extends React.Component {
mx_AppTileMenuBar_expanded: this.props.show,
});
return (
let contextMenu;
if (this.state.menuDisplayed) {
const elementRect = this._contextMenuButton.current.getBoundingClientRect();
const canUserModify = this._canUserModify();
const showEditButton = Boolean(this._scalarClient && canUserModify);
const showDeleteButton = (this.props.showDelete === undefined || this.props.showDelete) && canUserModify;
const showPictureSnapshotButton = this._hasCapability('m.capability.screenshot') && this.props.show;
const WidgetContextMenu = sdk.getComponent('views.context_menus.WidgetContextMenu');
contextMenu = (
<ContextMenu {...aboveLeftOf(elementRect, null)} onFinished={this._closeContextMenu}>
<WidgetContextMenu
onRevokeClicked={this._onRevokeClicked}
onEditClicked={showEditButton ? this._onEditClick : undefined}
onDeleteClicked={showDeleteButton ? this._onDeleteClick : undefined}
onSnapshotClicked={showPictureSnapshotButton ? this._onSnapshotClick : undefined}
onReloadClicked={this.props.showReload ? this._onReloadWidgetClick : undefined}
onFinished={this._closeContextMenu}
/>
</ContextMenu>
);
}
return <React.Fragment>
<div className={appTileClass} id={this.props.id}>
{ this.props.showMenubar &&
<div ref="menu_bar" className={menuBarClasses} onClick={this.onClickMenuBar}>
<div ref={this._menu_bar} className={menuBarClasses} onClick={this.onClickMenuBar}>
<span className="mx_AppTileMenuBarTitle" style={{pointerEvents: (this.props.handleMinimisePointerEvents ? 'all' : false)}}>
{ /* Minimise widget */ }
{ showMinimiseButton && <AccessibleButton
@ -725,20 +721,24 @@ export default class AppTile extends React.Component {
onClick={this._onPopoutWidgetClick}
/> }
{ /* Context menu */ }
{ <AccessibleButton
{ <ContextMenuButton
className="mx_AppTileMenuBar_iconButton mx_AppTileMenuBar_iconButton_menu"
title={_t('More options')}
label={_t('More options')}
isExpanded={this.state.menuDisplayed}
inputRef={this._contextMenuButton}
onClick={this._onContextMenuClick}
/> }
</span>
</div> }
{ appTileBody }
</div>
);
{ contextMenu }
</React.Fragment>;
}
}
AppTile.displayName ='AppTile';
AppTile.displayName = 'AppTile';
AppTile.propTypes = {
id: PropTypes.string.isRequired,

View file

@ -15,7 +15,7 @@ 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 createReactClass from 'create-react-class';
import {Key} from "../../../Keyboard";
@ -65,7 +65,7 @@ module.exports = createReactClass({
componentWillReceiveProps: function(nextProps) {
if (nextProps.initialValue !== this.props.initialValue) {
this.value = nextProps.initialValue;
if (this.refs.editable_div) {
if (this._editable_div.current) {
this.showPlaceholder(!this.value);
}
}
@ -76,24 +76,27 @@ module.exports = createReactClass({
// as React doesn't play nice with contentEditable.
this.value = '';
this.placeholder = false;
this._editable_div = createRef();
},
componentDidMount: function() {
this.value = this.props.initialValue;
if (this.refs.editable_div) {
if (this._editable_div.current) {
this.showPlaceholder(!this.value);
}
},
showPlaceholder: function(show) {
if (show) {
this.refs.editable_div.textContent = this.props.placeholder;
this.refs.editable_div.setAttribute("class", this.props.className + " " + this.props.placeholderClassName);
this._editable_div.current.textContent = this.props.placeholder;
this._editable_div.current.setAttribute("class", this.props.className
+ " " + this.props.placeholderClassName);
this.placeholder = true;
this.value = '';
} else {
this.refs.editable_div.textContent = this.value;
this.refs.editable_div.setAttribute("class", this.props.className);
this._editable_div.current.textContent = this.value;
this._editable_div.current.setAttribute("class", this.props.className);
this.placeholder = false;
}
},
@ -120,7 +123,7 @@ module.exports = createReactClass({
this.value = this.props.initialValue;
this.showPlaceholder(!this.value);
this.onValueChanged(false);
this.refs.editable_div.blur();
this._editable_div.current.blur();
},
onValueChanged: function(shouldSubmit) {
@ -219,7 +222,7 @@ module.exports = createReactClass({
</div>;
} else {
// show the content editable div, but manually manage its contents as react and contentEditable don't play nice together
editableEl = <div ref="editable_div"
editableEl = <div ref={this._editable_div}
contentEditable={true}
className={className}
onKeyDown={this.onKeyDown}

View file

@ -90,7 +90,7 @@ function isInLowerLeftHalf(x, y, rect) {
* tooltip along one edge of the target.
*/
export default class InteractiveTooltip extends React.Component {
propTypes: {
static propTypes = {
// Content to show in the tooltip
content: PropTypes.node.isRequired,
// Function to call when visibility of the tooltip changes

View file

@ -1,6 +1,7 @@
/*
Copyright 2017 New Vector Ltd.
Copyright 2018 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,20 +16,21 @@ 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 createReactClass from 'create-react-class';
import classNames from 'classnames';
import { MatrixClient } from 'matrix-js-sdk';
import sdk from '../../../index';
import dis from '../../../dispatcher';
import {_t} from '../../../languageHandler';
import { isOnlyCtrlOrCmdIgnoreShiftKeyEvent } from '../../../Keyboard';
import * as ContextualMenu from '../../structures/ContextualMenu';
import * as FormattingUtils from '../../../utils/FormattingUtils';
import FlairStore from '../../../stores/FlairStore';
import GroupStore from '../../../stores/GroupStore';
import TagOrderStore from '../../../stores/TagOrderStore';
import {ContextMenu, ContextMenuButton, toRightOf} from "../../structures/ContextMenu";
// A class for a child of TagPanel (possibly wrapped in a DNDTagTile) that represents
// a thing to click on for the user to filter the visible rooms in the RoomList to:
@ -58,6 +60,8 @@ export default createReactClass({
},
componentDidMount() {
this._contextMenuButton = createRef();
this.unmounted = false;
if (this.props.tag[0] === '+') {
FlairStore.addListener('updateGroupProfile', this._onFlairStoreUpdated);
@ -107,56 +111,35 @@ export default createReactClass({
}
},
_openContextMenu: function(x, y, chevronOffset) {
// Hide the (...) immediately
this.setState({ hover: false });
const TagTileContextMenu = sdk.getComponent('context_menus.TagTileContextMenu');
ContextualMenu.createMenu(TagTileContextMenu, {
chevronOffset: chevronOffset,
left: x,
top: y,
tag: this.props.tag,
onFinished: () => {
this.setState({ menuDisplayed: false });
},
});
this.setState({ menuDisplayed: true });
},
onContextButtonClick: function(e) {
e.preventDefault();
e.stopPropagation();
const elementRect = e.target.getBoundingClientRect();
// The window X and Y offsets are to adjust position when zoomed in to page
const x = elementRect.right + window.pageXOffset + 3;
const chevronOffset = 12;
let y = (elementRect.top + (elementRect.height / 2) + window.pageYOffset);
y = y - (chevronOffset + 8); // where 8 is half the height of the chevron
this._openContextMenu(x, y, chevronOffset);
},
onContextMenu: function(e) {
e.preventDefault();
const chevronOffset = 12;
this._openContextMenu(e.clientX, e.clientY - (chevronOffset + 8), chevronOffset);
},
onMouseOver: function() {
console.log("DEBUG onMouseOver");
this.setState({hover: true});
},
onMouseOut: function() {
console.log("DEBUG onMouseOut");
this.setState({hover: false});
},
openMenu: function(e) {
// Prevent the TagTile onClick event firing as well
e.stopPropagation();
e.preventDefault();
this.setState({
menuDisplayed: true,
hover: false,
});
},
closeMenu: function() {
this.setState({
menuDisplayed: false,
});
},
render: function() {
const BaseAvatar = sdk.getComponent('avatars.BaseAvatar');
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
const Tooltip = sdk.getComponent('elements.Tooltip');
const profile = this.state.profile || {};
const name = profile.name || this.props.tag;
@ -184,23 +167,46 @@ export default createReactClass({
const tip = this.state.hover ?
<Tooltip className="mx_TagTile_tooltip" label={name} /> :
<div />;
// FIXME: this ought to use AccessibleButton for a11y but that causes onMouseOut/onMouseOver to fire too much
const contextButton = this.state.hover || this.state.menuDisplayed ?
<div className="mx_TagTile_context_button" onClick={this.onContextButtonClick}>
<div className="mx_TagTile_context_button" onClick={this.openMenu} ref={this._contextMenuButton}>
{ "\u00B7\u00B7\u00B7" }
</div> : <div />;
return <AccessibleButton className={className} onClick={this.onClick} onContextMenu={this.onContextMenu}>
<div className="mx_TagTile_avatar" onMouseOver={this.onMouseOver} onMouseOut={this.onMouseOut}>
<BaseAvatar
name={name}
idName={this.props.tag}
url={httpUrl}
width={avatarHeight}
height={avatarHeight}
/>
{ tip }
{ contextButton }
{ badgeElement }
</div>
</AccessibleButton>;
</div> : <div ref={this._contextMenuButton} />;
let contextMenu;
if (this.state.menuDisplayed) {
const elementRect = this._contextMenuButton.current.getBoundingClientRect();
const TagTileContextMenu = sdk.getComponent('context_menus.TagTileContextMenu');
contextMenu = (
<ContextMenu {...toRightOf(elementRect)} onFinished={this.closeMenu}>
<TagTileContextMenu tag={this.props.tag} onFinished={this.closeMenu} />
</ContextMenu>
);
}
return <React.Fragment>
<ContextMenuButton
className={className}
onClick={this.onClick}
onContextMenu={this.openMenu}
label={_t("Options")}
isExpanded={this.state.menuDisplayed}
>
<div className="mx_TagTile_avatar" onMouseOver={this.onMouseOver} onMouseOut={this.onMouseOut}>
<BaseAvatar
name={name}
idName={this.props.tag}
url={httpUrl}
width={avatarHeight}
height={avatarHeight}
/>
{ tip }
{ contextButton }
{ badgeElement }
</div>
</ContextMenuButton>
{ contextMenu }
</React.Fragment>;
},
});

View file

@ -14,7 +14,7 @@ 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 createReactClass from 'create-react-class';
import { _t } from '../../../languageHandler';
@ -34,6 +34,10 @@ module.exports = createReactClass({
};
},
UNSAFE_componentWillMount: function() {
this._user_id_input = createRef();
},
addUser: function(user_id) {
if (this.props.selected_users.indexOf(user_id == -1)) {
this.props.onChange(this.props.selected_users.concat([user_id]));
@ -47,20 +51,20 @@ module.exports = createReactClass({
},
onAddUserId: function() {
this.addUser(this.refs.user_id_input.value);
this.refs.user_id_input.value = "";
this.addUser(this._user_id_input.current.value);
this._user_id_input.current.value = "";
},
render: function() {
const self = this;
return (
<div>
<ul className="mx_UserSelector_UserIdList" ref="list">
<ul className="mx_UserSelector_UserIdList">
{ this.props.selected_users.map(function(user_id, i) {
return <li key={user_id}>{ user_id } - <span onClick={function() {self.removeUser(user_id);}}>X</span></li>;
}) }
</ul>
<input type="text" ref="user_id_input" defaultValue="" className="mx_UserSelector_userIdInput" placeholder={_t("ex. @bob:example.com")} />
<input type="text" ref={this._user_id_input} defaultValue="" className="mx_UserSelector_userIdInput" placeholder={_t("ex. @bob:example.com")} />
<button onClick={this.onAddUserId} className="mx_UserSelector_AddUserId">
{ _t("Add User") }
</button>

View file

@ -62,7 +62,7 @@ EMOJIBASE.forEach(emoji => {
DATA_BY_CATEGORY[categoryId].push(emoji);
}
// This is used as the string to match the query against when filtering emojis.
emoji.filterString = `${emoji.annotation}\n${emoji.shortcodes.join('\n')}}\n${emoji.emoticon || ''}`;
emoji.filterString = `${emoji.annotation}\n${emoji.shortcodes.join('\n')}}\n${emoji.emoticon || ''}`.toLowerCase();
});
export const CATEGORY_HEADER_HEIGHT = 22;
@ -201,6 +201,7 @@ class EmojiPicker extends React.Component {
}
onChangeFilter(filter) {
filter = filter.toLowerCase(); // filter is case insensitive stored lower-case
for (const cat of this.categories) {
let emojis;
// If the new filter string includes the old filter string, we don't have to re-filter the whole dataset.

View file

@ -23,7 +23,6 @@ class ReactionPicker extends React.Component {
static propTypes = {
mxEvent: PropTypes.object.isRequired,
onFinished: PropTypes.func.isRequired,
closeMenu: PropTypes.func.isRequired,
reactions: PropTypes.object,
};
@ -89,7 +88,6 @@ class ReactionPicker extends React.Component {
onChoose(reaction) {
this.componentWillUnmount();
this.props.closeMenu();
this.props.onFinished();
const myReactions = this.getReactions();
if (myReactions.hasOwnProperty(reaction)) {

View file

@ -1,6 +1,7 @@
/*
Copyright 2017, 2018 New Vector Ltd
Copyright 2018 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.
@ -21,11 +22,12 @@ import createReactClass from 'create-react-class';
import { MatrixClient } from 'matrix-js-sdk';
import sdk from '../../../index';
import dis from '../../../dispatcher';
import AccessibleButton from '../elements/AccessibleButton';
import {_t} from '../../../languageHandler';
import classNames from 'classnames';
import MatrixClientPeg from "../../../MatrixClientPeg";
import {createMenu} from "../../structures/ContextualMenu";
import {ContextMenu, ContextMenuButton, toRightOf} from "../../structures/ContextMenu";
// XXX this class copies a lot from RoomTile.js
export default createReactClass({
displayName: 'GroupInviteTile',
@ -69,54 +71,49 @@ export default createReactClass({
});
},
_showContextMenu: function(x, y, chevronOffset) {
const GroupInviteTileContextMenu = sdk.getComponent('context_menus.GroupInviteTileContextMenu');
createMenu(GroupInviteTileContextMenu, {
chevronOffset,
left: x,
top: y,
group: this.props.group,
onFinished: () => {
this.setState({ menuDisplayed: false });
},
});
this.setState({ menuDisplayed: true });
},
onContextMenu: function(e) {
// Prevent the RoomTile onClick event firing as well
e.preventDefault();
_showContextMenu: function(boundingClientRect) {
// Only allow non-guests to access the context menu
if (MatrixClientPeg.get().isGuest()) return;
const chevronOffset = 12;
this._showContextMenu(e.clientX, e.clientY - (chevronOffset + 8), chevronOffset);
},
onBadgeClicked: function(e) {
// Prevent the RoomTile onClick event firing as well
e.stopPropagation();
// Only allow non-guests to access the context menu
if (MatrixClientPeg.get().isGuest()) return;
const state = {
contextMenuPosition: boundingClientRect,
};
// If the badge is clicked, then no longer show tooltip
if (this.props.collapsed) {
this.setState({ hover: false });
state.hover = false;
}
const elementRect = e.target.getBoundingClientRect();
this.setState(state);
},
// The window X and Y offsets are to adjust position when zoomed in to page
const x = elementRect.right + window.pageXOffset + 3;
const chevronOffset = 12;
let y = (elementRect.top + (elementRect.height / 2) + window.pageYOffset);
y = y - (chevronOffset + 8); // where 8 is half the height of the chevron
onContextMenuButtonClick: function(e) {
// Prevent the RoomTile onClick event firing as well
e.stopPropagation();
e.preventDefault();
this._showContextMenu(x, y, chevronOffset);
this._showContextMenu(e.target.getBoundingClientRect());
},
onContextMenu: function(e) {
// Prevent the native context menu
e.preventDefault();
this._showContextMenu({
right: e.clientX,
top: e.clientY,
height: 0,
});
},
closeMenu: function() {
this.setState({
contextMenuPosition: null,
});
},
render: function() {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
const BaseAvatar = sdk.getComponent('avatars.BaseAvatar');
const groupName = this.props.group.name || this.props.group.groupId;
@ -125,21 +122,31 @@ export default createReactClass({
const av = <BaseAvatar name={groupName} width={24} height={24} url={httpAvatarUrl} />;
const isMenuDisplayed = Boolean(this.state.contextMenuPosition);
const nameClasses = classNames('mx_RoomTile_name mx_RoomTile_invite mx_RoomTile_badgeShown', {
'mx_RoomTile_badgeShown': this.state.badgeHover || this.state.menuDisplayed,
'mx_RoomTile_badgeShown': this.state.badgeHover || isMenuDisplayed,
});
const label = <div title={this.props.group.groupId} className={nameClasses} dir="auto">
{ groupName }
</div>;
const badgeEllipsis = this.state.badgeHover || this.state.menuDisplayed;
const badgeEllipsis = this.state.badgeHover || isMenuDisplayed;
const badgeClasses = classNames('mx_RoomTile_badge mx_RoomTile_highlight', {
'mx_RoomTile_badgeButton': badgeEllipsis,
});
const badgeContent = badgeEllipsis ? '\u00B7\u00B7\u00B7' : '!';
const badge = <div className={badgeClasses} onClick={this.onBadgeClicked}>{ badgeContent }</div>;
const badge = (
<ContextMenuButton
className={badgeClasses}
onClick={this.onContextMenuButtonClick}
label={_t("Options")}
isExpanded={isMenuDisplayed}
>
{ badgeContent }
</ContextMenuButton>
);
let tooltip;
if (this.props.collapsed && this.state.hover) {
@ -148,17 +155,28 @@ export default createReactClass({
}
const classes = classNames('mx_RoomTile mx_RoomTile_highlight', {
'mx_RoomTile_menuDisplayed': this.state.menuDisplayed,
'mx_RoomTile_menuDisplayed': isMenuDisplayed,
'mx_RoomTile_selected': this.state.selected,
'mx_GroupInviteTile': true,
});
return (
<AccessibleButton className={classes}
onClick={this.onClick}
onMouseEnter={this.onMouseEnter}
onMouseLeave={this.onMouseLeave}
onContextMenu={this.onContextMenu}
let contextMenu;
if (isMenuDisplayed) {
const GroupInviteTileContextMenu = sdk.getComponent('context_menus.GroupInviteTileContextMenu');
contextMenu = (
<ContextMenu {...toRightOf(this.state.contextMenuPosition)} onFinished={this.closeMenu}>
<GroupInviteTileContextMenu group={this.props.group} onFinished={this.closeMenu} />
</ContextMenu>
);
}
return <React.Fragment>
<AccessibleButton
className={classes}
onClick={this.onClick}
onMouseEnter={this.onMouseEnter}
onMouseLeave={this.onMouseLeave}
onContextMenu={this.onContextMenu}
>
<div className="mx_RoomTile_avatar">
{ av }
@ -169,6 +187,8 @@ export default createReactClass({
</div>
{ tooltip }
</AccessibleButton>
);
{ contextMenu }
</React.Fragment>;
},
});

View file

@ -14,7 +14,7 @@ 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 * as HtmlUtils from '../../../HtmlUtils';
import { editBodyDiffToHtml } from '../../../utils/MessageDiffUtils';
@ -51,6 +51,8 @@ export default class EditHistoryMessage extends React.PureComponent {
}
const canRedact = room.currentState.maySendRedactionForEvent(event, userId);
this.state = {canRedact, sendStatus: event.getAssociatedStatus()};
this._content = createRef();
}
_onAssociatedStatusChanged = () => {
@ -78,8 +80,8 @@ export default class EditHistoryMessage extends React.PureComponent {
pillifyLinks() {
// not present for redacted events
if (this.refs.content) {
pillifyLinks(this.refs.content.children, this.props.mxEvent);
if (this._content.current) {
pillifyLinks(this._content.current.children, this.props.mxEvent);
}
}
@ -102,9 +104,9 @@ export default class EditHistoryMessage extends React.PureComponent {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
// hide the button when already redacted
let redactButton;
if (!this.props.mxEvent.isRedacted() && !this.props.isBaseEvent) {
if (!this.props.mxEvent.isRedacted() && !this.props.isBaseEvent && this.state.canRedact) {
redactButton = (
<AccessibleButton onClick={this._onRedactClick} disabled={!this.state.canRedact}>
<AccessibleButton onClick={this._onRedactClick}>
{_t("Remove")}
</AccessibleButton>
);
@ -140,13 +142,13 @@ export default class EditHistoryMessage extends React.PureComponent {
if (mxEvent.getContent().msgtype === "m.emote") {
const name = mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender();
contentContainer = (
<div className="mx_EventTile_content" ref="content">*&nbsp;
<div className="mx_EventTile_content" ref={this._content}>*&nbsp;
<span className="mx_MEmoteBody_sender">{ name }</span>
&nbsp;{contentElements}
</div>
);
} else {
contentContainer = <div className="mx_EventTile_content" ref="content">{contentElements}</div>;
contentContainer = <div className="mx_EventTile_content" ref={this._content}>{contentElements}</div>;
}
}

View file

@ -80,7 +80,7 @@ export default class MAudioBody extends React.Component {
if (this.state.error !== null) {
return (
<span className="mx_MAudioBody" ref="body">
<span className="mx_MAudioBody">
<img src={require("../../../../res/img/warning.svg")} width="16" height="16" />
{ _t("Error decrypting audio") }
</span>

View file

@ -15,7 +15,7 @@ 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 createReactClass from 'create-react-class';
import filesize from 'filesize';
@ -251,6 +251,12 @@ module.exports = createReactClass({
return MatrixClientPeg.get().mxcUrlToHttp(content.url);
},
UNSAFE_componentWillMount: function() {
this._iframe = createRef();
this._dummyLink = createRef();
this._downloadImage = createRef();
},
componentDidMount: function() {
// Add this to the list of mounted components to receive notifications
// when the tint changes.
@ -272,17 +278,17 @@ module.exports = createReactClass({
tint: function() {
// Update our tinted copy of require("../../../../res/img/download.svg")
if (this.refs.downloadImage) {
this.refs.downloadImage.src = tintedDownloadImageURL;
if (this._downloadImage.current) {
this._downloadImage.current.src = tintedDownloadImageURL;
}
if (this.refs.iframe) {
if (this._iframe.current) {
// If the attachment is encrypted then the download image
// will be inside the iframe so we wont be able to update
// it directly.
this.refs.iframe.contentWindow.postMessage({
this._iframe.current.contentWindow.postMessage({
code: remoteSetTint.toString(),
imgSrc: tintedDownloadImageURL,
style: computedStyle(this.refs.dummyLink),
style: computedStyle(this._dummyLink.current),
}, "*");
}
},
@ -325,7 +331,7 @@ module.exports = createReactClass({
};
return (
<span className="mx_MFileBody" ref="body">
<span className="mx_MFileBody">
<div className="mx_MFileBody_download">
<a href="javascript:void(0)" onClick={decrypt}>
{ _t("Decrypt %(text)s", { text: text }) }
@ -340,7 +346,7 @@ module.exports = createReactClass({
ev.target.contentWindow.postMessage({
code: remoteRender.toString(),
imgSrc: tintedDownloadImageURL,
style: computedStyle(this.refs.dummyLink),
style: computedStyle(this._dummyLink.current),
blob: this.state.decryptedBlob,
// Set a download attribute for encrypted files so that the file
// will have the correct name when the user tries to download it.
@ -367,9 +373,9 @@ module.exports = createReactClass({
* We'll use it to learn how the download link
* would have been styled if it was rendered inline.
*/ }
<a ref="dummyLink" />
<a ref={this._dummyLink} />
</div>
<iframe src={renderer_url} onLoad={onIframeLoad} ref="iframe" />
<iframe src={renderer_url} onLoad={onIframeLoad} ref={this._iframe} />
</div>
</span>
);
@ -439,7 +445,7 @@ module.exports = createReactClass({
<span className="mx_MFileBody">
<div className="mx_MFileBody_download">
<a {...downloadProps}>
<img src={tintedDownloadImageURL} width="12" height="14" ref="downloadImage" />
<img src={tintedDownloadImageURL} width="12" height="14" ref={this._downloadImage} />
{ _t("Download %(text)s", { text: text }) }
</a>
</div>

View file

@ -16,7 +16,7 @@ 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 { MatrixClient } from 'matrix-js-sdk';
@ -65,6 +65,8 @@ export default class MImageBody extends React.Component {
hover: false,
showImage: SettingsStore.getValue("showImages"),
};
this._image = createRef();
}
componentWillMount() {
@ -158,8 +160,8 @@ export default class MImageBody extends React.Component {
let loadedImageDimensions;
if (this.refs.image) {
const { naturalWidth, naturalHeight } = this.refs.image;
if (this._image.current) {
const { naturalWidth, naturalHeight } = this._image.current;
// this is only used as a fallback in case content.info.w/h is missing
loadedImageDimensions = { naturalWidth, naturalHeight };
}
@ -342,7 +344,7 @@ export default class MImageBody extends React.Component {
imageElement = <HiddenImagePlaceholder />;
} else {
imageElement = (
<img style={{display: 'none'}} src={thumbUrl} ref="image"
<img style={{display: 'none'}} src={thumbUrl} ref={this._image}
alt={content.body}
onError={this.onImageError}
onLoad={this.onImageLoad}
@ -385,7 +387,7 @@ export default class MImageBody extends React.Component {
// which has the same width as the timeline
// mx_MImageBody_thumbnail resizes img to exactly container size
img = (
<img className="mx_MImageBody_thumbnail" src={thumbUrl} ref="image"
<img className="mx_MImageBody_thumbnail" src={thumbUrl} ref={this._image}
style={{ maxWidth: maxWidth + "px" }}
alt={content.body}
onError={this.onImageError}
@ -459,7 +461,7 @@ export default class MImageBody extends React.Component {
if (this.state.error !== null) {
return (
<span className="mx_MImageBody" ref="body">
<span className="mx_MImageBody">
<img src={require("../../../../res/img/warning.svg")} width="16" height="16" />
{ _t("Error decrypting image") }
</span>
@ -477,7 +479,7 @@ export default class MImageBody extends React.Component {
const thumbnail = this._messageContent(contentUrl, thumbUrl, content);
const fileBody = this.getFileBody();
return <span className="mx_MImageBody" ref="body">
return <span className="mx_MImageBody">
{ thumbnail }
{ fileBody }
</span>;

View file

@ -132,7 +132,7 @@ module.exports = createReactClass({
if (this.state.error !== null) {
return (
<span className="mx_MVideoBody" ref="body">
<span className="mx_MVideoBody">
<img src={require("../../../../res/img/warning.svg")} width="16" height="16" />
{ _t("Error decrypting video") }
</span>
@ -144,8 +144,8 @@ module.exports = createReactClass({
// The attachment is decrypted in componentDidMount.
// For now add an img tag with a spinner.
return (
<span className="mx_MVideoBody" ref="body">
<div className="mx_MImageBody_thumbnail mx_MImageBody_thumbnail_spinner" ref="image">
<span className="mx_MVideoBody">
<div className="mx_MImageBody_thumbnail mx_MImageBody_thumbnail_spinner">
<img src={require("../../../../res/img/spinner.gif")} alt={content.body} width="16" height="16" />
</div>
</span>

View file

@ -1,6 +1,7 @@
/*
Copyright 2019 New Vector 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,17 +16,96 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import React, {useEffect} from 'react';
import PropTypes from 'prop-types';
import { _t } from '../../../languageHandler';
import sdk from '../../../index';
import dis from '../../../dispatcher';
import Modal from '../../../Modal';
import { createMenu } from '../../structures/ContextualMenu';
import {aboveLeftOf, ContextMenu, ContextMenuButton, useContextMenu} from '../../structures/ContextMenu';
import { isContentActionable, canEditContent } from '../../../utils/EventUtils';
import {RoomContext} from "../../structures/RoomView";
const OptionsButton = ({mxEvent, getTile, getReplyThread, permalinkCreator, onFocusChange}) => {
const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu();
useEffect(() => {
onFocusChange(menuDisplayed);
}, [onFocusChange, menuDisplayed]);
let contextMenu;
if (menuDisplayed) {
const MessageContextMenu = sdk.getComponent('context_menus.MessageContextMenu');
const tile = getTile && getTile();
const replyThread = getReplyThread && getReplyThread();
const onCryptoClick = () => {
Modal.createTrackedDialogAsync('Encrypted Event Dialog', '',
import('../../../async-components/views/dialogs/EncryptedEventDialog'),
{event: mxEvent},
);
};
let e2eInfoCallback = null;
if (mxEvent.isEncrypted()) {
e2eInfoCallback = onCryptoClick;
}
const buttonRect = button.current.getBoundingClientRect();
contextMenu = <ContextMenu {...aboveLeftOf(buttonRect)} onFinished={closeMenu}>
<MessageContextMenu
mxEvent={mxEvent}
permalinkCreator={permalinkCreator}
eventTileOps={tile && tile.getEventTileOps ? tile.getEventTileOps() : undefined}
collapseReplyThread={replyThread && replyThread.canCollapse() ? replyThread.collapse : undefined}
e2eInfoCallback={e2eInfoCallback}
onFinished={closeMenu}
/>
</ContextMenu>;
}
return <React.Fragment>
<ContextMenuButton
className="mx_MessageActionBar_maskButton mx_MessageActionBar_optionsButton"
label={_t("Options")}
onClick={openMenu}
isExpanded={menuDisplayed}
inputRef={button}
/>
{ contextMenu }
</React.Fragment>;
};
const ReactButton = ({mxEvent, reactions, onFocusChange}) => {
const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu();
useEffect(() => {
onFocusChange(menuDisplayed);
}, [onFocusChange, menuDisplayed]);
let contextMenu;
if (menuDisplayed) {
const buttonRect = button.current.getBoundingClientRect();
const ReactionPicker = sdk.getComponent('emojipicker.ReactionPicker');
contextMenu = <ContextMenu {...aboveLeftOf(buttonRect)} onFinished={closeMenu} catchTab={false}>
<ReactionPicker mxEvent={mxEvent} reactions={reactions} onFinished={closeMenu} />
</ContextMenu>;
}
return <React.Fragment>
<ContextMenuButton
className="mx_MessageActionBar_maskButton mx_MessageActionBar_reactButton"
label={_t("React")}
onClick={openMenu}
isExpanded={menuDisplayed}
inputRef={button}
/>
{ contextMenu }
</React.Fragment>;
};
export default class MessageActionBar extends React.PureComponent {
static propTypes = {
mxEvent: PropTypes.object.isRequired,
@ -62,14 +142,6 @@ export default class MessageActionBar extends React.PureComponent {
this.props.onFocusChange(focused);
};
onCryptoClick = () => {
const event = this.props.mxEvent;
Modal.createTrackedDialogAsync('Encrypted Event Dialog', '',
import('../../../async-components/views/dialogs/EncryptedEventDialog'),
{event},
);
};
onReplyClick = (ev) => {
dis.dispatch({
action: 'reply_to_event',
@ -84,71 +156,6 @@ export default class MessageActionBar extends React.PureComponent {
});
};
getMenuOptions = (ev) => {
const menuOptions = {};
const buttonRect = ev.target.getBoundingClientRect();
// The window X and Y offsets are to adjust position when zoomed in to page
const buttonRight = buttonRect.right + window.pageXOffset;
const buttonBottom = buttonRect.bottom + window.pageYOffset;
const buttonTop = buttonRect.top + window.pageYOffset;
// Align the right edge of the menu to the right edge of the button
menuOptions.right = window.innerWidth - buttonRight;
// Align the menu vertically on whichever side of the button has more
// space available.
if (buttonBottom < window.innerHeight / 2) {
menuOptions.top = buttonBottom;
} else {
menuOptions.bottom = window.innerHeight - buttonTop;
}
return menuOptions;
};
onReactClick = (ev) => {
const ReactionPicker = sdk.getComponent('emojipicker.ReactionPicker');
const menuOptions = {
...this.getMenuOptions(ev),
mxEvent: this.props.mxEvent,
reactions: this.props.reactions,
chevronFace: "none",
onFinished: () => this.onFocusChange(false),
};
createMenu(ReactionPicker, menuOptions);
this.onFocusChange(true);
};
onOptionsClick = (ev) => {
const MessageContextMenu = sdk.getComponent('context_menus.MessageContextMenu');
const { getTile, getReplyThread } = this.props;
const tile = getTile && getTile();
const replyThread = getReplyThread && getReplyThread();
let e2eInfoCallback = null;
if (this.props.mxEvent.isEncrypted()) {
e2eInfoCallback = () => this.onCryptoClick();
}
const menuOptions = {
...this.getMenuOptions(ev),
mxEvent: this.props.mxEvent,
chevronFace: "none",
permalinkCreator: this.props.permalinkCreator,
eventTileOps: tile && tile.getEventTileOps ? tile.getEventTileOps() : undefined,
collapseReplyThread: replyThread && replyThread.canCollapse() ? replyThread.collapse : undefined,
e2eInfoCallback: e2eInfoCallback,
onFinished: () => {
this.onFocusChange(false);
},
};
createMenu(MessageContextMenu, menuOptions);
this.onFocusChange(true);
};
render() {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
@ -158,11 +165,9 @@ export default class MessageActionBar extends React.PureComponent {
if (isContentActionable(this.props.mxEvent)) {
if (this.context.room.canReact) {
reactButton = <AccessibleButton
className="mx_MessageActionBar_maskButton mx_MessageActionBar_reactButton"
title={_t("React")}
onClick={this.onReactClick}
/>;
reactButton = (
<ReactButton mxEvent={this.props.mxEvent} reactions={this.props.reactions} onFocusChange={this.onFocusChange} />
);
}
if (this.context.room.canReply) {
replyButton = <AccessibleButton
@ -185,11 +190,12 @@ export default class MessageActionBar extends React.PureComponent {
{reactButton}
{replyButton}
{editButton}
<AccessibleButton
className="mx_MessageActionBar_maskButton mx_MessageActionBar_optionsButton"
title={_t("Options")}
onClick={this.onOptionsClick}
aria-haspopup={true}
<OptionsButton
mxEvent={this.props.mxEvent}
getReplyThread={this.props.getReplyThread}
getTile={this.props.getTile}
permalinkCreator={this.props.permalinkCreator}
onFocusChange={this.onFocusChange}
/>
</div>;
}

View file

@ -14,7 +14,7 @@ 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 createReactClass from 'create-react-class';
import sdk from '../../../index';
@ -47,8 +47,12 @@ module.exports = createReactClass({
maxImageHeight: PropTypes.number,
},
UNSAFE_componentWillMount: function() {
this._body = createRef();
},
getEventTileOps: function() {
return this.refs.body && this.refs.body.getEventTileOps ? this.refs.body.getEventTileOps() : null;
return this._body.current && this._body.current.getEventTileOps ? this._body.current.getEventTileOps() : null;
},
onTileUpdate: function() {
@ -103,7 +107,8 @@ module.exports = createReactClass({
}
return <BodyType
ref="body" mxEvent={this.props.mxEvent}
ref={this._body}
mxEvent={this.props.mxEvent}
highlights={this.props.highlights}
highlightLink={this.props.highlightLink}
showUrlPreview={this.props.showUrlPreview}

View file

@ -149,7 +149,11 @@ export default class ReactionsRow extends React.PureComponent {
</a>;
}
return <div className="mx_ReactionsRow">
return <div
className="mx_ReactionsRow"
role="toolbar"
aria-label={_t("Reactions")}
>
{items}
{showAllButton}
</div>;

View file

@ -20,6 +20,8 @@ import classNames from 'classnames';
import MatrixClientPeg from '../../../MatrixClientPeg';
import sdk from '../../../index';
import { _t } from '../../../languageHandler';
import { formatCommaSeparatedList } from '../../../utils/FormattingUtils';
export default class ReactionsRowButton extends React.PureComponent {
static propTypes = {
@ -79,7 +81,7 @@ export default class ReactionsRowButton extends React.PureComponent {
render() {
const ReactionsRowButtonTooltip =
sdk.getComponent('messages.ReactionsRowButtonTooltip');
const { content, count, reactionEvents, myReactionEvent } = this.props;
const { mxEvent, content, count, reactionEvents, myReactionEvent } = this.props;
const classes = classNames({
mx_ReactionsRowButton: true,
@ -96,18 +98,48 @@ export default class ReactionsRowButton extends React.PureComponent {
/>;
}
return <span className={classes}
const room = MatrixClientPeg.get().getRoom(mxEvent.getRoomId());
let label;
if (room) {
const senders = [];
for (const reactionEvent of reactionEvents) {
const member = room.getMember(reactionEvent.getSender());
const name = member ? member.name : reactionEvent.getSender();
senders.push(name);
}
label = _t(
"<reactors/><reactedWith> reacted with %(content)s</reactedWith>",
{
content,
},
{
reactors: () => {
return formatCommaSeparatedList(senders, 6);
},
reactedWith: (sub) => {
if (!content) {
return null;
}
return sub;
},
},
);
}
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
return <AccessibleButton className={classes}
aria-label={label}
onClick={this.onClick}
onMouseOver={this.onMouseOver}
onMouseOut={this.onMouseOut}
>
<span className="mx_ReactionsRowButton_content">
<span className="mx_ReactionsRowButton_content" aria-hidden="true">
{content}
</span>
<span className="mx_ReactionsRowButton_count">
<span className="mx_ReactionsRowButton_count" aria-hidden="true">
{count}
</span>
{tooltip}
</span>;
</AccessibleButton>;
}
}

View file

@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import React, {createRef} from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import createReactClass from 'create-react-class';
@ -27,12 +27,13 @@ import sdk from '../../../index';
import Modal from '../../../Modal';
import dis from '../../../dispatcher';
import { _t } from '../../../languageHandler';
import * as ContextualMenu from '../../structures/ContextualMenu';
import * as ContextMenu from '../../structures/ContextMenu';
import SettingsStore from "../../../settings/SettingsStore";
import ReplyThread from "../elements/ReplyThread";
import {pillifyLinks} from '../../../utils/pillify';
import {IntegrationManagers} from "../../../integrations/IntegrationManagers";
import {isPermalinkHost} from "../../../utils/permalinks/Permalinks";
import {toRightOf} from "../../structures/ContextMenu";
module.exports = createReactClass({
displayName: 'TextualBody',
@ -85,6 +86,10 @@ module.exports = createReactClass({
return successful;
},
UNSAFE_componentWillMount: function() {
this._content = createRef();
},
componentDidMount: function() {
this._unmounted = false;
if (!this.props.editState) {
@ -93,13 +98,13 @@ module.exports = createReactClass({
},
_applyFormatting() {
this.activateSpoilers(this.refs.content.children);
this.activateSpoilers(this._content.current.children);
// pillifyLinks BEFORE linkifyElement because plain room/user URLs in the composer
// are still sent as plaintext URLs. If these are ever pillified in the composer,
// we should be pillify them here by doing the linkifying BEFORE the pillifying.
pillifyLinks(this.refs.content.children, this.props.mxEvent);
HtmlUtils.linkifyElement(this.refs.content);
pillifyLinks(this._content.current.children, this.props.mxEvent);
HtmlUtils.linkifyElement(this._content.current);
this.calculateUrlPreview();
if (this.props.mxEvent.getContent().format === "org.matrix.custom.html") {
@ -162,7 +167,7 @@ module.exports = createReactClass({
//console.info("calculateUrlPreview: ShowUrlPreview for %s is %s", this.props.mxEvent.getId(), this.props.showUrlPreview);
if (this.props.showUrlPreview) {
let links = this.findLinks(this.refs.content.children);
let links = this.findLinks(this._content.current.children);
if (links.length) {
// de-dup the links (but preserve ordering)
const seen = new Set();
@ -272,18 +277,12 @@ module.exports = createReactClass({
const copyCode = button.parentNode.getElementsByTagName("code")[0];
const successful = this.copyToClipboard(copyCode.textContent);
const GenericTextContextMenu = sdk.getComponent('context_menus.GenericTextContextMenu');
const buttonRect = e.target.getBoundingClientRect();
// The window X and Y offsets are to adjust position when zoomed in to page
const x = buttonRect.right + window.pageXOffset;
const y = (buttonRect.top + (buttonRect.height / 2) + window.pageYOffset) - 19;
const {close} = ContextualMenu.createMenu(GenericTextContextMenu, {
chevronOffset: 10,
left: x,
top: y,
const GenericTextContextMenu = sdk.getComponent('context_menus.GenericTextContextMenu');
const {close} = ContextMenu.createMenu(GenericTextContextMenu, {
...toRightOf(buttonRect, 2),
message: successful ? _t('Copied!') : _t('Failed to copy'),
}, false);
});
e.target.onmouseleave = close;
};
@ -332,7 +331,7 @@ module.exports = createReactClass({
},
getInnerText: () => {
return this.refs.content.innerText;
return this._content.current.innerText;
},
};
},
@ -406,13 +405,18 @@ module.exports = createReactClass({
label={_t("Edited at %(date)s. Click to view edits.", {date: dateString})}
/>;
}
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
return (
<div
key="editedMarker" className="mx_EventTile_edited"
<AccessibleButton
key="editedMarker"
className="mx_EventTile_edited"
onClick={this._openHistoryDialog}
onMouseEnter={this._onMouseEnterEditedMarker}
onMouseLeave={this._onMouseLeaveEditedMarker}
>{editedTooltip}<span>{`(${_t("edited")})`}</span></div>
>
{ editedTooltip }<span>{`(${_t("edited")})`}</span>
</AccessibleButton>
);
},
@ -457,7 +461,7 @@ module.exports = createReactClass({
case "m.emote":
const name = mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender();
return (
<span ref="content" className="mx_MEmoteBody mx_EventTile_content">
<span ref={this._content} className="mx_MEmoteBody mx_EventTile_content">
*&nbsp;
<span
className="mx_MEmoteBody_sender"
@ -472,14 +476,14 @@ module.exports = createReactClass({
);
case "m.notice":
return (
<span ref="content" className="mx_MNoticeBody mx_EventTile_content">
<span ref={this._content} className="mx_MNoticeBody mx_EventTile_content">
{ body }
{ widgets }
</span>
);
default: // including "m.text"
return (
<span ref="content" className="mx_MTextBody mx_EventTile_content">
<span ref={this._content} className="mx_MTextBody mx_EventTile_content">
{ body }
{ widgets }
</span>

View file

@ -14,7 +14,7 @@ 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 {_t} from "../../../languageHandler";
import MatrixClientPeg from "../../../MatrixClientPeg";
@ -58,13 +58,15 @@ export default class RoomProfileSettings extends React.Component {
canSetTopic: room.currentState.maySendStateEvent('m.room.topic', client.getUserId()),
canSetAvatar: room.currentState.maySendStateEvent('m.room.avatar', client.getUserId()),
};
this._avatarUpload = createRef();
}
_uploadAvatar = (e) => {
e.stopPropagation();
e.preventDefault();
this.refs.avatarUpload.click();
this._avatarUpload.current.click();
};
_saveProfile = async (e) => {
@ -178,7 +180,7 @@ export default class RoomProfileSettings extends React.Component {
return (
<form onSubmit={this._saveProfile} autoComplete="off" noValidate={true}>
<input type="file" ref="avatarUpload" className="mx_ProfileSettings_avatarUpload"
<input type="file" ref={this._avatarUpload} className="mx_ProfileSettings_avatarUpload"
onChange={this._onAvatarChanged} accept="image/*" />
<div className="mx_ProfileSettings_profile">
<div className="mx_ProfileSettings_controls">

View file

@ -188,14 +188,15 @@ module.exports = createReactClass({
}
const callView = (
<CallView ref="callView" room={this.props.room}
<CallView
room={this.props.room}
ConferenceHandler={this.props.conferenceHandler}
onResize={this.props.onResize}
maxVideoHeight={this.props.maxHeight}
/>
);
const appsDrawer = <AppsDrawer ref="appsDrawer"
const appsDrawer = <AppsDrawer
room={this.props.room}
userId={this.props.userId}
maxHeight={this.props.maxHeight}

View file

@ -19,7 +19,7 @@ limitations under the License.
import ReplyThread from "../elements/ReplyThread";
import React from 'react';
import React, {createRef} from 'react';
import PropTypes from 'prop-types';
import createReactClass from 'create-react-class';
const classNames = require("classnames");
@ -224,6 +224,9 @@ module.exports = createReactClass({
// don't do RR animations until we are mounted
this._suppressReadReceiptAnimation = true;
this._verifyEvent(this.props.mxEvent);
this._tile = createRef();
this._replyThread = createRef();
},
componentDidMount: function() {
@ -494,6 +497,9 @@ module.exports = createReactClass({
if (ev.status === EventStatus.NOT_SENT) {
return;
}
if (ev.isState()) {
return; // we expect this to be unencrypted
}
// if the event is not encrypted, but it's an e2e room, show the open padlock
return <E2ePadlockUnencrypted {...props} />;
}
@ -509,11 +515,11 @@ module.exports = createReactClass({
},
getTile() {
return this.refs.tile;
return this._tile.current;
},
getReplyThread() {
return this.refs.replyThread;
return this._replyThread.current;
},
getReactions() {
@ -745,7 +751,7 @@ module.exports = createReactClass({
</a>
</div>
<div className="mx_EventTile_line">
<EventTileType ref="tile"
<EventTileType ref={this._tile}
mxEvent={this.props.mxEvent}
highlights={this.props.highlights}
highlightLink={this.props.highlightLink}
@ -759,7 +765,7 @@ module.exports = createReactClass({
return (
<div className={classes}>
<div className="mx_EventTile_line">
<EventTileType ref="tile"
<EventTileType ref={this._tile}
mxEvent={this.props.mxEvent}
highlights={this.props.highlights}
highlightLink={this.props.highlightLink}
@ -789,7 +795,7 @@ module.exports = createReactClass({
this.props.mxEvent,
this.props.onHeightChanged,
this.props.permalinkCreator,
'replyThread',
this._replyThread,
);
}
return (
@ -802,7 +808,7 @@ module.exports = createReactClass({
</a>
{ !isBubbleMessage && this._renderE2EPadlock() }
{ thread }
<EventTileType ref="tile"
<EventTileType ref={this._tile}
mxEvent={this.props.mxEvent}
highlights={this.props.highlights}
highlightLink={this.props.highlightLink}
@ -817,7 +823,7 @@ module.exports = createReactClass({
this.props.mxEvent,
this.props.onHeightChanged,
this.props.permalinkCreator,
'replyThread',
this._replyThread,
);
// tab-index=-1 to allow it to be focusable but do not add tab stop for it, primarily for screen readers
return (
@ -836,7 +842,7 @@ module.exports = createReactClass({
</a>
{ !isBubbleMessage && this._renderE2EPadlock() }
{ thread }
<EventTileType ref="tile"
<EventTileType ref={this._tile}
mxEvent={this.props.mxEvent}
replacingEventId={this.props.replacingEventId}
editState={this.props.editState}
@ -887,7 +893,7 @@ module.exports.haveTileForEvent = function(e) {
function E2ePadlockUndecryptable(props) {
return (
<E2ePadlock title={_t("Undecryptable")} icon="undecryptable" {...props} />
<E2ePadlock title={_t("This message cannot be decrypted")} icon="undecryptable" {...props} />
);
}
@ -899,19 +905,57 @@ function E2ePadlockUnverified(props) {
function E2ePadlockUnencrypted(props) {
return (
<E2ePadlock title={_t("Unencrypted message")} icon="unencrypted" {...props} />
<E2ePadlock title={_t("Unencrypted")} icon="unencrypted" {...props} />
);
}
function E2ePadlock(props) {
if (SettingsStore.getValue("alwaysShowEncryptionIcons")) {
return (<div
className={`mx_EventTile_e2eIcon mx_EventTile_e2eIcon_${props.icon}`}
title={props.title} onClick={props.onClick} />);
} else {
return (<div
className={`mx_EventTile_e2eIcon mx_EventTile_e2eIcon_hidden mx_EventTile_e2eIcon_${props.icon}`}
onClick={props.onClick} />);
class E2ePadlock extends React.Component {
static propTypes = {
icon: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
onClick: PropTypes.func,
};
constructor() {
super();
this.state = {
hover: false,
};
}
onClick = (e) => {
if (this.props.onClick) this.props.onClick(e);
};
onHoverStart = () => {
this.setState({hover: true});
};
onHoverEnd = () => {
this.setState({hover: false});
};
render() {
let tooltip = null;
if (this.state.hover) {
const Tooltip = sdk.getComponent("elements.Tooltip");
tooltip = <Tooltip className="mx_EventTile_e2eIcon_tooltip" label={this.props.title} dir="auto" />;
}
let classes = `mx_EventTile_e2eIcon mx_EventTile_e2eIcon_${this.props.icon}`;
if (!SettingsStore.getValue("alwaysShowEncryptionIcons")) {
classes += ' mx_EventTile_e2eIcon_hidden';
}
return (
<div
className={classes}
onClick={this.onClick}
onMouseEnter={this.onHoverStart}
onMouseLeave={this.onHoverEnd}
>{tooltip}</div>
);
}
}

View file

@ -14,7 +14,7 @@ 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 createReactClass from 'create-react-class';
import { linkifyElement } from '../../../HtmlUtils';
@ -54,17 +54,19 @@ module.exports = createReactClass({
}, (error)=>{
console.error("Failed to get URL preview: " + error);
});
this._description = createRef();
},
componentDidMount: function() {
if (this.refs.description) {
linkifyElement(this.refs.description);
if (this._description.current) {
linkifyElement(this._description.current);
}
},
componentDidUpdate: function() {
if (this.refs.description) {
linkifyElement(this.refs.description);
if (this._description.current) {
linkifyElement(this._description.current);
}
},
@ -129,7 +131,7 @@ module.exports = createReactClass({
<div className="mx_LinkPreviewWidget_caption">
<div className="mx_LinkPreviewWidget_title"><a href={this.props.link} target="_blank" rel="noopener">{ p["og:title"] }</a></div>
<div className="mx_LinkPreviewWidget_siteName">{ p["og:site_name"] ? (" - " + p["og:site_name"]) : null }</div>
<div className="mx_LinkPreviewWidget_description" ref="description">
<div className="mx_LinkPreviewWidget_description" ref={this._description}>
{ p["og:description"] }
</div>
</div>

View file

@ -14,7 +14,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import React, {createRef} from 'react';
import PropTypes from 'prop-types';
import { _t } from '../../../languageHandler';
import CallHandler from '../../../CallHandler';
@ -111,6 +111,8 @@ class UploadButton extends React.Component {
super(props, context);
this.onUploadClick = this.onUploadClick.bind(this);
this.onUploadFileInputChange = this.onUploadFileInputChange.bind(this);
this._uploadInput = createRef();
}
onUploadClick(ev) {
@ -118,7 +120,7 @@ class UploadButton extends React.Component {
dis.dispatch({action: 'require_registration'});
return;
}
this.refs.uploadInput.click();
this._uploadInput.current.click();
}
onUploadFileInputChange(ev) {
@ -150,7 +152,9 @@ class UploadButton extends React.Component {
onClick={this.onUploadClick}
title={_t('Upload file')}
>
<input ref="uploadInput" type="file"
<input
ref={this._uploadInput}
type="file"
style={uploadInputStyle}
multiple
onChange={this.onUploadFileInputChange}

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from "react";
import React, {createRef} from "react";
import dis from "../../../dispatcher";
import MatrixClientPeg from "../../../MatrixClientPeg";
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
@ -45,6 +45,8 @@ export default class RoomBreadcrumbs extends React.Component {
// The room IDs we're waiting to come down the Room handler and when we
// started waiting for them. Used to track a room over an upgrade/autojoin.
this._waitingRoomQueue = [/* { roomId, addedTs } */];
this._scroller = createRef();
}
componentWillMount() {
@ -284,8 +286,8 @@ export default class RoomBreadcrumbs extends React.Component {
}
this.setState({rooms});
if (this.refs.scroller) {
this.refs.scroller.moveToOrigin();
if (this._scroller.current) {
this._scroller.current.moveToOrigin();
}
// We don't track room aesthetics (badges, membership, etc) over the wire so we
@ -390,7 +392,7 @@ export default class RoomBreadcrumbs extends React.Component {
return (
<div role="toolbar" aria-label={_t("Recent rooms")}>
<IndicatorScrollbar
ref="scroller"
ref={this._scroller}
className="mx_RoomBreadcrumbs"
trackHorizontalOverflow={true}
verticalScrollsHorizontally={true}

View file

@ -55,7 +55,7 @@ export default createReactClass({
if (rows.length === 0) {
rooms = <i>{ _t('No rooms to show') }</i>;
} else {
rooms = <table ref="directory_table" className="mx_RoomDirectory_table">
rooms = <table className="mx_RoomDirectory_table">
<tbody>
{ this.getRows() }
</tbody>

View file

@ -15,7 +15,7 @@ limitations under the License.
*/
import sdk from '../../../index';
import React from 'react';
import React, {createRef} from 'react';
import { _t } from '../../../languageHandler';
import { linkifyElement } from '../../../HtmlUtils';
import { ContentRepo } from 'matrix-js-sdk';
@ -49,11 +49,15 @@ export default createReactClass({
},
_linkifyTopic: function() {
if (this.refs.topic) {
linkifyElement(this.refs.topic);
if (this._topic.current) {
linkifyElement(this._topic.current);
}
},
UNSAFE_componentWillMount: function() {
this._topic = createRef();
},
componentDidMount: function() {
this._linkifyTopic();
},
@ -104,7 +108,7 @@ export default createReactClass({
<td className="mx_RoomDirectory_roomDescription">
<div className="mx_RoomDirectory_name">{ name }</div>&nbsp;
{ perms }
<div className="mx_RoomDirectory_topic" ref="topic" onClick={this.onTopicClick}>
<div className="mx_RoomDirectory_topic" ref={this._topic} onClick={this.onTopicClick}>
{ room.topic }
</div>
<div className="mx_RoomDirectory_alias">{ getDisplayAliasForRoom(room) }</div>

View file

@ -14,7 +14,7 @@ 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 createReactClass from 'create-react-class';
import classNames from 'classnames';
@ -56,6 +56,10 @@ module.exports = createReactClass({
};
},
UNSAFE_componentWillMount: function() {
this._topic = createRef();
},
componentDidMount: function() {
const cli = MatrixClientPeg.get();
cli.on("RoomState.events", this._onRoomStateEvents);
@ -70,8 +74,8 @@ module.exports = createReactClass({
},
componentDidUpdate: function() {
if (this.refs.topic) {
linkifyElement(this.refs.topic);
if (this._topic.current) {
linkifyElement(this._topic.current);
}
},
@ -204,7 +208,7 @@ module.exports = createReactClass({
}
}
const topicElement =
<div className="mx_RoomHeader_topic" ref="topic" title={topic} dir="auto">{ topic }</div>;
<div className="mx_RoomHeader_topic" ref={this._topic} title={topic} dir="auto">{ topic }</div>;
const avatarSize = 28;
let roomAvatar;
if (this.props.room) {

View file

@ -65,14 +65,14 @@ module.exports = createReactClass({
return (
<div className="mx_RoomHeader_name">
<EditableText ref="editor"
className="mx_RoomHeader_nametext mx_RoomHeader_editable"
placeholderClassName="mx_RoomHeader_placeholder"
placeholder={this._placeholderName}
blurToCancel={false}
initialValue={this.state.name}
onValueChanged={this._onValueChanged}
dir="auto" />
<EditableText
className="mx_RoomHeader_nametext mx_RoomHeader_editable"
placeholderClassName="mx_RoomHeader_placeholder"
placeholder={this._placeholderName}
blurToCancel={false}
initialValue={this.state.name}
onValueChanged={this._onValueChanged}
dir="auto" />
</div>
);
},

View file

@ -451,16 +451,21 @@ module.exports = createReactClass({
if (isDM) {
title = _t("Do you want to chat with %(user)s?",
{ user: inviteMember.name });
subTitle = [
avatar,
_t("<userName/> wants to chat", {}, {userName: () => inviterElement}),
];
primaryActionLabel = _t("Start chatting");
} else {
title = _t("Do you want to join %(roomName)s?",
{ roomName: this._roomName() });
subTitle = [
avatar,
_t("<userName/> invited you", {}, {userName: () => inviterElement}),
];
primaryActionLabel = _t("Accept");
}
subTitle = [
avatar,
_t("<userName/> invited you", {}, {userName: () => inviterElement}),
];
primaryActionLabel = _t("Accept");
primaryActionHandler = this.props.onJoinClick;
secondaryActionLabel = _t("Reject");
secondaryActionHandler = this.props.onRejectClick;

View file

@ -17,7 +17,6 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import PropTypes from 'prop-types';
import createReactClass from 'create-react-class';
@ -26,10 +25,9 @@ import dis from '../../../dispatcher';
import MatrixClientPeg from '../../../MatrixClientPeg';
import DMRoomMap from '../../../utils/DMRoomMap';
import sdk from '../../../index';
import {createMenu} from '../../structures/ContextualMenu';
import {ContextMenu, ContextMenuButton, toRightOf} from '../../structures/ContextMenu';
import * as RoomNotifs from '../../../RoomNotifs';
import * as FormattingUtils from '../../../utils/FormattingUtils';
import AccessibleButton from '../elements/AccessibleButton';
import ActiveRoomObserver from '../../../ActiveRoomObserver';
import RoomViewStore from '../../../stores/RoomViewStore';
import SettingsStore from "../../../settings/SettingsStore";
@ -61,7 +59,7 @@ module.exports = createReactClass({
return ({
hover: false,
badgeHover: false,
menuDisplayed: false,
contextMenuPosition: null, // DOM bounding box, null if non-shown
roomName: this.props.room.name,
notifState: RoomNotifs.getRoomNotifsState(this.props.room.roomId),
notificationCount: this.props.room.getUnreadNotificationCount(),
@ -229,32 +227,6 @@ module.exports = createReactClass({
this.badgeOnMouseLeave();
},
_showContextMenu: function(x, y, chevronOffset) {
const RoomTileContextMenu = sdk.getComponent('context_menus.RoomTileContextMenu');
createMenu(RoomTileContextMenu, {
chevronOffset,
left: x,
top: y,
room: this.props.room,
onFinished: () => {
this.setState({ menuDisplayed: false });
this.props.refreshSubList();
},
});
this.setState({ menuDisplayed: true });
},
onContextMenu: function(e) {
// Prevent the RoomTile onClick event firing as well
e.preventDefault();
// Only allow non-guests to access the context menu
if (MatrixClientPeg.get().isGuest()) return;
const chevronOffset = 12;
this._showContextMenu(e.clientX, e.clientY - (chevronOffset + 8), chevronOffset);
},
badgeOnMouseEnter: function() {
// Only allow non-guests to access the context menu
// and only change it if it needs to change
@ -267,26 +239,46 @@ module.exports = createReactClass({
this.setState( { badgeHover: false } );
},
onOpenMenu: function(e) {
// Prevent the RoomTile onClick event firing as well
e.stopPropagation();
_showContextMenu: function(boundingClientRect) {
// Only allow non-guests to access the context menu
if (MatrixClientPeg.get().isGuest()) return;
const state = {
contextMenuPosition: boundingClientRect,
};
// If the badge is clicked, then no longer show tooltip
if (this.props.collapsed) {
this.setState({ hover: false });
state.hover = false;
}
const elementRect = e.target.getBoundingClientRect();
this.setState(state);
},
// The window X and Y offsets are to adjust position when zoomed in to page
const x = elementRect.right + window.pageXOffset + 3;
const chevronOffset = 12;
let y = (elementRect.top + (elementRect.height / 2) + window.pageYOffset);
y = y - (chevronOffset + 8); // where 8 is half the height of the chevron
onContextMenuButtonClick: function(e) {
// Prevent the RoomTile onClick event firing as well
e.stopPropagation();
e.preventDefault();
this._showContextMenu(x, y, chevronOffset);
this._showContextMenu(e.target.getBoundingClientRect());
},
onContextMenu: function(e) {
// Prevent the native context menu
e.preventDefault();
this._showContextMenu({
right: e.clientX,
top: e.clientY,
height: 0,
});
},
closeMenu: function() {
this.setState({
contextMenuPosition: null,
});
this.props.refreshSubList();
},
render: function() {
@ -303,6 +295,8 @@ module.exports = createReactClass({
subtext = this.state.statusMessage;
}
const isMenuDisplayed = Boolean(this.state.contextMenuPosition);
const classes = classNames({
'mx_RoomTile': true,
'mx_RoomTile_selected': this.state.selected,
@ -310,7 +304,7 @@ module.exports = createReactClass({
'mx_RoomTile_unreadNotify': notifBadges,
'mx_RoomTile_highlight': mentionBadges,
'mx_RoomTile_invited': isInvite,
'mx_RoomTile_menuDisplayed': this.state.menuDisplayed,
'mx_RoomTile_menuDisplayed': isMenuDisplayed,
'mx_RoomTile_noBadges': !badges,
'mx_RoomTile_transparent': this.props.transparent,
'mx_RoomTile_hasSubtext': subtext && !this.props.collapsed,
@ -322,7 +316,7 @@ module.exports = createReactClass({
const badgeClasses = classNames({
'mx_RoomTile_badge': true,
'mx_RoomTile_badgeButton': this.state.badgeHover || this.state.menuDisplayed,
'mx_RoomTile_badgeButton': this.state.badgeHover || isMenuDisplayed,
});
let name = this.state.roomName;
@ -344,7 +338,7 @@ module.exports = createReactClass({
const nameClasses = classNames({
'mx_RoomTile_name': true,
'mx_RoomTile_invite': this.props.isInvite,
'mx_RoomTile_badgeShown': badges || this.state.badgeHover || this.state.menuDisplayed,
'mx_RoomTile_badgeShown': badges || this.state.badgeHover || isMenuDisplayed,
});
subtextLabel = subtext ? <span className="mx_RoomTile_subtext">{ subtext }</span> : null;
@ -360,9 +354,17 @@ module.exports = createReactClass({
// incomingCallBox = <IncomingCallBox incomingCall={ this.props.incomingCall }/>;
//}
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
let contextMenuButton;
if (!MatrixClientPeg.get().isGuest()) {
contextMenuButton = <AccessibleButton className="mx_RoomTile_menuButton" onClick={this.onOpenMenu} />;
contextMenuButton = (
<ContextMenuButton
className="mx_RoomTile_menuButton"
label={_t("Options")}
isExpanded={isMenuDisplayed}
onClick={this.onContextMenuButtonClick} />
);
}
const RoomAvatar = sdk.getComponent('avatars.RoomAvatar');
@ -393,32 +395,47 @@ module.exports = createReactClass({
ariaLabel += " " + _t("Unread messages.");
}
return <AccessibleButton tabIndex="0"
className={classes}
onClick={this.onClick}
onMouseEnter={this.onMouseEnter}
onMouseLeave={this.onMouseLeave}
onContextMenu={this.onContextMenu}
aria-label={ariaLabel}
aria-selected={this.state.selected}
role="treeitem"
>
<div className={avatarClasses}>
<div className="mx_RoomTile_avatar_container">
<RoomAvatar room={this.props.room} width={24} height={24} />
{ dmIndicator }
let contextMenu;
if (isMenuDisplayed) {
const RoomTileContextMenu = sdk.getComponent('context_menus.RoomTileContextMenu');
contextMenu = (
<ContextMenu {...toRightOf(this.state.contextMenuPosition)} onFinished={this.closeMenu}>
<RoomTileContextMenu room={this.props.room} onFinished={this.closeMenu} />
</ContextMenu>
);
}
return <React.Fragment>
<AccessibleButton
tabIndex="0"
className={classes}
onClick={this.onClick}
onMouseEnter={this.onMouseEnter}
onMouseLeave={this.onMouseLeave}
onContextMenu={this.onContextMenu}
aria-label={ariaLabel}
aria-selected={this.state.selected}
role="treeitem"
>
<div className={avatarClasses}>
<div className="mx_RoomTile_avatar_container">
<RoomAvatar room={this.props.room} width={24} height={24} />
{ dmIndicator }
</div>
</div>
</div>
<div className="mx_RoomTile_nameContainer">
<div className="mx_RoomTile_labelContainer">
{ label }
{ subtextLabel }
<div className="mx_RoomTile_nameContainer">
<div className="mx_RoomTile_labelContainer">
{ label }
{ subtextLabel }
</div>
{ contextMenuButton }
{ badge }
</div>
{ contextMenuButton }
{ badge }
</div>
{ /* { incomingCallBox } */ }
{ tooltip }
</AccessibleButton>;
{ /* { incomingCallBox } */ }
{ tooltip }
</AccessibleButton>
{ contextMenu }
</React.Fragment>;
},
});

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import React, {createRef} from 'react';
import createReactClass from 'create-react-class';
const classNames = require('classnames');
const AccessibleButton = require('../../../components/views/elements/AccessibleButton');
@ -29,6 +29,10 @@ module.exports = createReactClass({
});
},
UNSAFE_componentWillMount: function() {
this._search_term = createRef();
},
onThisRoomClick: function() {
this.setState({ scope: 'Room' }, () => this._searchIfQuery());
},
@ -47,29 +51,41 @@ module.exports = createReactClass({
},
_searchIfQuery: function() {
if (this.refs.search_term.value) {
if (this._search_term.current.value) {
this.onSearch();
}
},
onSearch: function() {
this.props.onSearch(this.refs.search_term.value, this.state.scope);
this.props.onSearch(this._search_term.current.value, this.state.scope);
},
render: function() {
const searchButtonClasses = classNames({ mx_SearchBar_searchButton: true, mx_SearchBar_searching: this.props.searchInProgress });
const thisRoomClasses = classNames({ mx_SearchBar_button: true, mx_SearchBar_unselected: this.state.scope !== 'Room' });
const allRoomsClasses = classNames({ mx_SearchBar_button: true, mx_SearchBar_unselected: this.state.scope !== 'All' });
const searchButtonClasses = classNames("mx_SearchBar_searchButton", {
mx_SearchBar_searching: this.props.searchInProgress,
});
const thisRoomClasses = classNames("mx_SearchBar_button", {
mx_SearchBar_unselected: this.state.scope !== 'Room',
});
const allRoomsClasses = classNames("mx_SearchBar_button", {
mx_SearchBar_unselected: this.state.scope !== 'All',
});
return (
<div className="mx_SearchBar">
<AccessibleButton className={ thisRoomClasses } onClick={this.onThisRoomClick}>{_t("This Room")}</AccessibleButton>
<AccessibleButton className={ allRoomsClasses } onClick={this.onAllRoomsClick}>{_t("All Rooms")}</AccessibleButton>
<div className="mx_SearchBar_input mx_textinput">
<input ref="search_term" type="text" autoFocus={true} placeholder={_t("Search…")} onKeyDown={this.onSearchChange} />
<AccessibleButton className={ searchButtonClasses } onClick={this.onSearch}></AccessibleButton>
<div className="mx_SearchBar_buttons" role="radiogroup">
<AccessibleButton className={ thisRoomClasses } onClick={this.onThisRoomClick} aria-checked={this.state.scope === 'Room'} role="radio">
{_t("This Room")}
</AccessibleButton>
<AccessibleButton className={ allRoomsClasses } onClick={this.onAllRoomsClick} aria-checked={this.state.scope === 'All'} role="radio">
{_t("All Rooms")}
</AccessibleButton>
</div>
<AccessibleButton className="mx_SearchBar_cancel" onClick={this.props.onCancelClick}></AccessibleButton>
<div className="mx_SearchBar_input mx_textinput">
<input ref={this._search_term} type="text" autoFocus={true} placeholder={_t("Search…")} onKeyDown={this.onSearchChange} />
<AccessibleButton className={ searchButtonClasses } onClick={this.onSearch} />
</div>
<AccessibleButton className="mx_SearchBar_cancel" onClick={this.props.onCancelClick} />
</div>
);
},

View file

@ -14,12 +14,11 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import React, {createRef} from 'react';
import PropTypes from 'prop-types';
import { _t, _td } from '../../../languageHandler';
import CallHandler from '../../../CallHandler';
import MatrixClientPeg from '../../../MatrixClientPeg';
import Modal from '../../../Modal';
import sdk from '../../../index';
import dis from '../../../dispatcher';
import RoomViewStore from '../../../stores/RoomViewStore';
@ -27,7 +26,6 @@ import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
import Stickerpicker from './Stickerpicker';
import { makeRoomPermalink } from '../../../utils/permalinks/Permalinks';
import ContentMessages from '../../../ContentMessages';
import classNames from 'classnames';
import E2EIcon from './E2EIcon';
@ -143,6 +141,8 @@ class UploadButton extends React.Component {
super(props, context);
this.onUploadClick = this.onUploadClick.bind(this);
this.onUploadFileInputChange = this.onUploadFileInputChange.bind(this);
this._uploadInput = createRef();
}
onUploadClick(ev) {
@ -150,7 +150,7 @@ class UploadButton extends React.Component {
dis.dispatch({action: 'require_registration'});
return;
}
this.refs.uploadInput.click();
this._uploadInput.current.click();
}
onUploadFileInputChange(ev) {
@ -182,7 +182,7 @@ class UploadButton extends React.Component {
onClick={this.onUploadClick}
title={_t('Upload file')}
>
<input ref="uploadInput" type="file"
<input ref={this._uploadInput} type="file"
style={uploadInputStyle}
multiple
onChange={this.onUploadFileInputChange}

View file

@ -25,6 +25,7 @@ import ActiveWidgetStore from '../../../stores/ActiveWidgetStore';
import PersistedElement from "../elements/PersistedElement";
import {IntegrationManagers} from "../../../integrations/IntegrationManagers";
import SettingsStore from "../../../settings/SettingsStore";
import {ContextMenu} from "../../structures/ContextMenu";
const widgetType = 'm.stickerpicker';
@ -371,26 +372,8 @@ export default class Stickerpicker extends React.Component {
}
render() {
const ContextualMenu = sdk.getComponent('structures.ContextualMenu');
const GenericElementContextMenu = sdk.getComponent('context_menus.GenericElementContextMenu');
let stickerPicker;
let stickersButton;
const stickerPicker = <ContextualMenu
elementClass={GenericElementContextMenu}
chevronOffset={this.state.stickerPickerChevronOffset}
chevronFace={'bottom'}
left={this.state.stickerPickerX}
top={this.state.stickerPickerY}
menuWidth={this.popoverWidth}
menuHeight={this.popoverHeight}
element={this._getStickerpickerContent()}
onFinished={this._onFinished}
menuPaddingTop={0}
menuPaddingLeft={0}
menuPaddingRight={0}
zIndex={STICKERPICKER_Z_INDEX}
/>;
if (this.state.showStickers) {
// Show hide-stickers button
stickersButton =
@ -402,6 +385,23 @@ export default class Stickerpicker extends React.Component {
title={_t("Hide Stickers")}
>
</AccessibleButton>;
const GenericElementContextMenu = sdk.getComponent('context_menus.GenericElementContextMenu');
stickerPicker = <ContextMenu
chevronOffset={this.state.stickerPickerChevronOffset}
chevronFace="bottom"
left={this.state.stickerPickerX}
top={this.state.stickerPickerY}
menuWidth={this.popoverWidth}
menuHeight={this.popoverHeight}
onFinished={this._onFinished}
menuPaddingTop={0}
menuPaddingLeft={0}
menuPaddingRight={0}
zIndex={STICKERPICKER_Z_INDEX}
>
<GenericElementContextMenu element={this._getStickerpickerContent()} onResize={this._onFinished} />
</ContextMenu>;
} else {
// Show show-stickers button
stickersButton =
@ -415,8 +415,8 @@ export default class Stickerpicker extends React.Component {
</AccessibleButton>;
}
return <React.Fragment>
{stickersButton}
{this.state.showStickers && stickerPicker}
{ stickersButton }
{ stickerPicker }
</React.Fragment>;
}
}

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import React, {createRef} from 'react';
import {_t} from "../../../languageHandler";
import MatrixClientPeg from "../../../MatrixClientPeg";
import Field from "../elements/Field";
@ -48,13 +48,15 @@ export default class ProfileSettings extends React.Component {
avatarFile: null,
enableProfileSave: false,
};
this._avatarUpload = createRef();
}
_uploadAvatar = (e) => {
e.stopPropagation();
e.preventDefault();
this.refs.avatarUpload.click();
this._avatarUpload.current.click();
};
_saveProfile = async (e) => {
@ -156,7 +158,7 @@ export default class ProfileSettings extends React.Component {
return (
<form onSubmit={this._saveProfile} autoComplete="off" noValidate={true}>
<input type="file" ref="avatarUpload" className="mx_ProfileSettings_avatarUpload"
<input type="file" ref={this._avatarUpload} className="mx_ProfileSettings_avatarUpload"
onChange={this._onAvatarChanged} accept="image/*" />
<div className="mx_ProfileSettings_profile">
<div className="mx_ProfileSettings_controls">

View file

@ -14,7 +14,7 @@ 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 {_t} from "../../../../../languageHandler";
import MatrixClientPeg from "../../../../../MatrixClientPeg";
@ -44,13 +44,15 @@ export default class NotificationsSettingsTab extends React.Component {
}
this.setState({currentSound: soundData.name || soundData.url});
});
this._soundUpload = createRef();
}
async _triggerUploader(e) {
e.stopPropagation();
e.preventDefault();
this.refs.soundUpload.click();
this._soundUpload.current.click();
}
async _onSoundUploadChanged(e) {
@ -157,7 +159,7 @@ export default class NotificationsSettingsTab extends React.Component {
<div>
<h3>{_t("Set a new custom sound")}</h3>
<form autoComplete="off" noValidate={true}>
<input ref="soundUpload" className="mx_NotificationSound_soundUpload" type="file" onChange={this._onSoundUploadChanged.bind(this)} accept="audio/*" />
<input ref={this._soundUpload} className="mx_NotificationSound_soundUpload" type="file" onChange={this._onSoundUploadChanged.bind(this)} accept="audio/*" />
</form>
{currentUploadedFile}

View file

@ -49,8 +49,6 @@ export default class GeneralUserSettingsTab extends React.Component {
this.state = {
language: languageHandler.getCurrentLanguage(),
theme: SettingsStore.getValueAt(SettingLevel.ACCOUNT, "theme"),
useSystemTheme: SettingsStore.getValueAt(SettingLevel.DEVICE, "use_system_theme"),
haveIdServer: Boolean(MatrixClientPeg.get().getIdentityServerUrl()),
serverSupportsSeparateAddAndBind: null,
idServerHasUnsignedTerms: false,
@ -62,6 +60,7 @@ export default class GeneralUserSettingsTab extends React.Component {
},
emails: [],
msisdns: [],
...this._calculateThemeState(),
};
this.dispatcherRef = dis.register(this._onAction);
@ -80,6 +79,39 @@ export default class GeneralUserSettingsTab extends React.Component {
dis.unregister(this.dispatcherRef);
}
_calculateThemeState() {
// We have to mirror the logic from ThemeWatcher.getEffectiveTheme so we
// show the right values for things.
const themeChoice = SettingsStore.getValueAt(SettingLevel.ACCOUNT, "theme");
const systemThemeExplicit = SettingsStore.getValueAt(
SettingLevel.DEVICE, "use_system_theme", null, false, true);
const themeExplicit = SettingsStore.getValueAt(
SettingLevel.DEVICE, "theme", null, false, true);
// If the user has enabled system theme matching, use that.
if (systemThemeExplicit) {
return {
theme: themeChoice,
useSystemTheme: true,
};
}
// If the user has set a theme explicitly, use that (no system theme matching)
if (themeExplicit) {
return {
theme: themeChoice,
useSystemTheme: false,
};
}
// Otherwise assume the defaults for the settings
return {
theme: themeChoice,
useSystemTheme: SettingsStore.getValueAt(SettingLevel.DEVICE, "use_system_theme"),
};
}
_onAction = (payload) => {
if (payload.action === 'id_server_changed') {
this.setState({haveIdServer: Boolean(MatrixClientPeg.get().getIdentityServerUrl())});
@ -89,11 +121,11 @@ export default class GeneralUserSettingsTab extends React.Component {
_onEmailsChange = (emails) => {
this.setState({ emails });
}
};
_onMsisdnsChange = (msisdns) => {
this.setState({ msisdns });
}
};
async _getThreepidState() {
const cli = MatrixClientPeg.get();
@ -193,9 +225,9 @@ export default class GeneralUserSettingsTab extends React.Component {
_onUseSystemThemeChanged = (checked) => {
this.setState({useSystemTheme: checked});
SettingsStore.setValue("use_system_theme", null, SettingLevel.DEVICE, checked);
dis.dispatch({action: 'recheck_theme'});
}
};
_onPasswordChangeError = (err) => {
// TODO: Figure out a design that doesn't involve replacing the current dialog
@ -307,12 +339,15 @@ export default class GeneralUserSettingsTab extends React.Component {
_renderThemeSection() {
const SettingsFlag = sdk.getComponent("views.elements.SettingsFlag");
const LabelledToggleSwitch = sdk.getComponent("views.elements.LabelledToggleSwitch");
const themeWatcher = new ThemeWatcher();
let systemThemeSection;
if (themeWatcher.isSystemThemeSupported()) {
systemThemeSection = <div>
<SettingsFlag name="use_system_theme" level={SettingLevel.DEVICE}
<LabelledToggleSwitch
value={this.state.useSystemTheme}
label={SettingsStore.getDisplayName("use_system_theme")}
onChange={this._onUseSystemThemeChanged}
/>
</div>;

View file

@ -13,7 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import React, {createRef} from 'react';
import PropTypes from 'prop-types';
import createReactClass from 'create-react-class';
import dis from '../../../dispatcher';
@ -56,6 +56,10 @@ module.exports = createReactClass({
};
},
UNSAFE_componentWillMount: function() {
this._video = createRef();
},
componentDidMount: function() {
this.dispatcherRef = dis.register(this.onAction);
this.showCall();
@ -128,7 +132,7 @@ module.exports = createReactClass({
},
getVideoView: function() {
return this.refs.video;
return this._video.current;
},
render: function() {
@ -147,7 +151,9 @@ module.exports = createReactClass({
return (
<div>
<VideoView ref="video" onClick={this.props.onClick}
<VideoView
ref={this._video}
onClick={this.props.onClick}
onResize={this.props.onResize}
maxHeight={this.props.maxVideoHeight}
/>

View file

@ -14,7 +14,7 @@ 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 createReactClass from 'create-react-class';
@ -30,12 +30,16 @@ module.exports = createReactClass({
onResize: PropTypes.func,
},
UNSAFE_componentWillMount() {
this._vid = createRef();
},
componentDidMount() {
this.refs.vid.addEventListener('resize', this.onResize);
this._vid.current.addEventListener('resize', this.onResize);
},
componentWillUnmount() {
this.refs.vid.removeEventListener('resize', this.onResize);
this._vid.current.removeEventListener('resize', this.onResize);
},
onResize: function(e) {
@ -46,7 +50,7 @@ module.exports = createReactClass({
render: function() {
return (
<video ref="vid" style={{maxHeight: this.props.maxHeight}}>
<video ref={this._vid} style={{maxHeight: this.props.maxHeight}}>
</video>
);
},

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import React, {createRef} from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import createReactClass from 'create-react-class';
@ -49,6 +49,11 @@ module.exports = createReactClass({
onResize: PropTypes.func,
},
UNSAFE_componentWillMount: function() {
this._local = createRef();
this._remote = createRef();
},
componentDidMount: function() {
this.dispatcherRef = dis.register(this.onAction);
},
@ -58,7 +63,7 @@ module.exports = createReactClass({
},
getRemoteVideoElement: function() {
return ReactDOM.findDOMNode(this.refs.remote);
return ReactDOM.findDOMNode(this._remote.current);
},
getRemoteAudioElement: function() {
@ -74,7 +79,7 @@ module.exports = createReactClass({
},
getLocalVideoElement: function() {
return ReactDOM.findDOMNode(this.refs.local);
return ReactDOM.findDOMNode(this._local.current);
},
setContainer: function(c) {
@ -125,11 +130,11 @@ module.exports = createReactClass({
return (
<div className="mx_VideoView" ref={this.setContainer} onClick={this.props.onClick}>
<div className="mx_VideoView_remoteVideoFeed">
<VideoFeed ref="remote" onResize={this.props.onResize}
<VideoFeed ref={this._remote} onResize={this.props.onResize}
maxHeight={maxVideoHeight} />
</div>
<div className={localVideoFeedClasses}>
<VideoFeed ref="local" />
<VideoFeed ref={this._local} />
</div>
</div>
);

View file

@ -18,7 +18,6 @@
"This phone number is already in use": "رقم الهاتف هذا مستخدم بالفعل",
"Failed to verify email address: make sure you clicked the link in the email": "فشل تأكيد عنوان البريد الإلكتروني: تحقق من نقر الرابط في البريد",
"The version of Riot.im": "إصدارة Riot.im",
"Whether or not you're logged in (we don't record your user name)": "فيما إذا كنت والجا أم لا (لا نسجّل اسم المستخدم)",
"Whether or not you're using the Richtext mode of the Rich Text Editor": "فيما إذا كنت تستخدم وضع النص الغني لمحرر النصوص الغني أم لا",
"Your homeserver's URL": "عنوان خادوم المنزل",
"Your identity server's URL": "عنوان خادوم التعريف",
@ -39,7 +38,6 @@
"Update": "تحديث",
"What's New": "آخِر المُستجدّات",
"Toolbox": "علبة الأدوات",
"Add an email address above to configure email notifications": "أضف بريداً إلكترونياً أعلاه من أجل ضبط الإشعارات عبر البريد الإلكتروني",
"Collecting logs": "تجميع السجلات",
"No update available.": "لا يوجد هناك أي تحديث.",
"An error occurred whilst saving your email notification preferences.": "حدث خطأ ما أثناء عملية حفظ إعدادات الإشعارات عبر البريد الإلكتروني.",
@ -49,7 +47,6 @@
"Send Account Data": "إرسال بيانات الحساب",
"Waiting for response from server": "في انتظار الرد مِن الخادوم",
"This will allow you to return to your account after signing out, and sign in on other devices.": "سيسمح لك هذا بالعودة إلى حسابك بعد الخروج، وتسجيل الدخول على الأجهزة الأخرى.",
"Directory": "الدليل",
"Send logs": "إرسال السِجلات",
"Download this file": "تنزيل هذا الملف",
"Thank you!": "شكرًا !",
@ -63,7 +60,6 @@
"What's new?": "ما الجديد ؟",
"You have successfully set a password and an email address!": "لقد قمت بتعيين كلمة سرية و إدخال عنوان للبريد الإلكتروني بنجاح !",
"Cancel Sending": "إلغاء الإرسال",
"Collapse panel": "طي الجدول",
"Set Password": "تعيين كلمة سرية",
"Checking for an update...": "البحث عن تحديث …",
"powered by Matrix": "مشغل بواسطة Matrix",

View file

@ -4,7 +4,6 @@
"Uploading report": "Hesabatın göndərilməsi",
"Waiting for response from server": "Serverdən cavabın gözlənməsi",
"Messages containing my display name": "Mənim adımı özündə saxlayan mesajlar",
"Messages containing my user name": "Mənim istifadəçinin adımı özündə saxlayan mesaj",
"Messages in one-to-one chats": "Fərdi çatlarda mesajlar",
"Messages in group chats": "Qrup çatlarında mesajlar",
"When I'm invited to a room": "Nə vaxt ki, məni otağa dəvət edirlər",
@ -24,11 +23,9 @@
"Notify me for anything else": "Bütün qalan hadisələrdə xəbər vermək",
"Enable notifications for this account": "Bu hesab üçün xəbərdarlıqları qoşmaq",
"All notifications are currently disabled for all targets.": "Bütün qurğular üçün bütün bildirişlər kəsilmişdir.",
"Add an email address above to configure email notifications": "Yuxarı email-i xəbərdarlıqların qurması üçün əlavə edin",
"Failed to verify email address: make sure you clicked the link in the email": "Email-i yoxlamağı bacarmadı: əmin olun ki, siz məktubda istinaddakı ünvana keçdiniz",
"The platform you're on": "İstifadə edilən platforma",
"The version of Riot.im": "Riot.im versiyası",
"Whether or not you're logged in (we don't record your user name)": "Siz sistemə girdiniz ya yox (biz sizin istifadəçinin adınızı saxlamırıq)",
"Your language of choice": "Seçilmiş dil",
"Which officially provided instance you are using, if any": "Hansı rəsmən dəstəklənən müştəri tərəfindən siz istifadə edirsiniz ( əgər istifadə edirsinizsə)",
"Whether or not you're using the Richtext mode of the Rich Text Editor": "Siz Rich Text Editor redaktorunda Richtext rejimindən istifadə edirsinizmi",
@ -47,12 +44,7 @@
"VoIP is unsupported": "Zənglər dəstəklənmir",
"You cannot place VoIP calls in this browser.": "Zənglər bu brauzerdə dəstəklənmir.",
"You cannot place a call with yourself.": "Siz özünə zəng vura bilmirsiniz.",
"Conference calls are not supported in encrypted rooms": "Konfrans-əlaqə şifrlənmiş otaqlarda dəstəklənmir",
"Conference calls are not supported in this client": "Bu müştəridə konfrans-əlaqə dəstəklənmir",
"Warning!": "Diqqət!",
"Conference calling is in development and may not be reliable.": "Konfrans-əlaqə hazırlamadadır və işləməyə bilər.",
"Failed to set up conference call": "Konfrans-zəngi etməyi bacarmadı",
"Conference call failed.": "Konfrans-zəngin nasazlığı.",
"Upload Failed": "Faylın göndərilməsinin nasazlığı",
"Failure to create room": "Otağı yaratmağı bacarmadı",
"Sun": "Baz",
@ -83,10 +75,8 @@
"Admin": "Administrator",
"Start a chat": "Danışığa başlamaq",
"Who would you like to communicate with?": "Kimlə siz əlaqə saxlamaq istəyirdiniz?",
"Email, name or matrix ID": "Email, ad və ya ZT-ID",
"Start Chat": "Danışığa başlamaq",
"Invite new room members": "Yeni iştirakçıların otağına dəvət etmək",
"Who would you like to add to this room?": "Bu otaqa kimi dəvət etmək istərdiniz?",
"You need to be logged in.": "Siz sistemə girməlisiniz.",
"You need to be able to invite users to do that.": "Bunun üçün siz istifadəçiləri dəvət etmək imkanına malik olmalısınız.",
"Failed to send request.": "Sorğunu göndərməyi bacarmadı.",
@ -131,7 +121,6 @@
"(not supported by this browser)": "(bu brauzerlə dəstəklənmir)",
"%(senderName)s answered the call.": "%(senderName)s zəngə cavab verdi.",
"%(senderName)s ended the call.": "%(senderName)s zəng qurtardı.",
"%(senderName)s placed a %(callType)s call.": "%(senderName)s ) %(callType)s-zəng başladı.",
"%(senderName)s made future room history visible to all room members, from the point they are invited.": "%(senderName)s dəvət edilmiş iştirakçılar üçün danışıqların tarixini açdı.",
"%(senderName)s made future room history visible to all room members, from the point they joined.": "%(senderName)s girmiş iştirakçılar üçün danışıqların tarixini açdı.",
"%(senderName)s made future room history visible to all room members.": "%(senderName)s iştirakçılar üçün danışıqların tarixini açdı.",
@ -140,23 +129,15 @@
"%(senderName)s turned on end-to-end encryption (algorithm %(algorithm)s).": "%(senderName)s включил(а) в комнате сквозное шифрование (алгоритм %(algorithm)s).",
"%(userId)s from %(fromPowerLevel)s to %(toPowerLevel)s": "%(userId)s üçün %(fromPowerLevel)s-dan %(toPowerLevel)s-lə",
"%(senderName)s changed the power level of %(powerLevelDiffText)s.": "%(senderName)s hüquqların səviyyələrini dəyişdirdi %(powerLevelDiffText)s.",
"%(displayName)s is typing": "%(displayName)s çap edir",
"%(names)s and %(lastPerson)s are typing": "%(names)s və %(lastPerson)s çap edirlər",
"Failed to join room": "Otağa girməyi bacarmadı",
"Disable Emoji suggestions while typing": "Mətnin yığılması vaxtı Emoji-i təklif etməmək",
"Hide read receipts": "Oxuma haqqında nişanları gizlətmək",
"Always show message timestamps": "Həmişə mesajların göndərilməsi vaxtını göstərmək",
"Autoplay GIFs and videos": "GIF animasiyalarını və videolarını avtomatik olaraq oynayır",
"Don't send typing notifications": "Nə vaxt ki, mən çap edirəm, o haqda bildirişləri göndərməmək",
"Never send encrypted messages to unverified devices from this device": "Heç vaxt (bu qurğudan) yoxlanılmamış qurğulara şifrlənmiş mesajları göndərməmək",
"Never send encrypted messages to unverified devices in this room from this device": "Heç vaxt (bu otaqda, bu qurğudan) yoxlanılmamış qurğulara şifrlənmiş mesajları göndərməmək",
"Accept": "Qəbul etmək",
"Error": "Səhv",
"A text message has been sent to +%(msisdn)s. Please enter the verification code it contains": "Mətn mesajı +%(msisdn)s-a göndərilmişdi. Mesajdan yoxlama kodunu daxil edin",
"Incorrect verification code": "Təsdiq etmənin səhv kodu",
"Enter Code": "Kodu daxil etmək",
"Phone": "Telefon",
"Add phone number": "Telefon nömrəsini əlavə etmək",
"New passwords don't match": "Yeni şifrlər uyğun gəlmir",
"Passwords can't be empty": "Şifrələr boş ola bilməz",
"Continue": "Davam etmək",
@ -173,10 +154,7 @@
"On": "Qoşmaq",
"Invalid alias format": "Adının yolverilməz formatı",
"'%(alias)s' is not a valid format for an alias": "Ad '%(alias)s' yolverilməz formata malikdir",
"Invalid address format": "Ünvanın yolverilməz formatı",
"'%(alias)s' is not a valid format for an address": "Ünvan '%(alias)s' yolverilməz formata malikdir",
"not specified": "qeyd edilmədi",
"not set": "qeyd edilmədi",
"Local addresses for this room:": "Sizin serverinizdə bu otağın ünvanları:",
"New address (e.g. #foo:%(localDomain)s)": "Yeni ünvan (məsələn, #nəsə:%(localDomain)s)",
"Blacklisted": "Qara siyahıda",
@ -196,14 +174,9 @@
"Ignore": "Bloklamaq",
"User Options": "Hərəkətlər",
"Direct chats": "Şəxsi çatlar",
"Level:": "Səviyyə:",
"Invited": "Dəvət edilmişdir",
"Filter room members": "İştirakçılara görə axtarış",
"Attachment": "Əlavə",
"Upload Files": "Faylların göndərilməsi",
"Are you sure you want to upload the following files?": "Siz əminsiniz ki, siz bu faylları göndərmək istəyirsiniz?",
"Encrypted room": "Şifrlənmiş otaq",
"Unencrypted room": "Şifrələnməyən otaq",
"Hangup": "Bitirmək",
"Voice call": "Səs çağırış",
"Video call": "Video çağırış",
@ -217,30 +190,15 @@
"Upload avatar": "Avatar-ı yükləmək",
"Settings": "Qurmalar",
"Forget room": "Otağı unutmaq",
"Drop here to tag %(section)s": "Bura daşıyın %(section)s nişan qoymaq üçün",
"Invites": "Dəvətlər",
"Favourites": "Seçilmişlər",
"People": "İnsanlar",
"Low priority": "Əhəmiyyətsizlər",
"Historical": "Arxiv",
"Rejoin": "Yenidən girmək",
"You are trying to access %(roomName)s.": "Siz %(roomName)s-a girməyə çalışırsınız.",
"You are trying to access a room.": "Siz otağa girməyə çalışırsınız.",
"<a>Click here</a> to join the discussion!": "<a>Qoşulmaq üçün</a> buraya basın!",
"Failed to unban": "Blokdan çıxarmağı bacarmadı",
"Banned by %(displayName)s": "%(displayName)s bloklanıb",
"Changes to who can read history will only apply to future messages in this room": "Tarixə girişin qaydalarının dəyişikliyi yalnız bu otaqda gələcək mesajlara tətbiq ediləcək",
"unknown error code": "naməlum səhv kodu",
"Failed to forget room %(errCode)s": "Otağı unutmağı bacarmadı: %(errCode)s",
"End-to-end encryption is in beta and may not be reliable": "İki tərəfi açıq şifrləmə indi beta-testdə və işləməyə bilər",
"You should not yet trust it to secure data": "Hal-hazırda yazışmalarınızın şifrələnəcəyinə etibar etməməlisiniz",
"Devices will not yet be able to decrypt history from before they joined the room": "Qurğular otağa girişinin anına qədər mesajların tarixinin şifrini aça bilməyəcək",
"Once encryption is enabled for a room it cannot be turned off again (for now)": "Otaqda şifrləmənin qoşmasından sonra siz o yenidən söndürə bilməyəcəksiniz (müvəqqəti)",
"Encrypted messages will not be visible on clients that do not yet implement encryption": "Şifrlənmiş mesajlar daha iki tərəfi açıq şifrləməni dəstəkləməyən müştərilərdə görülməyəcək",
"Enable encryption": "Şifrləməni qoşmaq",
"(warning: cannot be disabled again!)": "(xəbərdarlıq: dəyişdirmək mümkün olmayacaq!)",
"To send messages, you must be a": "Mesajların göndərilməsi üçün, olmaq lazımdır",
"To invite users into the room, you must be a": "Otağa iştirakçıları dəvət etmək üçün, olmaq lazımdır",
"No users have specific privileges in this room": "Heç bir istifadəçi bu otaqda xüsusi hüquqlara malik deyil",
"Banned users": "Bloklanmış istifadəçilər",
"Favourite": "Seçilmiş",
@ -259,14 +217,7 @@
"Decrypt %(text)s": "Şifrini açmaq %(text)s",
"Download %(text)s": "Yükləmək %(text)s",
"Message removed by %(userId)s": "%(userId)s mesajı silinmişdir",
"Password:": "Şifrə:",
"Username on %(hs)s": "İstifadəçinin adı %(hs)s",
"User name": "İstifadəçinin adı",
"Mobile phone number": "Mobil telefonun nömrəsi",
"Forgot your password?": "Şifrənizi unutmusunuz?",
"Sign in with": "Seçmək",
"Email address (optional)": "Email (qeyri-məcburi)",
"Mobile phone number (optional)": "Mobil telefonun (qeyri-məcburi) nömrəsi",
"Register": "Qeydiyyatdan keçmək",
"Remove": "Silmək",
"You are not receiving desktop notifications": "Siz sistem xəbərdarlıqlarını almırsınız",
@ -274,7 +225,6 @@
"Update": "Yeniləmək",
"Create new room": "Otağı yaratmaq",
"No results": "Nəticə yoxdur",
"Delete": "Silmək",
"Home": "Başlanğıc",
"Could not connect to the integration server": "İnteqrasiyanın serverinə qoşulmağ mümkün deyil",
"Manage Integrations": "İnteqrasiyaları idarə etmə",
@ -282,9 +232,6 @@
"Room directory": "Otaqların kataloqu",
"Start chat": "Çata başlamaq",
"Create Room": "Otağı yaratmaq",
"Advanced options": "Daha çox seçim",
"Block users on other matrix homeservers from joining this room": "Başqa serverlərdən bu otağa daxil olan istifadəçiləri bloklamaq",
"This setting cannot be changed later!": "Bu seçim sonra dəyişdirmək olmaz!",
"Deactivate Account": "Hesabı bağlamaq",
"Send Account Data": "Hesabın məlumatlarını göndərmək",
"An error has occurred.": "Səhv oldu.",
@ -293,7 +240,6 @@
"Please check your email and click on the link it contains. Once this is done, click continue.": "Öz elektron poçtunu yoxlayın və olan istinadı basın. Bundan sonra düyməni Davam etməyə basın.",
"Unable to add email address": "Email-i əlavə etməyə müvəffəq olmur",
"Unable to verify email address.": "Email-i yoxlamağı bacarmadı.",
"User names may only contain letters, numbers, dots, hyphens and underscores.": "İstifadəçilərin adları yalnız hərfləri, rəqəmləri, nöqtələri, defisləri və altından xətt çəkmənin simvollarını özündə saxlaya bilər.",
"Username not available": "İstifadəçi adı mövcud deyil",
"An error occurred: %(error_string)s": "Səhv baş verdi: %(error_string)s",
"Username available": "İstifadəçi adı mövcuddur",
@ -301,13 +247,8 @@
"Reject invitation": "Dəvəti rədd etmək",
"Are you sure you want to reject the invitation?": "Siz əminsiniz ki, siz dəvəti rədd etmək istəyirsiniz?",
"Name": "Ad",
"Topic": "Mövzu",
"Make this room private": "Bu otağı bağlanmış etmək",
"Share message history with new users": "Mesajların tarixinə girişi yeni istifadəçilərə icazə vermək",
"Encrypt room": "Otağın şifrələnməsi",
"There are no visible files in this room": "Bu otaqda görülən fayl yoxdur",
"Featured Users:": "Seçilmiş istifadəçilər:",
"Couldn't load home page": "Ana səhifəni yükləməyi bacarmadı",
"Failed to reject invitation": "Dəvəti rədd etməyi bacarmadı",
"Failed to leave room": "Otaqdan çıxmağı bacarmadı",
"For security, this session has been signed out. Please sign in again.": "Təhlükəsizliyin təmin olunması üçün sizin sessiyanız başa çatmışdır idi. Zəhmət olmasa, yenidən girin.",
@ -315,45 +256,27 @@
"You have no visible notifications": "Görülən xəbərdarlıq yoxdur",
"Files": "Fayllar",
"Notifications": "Xəbərdarlıqlar",
"Hide panel": "Paneli gizlətmək",
"#example": "#misal",
"Connectivity to the server has been lost.": "Serverlə əlaqə itirilmişdir.",
"Sent messages will be stored until your connection has returned.": "Hələ ki serverlə əlaqə bərpa olmayacaq, göndərilmiş mesajlar saxlanacaq.",
"Active call": "Aktiv çağırış",
"Failed to upload file": "Faylı göndərməyi bacarmadı",
"No more results": "Daha çox nəticə yoxdur",
"Failed to save settings": "Qurmaları saxlamağı bacarmadı",
"Failed to reject invite": "Dəvəti rədd etməyi bacarmadı",
"Fill screen": "Ekranı doldurmaq",
"Click to unmute video": "Klikləyin, videonu qoşmaq üçün",
"Click to mute video": "Klikləyin, videonu söndürmək üçün",
"Click to unmute audio": "Klikləyin, səsi qoşmaq üçün",
"Click to mute audio": "Klikləyin, səsi söndürmək üçün",
"Expand panel": "Paneli açmaq",
"Filter room names": "Otaqlar üzrə axtarış",
"Failed to load timeline position": "Xronologiyadan nişanı yükləməyi bacarmadı",
"Can't load user settings": "İstifadəçi qurmalarını yükləmək mümkün deyil",
"Your password was successfully changed. You will not receive push notifications on other devices until you log back in to them": "Şifrə uğurla dəyişdirildi. Təkrar avtorizasiyaya qədər siz başqa cihazlarda push-xəbərdarlıqları almayacaqsınız",
"Remove Contact Information?": "Əlaqə məlumatı silinsin?",
"Unable to remove contact information": "Əlaqə məlumatlarının silməyi bacarmadı",
"Interface Language": "İnterfeysin dili",
"User Interface": "İstifadəçi interfeysi",
"<not supported>": "<dəstəklənmir>",
"Import E2E room keys": "Şifrləmənin açarlarının idxalı",
"Cryptography": "Kriptoqrafiya",
"Ignored Users": "Bloklanan istifadəçilər",
"Privacy is important to us, so we don't collect any personal or identifiable data for our analytics.": "Məxfilik bizim üçün əhəmiyyətlidir, buna görə biz bizim analitikamız üçün heç bir şəxsi və ya müəyyən edən məlumat yığmırıq.",
"Learn more about how we use analytics.": "O haqda daha ətraflı, necə biz analitikadan istifadə edirik.",
"Labs": "Laboratoriya",
"Use with caution": "Ehtiyatlılıqla istifadə etmək",
"Deactivate my account": "Mənim hesabımı bağlamaq",
"Clear Cache": "Keşi təmizləmək",
"Clear Cache and Reload": "Keşi təmizləmək və yenidən yükləmək",
"Bulk Options": "Qrup parametrləri",
"Email": "E-poçt",
"Add email address": "Email-i əlavə etmək",
"Profile": "Profil",
"Display name": "Göstərilən ad",
"Account": "Hesab",
"Access Token:": "Girişin token-i:",
"click to reveal": "açılış üçün basın",
@ -365,23 +288,11 @@
"A new password must be entered.": "Yeni parolu daxil edin.",
"New passwords must match each other.": "Yeni şifrələr uyğun olmalıdır.",
"I have verified my email address": "Mən öz email-i təsdiq etdim",
"Your password has been reset": "Sizin şifrə sıfırlandı",
"You have been logged out of all devices and will no longer receive push notifications. To re-enable notifications, sign in again on each device": "Siz bütün qurğulardan çıxdınız və push-xəbərdarlıqları almayacaqsınız. Xəbərdarlıq aktivləşdirmək üçün hər cihaza yenidən daxil olun",
"Return to login screen": "Girişin ekranına qayıtmaq",
"New password": "Yeni şifrə",
"Confirm your new password": "Yeni Şifrə təsdiq edin",
"Send Reset Email": "Şifrənizi sıfırlamaq üçün istinadla məktubu göndərmək",
"Create an account": "Hesabı yaratmaq",
"Set a display name:": "Görünüş adını daxil edin:",
"Upload an avatar:": "Avatar yüklə:",
"This server does not support authentication with a phone number.": "Bu server telefon nömrəsinin köməyi ilə müəyyənləşdirilməni dəstəkləmir.",
"Missing password.": "Şifrə yoxdur.",
"Passwords don't match.": "Şifrələr uyğun gəlmir.",
"Password too short (min %(MIN_PASSWORD_LENGTH)s).": "Şifrə çox qısa (min. %(MIN_PASSWORD_LENGTH)s).",
"This doesn't look like a valid email address.": "Bu etibarlı bir e-poçt kimi görünmür.",
"This doesn't look like a valid phone number.": "Yanlış telefon nömrəsi.",
"An unknown error occurred.": "Bilinməyən bir səhv baş verdi.",
"I already have an account": "Məndə hesab var",
"Commands": "Komandalar",
"Emoji": "Smaylar",
"Users": "İstifadəçilər",
@ -449,7 +360,6 @@
"Restricted": "Məhduddur",
"Email, name or Matrix ID": "E-poçt, ad və ya Matrix ID",
"Send Invites": "Dəvət göndərin",
"Failed to invite user": "İstifadəçi dəvət olunmadı",
"Failed to invite": "Dəvət alınmadı",
"Failed to invite users to the room:": "İstifadəçiləri otağa dəvət etmək alınmadı:",
"Unable to create widget.": "Widjet yaratmaq olmur.",
@ -462,11 +372,9 @@
"Upgrades a room to a new version": "Bir otağı yeni bir versiyaya yüksəldir",
"Room upgrade confirmation": "Otaq yenilənməsi quraşdırılması",
"Upgrading a room can be destructive and isn't always necessary.": "Bir otağı təkmilləşdirməsi dağıdıcı ola bilər və həmişə lazım deyil.",
"Upgrade": "Yeniləmə",
"Changes your display nickname in the current room only": "Yalnız cari otaqda ekran ləqəbinizi dəyişdirir",
"Changes your avatar in this current room only": "Avatarınızı yalnız bu cari otaqda dəyişir",
"Changes your avatar in all rooms": "Bütün otaqlarda avatarınızı dəyişdirir",
"Changes colour scheme of current room": "Cari otağın rəng sxemini dəyişdirir",
"Gets or sets the room topic": "Otaq mövzusunu alır və ya təyin edir",
"This room has no topic.": "Bu otağın mövzusu yoxdur.",
"Sets the room name": "Otaq adını təyin edir",

View file

@ -1,6 +1,5 @@
{
"Couldn't find a matching Matrix room": "Не атрымалася знайсці адпаведны пакой Matrix",
"Enable audible notifications in web client": "Ўключыць гукавыя апавяшчэнні ў вэб-кліенце",
"All messages (noisy)": "Усе паведамленні (гучна)",
"Reject": "Адхіліць",
"Failed to forget room %(errCode)s": "Не атрымалася забыць пакой %(errCode)s",
@ -12,7 +11,6 @@
"Enable them now": "Уключыць іх зараз",
"Notification targets": "Мэты апавяшчэння",
"Failed to set direct chat tag": "Не ўдалося ўсталяваць тэг прамога чата",
"Failed to get protocol list from Home Server": "Не ўдалося атрымаць спіс пратаколаў ад хатняга сервера",
"Failed to set Direct Message status of room": "Не ўдалося ўсталяваць статут прамога паведамлення пакою",
"Favourite": "Улюбёнае",
"Quote": "Цытата",
@ -26,7 +24,6 @@
"Riot does not know how to join a room on this network": "Riot не ведае, як увайсці ў пакой у гэтай сетке",
"Members": "Удзельнікі",
"Can't update user notification settings": "Немагчыма абнавіць налады апавяшчэнняў карыстальніка",
"Add an email address above to configure email notifications": "Дадайце адрас электроннай пошты вышэй, каб наладзіць апавяшчэнні",
"Failed to change settings": "Не атрымалася змяніць налады",
"Noisy": "Шумна",
"Resend": "Паўторна",
@ -34,29 +31,22 @@
"remove %(name)s from the directory.": "выдаліць %(name)s з каталога.",
"Off": "Выключыць",
"Delete the room alias %(alias)s and remove %(name)s from the directory?": "Выдаліць псеўданім пакоя %(alias)s і выдаліць %(name)s з каталога?",
"Filter room names": "Фільтр iмёнаў пакояў",
"Invite to this room": "Запрасіць у гэты пакой",
"Notifications on the following keywords follow rules which cant be displayed here:": "Апавяшчэнні па наступных ключавых словах прытрымліваюцца правілаў, якія не могуць быць адлюстраваны тут:",
"#example": "#прыклад",
"Mentions only": "Толькі згадкі",
"Failed to get public room list": "Не ўдалося атрымаць спіс агульных пакояў",
"Remove": "Выдалiць",
"Failed to remove tag %(tagName)s from room": "Не ўдалося выдаліць %(tagName)s з пакоя",
"Leave": "Пакінуць",
"Enable notifications for this account": "Ўключыць апавяшчэнні для гэтага ўліковага запісу",
"Enable desktop notifications": "Ўключыць апавяшчэнні на працоўным стале",
"Error": "Памылка",
"Directory": "Каталог",
"No rooms to show": "Няма пакояў для паказу",
"Download this file": "Спампаваць гэты файл",
"Search for a room": "Пошук па пакоі",
"Operation failed": "Не атрымалася выканаць аперацыю",
"delete the alias.": "выдаліць псеўданім.",
"Forget": "Забыць",
"Mute": "Без гуку",
"Error saving email notification preferences": "Памылка захавання налад апавяшчэнняў па электроннай пошце",
"Enter keywords separated by a comma:": "Калі ласка, увядзіце ключавыя словы, падзеленыя коскамі:",
"The Home Server may be too old to support third party networks": "Хатні сервер можа быць занадта стары для падтрымкі іншых сетак",
"powered by Matrix": "працуе на Matrix",
"Custom Server Options": "Карыстальніцкія параметры сервера",
"Remove %(name)s from the directory?": "Выдаліць %(name)s з каталога?",

File diff suppressed because it is too large Load diff

View file

@ -2,14 +2,12 @@
"People": "Gent",
"Add a widget": "Afegeix un giny",
"Account": "Compte",
"VoIP": "Veu IP",
"No Microphones detected": "No s'ha detectat cap micròfon",
"No Webcams detected": "No s'ha detectat cap càmera web",
"Microphone": "Micròfon",
"Camera": "Càmera",
"Advanced": "Avançat",
"Algorithm": "Algoritme",
"Hide removed messages": "Amaga els missatges esborrats",
"Always show message timestamps": "Mostra sempre la marca de temps del missatge",
"Alias (optional)": "Àlies (opcional)",
"Cancel": "Cancel·la",
@ -30,7 +28,6 @@
"Remove": "Elimina",
"unknown error code": "codi d'error desconegut",
"OK": "D'acord",
"A text message has been sent to +%(msisdn)s. Please enter the verification code it contains": "S'ha enviat un missatge de text a +%(msisdn)s. Entreu si us plau el codi de verificació que conté",
"Operation failed": "No s'ha pogut realitzar l'operació",
"Search": "Cerca",
"powered by Matrix": "amb tecnologia de Matrix",
@ -58,14 +55,7 @@
"VoIP is unsupported": "El VoIP no és compatible",
"You cannot place VoIP calls in this browser.": "No es poden fer trucades VoIP amb aquest navegador.",
"You cannot place a call with yourself.": "No és possible trucar-se a un mateix.",
"Conference calls are not supported in this client": "Aquest client no és compatible amb les trucades de conferència",
"Conference calls are not supported in encrypted rooms": "Les trucades de conferència no es poden fer dins les sales encriptades",
"Warning!": "Avís!",
"Conference calling is in development and may not be reliable.": "Les conferències estan en desenvolupament i podrien no ser fiables.",
"Failed to set up conference call": "No s'ha pogut realitzar la trucada de conferència",
"Conference call failed.": "No s´ha pogut realitzar la trucada de conferència.",
"The file '%(fileName)s' failed to upload": "No s'ha pogut pujar el fitxer '%(fileName)s'",
"The file '%(fileName)s' exceeds this home server's size limit for uploads": "El fitxer «%(fileName)s» supera el límit de mida per a les pujades d'aquest servidor",
"Upload Failed": "No s'ha pogut realitzar la pujada",
"Sun": "dg.",
"Mon": "dl.",
@ -95,7 +85,6 @@
"Who would you like to add to this community?": "A qui voleu afegir a aquesta comunitat?",
"Warning: any person you add to a community will be publicly visible to anyone who knows the community ID": "Avís: les persones que afegiu a aquesta comunitat seran visibles públicament per a qualsevol que conegui l'ID de la comunitat",
"Invite new community members": "Convida nous membres a unir-se a la comunitat",
"Name or matrix ID": "Nom o ID de Matrix",
"Invite to Community": "Convida a la comunitat",
"Which rooms would you like to add to this community?": "Quines sales voleu afegir a aquesta comunitat?",
"Show these rooms to non-members on the community page and room list?": "Voleu mostrar aquestes sales als que no son membres a la pàgina de la comunitat i a la llista de sales?",
@ -117,12 +106,9 @@
"Admin": "Administrador",
"Start a chat": "Comença un xat",
"Who would you like to communicate with?": "Amb qui us voleu comunicar?",
"Email, name or matrix ID": "Correu electrònic, nom o ID de Matrix",
"Start Chat": "Comença un xat",
"Invite new room members": "Convida a nous membres a la sala",
"Who would you like to add to this room?": "A qui vol afegir a aquesta sala?",
"Send Invites": "Envia invitacions",
"Failed to invite user": "No s'ha pogut convidar al usuari",
"Failed to invite": "No s'ha pogut tramitar la invitació",
"Failed to invite the following users to the %(roomName)s room:": "No s'ha pogut convidar a la sala %(roomName)s els següents usuaris:",
"You need to be logged in.": "És necessari estar autenticat.",
@ -182,7 +168,6 @@
"(no answer)": "(sense resposta)",
"(unknown failure: %(reason)s)": "(error desconegut: %(reason)s)",
"%(senderName)s ended the call.": "%(senderName)s ha penjat.",
"%(senderName)s placed a %(callType)s call.": "%(senderName)s ha fet una trucada de %(callType)s.",
"%(senderName)s sent an invitation to %(targetDisplayName)s to join the room.": "%(senderName)s ha convidat a %(targetDisplayName)s a entrar a la sala.",
"%(senderName)s made future room history visible to all room members, from the point they are invited.": "%(senderName)s ha fet visible l'històric futur de la sala per a tots els membres, a partir de que hi són convidats.",
"%(senderName)s made future room history visible to all room members, from the point they joined.": "%(senderName)s ha fet visible l'històric futur de la sala a tots els membres, des de que entren a la sala.",
@ -196,10 +181,6 @@
"%(widgetName)s widget modified by %(senderName)s": "%(senderName)s ha modificat el giny %(widgetName)s",
"%(widgetName)s widget added by %(senderName)s": "%(senderName)s ha afegit el giny %(widgetName)s",
"%(widgetName)s widget removed by %(senderName)s": "%(senderName)s ha eliminat el giny %(widgetName)s",
"%(displayName)s is typing": "%(displayName)s està escrivint",
"%(names)s and %(count)s others are typing|other": "%(names)s i %(count)s més estan escrivint",
"%(names)s and %(count)s others are typing|one": "%(names)s i algú altre està escrivint",
"%(names)s and %(lastPerson)s are typing": "%(names)s i %(lastPerson)s estan escrivint",
"Failure to create room": "No s'ha pogut crear la sala",
"Server may be unavailable, overloaded, or you hit a bug.": "És possible que el servidor no estigui disponible, amb sobrecàrrega o que s'hagi trobat un error.",
"Send anyway": "Envia de totes maneres",
@ -210,19 +191,11 @@
"Authentication check failed: incorrect password?": "Ha fallat l'autenticació: heu introduït correctament la contrasenya?",
"Failed to join room": "No s'ha pogut entrar a la sala",
"Message Pinning": "Fixació de missatges",
"Disable Emoji suggestions while typing": "Desactiva els suggeriments d'Emoji mentre s'escriu",
"Use compact timeline layout": "Utilitza el disseny compacte de la línia de temps",
"Hide join/leave messages (invites/kicks/bans unaffected)": "Amaga els missatges d'entrada i sortida (no afecta a les invitacions, expulsions o prohibicions)",
"Hide avatar changes": "Amaga els canvis de foto de perfil",
"Hide display name changes": "Amaga els canvis de nom visible",
"Hide read receipts": "Amaga els rebuts llegits",
"Show timestamps in 12 hour format (e.g. 2:30pm)": "Mostra les marques de temps en format de 12 hores (per exemple, 2:30pm)",
"Autoplay GIFs and videos": "Reprodueix de forma automàtica els GIF i vídeos",
"Enable automatic language detection for syntax highlighting": "Activa la detecció automàtica d'idiomes per al ressaltat de sintaxi",
"Disable big emoji in chat": "Desactiva els grans emoji al xat",
"Don't send typing notifications": "No enviïs notificacions d'escriptura",
"Automatically replace plain text Emoji": "Substitueix automàticament Emoji de text pla",
"Disable Peer-to-Peer for 1:1 calls": "Desactiva el Peer-to-Peer per a trucades entre dos",
"Never send encrypted messages to unverified devices in this room from this device": "No enviïs mai missatges xifrats a dispositius no verificats en aquesta sala des d'aquest dispositiu",
"Enable inline URL previews by default": "Activa per defecte la vista prèvia d'URL en línia",
"Enable URL previews for this room (only affects you)": "Activa la vista prèvia d'URL d'aquesta sala (no afecta altres usuaris)",
@ -231,17 +204,14 @@
"Active call (%(roomName)s)": "Trucada activa (%(roomName)s)",
"unknown caller": "trucada d'un desconegut",
"Incoming voice call from %(name)s": "Trucada de veu entrant de %(name)s",
"Hide avatars in user and room mentions": "Amaga els avatars a les mencions de l'usuari i de la sala",
"Never send encrypted messages to unverified devices from this device": "No enviïs mai missatges xifrats a dispositius no verificats des d'aquest dispositiu",
"Incoming video call from %(name)s": "Trucada de vídeo entrant de %(name)s",
"Incoming call from %(name)s": "Trucada entrant de %(name)s",
"Decline": "Declina",
"Accept": "Accepta",
"Incorrect verification code": "El codi de verificació és incorrecte",
"Enter Code": "Introduïu el codi",
"Submit": "Envia",
"Phone": "Telèfon",
"Add phone number": "Afegiu un número de telèfon",
"Add": "Afegeix",
"Failed to upload profile picture!": "No s'ha pogut pujar la imatge!",
"Upload new:": "Puja un nou:",
@ -256,15 +226,12 @@
"New Password": "Nova contrasenya",
"Confirm password": "Confirma la contrasenya",
"Change Password": "Canvia la contrasenya",
"Your home server does not support device management.": "El seu servidor amfitrió no és compatible amb la gestió de dispositius.",
"Unable to load device list": "No s'ha pogut carregar la llista de dispositius",
"Authentication": "Autenticació",
"Delete %(count)s devices|other": "Suprimeix %(count)s dispositius",
"Delete %(count)s devices|one": "Suprimeix el dispositiu",
"Device ID": "ID del dispositiu",
"Device Name": "Nom del dispositiu",
"Last seen": "Vist per última vegada",
"Select devices": "Selecciona els dispositius",
"Failed to set display name": "No s'ha pogut establir el nom visible",
"Disable Notifications": "Desactiva les notificacions",
"Enable Notifications": "Activa les notificacions",
@ -280,13 +247,10 @@
"%(senderName)s uploaded a file": "%(senderName)s ha pujat un fitxer",
"Options": "Opcions",
"Undecryptable": "Indesxifrable",
"Encrypted by a verified device": "Xifrat per un dispositiu verificat",
"Encrypted by an unverified device": "Xifrat per un dispositiu no verificat",
"Unencrypted message": "Missatge no xifrat",
"Please select the destination room for this message": "Si us plau, seleccioneu la sala destinatària per a aquest missatge",
"Blacklisted": "Llista negre",
"Verified": "Verificat",
"Unverified": "No verificat",
"device id: ": "ID del dispositiu: ",
"Disinvite": "Descarta la invitació",
"Kick": "Fes fora",
@ -318,17 +282,12 @@
"Revoke Moderator": "Revoca el moderador",
"Make Moderator": "Fes-lo moderador",
"Admin Tools": "Eines d'administració",
"Level:": "Nivell:",
"and %(count)s others...|other": "i %(count)s altres...",
"and %(count)s others...|one": "i un altre...",
"Invited": "Convidat",
"Filter room members": "Filtra els membres de la sala",
"%(userName)s (power %(powerLevelNumber)s)": "%(userName)s (poder %(powerLevelNumber)s)",
"Attachment": "Adjunt",
"Upload Files": "Puja fitxers",
"Are you sure you want to upload the following files?": "Confirmeu que voleu pujar els següents fitxers?",
"Encrypted room": "Sala xifrada",
"Unencrypted room": "Sala no xifrada",
"Hangup": "Penja",
"Voice call": "Trucada de veu",
"Video call": "Trucada de vídeo",
@ -339,8 +298,6 @@
"Send an encrypted message…": "Envia un missatge xifrat…",
"Send a message (unencrypted)…": "Envia un missatge (sense xifrar)…",
"You do not have permission to post to this room": "No teniu el permís per escriure en aquesta sala",
"Turn Markdown on": "Activa el Markdown",
"Turn Markdown off": "Desactiva el Markdown",
"Hide Text Formatting Toolbar": "Amaga la barra d'eines de format de text",
"Server error": "S'ha produït un error al servidor",
"Mirror local video feed": "Mostra el vídeo local com un mirall",
@ -348,12 +305,6 @@
"Command error": "S'ha produït un error en l'ordre",
"bold": "negreta",
"italic": "cursiva",
"strike": "tatxat",
"underline": "subratllat",
"code": "codi",
"quote": "cita",
"bullet": "pic",
"numbullet": "pic numerat",
"Markdown is disabled": "El Markdown està desactivat",
"Markdown is enabled": "El Markdown està activat",
"Jump to message": "Salta al missatge",
@ -376,73 +327,27 @@
"Seen by %(userName)s at %(dateTime)s": "Vist per %(userName)s a les %(dateTime)s",
"No rooms to show": "No hi ha cap sala per a mostrar",
"Unnamed room": "Sala sense nom",
"Failed to set avatar.": "No s'ha pogut establir l'avatar.",
"Save": "Desa",
"(~%(count)s results)|other": "(~%(count)s resultats)",
"(~%(count)s results)|one": "(~%(count)s resultat)",
"Join Room": "Entra a la sala",
"Upload avatar": "Puja l'avatar",
"Remove avatar": "Elimina l'avatar",
"Forget room": "Oblida la sala",
"Show panel": "Mostra el plafó",
"Drop here to favourite": "Deixa-ho anar aquí per a marcar-ho com a favorit",
"Drop here to tag direct chat": "Deixa'l anar aquí per posar-li la etiqueta de xat directe",
"Drop here to restore": "Deixa'l anar aquí per a restaurar-lo",
"Drop here to demote": "Deixa'l anar aquí per a baixar-lo de grau",
"Drop here to tag %(section)s": "Deixa´l anar aquí per posar-li la etiqueta de %(section)s",
"You're not in any rooms yet! Press <CreateRoomButton> to make a room or <RoomDirectoryButton> to browse the directory": "Encara no ha entrat a cap sala. Premeu <CreateRoomButton>per crear una sala o bé <RoomDirectoryButton> per fullejar el directori",
"Community Invites": "Invitacions de les comunitats",
"Invites": "Invitacions",
"Favourites": "Preferits",
"Low priority": "Baixa prioritat",
"Historical": "Històric",
"Unable to ascertain that the address this invite was sent to matches one associated with your account.": "No s'ha pogut determinar que s'hagi enviat la invitació a una adreça associada al vostre compte.",
"This invitation was sent to an email address which is not associated with this account:": "Aquesta invitació s'ha enviat a una adreça de correu electrònic que no està associada a aquest compte:",
"Press <StartChatButton> to start a chat with someone": "Prem <StartChatButton> per a començar un xat amb algú",
"You may wish to login with a different account, or add this email to this account.": "És possible que vulgueu iniciar la sessió amb un altre compte o bé afegir aquest correu electrònic a aquest compte.",
"You have been invited to join this room by %(inviterName)s": "Heu sigut convidat a aquesta sala per %(inviterName)s",
"Would you like to <acceptText>accept</acceptText> or <declineText>decline</declineText> this invitation?": "Voleu <acceptText>accept</acceptText> o bé <declineText>decline</declineText> aquesta invitació?",
"Reason: %(reasonText)s": "Raó: %(reasonText)s",
"Rejoin": "Trona a entrar",
"You have been kicked from %(roomName)s by %(userName)s.": "%(userName)s us ha fet fora de la sala %(roomName)s.",
"You have been kicked from this room by %(userName)s.": "%(userName)s vos ha fet fora de la sala.",
"You have been banned from %(roomName)s by %(userName)s.": "%(userName)s vos ha expulsat de la sala %(roomName)s.",
"You have been banned from this room by %(userName)s.": "Heu sigut expulsat d'aquesta sala per %(userName)s.",
"This room": "Aquesta sala",
"%(roomName)s does not exist.": "La sala %(roomName)s no existeix.",
"%(roomName)s is not accessible at this time.": "La sala %(roomName)s no és accessible en aquest moment.",
"You are trying to access %(roomName)s.": "Esteu intentant accedir a la sala %(roomName)s.",
"You are trying to access a room.": "Esteu intentant accedir a una sala.",
"<a>Click here</a> to join the discussion!": "<a>Click here</a> per a entrar al debat!",
"This is a preview of this room. Room interactions have been disabled": "Aquesta és una vista prèvia de la sala. No s'hi pot interactuar des d'aquí",
"To change the room's avatar, you must be a": "Per canviar l'avatar de la sala, heu de ser",
"To change the room's name, you must be a": "Per canviar el nom de la sala, heu de ser",
"To change the room's main address, you must be a": "Per canviar l'adreça principal de la sala, heu de ser",
"To change the room's history visibility, you must be a": "Per canviar la visibilitat de l'historial de la sala, heu de ser",
"To change the permissions in the room, you must be a": "Per canviar els permisos a la sala, heu de ser",
"To change the topic, you must be a": "Per canviar el tema, heu de ser",
"To modify widgets in the room, you must be a": "Per modificar els ginys de la sala, has de ser",
"Failed to unban": "No s'ha pogut expulsar",
"Banned by %(displayName)s": "Expulsat per %(displayName)s",
"Privacy warning": "Avís de privadesa",
"Changes to who can read history will only apply to future messages in this room": "Els canvis de qui pot llegir l'historial només s'aplicaran als missatges futurs d'aquesta sala",
"The visibility of existing history will be unchanged": "La visibilitat de l'historial existent no es modificarà",
"End-to-end encryption is in beta and may not be reliable": "El xifratge d'extrem a extrem està en fase beta i pot ser que no sigui fiable",
"You should not yet trust it to secure data": "Encara no hi heu de confiar per a comunicacions segures",
"Devices will not yet be able to decrypt history from before they joined the room": "Els dispositius encara no podran desxifrar l'historial d'abans d'entrar a la sala",
"Once encryption is enabled for a room it cannot be turned off again (for now)": "Quan s'activa el xifratge en una sala, no es pot desactivar posteriorment (per ara)",
"Encrypted messages will not be visible on clients that do not yet implement encryption": "Els missatges xifrats no es podran veure en els clients que encara no tinguin implementat el xifratge",
"Enable encryption": "El xifratge està activat",
"(warning: cannot be disabled again!)": "(avís: no es pot desactivar de nou!)",
"Encryption is enabled in this room": "El xifratge està activat en aquesta sala",
"Encryption is not enabled in this room": "El xifratge no està activat en aquesta sala",
"Privileged Users": "Usuaris amb privilegis",
"No users have specific privileges in this room": "Cap usuari té privilegis específics en aquesta sala",
"Banned users": "Usuaris expulsats",
"This room is not accessible by remote Matrix servers": "Aquesta sala no és accessible per a servidors de Matrix remots",
"Leave room": "Surt de la sala",
"Tagged as: ": "Etiquetats com: ",
"To link to a room it must have <a>an address</a>.": "Per poder fer un enllaç a una sala aquesta ha de tenir <a>an address</a>.",
"Guests cannot join this room even if explicitly invited.": "Els usuaris d'altres xarxes no poden entrar a la sala d'aquest esdeveniment encara que hi hagin sigut convidats de forma explícita.",
"Click here to fix": "Feu clic aquí per corregir-ho",
"Who can access this room?": "Qui pot entrar a aquesta sala?",
@ -455,28 +360,13 @@
"Members only (since they were invited)": "Només els membres (a partir del punt en què hi són convidats)",
"Members only (since they joined)": "Només els membres (a partir del punt en què entrin a la sala)",
"Permissions": "Permisos",
"The default role for new room members is": "El rol per defecte dels nous membres de la sala és",
"To send messages, you must be a": "Per poder enviar missatges, heu de ser",
"To invite users into the room, you must be a": "Per poder convidar a usuaris a aquesta sala, heu de ser",
"To configure the room, you must be a": "Per poder configurar aquesta sala, heu de ser",
"To kick users, you must be a": "Per poder fer fora a usuaris, heu de ser",
"To ban users, you must be a": "Per expulsar a usuaris, heu de ser",
"To remove other users' messages, you must be a": "Per eliminar missatges d'altres usuaris, heu de ser",
"To send events of type <eventType/>, you must be a": "Per poder enviar esdeveniments de tipus <eventType/>, heu de ser",
"This room's internal ID is": "L'ID d'aquesta sala és",
"Add a topic": "Afegeix un tema",
"Scroll to unread messages": "Desplaça't fins els missatges no llegits",
"Jump to first unread message.": "Salta al primer missatge no llegit.",
"Invalid alias format": "El format de l'àlies no és vàlid",
"'%(alias)s' is not a valid format for an alias": "'%(alias)s' no és un format d'àlies vàlid",
"Invalid address format": "L'adreça no té un format vàlid",
"Anyone who knows the room's link, including guests": "Qualsevol que conegui l'enllaç de la sala, inclosos els usuaris d'altres xarxes",
"'%(alias)s' is not a valid format for an address": "'%(alias)s' no és un format vàlid per a una adreça",
"not specified": "sense especificar",
"not set": "sense definir",
"Remote addresses for this room:": "Adreces remotes per a aquesta sala:",
"Addresses": "Adreces",
"The main address for this room is": "L'adreça principal d'aquesta sala és",
"Local addresses for this room:": "Adreces locals d'aquesta sala:",
"This room has no local addresses": "Aquesta sala no té adreces locals",
"New address (e.g. #foo:%(localDomain)s)": "Nova adreça (per exemple #foo:%(localDomain)s)",
@ -504,35 +394,17 @@
"Removed or unknown message type": "El tipus de missatge ha sigut eliminat o és desconegut",
"Message removed by %(userId)s": "El missatge ha sigut eliminat per l'usuari %(userId)s",
"Message removed": "S'ha eliminat el missatge",
"Robot check is currently unavailable on desktop - please use a <a>web browser</a>": "Actualment, la verificació del robot no està disponible a l'escriptori: utilitzeu un <a>web browser</a>",
"Sign in with CAS": "Inicieu sessió amb CAS",
"You can use the custom server options to sign into other Matrix servers by specifying a different Home server URL.": "Podeu utilitzar les opcions de servidor personalitzades per a iniciar sessió en altres servidors Matrix, especificant un altre URL de servidor principal.",
"This allows you to use this app with an existing Matrix account on a different home server.": "Això us permet utilitzar aquesta aplicació amb un compte de Matrix existent en un altre servidor.",
"You can also set a custom identity server but this will typically prevent interaction with users based on email address.": "També podeu establir un servidor d'identitat personalitzat, però normalment això evitarà la interacció basada en l'adreça de correu electrònic amb altres usuaris.",
"To continue, please enter your password.": "Per poder continuar, si us plau, introduïu una contrasenya.",
"Password:": "Contrasenya:",
"An email has been sent to %(emailAddress)s": "S'ha enviat un correu electrònic a %(emailAddress)s",
"Please check your email to continue registration.": "Reviseu el vostre correu electrònic per a poder continuar amb el registre.",
"Token incorrect": "El testimoni és incorrecte",
"A text message has been sent to %(msisdn)s": "S'ha enviat un missatge de text a %(msisdn)s",
"Please enter the code it contains:": "Introduïu el codi que conté:",
"Start authentication": "Inicia l'autenticació",
"Username on %(hs)s": "Nom d'usuari a %(hs)s",
"User name": "Nom d'usuari",
"Mobile phone number": "Número de telèfon mòbil",
"Forgot your password?": "Heu oblidat la vostra contrasenya?",
"%(serverName)s Matrix ID": "ID de Matrix de %(serverName)s",
"Sign in with": "Inicieu sessió amb",
"Email address": "Correu electrònic",
"Sign in": "Inicia sessió",
"If you don't specify an email address, you won't be able to reset your password. Are you sure?": "Si no especifiqueu una adreça de correu electrònic, no podreu restablir la vostra contrasenya. N'esteu segur?",
"Email address (optional)": "Correu electrònic (opcional)",
"You are registering with %(SelectedTeamName)s": "Esteu registrant-vos amb %(SelectedTeamName)s",
"Mobile phone number (optional)": "Número de telèfon mòbil (opcional)",
"Default server": "Servidor per defecte",
"Custom server": "Servidor personalitzat",
"Identity server URL": "URL del servidor d'identitat",
"What does this mean?": "Què vol dir això?",
"Remove from community": "Elimina de la comunitat",
"Disinvite this user from community?": "Voleu retirar la invitació de aquest usuari a la comunitat?",
"Remove this user from community?": "Voleu eliminar de la comunitat a aquest usuari?",
@ -540,7 +412,6 @@
"Failed to remove user from community": "No s'ha pogut treure l'usuari de la comunitat",
"Filter community members": "Filtra els membres de la comunitat",
"Are you sure you want to remove '%(roomName)s' from %(groupId)s?": "Esteu segur que voleu treure l'usuari '%(roomName)s' del grup %(groupId)s?",
"Home server URL": "URL del servidor d'origen",
"<a>In reply to</a> <pill>": "<a>In reply to</a> <pill>",
"Removing a room from the community will also remove it from the community page.": "L'eliminació d'una sala de la comunitat també l'eliminarà de la pàgina de la comunitat.",
"Failed to remove room from community": "No s'ha pogut eliminar la sala de la comunitat",
@ -554,27 +425,21 @@
"Something went wrong when trying to get your communities.": "S'ha produït un error en intentar obtenir les vostres comunitats.",
"You're not currently a member of any communities.": "Actualment no sou membre de cap comunitat.",
"Unknown Address": "Adreça desconeguda",
"NOTE: Apps are not end-to-end encrypted": "NOTA: Les aplicacions no estan xifrades d'extrem a extrem",
"Do you want to load widget from URL:": "Carregar ginys des de l'URL:",
"Allow": "Permetre",
"Delete Widget": "Suprimeix el giny",
"Deleting a widget removes it for all users in this room. Are you sure you want to delete this widget?": "La supressió d'un giny l'elimina per a tots els usuaris d'aquesta sala. Esteu segur que voleu eliminar aquest giny?",
"Delete widget": "Suprimeix el giny",
"Revoke widget access": "Revoca l'accés del giny",
"Minimize apps": "Minimitza les aplicacions",
"Blacklist": "Llista negre",
"Unverify": "Sense verificar",
"Verify...": "Verificar...",
"No results": "Sense resultats",
"Delete": "Esborra",
"Communities": "Comunitats",
"Home": "Inici",
"Integrations Error": "S'ha produït un error d'integració",
"Could not connect to the integration server": "No s'ha pogut connectar amb el servidor d'integració",
"Manage Integrations": "Gestiona les integracions",
"%(nameList)s %(transitionList)s": "%(transitionList)s%(nameList)s",
"%(severalUsers)sjoined %(count)s times|one": "%(severalUsers)s han entrat",
"Guest access is disabled on this Home Server.": "L'accés a usuaris d'altres xarxes no està permès en aquest servidor.",
"Unblacklist": "Treure de la llista negre",
"%(oneUser)sjoined %(count)s times|one": "%(oneUser)s s'ha unit",
"%(severalUsers)sleft %(count)s times|one": "%(severalUsers)s han sortit",
@ -624,7 +489,6 @@
"%(items)s and %(lastItem)s": "%(items)s i %(lastItem)s",
"collapse": "col·lapsa",
"expand": "expandeix",
"Custom of %(powerLevel)s": "Personalitzat de %(powerLevel)s",
"Custom level": "Nivell personalitzat",
"And %(count)s more...|other": "I %(count)s més...",
"ex. @bob:example.com": "per exemple @carles:exemple.cat",
@ -634,21 +498,12 @@
"email address": "correu electrònic",
"Try using one of the following valid address types: %(validTypesList)s.": "Proveu d'utilitzar un dels següents tipus d'adreça vàlids: %(validTypesList)s.",
"You have entered an invalid address.": "No heu introduït una adreça vàlida.",
"Create a new chat or reuse an existing one": "Creeu un xat nou o feu-ne servit un d'existent",
"Start new chat": "Inicia un xat nou",
"You already have existing direct chats with this user:": "Ja teniu xats directes amb aquest usuari:",
"Start chatting": "Comença a xerrar",
"Click on the button below to start chatting!": "Feu clic al botó de sota per començar a xerrar!",
"Start Chatting": "Comenceu a xatejar",
"Confirm Removal": "Confirmeu l'eliminació",
"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.": "Esteu segur que voleu eliminar (suprimir) aquest esdeveniment? Tingueu en compte que si suprimiu un nom sala o si feu un canvi de tema, desfaria el canvi.",
"This room is not showing flair for any communities": "Aquesta sala no mostra talent per a cap comunitat",
"Flair": "Talents",
"Showing flair for these communities:": "Mostra els talents d'aquestes comunitats:",
"Flair will appear if enabled in room settings": "Els talents es mostraran si són activats a la configuració de la sala",
"Flair will not appear": "Els talents no es mostraran",
"Display your community flair in rooms configured to show it.": "Mostra els talents de la vostra comunitat dins les sales configurades per a mostrar-los.",
"This Home Server would like to make sure you are not a robot": "Aquest servidor amfitrió es vol assegurar que no sou un robot",
"%(severalUsers)sjoined %(count)s times|other": "%(severalUsers)s han entrat %(count)s vegades",
"%(oneUser)sjoined %(count)s times|other": "%(oneUser)s ha entrat %(count)s vegades",
"%(severalUsers)sleft %(count)s times|other": "%(severalUsers)s han sortit %(count)s vegades",
@ -663,9 +518,6 @@
"example": "exemple",
"Create": "Crea",
"Create Room": "Crea una sala",
"Room name (optional)": "Nom de la sala (opcional)",
"Advanced options": "Opcions avançades",
"This setting cannot be changed later!": "Aquests paràmetres no es poden canviar després!",
"Unknown error": "S'ha produït un error desconegut",
"Incorrect password": "Contrasenya incorrecta",
"Deactivate Account": "Desactivar el compte",
@ -673,7 +525,6 @@
"Device name": "Nom del dispositiu",
"Device key": "Clau del dispositiu",
"If it matches, press the verify button below. If it doesn't, then someone else is intercepting this device and you probably want to press the blacklist button instead.": "Si coincideix, premeu el botó de verificació de sota. Si no coincideix, algú més està interceptant aquest dispositiu i probablement voleu prémer el botó de llista negra.",
"In future this verification process will be more sophisticated.": "En un futur, aquest procés de verificació serà més sofisticat.",
"Verify device": "Verifica el dispositiu",
"I verify that the keys match": "Verifico que les claus coincideixen",
"An error has occurred.": "S'ha produït un error.",
@ -693,7 +544,6 @@
"Unable to verify email address.": "No s'ha pogut verificar el correu electrònic.",
"This will allow you to reset your password and receive notifications.": "Això us permetrà restablir la vostra contrasenya i rebre notificacions.",
"Skip": "Omet",
"User names may only contain letters, numbers, dots, hyphens and underscores.": "Els noms d'usuari només poden contenir lletres, números, punts, guionets i guionets baixos.",
"Username not available": "Aquest nom d'usuari no està disponible",
"Username invalid: %(errMessage)s": "El nom d'usuari és invàlid: %(errMessage)s",
"An error occurred: %(error_string)s": "S'ha produït un error: %(error_string)s",
@ -701,7 +551,6 @@
"To get started, please pick a username!": "Per començar, seleccioneu un nom d'usuari!",
"This will be your account name on the <span></span> homeserver, or you can pick a <a>different server</a>.": "Aquest serà el nom del seu compte al <span></span> servidor amfitrió, o bé trieu-ne un altre <a>different server</a>.",
"If you already have a Matrix account you can <a>log in</a> instead.": "Si ja teniu un compte a Matrix, podeu <a>log in</a>.",
"Block users on other matrix homeservers from joining this room": "Impedeix als usuaris d'altres servidors de Matrix d'entrar a aquesta sala",
"If you have previously used a more recent version of Riot, your session may be incompatible with this version. Close this window and return to the more recent version.": "Si anteriorment heu utilitzat un versió de Riot més recent, la vostra sessió podría ser incompatible amb aquesta versió. Tanqueu aquesta finestra i torneu a la versió més recent.",
"You are currently blacklisting unverified devices; to send messages to these devices you must verify them.": "Actualment teniu a la llista negre els dispositius no verificats; per enviar missatges a aquests dispositius, els heu de verificar abans.",
"We recommend you go through the verification process for each device to confirm they belong to their legitimate owner, but you can resend the message without verifying if you prefer.": "Recomanem que dugueu a terme el procès de verificació per a cada dispositiu per tal de confirmar que són del legítim propietari, però podeu enviar el missatge sense verificar-ho si ho preferiu.",
@ -712,10 +561,6 @@
"Public Chat": "Xat públic",
"Custom": "Personalitzat",
"Name": "Nom",
"Topic": "Tema",
"Make this room private": "Fes que aquesta sala sigui privada",
"Share message history with new users": "Comparteix l'historial dels missatges amb els nous usuaris",
"Encrypt room": "Sala xifrada",
"You must <a>register</a> to use this functionality": "Heu de <a>register</a> per utilitzar aquesta funcionalitat",
"You must join the room to see its files": "Heu d'entrar a la sala per poder-ne veure els fitxers",
"There are no visible files in this room": "No hi ha fitxers visibles en aquesta sala",
@ -752,7 +597,6 @@
"Long Description (HTML)": "Descripció llarga (HTML)",
"Description": "Descripció",
"Community %(groupId)s not found": "No s'ha pogut trobar la comunitat %(groupId)s",
"This Home server does not support communities": "Aquest servidor amfitrió no admet comunitats",
"Failed to load %(groupId)s": "No s'ha pogut carregar la comunitat %(groupId)s",
"Reject invitation": "Rebutja la invitació",
"Are you sure you want to reject the invitation?": "Esteu segur que voleu rebutjar la invitació?",
@ -775,19 +619,14 @@
"Warning": "Avís",
"Connectivity to the server has been lost.": "S'ha perdut la connectivitat amb el servidor.",
"Sent messages will be stored until your connection has returned.": "Els missatges enviats s'emmagatzemaran fins que la vostra connexió hagi tornat.",
"%(count)s new messages|other": "%(count)s nous missatges",
"%(count)s new messages|one": "%(count)s nou missatge",
"Active call": "Trucada activa",
"You seem to be uploading files, are you sure you want to quit?": "Sembla que s'està pujant fitxers, esteu segur que voleu sortir?",
"You seem to be in a call, are you sure you want to quit?": "Sembla que està en una trucada, estàs segur que vols sortir?",
"Failed to upload file": "No s'ha pogut pujar el fitxer",
"Server may be unavailable, overloaded, or the file too big": "El servidor pot estar no disponible, sobrecarregat o el fitxer és massa gran",
"Search failed": "No s'ha pogut cercar",
"Server may be unavailable, overloaded, or search timed out :(": "Pot ser que el servidor no estigui disponible, que estigui sobrecarregat o que s'ha esgotat el temps de cerca :(",
"No more results": "No hi ha més resultats",
"Unknown room %(roomId)s": "La sala %(roomId)s és desconeguda",
"Room": "Sala",
"Failed to save settings": "No s'ha pogut desar la configuració",
"Failed to reject invite": "No s'ha pogut rebutjar la invitació",
"Fill screen": "Emplena la pantalla",
"Click to unmute video": "Feu clic per activar el so de vídeo",
@ -806,26 +645,15 @@
"Uploading %(filename)s and %(count)s others|zero": "Pujant %(filename)s",
"Light theme": "Tema clar",
"Dark theme": "Tema fosc",
"Status.im theme": "Tema d'Status.im",
"Sign out": "Tancar sessió",
"Remove %(threePid)s?": "Esborrar %(threePid)s?",
"Interface Language": "Idioma de l'interfície",
"User Interface": "Interfície d'usuari",
"Import E2E room keys": "Importar claus E2E de sala",
"Cryptography": "Criptografia",
"Device ID:": "ID del dispositiu:",
"Device key:": "Clau del dispositiu:",
"Ignored Users": "Usuaris ignorats",
"Labs": "Laboraroris",
"Use with caution": "Utilitzar amb precaució",
"Deactivate my account": "Desactivar la meva compte",
"Updates": "Actualitzacions",
"matrix-react-sdk version:": "Versió de matrix-react-sdk:",
"riot-web version:": "Versió de riot-web:",
"olm version:": "Versió d'olm:",
"Your password has been reset": "La teva contrasenya s'ha reiniciat",
"New password": "Nova contrasenya",
"Confirm your new password": "Confirma la teva nova contrasenya",
"Incorrect username and/or password.": "Usuari i/o contrasenya incorrectes.",
"The phone number entered looks invalid": "El número de telèfon introduït sembla erroni",
"none": "cap",
@ -845,26 +673,21 @@
"Import": "Importa",
"The version of Riot.im": "La versió del Riot.im",
"Email": "Correu electrònic",
"Add email address": "Afegeix correu electrònic",
"I have verified my email address": "He verificat l'adreça de correu electrònic",
"Send Reset Email": "Envia email de reinici",
"Your homeserver's URL": "L'URL del vostre servidor personal",
"Your identity server's URL": "L'URL del vostre servidor d'identitat",
"Analytics": "Analítiques",
"%(oldDisplayName)s changed their display name to %(displayName)s.": "%(oldDisplayName)s ha canviat el seu nom visible a %(displayName)s.",
"Server may be unavailable or overloaded": "El servidor pot estar inaccessible o sobrecarregat",
"Display name": "Nom visible",
"Identity Server is": "El servidor d'identitat és",
"Submit debug logs": "Enviar logs de depuració",
"The platform you're on": "La plataforma a la que estàs",
"Whether or not you're logged in (we don't record your user name)": "Si estàs identificat o no (no desem el teu nom d'usuari)",
"Your language of choice": "El teu idioma preferit",
"Which officially provided instance you are using, if any": "Quina instància oficial estàs utilitzant, si escau",
"Whether or not you're using the Richtext mode of the Rich Text Editor": "Si estàs utilitzant el mode Richtext del Rich Text Editor o no",
"The information being sent to us to help make Riot.im better includes:": "La informació enviada a Riot.im per ajudar-nos a millorar inclou:",
"Fetching third party location failed": "S'ha produït un error en obtenir la ubicació de tercers",
"A new version of Riot is available.": "Hi ha una versió nova del Riot disponible.",
"Couldn't load home page": "No s'ha pogut carregar la pàgina d'inici",
"Send Account Data": "Envia les dades del compte",
"Advanced notification settings": "Paràmetres avançats de notificacions",
"Uploading report": "S'està enviant l'informe",
@ -878,11 +701,7 @@
"Friday": "Divendres",
"Update": "Actualització",
"What's New": "Novetats",
"Add an email address above to configure email notifications": "Afegiu més amunt un correu electrònic per a configurar les notificacions",
"Expand panel": "Expandeix el panel",
"On": "Engegat",
"%(count)s Members|other": "%(count)s membres",
"Filter room names": "Filtra els noms de les sales",
"Changelog": "Registre de canvis",
"Waiting for response from server": "S'està esperant una resposta del servidor",
"Uploaded on %(date)s by %(user)s": "Pujat el %(date)s per l'usuari %(user)s",
@ -892,12 +711,9 @@
"delete the alias.": "esborra l'alies.",
"To return to your account in future you need to <u>set a password</u>": "Per poder tornar al vostre compte en un futur, heu de <u>set a password</u>",
"Forget": "Oblida",
"#example": "#exemple",
"Hide panel": "Amaga el panel",
"You cannot delete this image. (%(code)s)": "No podeu eliminar aquesta imatge. (%(code)s)",
"Cancel Sending": "Cancel·la l'enviament",
"This Room": "Aquesta sala",
"The Home Server may be too old to support third party networks": "El servidor local pot ser massa antic per a ser compatible amb xarxes de tercers",
"Resend": "Reenvia",
"Room not found": "No s'ha trobat la sala",
"Messages containing my display name": "Missatges que contenen el meu nom visible",
@ -906,10 +722,8 @@
"Error saving email notification preferences": "No s'han pogut desar les preferències de les notificacions a causa d'un error",
"View Decrypted Source": "Mostra el codi desxifrat",
"Failed to update keywords": "No s'han pogut actualitzar les paraules clau",
"Notes:": "Notes:",
"remove %(name)s from the directory.": "elimina %(name)s del directori.",
"Notifications on the following keywords follow rules which cant be displayed here:": "Les notificacions sobre les següents paraules clau segueixen regles que no es poden mostrar aquí:",
"<safariLink>Safari</safariLink> and <operaLink>Opera</operaLink> work too.": "<safariLink>Safari</safariLink> i <operaLink>Opera</operaLink> també fan la feina.",
"Please set a password!": "Si us plau, establiu una contrasenya",
"You have successfully set a password!": "Heu establert correctament la contrasenya",
"An error occurred whilst saving your email notification preferences.": "S'ha produït un error en desar les vostres preferències de notificació per correu electrònic.",
@ -920,14 +734,11 @@
"Members": "Membres",
"No update available.": "No hi ha cap actualització disponible.",
"Noisy": "Sorollós",
"Failed to get protocol list from Home Server": "No s'ha pogut obtenir la llista de protocols del servidor local",
"Collecting app version information": "S'està recollint la informació de la versió de l'aplicació",
"Delete the room alias %(alias)s and remove %(name)s from the directory?": "Voleu esborrar de la sala l'alies %(alias)s i retirar %(name)s del directori?",
"This will allow you to return to your account after signing out, and sign in on other devices.": "Això farà possible que pugueu tronar al vostre compte des de qualsevol dispositiu.",
"Enable notifications for this account": "Habilita les notificacions per aquest compte",
"Directory": "Directori",
"Invite to this community": "Convida a aquesta comunitat",
"Search for a room": "Busca una sala",
"Search…": "Cerca…",
"Messages containing <span>keywords</span>": "Missatges que contenen <span>keywords</span>",
"When I'm invited to a room": "Quan sóc convidat a una sala",
@ -949,17 +760,12 @@
"Monday": "Dilluns",
"All messages (noisy)": "Tots els missatges (sorollós)",
"Enable them now": "Habilita-ho ara",
"Messages containing my user name": "Missatges que contenen el meu nom d'usuari",
"Toolbox": "Caixa d'eines",
"Collecting logs": "S'estan recopilant els registres",
"more": "més",
"GitHub issue link:": "Enllaç de l'issue de GitHub:",
"Failed to get public room list": "No s'ha pogut obtenir el llistat de sales públiques",
"You must specify an event type!": "Heu d'especificar un tipus d'esdeveniment",
"(HTTP status %(httpStatus)s)": "(Estat de l´HTTP %(httpStatus)s)",
"All Rooms": "Totes les sales",
"State Key": "Clau d'estat",
"Please install <chromeLink>Chrome</chromeLink> or <firefoxLink>Firefox</firefoxLink> for the best experience.": "Si us plau, instal·leu <chromeLink>Chrome</chromeLink> or <firefoxLink>Firefox</firefoxLink> per gaudir d'una millor experiència.",
"Wednesday": "Dimecres",
"Send logs": "Envia els registres",
"All messages": "Tots els missatges",
@ -992,28 +798,23 @@
"Messages in group chats": "Missatges en xats de grup",
"Yesterday": "Ahir",
"Error encountered (%(errorDetail)s).": "S'ha trobat un error (%(errorDetail)s).",
"Login": "Inicia sessió",
"Low Priority": "Baixa prioritat",
"Unable to fetch notification target list": "No s'ha pogut obtenir la llista d'objectius de les notificacions",
"Set Password": "Establiu una contrasenya",
"Enable audible notifications in web client": "Habilita les notificacions d'àudio al client web",
"Off": "Apagat",
"Riot does not know how to join a room on this network": "El Riot no sap com unir-se a una sala en aquesta xarxa",
"Mentions only": "Només mencions",
"Failed to remove tag %(tagName)s from room": "No s'ha pogut esborrar l'etiqueta %(tagName)s de la sala",
"You can now return to your account after signing out, and sign in on other devices.": "Ara podreu tornar a entrar al vostre compte des de altres dispositius.",
"Enable desktop notifications": "Habilita les notificacions d'escriptori",
"Enable email notifications": "Habilita les notificacions per correu electrònic",
"Event Type": "Tipus d'esdeveniment",
"Download this file": "Descarrega aquest fitxer",
"Pin Message": "Enganxa el missatge",
"Failed to change settings": "No s'han pogut modificar els paràmetres",
"View Community": "Mira la communitat",
"%(count)s Members|one": "%(count)s membre",
"Event sent!": "S'ha enviat l'esdeveniment",
"Event Content": "Contingut de l'esdeveniment",
"Thank you!": "Gràcies!",
"Collapse panel": "Col·lapsa el tauler",
"With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "Amb el vostre navegador actual, l'aparença de l'aplicació pot ser completament incorrecta i algunes o totes les funcions poden no funcionar correctament. Si voleu provar-ho de totes maneres, podeu continuar, però esteu sols pel que fa als problemes que pugueu trobar!",
"Checking for an update...": "Comprovant si hi ha actualitzacions...",
"There are advanced notifications which are not shown here": "Hi ha notificacions avançades que no es mostren aquí",
@ -1024,7 +825,6 @@
"Your device resolution": "La resolució del vostre dispositiu",
"Show Stickers": "Mostra els adhesius",
"Where this page includes identifiable information, such as a room, user or group ID, that data is removed before being sent to the server.": "Quan aquesta pàgina contingui informació identificable, com per exemple una sala, usuari o ID de grup, aquestes dades se suprimeixen abans d'enviar-se al servidor.",
"A conference call could not be started because the intgrations server is not available": "No s'ha pogut iniciar la trucada de conferència perquè el servidor d'integració no és disponible",
"Call in Progress": "Trucada en curs",
"A call is currently being placed!": "S'està fent una trucada en aquest moment!",
"A call is already in progress!": "Ja hi ha una trucada en curs!",
@ -1034,18 +834,14 @@
"Registration Required": "Es requereix registre",
"You need to register to do this. Would you like to register now?": "Us heu de registrar per fer això. Us voleu registrar ara?",
"Failed to invite users to the room:": "No s'ha pogut convidar els usuaris a aquesta sala:",
"Waiting for %(userId)s to accept...": "S'està esperant a que %(userId)s accepti...",
"Waiting for %(userId)s to confirm...": "S'està esperant a que %(userId)s confirmi...",
"Missing roomId.": "Manca l'ID de la sala.",
"Searches DuckDuckGo for results": "Cerca al DuckDuckGo els resultats",
"Changes your display nickname": "Canvia el vostre malnom",
"Changes colour scheme of current room": "Canvia l'esquema de colors de la sala actual",
"Sets the room topic": "Estableix el tema de la sala",
"Invites user with given id to current room": "Convida l'usuari amb l'id donat a la sala actual",
"Joins room with given alias": "Us introdueix a la sala amb l'àlies donat",
"Kicks user with given id": "Expulsa l'usuari amb l'id donat",
"Bans user with given id": "Bandeja l'usuari amb l'id donat",
"Unbans user with given id": "Permet l'accés a l'usuari amb l'id donat",
"Ignores a user, hiding their messages from you": "Ignora un usuari, amagant-te els seus missatges",
"Stops ignoring a user, showing their messages going forward": "Deixa d'ignorar un usuari, mostrant els seus missatges ara en avant",
"Define the power level of a user": "Defineix el nivell d'autoritat d'un usuari",
@ -1053,7 +849,6 @@
"Opens the Developer Tools dialog": "Obre el diàleg d'Eines del desenvolupador",
"Verifies a user, device, and pubkey tuple": "Verifica un usuari, dispositiu i tupla de clau pública",
"Displays action": "Mostra l'acció",
"You can also set a custom identity server, but you won't be able to invite users by email address, or be invited by email address yourself.": "També podeu establir un servidor d'identitat personalitzat, però no podreu convidar usuaris o ser convidats vosaltres mateixos per adreça de correu electrònic.",
"Whether or not you're logged in (we don't record your username)": "Si heu iniciat sessió o no (no desem el vostre usuari)",
"The file '%(fileName)s' exceeds this homeserver's size limit for uploads": "El fitxer %(fileName)s supera el límit de pujades del servidor",
"Upgrades a room to a new version": "Actualitza la sala a una versió nova",
@ -1109,10 +904,8 @@
"Unable to find profiles for the Matrix IDs listed below - would you like to invite them anyway?": "No s'ha trobat el perfil pels IDs de Matrix següents, els voleu convidar igualment?",
"Invite anyway and never warn me again": "Convidar igualment i no avisar-me de nou",
"Invite anyway": "Convidar igualment",
"Use an email address to recover your account. Other users can invite you to rooms using your contact details.": "Feu servir una adreça de correu electrònic per recuperar el vostre compte. Altres usuaris us poden convidar a sales amb les vostres dades de contacte.",
"You are an administrator of this community. You will not be able to rejoin without an invite from another administrator.": "Sou administradors d'aquesta comunitat. No hi podreu tornar a entrar sense que un altre administrador us convidi.",
"Guest": "Visitant",
"Guest access is disabled on this homeserver.": "L'accés als visitants està desactivat en aquest servidor.",
"This homeserver has hit its Monthly Active User limit.": "Aquest homeserver ha assolit el seu límit d'usuaris actius mensuals.",
"This homeserver has exceeded one of its resource limits.": "Aquest homeserver ha sobrepassat on dels seus límits de recursos.",
"Please <a>contact your service administrator</a> to continue using the service.": "Si us plau <a>poseu-vos en contacte amb l'administrador</a> per poder continuar usant el servei.",

File diff suppressed because it is too large Load diff

View file

@ -42,45 +42,25 @@
"Sign in": "Log ind",
"Warning!": "Advarsel!",
"Account": "Konto",
"Add email address": "Tilføj e-mail-adresse",
"Add phone number": "Tilføj telefonnummer",
"Admin": "Administrator",
"Advanced": "Avanceret",
"Anyone who knows the room's link, apart from guests": "Alle der kender link til rummet, bortset fra gæster",
"Anyone who knows the room's link, including guests": "Alle der kender link til rummet, inklusiv gæster",
"Are you sure you want to reject the invitation?": "Er du sikker på du vil afvise invitationen?",
"Are you sure you want to upload the following files?": "Er du sikker på du vil sende de følgende filer?",
"Banned users": "Bortviste brugere",
"Bulk Options": "Masseindstillinger",
"Can't load user settings": "Kan ikke indlæse brugerindstillinger",
"Changes to who can read history will only apply to future messages in this room": "Ændringer til hvem der kan læse historie gælder kun for fremtidige meddelelser i dette rum",
"Clear Cache and Reload": "Ryd cache og genindlæs",
"Clear Cache": "Ryd cache",
"Click here to fix": "Klik her for at rette",
"Confirm your new password": "Bekræft din nye adgangskode",
"Continue": "Fortsæt",
"Could not connect to the integration server": "Kunne ikke oprette forbindelse til integrationsserveren",
"Create an account": "Opret en brugerkonto",
"Create Room": "Opret rum",
"Cryptography": "Kryptografi",
"Deactivate Account": "Deaktiver brugerkonto",
"Deactivate my account": "Deaktiver min brugerkonto",
"Default": "Standard",
"Devices will not yet be able to decrypt history from before they joined the room": "Enhederne vil ikke være i stand til at dekryptere historikken fra, før de kom til rummet",
"Display name": "Visningsnavn",
"Email, name or matrix ID": "E-mail, navn eller matrix-ID",
"Encrypted messages will not be visible on clients that do not yet implement encryption": "Krypterede meddelelser vil ikke være synlige på klienter, der endnu ikke implementerer kryptering",
"Encrypted room": "Krypteret rummet",
"Encryption is enabled in this room": "Kryptering er aktiveret i dette rum",
"Encryption is not enabled in this room": "Kryptering er ikke aktiveret i dette rum",
"End-to-end encryption is in beta and may not be reliable": "End-to-end kryptering er i beta og kan ikke være pålidelig",
"Error": "Fejl",
"Export E2E room keys": "Eksporter E2E rum nøgler",
"Failed to change password. Is your password correct?": "Kunne ikke ændre password. Er dit password korrekt?",
"Failed to leave room": "Kunne ikke forlade rum",
"Failed to reject invitation": "Kunne ikke afvise invitationen",
"Failed to send email": "Kunne ikke sende e-mail",
"Failed to set avatar.": "Kunne ikke angive avatar.",
"Failed to unban": "Var ikke i stand til at ophæve forbuddet",
"Favourite": "Favorit",
"Notifications": "Notifikationer",
@ -89,7 +69,6 @@
"unknown error code": "Ukendt fejlkode",
"%(targetName)s accepted an invitation.": "%(targetName)s accepterede en invitation.",
"%(targetName)s accepted the invitation for %(displayName)s.": "%(targetName)s accepterede invitationen til %(displayName)s.",
"%(names)s and %(lastPerson)s are typing": "%(names)s og %(lastPerson)s er ved at skrive",
"%(senderName)s answered the call.": "%(senderName)s besvarede opkaldet.",
"Add a widget": "Tilføj en widget",
"OK": "OK",
@ -121,13 +100,6 @@
"VoIP is unsupported": "VoIP er ikke understøttet",
"You cannot place VoIP calls in this browser.": "Du kan ikke lave VoIP-opkald i denne browser.",
"You cannot place a call with yourself.": "Du kan ikke ringe til dig selv.",
"Conference calls are not supported in this client": "Konferenceopkald er ikke undersøttede i denne klient",
"Conference calls are not supported in encrypted rooms": "Konferenceopkald er ikke understøttede i krypterede rum",
"Conference calling is in development and may not be reliable.": "Konferenceopkald er under udvikling og kan være utilregnelige.",
"Failed to set up conference call": "Kunne ikke starte konferenceopkald",
"Conference call failed.": "Konferenceopkald fejlede.",
"The file '%(fileName)s' failed to upload": "Filen '%(fileName)s' kunne ikke uploades",
"The file '%(fileName)s' exceeds this home server's size limit for uploads": "Filen '%(fileName)s' overskrider denne home servers størrelsesbegrænsning på uploads",
"Upload Failed": "Upload Fejlede",
"Sun": "Søn",
"Mon": "Man",
@ -156,7 +128,6 @@
"Who would you like to add to this community?": "Hvem vil du tilføje til dette fællesskab?",
"Warning: any person you add to a community will be publicly visible to anyone who knows the community ID": "Advarsel: alle personer du tilføjer til et fællesskab vil være synlige for alle der kender Fællesskabs ID'et",
"Invite new community members": "Inviter nye fællesskabsmedlemmer",
"Name or matrix ID": "Navn eller matrix ID",
"Invite to Community": "Inviter til Fællesskab",
"Which rooms would you like to add to this community?": "Hvilke rum vil du tilføje til dette fællesskab?",
"Show these rooms to non-members on the community page and room list?": "Vis disse rum til ikke-medlemmer på fællesskabssiden og rumlisten?",
@ -178,9 +149,7 @@
"Who would you like to communicate with?": "Hvem vil du kommunikere med?",
"Start Chat": "Start Chat",
"Invite new room members": "Inviter nye rummedlemmer",
"Who would you like to add to this room?": "Hvem vil du tilføje til dette rum?",
"Send Invites": "Send invitationer",
"Failed to invite user": "Kunne ikke invitere bruger",
"Operation failed": "Operation mislykkedes",
"Failed to invite": "Kunne ikke invitere",
"Failed to invite the following users to the %(roomName)s room:": "Kunne ikke invitere de følgende brugere til %(roomName)s rummet:",
@ -237,13 +206,11 @@
"(no answer)": "(intet svar)",
"(unknown failure: %(reason)s)": "(ukendt fejl: %(reason)s)",
"%(senderName)s ended the call.": "%(senderName)s afsluttede opkaldet.",
"%(senderName)s placed a %(callType)s call.": "%(senderName)s startede et %(callType)s opkald.",
"%(senderName)s sent an invitation to %(targetDisplayName)s to join the room.": "%(senderName)s inviterede %(targetDisplayName)s til rummet.",
"Submit debug logs": "Indsend debug-logfiler",
"Online": "Online",
"Fetching third party location failed": "Hentning af tredjeparts placering mislykkedes",
"A new version of Riot is available.": "En ny version a Riot er tilgængelig.",
"Couldn't load home page": "Kunne ikke indlæse startsiden",
"Send Account Data": "Send Konto Data",
"All notifications are currently disabled for all targets.": "Alle meddelelser er for øjeblikket deaktiveret for alle mål.",
"Uploading report": "Uploader rapport",
@ -257,10 +224,7 @@
"Friday": "Fredag",
"Update": "Opdater",
"What's New": "Hvad er nyt",
"Add an email address above to configure email notifications": "Tilføj en emailadresse ovenfor for at konfigurere e-mail-underretninger",
"Expand panel": "Udvid panel",
"On": "Tændt",
"Filter room names": "Filtrér rumnavne",
"Changelog": "Ændringslog",
"Waiting for response from server": "Venter på svar fra server",
"Uploaded on %(date)s by %(user)s": "Uploadet den %(date)s af %(user)s",
@ -270,13 +234,10 @@
"delete the alias.": "Slet aliaset.",
"To return to your account in future you need to <u>set a password</u>": "For at komme ind på din konto i fremtiden skal du <u>indstille et password</u>",
"Forget": "Glem",
"#example": "#eksempel",
"Hide panel": "Gem panel",
"You cannot delete this image. (%(code)s)": "Du kan ikke slette dette billede. (%(code)s)",
"Cancel Sending": "Stop Forsendelse",
"Warning": "Advarsel",
"This Room": "Dette rum",
"The Home Server may be too old to support third party networks": "Hjemmeserveren kan være for gammel til at understøtte tredjepartsnetværk",
"Room not found": "Rummet ikke fundet",
"Messages containing my display name": "Beskeder der indeholder mit viste navn",
"Messages in one-to-one chats": "Beskeder i en-til-en chats",
@ -286,7 +247,6 @@
"Failed to update keywords": "Kunne ikke opdatere søgeord",
"remove %(name)s from the directory.": "fjern %(name)s fra kataloget.",
"Notifications on the following keywords follow rules which cant be displayed here:": "Meddelelser om følgende søgeord følger regler, der ikke kan vises her:",
"<safariLink>Safari</safariLink> and <operaLink>Opera</operaLink> work too.": "<safariLink>Safari</safariLink> og <operaLink>Opera</operaLink> virker også.",
"Please set a password!": "Indstil venligst et password!",
"You have successfully set a password!": "Du har succesfuldt indstillet et password!",
"An error occurred whilst saving your email notification preferences.": "Der opstod en fejl under opbevaring af dine e-mail-underretningsindstillinger.",
@ -297,15 +257,12 @@
"Members": "Medlemmer",
"No update available.": "Ingen opdatering tilgængelig.",
"Noisy": "Støjende",
"Failed to get protocol list from Home Server": "Kunne ikke få protokolliste fra Home Server",
"Collecting app version information": "Indsamler app versionsoplysninger",
"Delete the room alias %(alias)s and remove %(name)s from the directory?": "Slet rumaliaset %(alias)s og fjern %(name)s fra kataloget?",
"This will allow you to return to your account after signing out, and sign in on other devices.": "Dette vil tillade dig at vende tilbage til din konto efter at have logget ud og at logge ind på andre enheder.",
"Keywords": "Søgeord",
"Enable notifications for this account": "Aktivér underretninger for dette brugernavn",
"Directory": "Rum katalog",
"Invite to this community": "Inviter til dette fællesskab",
"Search for a room": "Søg efter et rum",
"Search…": "Søg…",
"Messages containing <span>keywords</span>": "Beskeder der indeholder <span>keywords</span>",
"When I'm invited to a room": "Når jeg bliver inviteret til et rum",
@ -325,16 +282,12 @@
"Monday": "Mandag",
"Remove from Directory": "Fjern fra Katalog",
"Enable them now": "Aktivér dem nu",
"Messages containing my user name": "Beskeder der indeholder mit brugernavn",
"Toolbox": "Værktøjer",
"Collecting logs": "Indsamler logfiler",
"more": "mere",
"You must specify an event type!": "Du skal angive en begivenhedstype!",
"(HTTP status %(httpStatus)s)": "(HTTP tilstand %(httpStatus)s)",
"Invite to this room": "Inviter til dette rum",
"State Key": "Tilstandsnøgle",
"Please install <chromeLink>Chrome</chromeLink> or <firefoxLink>Firefox</firefoxLink> for the best experience.": "Installer venligst <chromeLink>Chrome</chromeLink> eller <firefoxLink>Firefox</firefoxLink> for den bedste oplevelse.",
"Failed to get public room list": "Kunne ikke få offentlig rumliste",
"Send": "Send",
"Send logs": "Send logs",
"All messages": "Alle beskeder",
@ -367,36 +320,28 @@
"Low Priority": "Lav prioritet",
"Unable to fetch notification target list": "Kan ikke hente meddelelsesmålliste",
"Set Password": "Indstil Password",
"Enable audible notifications in web client": "Aktivér hørbare underretninger i webklienten",
"Resend": "Send igen",
"Riot does not know how to join a room on this network": "Riot ved ikke, hvordan man kan deltage i et rum på dette netværk",
"Mentions only": "Kun nævninger",
"Failed to remove tag %(tagName)s from room": "Kunne ikke fjerne tag(s): %(tagName)s fra rummet",
"Wednesday": "Onsdag",
"You can now return to your account after signing out, and sign in on other devices.": "Du kan nu vende tilbage til din konto efter at have logget ud og logge ind på andre enheder.",
"Enable desktop notifications": "Aktivér desktop meddelelser",
"Enable email notifications": "Aktivér e-mail-underretninger",
"Login": "Log ind",
"Download this file": "Download denne fil",
"Pin Message": "Fasthold Besked",
"Failed to change settings": "Kunne ikke ændre indstillinger",
"Developer Tools": "Udviklingsværktøjer",
"Event Content": "Begivenhedsindhold",
"Thank you!": "Tak!",
"Collapse panel": "Slå panel sammen",
"With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "Med din nuværnde broser kan udseendet og fornemmelsen af programmet være helt forkert og nogle funktioner virker måske ikke. Hvis du alligevel vil prøve så kan du fortsætte, men det er på egen risiko!",
"Checking for an update...": "Checker om der er en opdatering...",
"There are advanced notifications which are not shown here": "Der er avancerede meddelelser, som ikke vises her",
"%(count)s Members|other": "%(count)s medlemmer",
"Logs sent": "Logfiler sendt",
"Reply": "Besvar",
"All messages (noisy)": "Alle meddelelser (højlydt)",
"GitHub issue link:": "Link til GitHub issue:",
"Debug logs contain application usage data including your username, the IDs or aliases of the rooms or groups you have visited and the usernames of other users. They do not contain messages.": "Debug-logfiler indeholder brugerdata såsom brugernavn, ID'er eller aliaser for de rum eller grupper, du har besøgt, og andres brugernavne. De indeholder ikke meddelelser.",
"Failed to send logs: ": "Kunne ikke sende logfiler: ",
"View Community": "Vis community",
"%(count)s Members|one": "%(count)s medlem",
"Notes:": "Noter:",
"Preparing to send logs": "Forbereder afsendelse af logfiler",
"The platform you're on": "Den platform du bruger",
"The version of Riot.im": "Versionen af Riot.im",
@ -463,7 +408,6 @@
"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 />.": "Rumopgraderinger påvirker normalt kun <i>servernes</i> behandling af rum. Hvis du har problemer med din Riot-klient bedes du oprette en sag på <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>Advarsel:</b> Opgradering af et rum <i>flytter ikke automatisk rummets medlemmer til den nye version af rummet.</i> Vi sender et link til den nye version i den gamle version af rummet - rummets medlemmer må klikke på dette link for at tilgå det nye rum.",
"Please confirm that you'd like to go forward with upgrading this room from <oldVersion /> to <newVersion />.": "Bekræft venligst at du vil fortsætte med at opgradere rummet fra <oldVersion /> til <newVersion />.",
"Upgrade": "Opgradering",
"Changes your display nickname in the current room only": "Ændrer dit viste navn kun for det nuværende rum",
"Changes the avatar of the current room": "Ændrer avataren af det nuværende rum",
"Changes your avatar in this current room only": "Ændrer din avatar kun for det nuværende rum",

File diff suppressed because it is too large Load diff

View file

@ -12,10 +12,7 @@
"%(targetName)s accepted the invitation for %(displayName)s.": "%(targetName)s δέχτηκες την πρόσκληση για %(displayName)s.",
"Account": "Λογαριασμός",
"Add a topic": "Προσθήκη θέματος",
"Add email address": "Προσθήκη διεύθυνσης ηλ. αλληλογραφίας",
"Add phone number": "Προσθήκη αριθμού",
"Admin": "Διαχειριστής",
"VoIP": "VoIP",
"No Microphones detected": "Δεν εντοπίστηκε μικρόφωνο",
"No Webcams detected": "Δεν εντοπίστηκε κάμερα",
"Default Device": "Προεπιλεγμένη συσκευή",
@ -23,7 +20,6 @@
"Camera": "Κάμερα",
"Advanced": "Προχωρημένα",
"Algorithm": "Αλγόριθμος",
"Hide removed messages": "Απόκρυψη διαγραμμένων μηνυμάτων",
"Authentication": "Πιστοποίηση",
"A new password must be entered.": "Ο νέος κωδικός πρόσβασης πρέπει να εισαχθεί.",
"%(senderName)s answered the call.": "Ο χρήστης %(senderName)s απάντησε την κλήση.",
@ -32,36 +28,27 @@
"Are you sure?": "Είστε σίγουροι;",
"Are you sure you want to leave the room '%(roomName)s'?": "Είστε σίγουροι ότι θέλετε να αποχωρήσετε από το δωμάτιο '%(roomName)s';",
"Are you sure you want to reject the invitation?": "Είστε σίγουροι ότι θέλετε να απορρίψετε την πρόσκληση;",
"Are you sure you want to upload the following files?": "Είστε σίγουροι ότι θέλετε να αποστείλετε τα ακόλουθα αρχεία;",
"Attachment": "Επισύναψη",
"%(senderName)s banned %(targetName)s.": "Ο χρήστης %(senderName)s έδιωξε τον χρήστη %(targetName)s.",
"Autoplay GIFs and videos": "Αυτόματη αναπαραγωγή GIFs και βίντεο",
"Anyone who knows the room's link, apart from guests": "Oποιοσδήποτε",
"%(items)s and %(lastItem)s": "%(items)s %(lastItem)s",
"A text message has been sent to +%(msisdn)s. Please enter the verification code it contains": "Ένα μήνυμα στάλθηκε στο +%(msisdn)s. Παρακαλώ γράψε τον κωδικό επαλήθευσης που περιέχει",
"Access Token:": "Κωδικός πρόσβασης:",
"Always show message timestamps": "Εμφάνιση πάντα της ένδειξης ώρας στα μηνύματα",
"and %(count)s others...|one": "και ένας ακόμα...",
"and %(count)s others...|other": "και %(count)s άλλοι...",
"%(names)s and %(lastPerson)s are typing": "%(names)s και %(lastPerson)s γράφουν",
"Anyone who knows the room's link, including guests": "Οποιοσδήποτε γνωρίζει τον σύνδεσμο του δωματίου, συμπεριλαμβανομένων των επισκεπτών",
"Blacklisted": "Στη μαύρη λίστα",
"Can't load user settings": "Δεν είναι δυνατή η φόρτωση των ρυθμίσεων χρήστη",
"Change Password": "Αλλαγή κωδικού πρόσβασης",
"%(senderName)s changed their profile picture.": "Ο %(senderName)s άλλαξε τη φωτογραφία του προφίλ του.",
"%(senderDisplayName)s changed the room name to %(roomName)s.": "Ο %(senderDisplayName)s άλλαξε το όνομα του δωματίου σε %(roomName)s.",
"%(senderDisplayName)s changed the topic to \"%(topic)s\".": "Ο %(senderDisplayName)s άλλαξε το θέμα σε \"%(topic)s\".",
"Clear Cache and Reload": "Εκκαθάριση μνήμης και ανανέωση",
"Clear Cache": "Εκκαθάριση μνήμης",
"Bans user with given id": "Αποκλεισμός χρήστη με το συγκεκριμένο αναγνωριστικό",
"%(senderDisplayName)s removed the room name.": "Ο %(senderDisplayName)s διέγραψε το όνομα του δωματίου.",
"Changes your display nickname": "Αλλάζει το ψευδώνυμο χρήστη",
"Conference call failed.": "Η κλήση συνδιάσκεψης απέτυχε.",
"powered by Matrix": "λειτουργεί με το Matrix",
"Confirm password": "Επιβεβαίωση κωδικού πρόσβασης",
"Confirm your new password": "Επιβεβαίωση του νέου κωδικού πρόσβασης",
"Continue": "Συνέχεια",
"Create an account": "Δημιουργία λογαριασμού",
"Create Room": "Δημιουργία δωματίου",
"Cryptography": "Κρυπτογραφία",
"Current password": "Τωρινός κωδικός πρόσβασης",
@ -69,10 +56,8 @@
"Custom level": "Προσαρμοσμένο επίπεδο",
"/ddg is not a command": "/ddg δεν αναγνωρίζεται ως εντολή",
"Deactivate Account": "Απενεργοποίηση λογαριασμού",
"Deactivate my account": "Απενεργοποίηση του λογαριασμού μου",
"Decrypt %(text)s": "Αποκρυπτογράφηση %(text)s",
"Decryption error": "Σφάλμα αποκρυπτογράφησης",
"Delete": "Διαγραφή",
"Default": "Προεπιλογή",
"Device already verified!": "Η συσκευή έχει ήδη επαληθευτεί!",
"Device ID": "Αναγνωριστικό συσκευής",
@ -82,16 +67,11 @@
"Devices": "Συσκευές",
"Direct chats": "Απευθείας συνομιλίες",
"Disinvite": "Ανάκληση πρόσκλησης",
"Display name": "Όνομα χρήστη",
"Download %(text)s": "Λήψη %(text)s",
"Ed25519 fingerprint": "Αποτύπωμα Ed25519",
"Email": "Ηλεκτρονική διεύθυνση",
"Email address": "Ηλεκτρονική διεύθυνση",
"Email address (optional)": "Ηλεκτρονική διεύθυνση (προαιρετικό)",
"Email, name or matrix ID": "Ηλεκτρονική διεύθυνση, όνομα ή matrix ID",
"Emoji": "Εικονίδια",
"Encrypted messages will not be visible on clients that do not yet implement encryption": "Τα κρυπτογραφημένα μηνύματα δεν θα είναι ορατά σε εφαρμογές που δεν παρέχουν τη δυνατότητα κρυπτογράφησης",
"Encrypted room": "Κρυπτογραφημένο δωμάτιο",
"%(senderName)s ended the call.": "%(senderName)s τερμάτισε την κλήση.",
"End-to-end encryption information": "Πληροφορίες σχετικά με τη κρυπτογράφηση από άκρο σε άκρο (End-to-end encryption)",
"Error decrypting attachment": "Σφάλμα κατά την αποκρυπτογράφηση της επισύναψης",
@ -105,7 +85,6 @@
"Failed to mute user": "Δεν ήταν δυνατή η σίγαση του χρήστη",
"Failed to reject invite": "Δεν ήταν δυνατή η απόρριψη της πρόσκλησης",
"Failed to reject invitation": "Δεν ήταν δυνατή η απόρριψη της πρόσκλησης",
"Failed to save settings": "Δεν ήταν δυνατή η αποθήκευση των ρυθμίσεων",
"Failed to send email": "Δεν ήταν δυνατή η αποστολή ηλ. αλληλογραφίας",
"Failed to verify email address: make sure you clicked the link in the email": "Δεν ήταν δυνατή η επιβεβαίωση της διεύθυνσης ηλεκτρονικής αλληλογραφίας: βεβαιωθείτε οτι κάνατε κλικ στον σύνδεσμο που σας στάλθηκε",
"Favourite": "Αγαπημένο",
@ -113,9 +92,7 @@
"Fill screen": "Γέμισε την οθόνη",
"Filter room members": "Φιλτράρισμα μελών",
"Forget room": "Αγνόηση δωματίου",
"Forgot your password?": "Ξεχάσατε τoν κωδικό πρόσβασης σας;",
"For security, this session has been signed out. Please sign in again.": "Για λόγους ασφαλείας, αυτή η συνεδρία έχει τερματιστεί. Παρακαλούμε συνδεθείτε ξανά.",
"For security, logging out will delete any end-to-end encryption keys from this browser. If you want to be able to decrypt your conversation history from future Riot sessions, please export your room keys for safe-keeping.": "Για λόγους ασφαλείας, τα κλειδιά κρυπτογράφησης θα διαγράφονται από τον περιηγητή κατά την αποσύνδεση σας. Εάν επιθυμείτε να αποκρυπτογραφήσετε τις συνομιλίες σας στο μέλλον, εξάγετε τα κλειδιά σας και κρατήστε τα ασφαλή.",
"Hangup": "Κλείσιμο",
"Historical": "Ιστορικό",
"Homeserver is": "Ο διακομιστής είναι",
@ -125,12 +102,10 @@
"Import E2E room keys": "Εισαγωγή κλειδιών E2E",
"Incorrect username and/or password.": "Λανθασμένο όνομα χρήστη και/ή κωδικός.",
"Incorrect verification code": "Λανθασμένος κωδικός επαλήθευσης",
"Interface Language": "Γλώσσα διεπαφής",
"Invalid Email Address": "Μη έγκυρη διεύθυνση ηλεκτρονικής αλληλογραφίας",
"Invite new room members": "Προσκαλέστε νέα μέλη",
"Invited": "Προσκλήθηκε",
"Invites": "Προσκλήσεις",
"%(displayName)s is typing": "Ο χρήστης %(displayName)s γράφει",
"Sign in with": "Συνδεθείτε με",
"%(targetName)s joined the room.": "ο %(targetName)s συνδέθηκε στο δωμάτιο.",
"Jump to first unread message.": "Πηγαίνετε στο πρώτο μη αναγνωσμένο μήνυμα.",
@ -141,27 +116,19 @@
"Leave room": "Αποχώρηση από το δωμάτιο",
"%(targetName)s left the room.": "Ο χρήστης %(targetName)s έφυγε από το δωμάτιο.",
"Local addresses for this room:": "Τοπική διεύθυνση για το δωμάτιο:",
"Logged in as:": "Συνδεθήκατε ως:",
"Logout": "Αποσύνδεση",
"Low priority": "Χαμηλής προτεραιότητας",
"matrix-react-sdk version:": "Έκδοση matrix-react-sdk:",
"Message not sent due to unknown devices being present": "Το μήνυμα δεν στάλθηκε γιατί υπάρχουν άγνωστες συσκευές",
"Mobile phone number": "Αριθμός κινητού τηλεφώνου",
"Click here to fix": "Κάνε κλικ εδώ για διόρθωση",
"Command error": "Σφάλμα εντολής",
"Commands": "Εντολές",
"Conference calls are not supported in encrypted rooms": "Οι κλήσεις συνδιάσκεψης δεν είναι υποστηρίζονται σε κρυπτογραφημένα δωμάτια",
"Conference calls are not supported in this client": "Οι κλήσεις συνδιάσκεψης δεν είναι υποστηρίζονται από την εφαρμογή",
"Enable encryption": "Ενεργοποίηση κρυπτογραφίας",
"Enter Code": "Εισαγωγή κωδικού πρόσβασης",
"Failed to send request.": "Δεν ήταν δυνατή η αποστολή αιτήματος.",
"Failed to upload file": "Δεν ήταν δυνατή η αποστολή του αρχείου",
"Failure to create room": "Δεν ήταν δυνατή η δημιουργία δωματίου",
"Join Room": "Είσοδος σε δωμάτιο",
"Moderator": "Συντονιστής",
"Name": "Όνομα",
"New address (e.g. #foo:%(localDomain)s)": "Νέα διεύθυνση (e.g. #όνομα:%(localDomain)s)",
"New password": "Νέος κωδικός πρόσβασης",
"New passwords don't match": "Οι νέοι κωδικοί πρόσβασης είναι διαφορετικοί",
"New passwords must match each other.": "Οι νέοι κωδικοί πρόσβασης πρέπει να ταιριάζουν.",
"none": "κανένα",
@ -172,14 +139,12 @@
"OK": "Εντάξει",
"olm version:": "Έκδοση olm:",
"Password": "Κωδικός πρόσβασης",
"Password:": "Κωδικός πρόσβασης:",
"Passwords can't be empty": "Οι κωδικοί πρόσβασης δεν γίνετε να είναι κενοί",
"People": "Άτομα",
"Phone": "Τηλέφωνο",
"Register": "Εγγραφή",
"riot-web version:": "Έκδοση riot-web:",
"Room Colour": "Χρώμα δωματίου",
"Room name (optional)": "Όνομα δωματίου (προαιρετικό)",
"Rooms": "Δωμάτια",
"Save": "Αποθήκευση",
"Search failed": "Η αναζήτηση απέτυχε",
@ -198,9 +163,6 @@
"Dismiss": "Απόρριψη",
"bold": "έντονα",
"italic": "πλάγια",
"underline": "υπογράμμιση",
"code": "κώδικας",
"quote": "παράθεση",
"Close": "Κλείσιμο",
"Create new room": "Δημιουργία νέου δωματίου",
"Room directory": "Ευρετήριο",
@ -213,52 +175,38 @@
"Alias (optional)": "Ψευδώνυμο (προαιρετικό)",
"Ban": "Αποκλεισμός",
"Banned users": "Αποκλεισμένοι χρήστες",
"Bulk Options": "Μαζικές επιλογές",
"Call Timeout": "Λήξη χρόνου κλήσης",
"<a>Click here</a> to join the discussion!": "<a>Κλικ εδώ</a> για να συμμετάσχετε στην συζήτηση!",
"Click to mute audio": "Κάντε κλικ για σίγαση του ήχου",
"Click to mute video": "Κάντε κλικ για σίγαση του βίντεο",
"click to reveal": "κάντε κλικ για εμφάνιση",
"Click to unmute video": "Κάντε κλικ για άρση σίγασης του βίντεο",
"Click to unmute audio": "Κάντε κλικ για άρση σίγασης του ήχου",
"%(count)s new messages|one": "%(count)s νέο μήνυμα",
"%(count)s new messages|other": "%(count)s νέα μηνύματα",
"Custom": "Προσαρμοσμένο",
"Decline": "Απόρριψη",
"Disable Notifications": "Απενεργοποίηση ειδοποιήσεων",
"Drop File Here": "Αποθέστε εδώ το αρχείο",
"Enable Notifications": "Ενεργοποίηση ειδοποιήσεων",
"Encryption is enabled in this room": "Η κρυπτογράφηση είναι ενεργοποιημένη σε αυτό το δωμάτιο",
"Encryption is not enabled in this room": "Η κρυπτογράφηση είναι απενεργοποιημένη σε αυτό το δωμάτιο",
"Enter passphrase": "Εισαγωγή συνθηματικού",
"Failed to set avatar.": "Δεν ήταν δυνατό ο ορισμός της προσωπικής εικόνας.",
"Failed to set display name": "Δεν ήταν δυνατό ο ορισμός του ονόματος εμφάνισης",
"Failed to set up conference call": "Δεν ήταν δυνατή η ρύθμιση κλήσης συνδιάσκεψης",
"Failed to toggle moderator status": "Δεν ήταν δυνατή η εναλλαγή κατάστασης του συντονιστή",
"Failed to upload profile picture!": "Δεν ήταν δυνατή η αποστολή της εικόνας προφίλ!",
"Hide read receipts": "Απόκρυψη αποδείξεων ανάγνωσης",
"Home": "Αρχική",
"Last seen": "Τελευταία εμφάνιση",
"Level:": "Επίπεδο:",
"Manage Integrations": "Διαχείριση ενσωματώσεων",
"Markdown is disabled": "Το Markdown είναι απενεργοποιημένο",
"Markdown is enabled": "Το Markdown είναι ενεργοποιημένο",
"Missing room_id in request": "Λείπει το room_id στο αίτημα",
"Permissions": "Δικαιώματα",
"Power level must be positive integer.": "Το επίπεδο δύναμης πρέπει να είναι ένας θετικός ακέραιος.",
"Privacy warning": "Προειδοποίηση ιδιωτικότητας",
"Private Chat": "Προσωπική συνομιλία",
"Privileged Users": "Προνομιούχοι χρήστες",
"Profile": "Προφίλ",
"Public Chat": "Δημόσια συνομιλία",
"Reason": "Αιτία",
"Reason: %(reasonText)s": "Αιτία: %(reasonText)s",
"Revoke Moderator": "Ανάκληση συντονιστή",
"%(targetName)s rejected the invitation.": "Ο %(targetName)s απέρριψε την πρόσκληση.",
"Reject invitation": "Απόρριψη πρόσκλησης",
"Remote addresses for this room:": "Απομακρυσμένες διευθύνσεις για το δωμάτιο:",
"Remove Contact Information?": "Αφαίρεση πληροφοριών επαφής;",
"Remove %(threePid)s?": "Αφαίρεση %(threePid)s;",
"Results from DuckDuckGo": "Αποτελέσματα από DuckDuckGo",
"Return to login screen": "Επιστροφή στην οθόνη σύνδεσης",
"Room %(roomId)s not visible": "Το δωμάτιο %(roomId)s δεν είναι ορατό",
@ -269,22 +217,14 @@
"Send Invites": "Αποστολή προσκλήσεων",
"Send Reset Email": "Αποστολή μηνύματος επαναφοράς",
"%(senderDisplayName)s sent an image.": "Ο %(senderDisplayName)s έστειλε μια φωτογραφία.",
"Server may be unavailable or overloaded": "Ο διακομιστής μπορεί να είναι μη διαθέσιμος ή υπερφορτωμένος",
"Session ID": "Αναγνωριστικό συνεδρίας",
"%(senderName)s set a profile picture.": "Ο %(senderName)s όρισε τη φωτογραφία του προφίλ του.",
"Start authentication": "Έναρξη πιστοποίησης",
"Submit": "Υποβολή",
"Tagged as: ": "Με ετικέτα: ",
"The default role for new room members is": "Ο προεπιλεγμένος ρόλος για νέα μέλη είναι",
"The main address for this room is": "Η κύρια διεύθυνση για το δωμάτιο είναι",
"The file '%(fileName)s' failed to upload": "Απέτυχε η αποστολή του αρχείου '%(fileName)s'",
"This room has no local addresses": "Αυτό το δωμάτιο δεν έχει τοπικές διευθύνσεις",
"This doesn't appear to be a valid email address": "Δεν μοιάζει με μια έγκυρη διεύθυνση ηλεκτρονικής αλληλογραφίας",
"This phone number is already in use": "Αυτός ο αριθμός τηλεφώνου είναι ήδη σε χρήση",
"This room": "Αυτό το δωμάτιο",
"This room's internal ID is": "Το εσωτερικό αναγνωριστικό του δωματίου είναι",
"Turn Markdown off": "Απενεργοποίηση Markdown",
"Turn Markdown on": "Ενεργοποίηση Markdown",
"Unable to add email address": "Αδυναμία προσθήκης διεύθυνσης ηλ. αλληλογραφίας",
"Unable to remove contact information": "Αδυναμία αφαίρεσης πληροφοριών επαφής",
"Unable to verify email address.": "Αδυναμία επιβεβαίωσης διεύθυνσης ηλεκτρονικής αλληλογραφίας.",
@ -292,7 +232,6 @@
"%(senderName)s unbanned %(targetName)s.": "Ο χρήστης %(senderName)s έδιωξε τον χρήστη %(targetName)s.",
"Unable to enable Notifications": "Αδυναμία ενεργοποίησης των ειδοποιήσεων",
"Unable to load device list": "Αδυναμία φόρτωσης της λίστας συσκευών",
"Unencrypted room": "Μη κρυπτογραφημένο δωμάτιο",
"unencrypted": "μη κρυπτογραφημένο",
"Unencrypted message": "Μη κρυπτογραφημένο μήνυμα",
"unknown caller": "άγνωστος καλών",
@ -302,17 +241,12 @@
"Unnamed Room": "Ανώνυμο δωμάτιο",
"Unrecognised command:": "Μη αναγνωρίσιμη εντολή:",
"Unrecognised room alias:": "Μη αναγνωρίσιμο ψευδώνυμο:",
"Unverified": "Ανεπιβεβαίωτο",
"Upload avatar": "Αποστολή προσωπικής εικόνας",
"Upload Failed": "Απέτυχε η αποστολή",
"Upload Files": "Αποστολή αρχείων",
"Upload file": "Αποστολή αρχείου",
"Upload new:": "Αποστολή νέου:",
"Usage": "Χρήση",
"Use with caution": "Χρησιμοποιήστε τα με προσοχή",
"User ID": "Αναγνωριστικό χρήστη",
"User Interface": "Διεπαφή χρήστη",
"User name": "Όνομα χρήστη",
"Username invalid: %(errMessage)s": "Μη έγκυρο όνομα χρήστη: %(errMessage)s",
"Users": "Χρήστες",
"Video call": "Βιντεοκλήση",
@ -323,8 +257,6 @@
"You have no visible notifications": "Δεν έχετε ορατές ειδοποιήσεις",
"You must <a>register</a> to use this functionality": "Πρέπει να <a>εγγραφείτε</a> για να χρησιμοποιήσετε αυτή την λειτουργία",
"You need to be logged in.": "Πρέπει να είστε συνδεδεμένος.",
"You need to enter a user name.": "Πρέπει να εισάγετε ένα όνομα χρήστη.",
"Your password has been reset": "Ο κωδικός πρόσβασης σας έχει επαναφερθεί",
"Sun": "Κυρ",
"Mon": "Δευ",
"Tue": "Τρί",
@ -349,21 +281,12 @@
"Set a display name:": "Ορισμός ονόματος εμφάνισης:",
"Upload an avatar:": "Αποστολή προσωπικής εικόνας:",
"This server does not support authentication with a phone number.": "Αυτός ο διακομιστής δεν υποστηρίζει πιστοποίηση με αριθμό τηλεφώνου.",
"Missing password.": "Λείπει ο κωδικός πρόσβασης.",
"Passwords don't match.": "Δεν ταιριάζουν οι κωδικοί πρόσβασης.",
"This doesn't look like a valid email address.": "Δεν μοιάζει με μια έγκυρη διεύθυνση ηλ. αλληλογραφίας.",
"An unknown error occurred.": "Προέκυψε ένα άγνωστο σφάλμα.",
"I already have an account": "Έχω ήδη λογαριασμό",
"An error occurred: %(error_string)s": "Προέκυψε ένα σφάλμα: %(error_string)s",
"Topic": "Θέμα",
"Make Moderator": "Ορισμός συντονιστή",
"Encrypt room": "Κρυπτογράφηση δωματίου",
"Room": "Δωμάτιο",
"(~%(count)s results)|one": "(~%(count)s αποτέλεσμα)",
"(~%(count)s results)|other": "(~%(count)s αποτελέσματα)",
"Active call": "Ενεργή κλήση",
"strike": "επιγράμμιση",
"bullet": "κουκκίδα",
"New Password": "Νέος κωδικός πρόσβασης",
"Start automatically after system login": "Αυτόματη έναρξη μετά τη σύνδεση",
"Options": "Επιλογές",
@ -373,13 +296,11 @@
"Confirm passphrase": "Επιβεβαίωση συνθηματικού",
"Import room keys": "Εισαγωγή κλειδιών δωματίου",
"File to import": "Αρχείο για εισαγωγή",
"Start new chat": "Έναρξη νέας συνομιλίας",
"Confirm Removal": "Επιβεβαίωση αφαίρεσης",
"Unknown error": "Άγνωστο σφάλμα",
"Incorrect password": "Λανθασμένος κωδικός πρόσβασης",
"To continue, please enter your password.": "Για να συνεχίσετε, παρακαλούμε πληκτρολογήστε τον κωδικό πρόσβασής σας.",
"Device name": "Όνομα συσκευής",
"Device Name": "Όνομα συσκευής",
"Device key": "Κλειδί συσκευής",
"Verify device": "Επιβεβαίωση συσκευής",
"Unable to restore session": "Αδυναμία επαναφοράς συνεδρίας",
@ -389,15 +310,8 @@
"Verify...": "Επιβεβαίωση...",
"ex. @bob:example.com": "π.χ @bob:example.com",
"Add User": "Προσθήκη χρήστη",
"Sign in with CAS": "Σύνδεση με CAS",
"You can use the custom server options to sign into other Matrix servers by specifying a different Home server URL.": "Μπορείτε να χρησιμοποιήσετε τις προσαρμοσμένες ρυθμίσεις για να εισέλθετε σε άλλους διακομιστές Matrix επιλέγοντας μια διαφορετική διεύθυνση για το διακομιστή.",
"Token incorrect": "Εσφαλμένο διακριτικό",
"Please enter the code it contains:": "Παρακαλούμε εισάγετε τον κωδικό που περιέχει:",
"Default server": "Προεπιλεγμένος διακομιστής",
"Custom server": "Προσαρμοσμένος διακομιστής",
"Home server URL": "Διεύθυνση διακομιστή",
"Identity server URL": "Διεύθυνση διακομιστή ταυτοποίησης",
"What does this mean?": "Τι σημαίνει αυτό;",
"Error decrypting audio": "Σφάλμα κατά την αποκρυπτογράφηση του ήχου",
"Error decrypting image": "Σφάλμα κατά την αποκρυπτογράφηση της εικόνας",
"Error decrypting video": "Σφάλμα κατά την αποκρυπτογράφηση του βίντεο",
@ -407,18 +321,12 @@
"Online": "Σε σύνδεση",
"Idle": "Αδρανής",
"Offline": "Εκτός σύνδεσης",
"Start chatting": "Έναρξη συνομιλίας",
"Start Chatting": "Έναρξη συνομιλίας",
"Click on the button below to start chatting!": "Κάντε κλικ στο κουμπί παρακάτω για να ξεκινήσετε μια συνομιλία!",
"%(senderDisplayName)s removed the room avatar.": "Ο %(senderDisplayName)s διέγραψε την προσωπική εικόνα του δωματίου.",
"%(senderDisplayName)s changed the avatar for %(roomName)s": "Ο %(senderDisplayName)s άλλαξε την προσωπική εικόνα του %(roomName)s",
"Username available": "Διαθέσιμο όνομα χρήστη",
"Username not available": "Μη διαθέσιμο όνομα χρήστη",
"Something went wrong!": "Κάτι πήγε στραβά!",
"Could not connect to the integration server": "Αδυναμία σύνδεσης στον διακομιστή ενσωμάτωσης",
"Create a new chat or reuse an existing one": "Δημιουργία νέας συνομιλίας ή επαναχρησιμοποίηση μιας υπάρχουσας",
"Don't send typing notifications": "Να μη γίνετε αποστολή ειδοποιήσεων πληκτρολόγησης",
"Encrypted by a verified device": "Κρυπτογραφημένο από μια επιβεβαιωμένη συσκευή",
"Encrypted by an unverified device": "Κρυπτογραφημένο από μια ανεπιβεβαίωτη συσκευή",
"Error: Problem communicating with the given homeserver.": "Σφάλμα: πρόβλημα κατά την επικοινωνία με τον ορισμένο διακομιστή.",
"Failed to ban user": "Δεν ήταν δυνατό ο αποκλεισμός του χρήστη",
@ -426,18 +334,15 @@
"Failed to fetch avatar URL": "Δεν ήταν δυνατή η ανάκτηση της διεύθυνσης εικόνας",
"Failed to unban": "Δεν ήταν δυνατή η άρση του αποκλεισμού",
"%(userId)s from %(fromPowerLevel)s to %(toPowerLevel)s": "%(userId)s από %(fromPowerLevel)s σε %(toPowerLevel)s",
"Guest access is disabled on this Home Server.": "Έχει απενεργοποιηθεί η πρόσβαση στους επισκέπτες σε αυτόν τον διακομιστή.",
"Guests cannot join this room even if explicitly invited.": "Οι επισκέπτες δεν μπορούν να συνδεθούν στο δωμάτιο ακόμη και αν έχουν καλεστεί.",
"Hide Text Formatting Toolbar": "Απόκρυψη εργαλειοθήκης μορφοποίησης κειμένου",
"Incoming call from %(name)s": "Εισερχόμενη κλήση από %(name)s",
"Incoming video call from %(name)s": "Εισερχόμενη βιντεοκλήση από %(name)s",
"Incoming voice call from %(name)s": "Εισερχόμενη φωνητική κλήση από %(name)s",
"Invalid alias format": "Μη έγκυρη μορφή ψευδώνυμου",
"Invalid address format": "Μη έγκυρη μορφή διεύθυνσης",
"Invalid file%(extra)s": "Μη έγκυρο αρχείο %(extra)s",
"%(senderName)s invited %(targetName)s.": "Ο %(senderName)s προσκάλεσε τον %(targetName)s.",
"Invites user with given id to current room": "Προσκαλεί τον χρήστη με το δοσμένο αναγνωριστικό στο τρέχον δωμάτιο",
"'%(alias)s' is not a valid format for an address": "Το '%(alias)s' δεν είναι μια έγκυρη μορφή διεύθυνσης",
"'%(alias)s' is not a valid format for an alias": "Το '%(alias)s' δεν είναι μια έγκυρη μορφή ψευδώνυμου",
"%(senderName)s made future room history visible to all room members, from the point they are invited.": "Ο %(senderName)s έκανε το μελλοντικό ιστορικό του δωματίου δημόσιο όλα τα μέλη, από τη στιγμή που προσκλήθηκαν.",
"%(senderName)s made future room history visible to all room members, from the point they joined.": "Ο %(senderName)s έκανε το μελλοντικό ιστορικό του δωματίου δημόσιο όλα τα μέλη, από τη στιγμή που συνδέθηκαν.",
@ -445,21 +350,15 @@
"%(senderName)s made future room history visible to anyone.": "Ο %(senderName)s έκανε το μελλοντικό ιστορικό του δωματίου δημόσιο οποιοσδήποτε.",
"%(senderName)s made future room history visible to unknown (%(visibility)s).": "Ο %(senderName)s έκανε το μελλοντικό ιστορικό του δωματίου δημόσιο άγνωστο (%(visibility)s).",
"Missing user_id in request": "Λείπει το user_id στο αίτημα",
"Mobile phone number (optional)": "Αριθμός κινητού τηλεφώνου (προαιρετικό)",
"Never send encrypted messages to unverified devices from this device": "Να μη γίνει ποτέ αποστολή κρυπτογραφημένων μηνυμάτων σε ανεπιβεβαίωτες συσκευές από αυτή τη συσκευή",
"Never send encrypted messages to unverified devices in this room from this device": "Να μη γίνει ποτέ αποστολή κρυπτογραφημένων μηνυμάτων σε ανεπιβεβαίωτες συσκευές, σε αυτό το δωμάτιο, από αυτή τη συσκευή",
"not set": "δεν έχει οριστεί",
"not specified": "μη καθορισμένο",
"NOT verified": "ΧΩΡΙΣ επαλήθευση",
"No devices with registered encryption keys": "Καθόλου συσκευές με εγγεγραμένα κλειδιά κρυπτογράφησης",
"No display name": "Χωρίς όνομα",
"No users have specific privileges in this room": "Κανένας χρήστης δεν έχει συγκεκριμένα δικαιώματα σε αυτό το δωμάτιο",
"Once encryption is enabled for a room it cannot be turned off again (for now)": "Μόλις ενεργοποιηθεί η κρυπτογράφηση για ένα δωμάτιο, δεν μπορεί να απενεργοποιηθεί ξανά (για τώρα)",
"Only people who have been invited": "Μόνο άτομα που έχουν προσκληθεί",
"%(senderName)s placed a %(callType)s call.": "Ο %(senderName)s πραγματοποίησε μια %(callType)s κλήση.",
"Please check your email and click on the link it contains. Once this is done, click continue.": "Παρακαλούμε ελέγξτε την ηλεκτρονική σας αλληλογραφία και κάντε κλικ στον σύνδεσμο που περιέχει. Μόλις γίνει αυτό, κάντε κλίκ στο κουμπί συνέχεια.",
"Refer a friend to Riot:": "Πείτε για το Riot σε έναν φίλο σας:",
"Rejoin": "Επανασύνδεση",
"%(senderName)s removed their profile picture.": "Ο %(senderName)s αφαίρεσε τη φωτογραφία του προφίλ του.",
"%(senderName)s requested a VoIP conference.": "Ο %(senderName)s αιτήθηκε μια συνδιάσκεψη VoIP.",
"Riot does not have permission to send you notifications - please check your browser settings": "Το Riot δεν έχει δικαιώματα για αποστολή ειδοποιήσεων - παρακαλούμε ελέγξτε τις ρυθμίσεις του περιηγητή σας",
@ -467,13 +366,10 @@
"Room contains unknown devices": "Το δωμάτιο περιέχει άγνωστες συσκευές",
"%(roomName)s is not accessible at this time.": "Το %(roomName)s δεν είναι προσβάσιμο αυτή τη στιγμή.",
"Scroll to bottom of page": "Μετάβαση στο τέλος της σελίδας",
"Scroll to unread messages": "Μεταβείτε στα μη αναγνωσμένα μηνύματα",
"Sender device information": "Πληροφορίες συσκευής αποστολέα",
"Server may be unavailable, overloaded, or search timed out :(": "Ο διακομιστής μπορεί να είναι μη διαθέσιμος, υπερφορτωμένος, ή να έχει λήξει η αναζήτηση :(",
"Server may be unavailable, overloaded, or the file too big": "Ο διακομιστής μπορεί να είναι μη διαθέσιμος, υπερφορτωμένος, ή το αρχείο να είναι πολύ μεγάλο",
"Server may be unavailable, overloaded, or you hit a bug.": "Ο διακομιστής μπορεί να είναι μη διαθέσιμος, υπερφορτωμένος, ή να πέσατε σε ένα σφάλμα.",
"Server unavailable, overloaded, or something else went wrong.": "Ο διακομιστής μπορεί να είναι μη διαθέσιμος, υπερφορτωμένος, ή κάτι άλλο να πήγε στραβά.",
"Show panel": "Εμφάνιση καρτέλας",
"Show Text Formatting Toolbar": "Εμφάνιση της εργαλειοθήκης μορφοποίησης κειμένου",
"%(count)s of your messages have not been sent.|other": "Μερικά από τα μηνύματα σας δεν έχουν αποσταλεί.",
"This room is not recognised.": "Αυτό το δωμάτιο δεν αναγνωρίζεται.",
@ -485,103 +381,63 @@
"Verification Pending": "Εκκρεμεί επιβεβαίωση",
"Verification": "Επιβεβαίωση",
"verified": "επαληθεύτηκε",
"Verified": "Επαληθεύτηκε",
"Verified key": "Επιβεβαιωμένο κλειδί",
"VoIP conference finished.": "Ολοκληρώθηκε η συνδιάσκεψη VoIP.",
"VoIP conference started.": "Ξεκίνησησε η συνδιάσκεψη VoIP.",
"VoIP is unsupported": "Δεν υποστηρίζεται το VoIP",
"(warning: cannot be disabled again!)": "(προειδοποίηση: δεν μπορεί να απενεργοποιηθεί ξανά)",
"WARNING: Device already verified, but keys do NOT MATCH!": "ΠΡΟΕΙΔΟΠΟΙΗΣΗ: Η συσκευή έχει επαληθευτεί, αλλά τα κλειδιά ΔΕΝ ΤΑΙΡΙΑΖΟΥΝ!",
"Who can access this room?": "Ποιος μπορεί να προσπελάσει αυτό το δωμάτιο;",
"Who can read history?": "Ποιος μπορεί να διαβάσει το ιστορικό;",
"Who would you like to add to this room?": "Ποιον θέλετε να προσθέσετε σε αυτό το δωμάτιο;",
"%(senderName)s withdrew %(targetName)s's invitation.": "Ο %(senderName)s ανακάλεσε την πρόσκληση του %(targetName)s.",
"You cannot place a call with yourself.": "Δεν μπορείτε να καλέσετε τον ευατό σας.",
"You cannot place VoIP calls in this browser.": "Δεν μπορείτε να πραγματοποιήσετε κλήσεις VoIP με αυτόν τον περιηγητή.",
"You do not have permission to post to this room": "Δεν έχετε δικαιώματα για να δημοσιεύσετε σε αυτό το δωμάτιο",
"You have been banned from %(roomName)s by %(userName)s.": "Έχετε αποκλειστεί από το δωμάτιο %(roomName)s από τον %(userName)s.",
"You have been invited to join this room by %(inviterName)s": "Έχετε προσκληθεί να συνδεθείτε στο δωμάτιο από τον %(inviterName)s",
"You seem to be in a call, are you sure you want to quit?": "Φαίνεται ότι είστε σε μια κλήση, είστε βέβαιοι ότι θέλετε να αποχωρήσετε;",
"%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s %(time)s": "%(weekDayName)s, %(day)s %(monthName)s %(fullYear)s %(time)s",
"This doesn't look like a valid phone number.": "Δεν μοιάζει με έναν έγκυρο αριθμό τηλεφώνου.",
"Make this room private": "Κάντε το δωμάτιο ιδιωτικό",
"There are no visible files in this room": "Δεν υπάρχουν ορατά αρχεία σε αυτό το δωμάτιο",
"Connectivity to the server has been lost.": "Χάθηκε η συνδεσιμότητα στον διακομιστή.",
"Please select the destination room for this message": "Παρακαλούμε επιλέξτε ένα δωμάτιο προορισμού για αυτό το μήνυμα",
"Desktop specific": "Μόνο για επιφάνεια εργασίας",
"Analytics": "Αναλυτικά δεδομένα",
"Riot collects anonymous analytics to allow us to improve the application.": "Το Riot συλλέγει ανώνυμα δεδομένα επιτρέποντας μας να βελτιώσουμε την εφαρμογή.",
"Failed to invite": "Δεν ήταν δυνατή η πρόσκληση",
"Failed to invite user": "Δεν ήταν δυνατή η πρόσκληση του χρήστη",
"In future this verification process will be more sophisticated.": "Στο μέλλον η διαδικασία επαλήθευσης θα είναι πιο εξελιγμένη.",
"I verify that the keys match": "Επιβεβαιώνω πως ταιριάζουν τα κλειδιά",
"\"%(RoomName)s\" contains devices that you haven't seen before.": "Το \"%(RoomName)s\" περιέχει συσκευές που δεν έχετε ξαναδεί.",
"This Home Server would like to make sure you are not a robot": "Ο διακομιστής θέλει να σιγουρευτεί ότι δεν είσαστε ρομπότ",
"Please check your email to continue registration.": "Παρακαλούμε ελέγξτε την ηλεκτρονική σας αλληλογραφία για να συνεχίσετε με την εγγραφή.",
"If you don't specify an email address, you won't be able to reset your password. Are you sure?": "Αν δεν ορίσετε μια διεύθυνση ηλεκτρονικής αλληλογραφίας, δεν θα θα μπορείτε να επαναφέρετε τον κωδικό πρόσβασης σας. Είστε σίγουροι;",
"You are registering with %(SelectedTeamName)s": "Εγγραφείτε με %(SelectedTeamName)s",
"Removed or unknown message type": "Αφαιρέθηκε ή άγνωστος τύπος μηνύματος",
" (unsupported)": " (μη υποστηριζόμενο)",
"%(senderDisplayName)s changed the room avatar to <img/>": "Ο %(senderDisplayName)s άλλαξε την εικόνα του δωματίου σε <img/>",
"Missing Media Permissions, click here to request.": "Λείπουν τα δικαιώματα πολύμεσων, κάντε κλικ για να ζητήσετε.",
"You may need to manually permit Riot to access your microphone/webcam": "Μπορεί να χρειαστεί να ορίσετε χειροκίνητα την πρόσβαση του Riot στο μικρόφωνο/κάμερα",
"Can't connect to homeserver - please check your connectivity, ensure your <a>homeserver's SSL certificate</a> is trusted, and that a browser extension is not blocking requests.": "Δεν είναι δυνατή η σύνδεση στον διακομιστή - παρακαλούμε ελέγξτε την συνδεσιμότητα, βεβαιωθείτε ότι το <a>πιστοποιητικό SSL</a> του διακομιστή είναι έμπιστο και ότι κάποιο πρόσθετο περιηγητή δεν αποτρέπει τα αιτήματα.",
"Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. Either use HTTPS or <a>enable unsafe scripts</a>.": "Δεν είναι δυνατή η σύνδεση στον διακομιστή μέσω HTTP όταν μια διεύθυνση HTTPS βρίσκεται στην μπάρα του περιηγητή. Είτε χρησιμοποιήστε HTTPS ή <a>ενεργοποιήστε τα μη ασφαλή σενάρια εντολών</a>.",
"%(senderName)s changed the power level of %(powerLevelDiffText)s.": "Ο %(senderName)s άλλαξε το επίπεδο δύναμης του %(powerLevelDiffText)s.",
"Changes to who can read history will only apply to future messages in this room": "Οι αλλαγές που αφορούν την ορατότητα του ιστορικού θα εφαρμοστούν μόνο στα μελλοντικά μηνύματα του δωματίου",
"Conference calling is in development and may not be reliable.": "Η κλήση συνδιάσκεψης είναι υπό ανάπτυξη και μπορεί να μην είναι αξιόπιστη.",
"Devices will not yet be able to decrypt history from before they joined the room": "Οι συσκευές δεν θα είναι σε θέση να αποκρυπτογραφήσουν το ιστορικό πριν από την είσοδο τους στο δωμάτιο",
"End-to-end encryption is in beta and may not be reliable": "Η κρυπτογράφηση από άκρο σε άκρο είναι σε δοκιμαστικό στάδιο και μπορεί να μην είναι αξιόπιστη",
"%(senderName)s removed their display name (%(oldDisplayName)s).": "Ο %(senderName)s αφαίρεσε το όνομα εμφάνισης του (%(oldDisplayName)s).",
"%(senderName)s sent an invitation to %(targetDisplayName)s to join the room.": "Ο %(senderName)s έστειλε μια πρόσκληση στον %(targetDisplayName)s για να συνδεθεί στο δωμάτιο.",
"%(senderName)s set their display name to %(displayName)s.": "Ο %(senderName)s όρισε το όνομα του σε %(displayName)s.",
"The phone number entered looks invalid": "Ο αριθμός που καταχωρίσατε δεν είναι έγκυρος",
"The email address linked to your account must be entered.": "Πρέπει να εισηχθεί η διεύθυνση ηλ. αλληλογραφίας που είναι συνδεδεμένη με τον λογαριασμό σας.",
"The file '%(fileName)s' exceeds this home server's size limit for uploads": "Το αρχείο '%(fileName)s' υπερβαίνει το όριο μεγέθους του διακομιστή για αποστολές",
"The remote side failed to pick up": "Η απομακρυσμένη πλευρά απέτυχε να συλλέξει",
"This Home Server does not support login using email address.": "Ο διακομιστής δεν υποστηρίζει σύνδεση με διευθύνσεις ηλ. αλληλογραφίας.",
"This invitation was sent to an email address which is not associated with this account:": "Η πρόσκληση στάλθηκε σε μια διεύθυνση που δεν έχει συσχετιστεί με αυτόν τον λογαριασμό:",
"These are experimental features that may break in unexpected ways": "Αυτά είναι πειραματικά χαρακτηριστικά και μπορεί να καταρρεύσουν με απροσδόκητους τρόπους",
"The visibility of existing history will be unchanged": "Η ορατότητα του υπάρχοντος ιστορικού θα παραμείνει αμετάβλητη",
"This is a preview of this room. Room interactions have been disabled": "Αυτή είναι μια προεπισκόπηση του δωματίου. Οι αλληλεπιδράσεις δωματίου έχουν απενεργοποιηθεί",
"This room is not accessible by remote Matrix servers": "Αυτό το δωμάτιο δεν είναι προσβάσιμο από απομακρυσμένους διακομιστές Matrix",
"To reset your password, enter the email address linked to your account": "Για να επαναφέρετε τον κωδικό πρόσβασης σας, πληκτρολογήστε τη διεύθυνση ηλ. αλληλογραφίας όπου είναι συνδεδεμένη με τον λογαριασμό σας",
"%(senderName)s turned on end-to-end encryption (algorithm %(algorithm)s).": "Ο %(senderName)s ενεργοποίησε την από άκρο σε άκρο κρυπτογράφηση (algorithm %(algorithm)s).",
"Undecryptable": "Μη αποκρυπτογραφημένο",
"Uploading %(filename)s and %(count)s others|one": "Γίνεται αποστολή του %(filename)s και %(count)s υπολοίπα",
"Would you like to <acceptText>accept</acceptText> or <declineText>decline</declineText> this invitation?": "Θα θέλατε να <acceptText>δεχθείτε</acceptText> ή να <declineText>απορρίψετε</declineText> την πρόσκληση;",
"You already have existing direct chats with this user:": "Έχετε ήδη απευθείας συνομιλίες με τον χρήστη:",
"You are trying to access %(roomName)s.": "Προσπαθείτε να έχετε πρόσβαση στο %(roomName)s.",
"You have been kicked from %(roomName)s by %(userName)s.": "Έχετε διωχθεί από το δωμάτιο %(roomName)s από τον %(userName)s.",
"You have been logged out of all devices and will no longer receive push notifications. To re-enable notifications, sign in again on each device": "Έχετε αποσυνδεθεί από όλες τις συσκευές και δεν θα λαμβάνετε πλέον ειδοποιήσεις push. Για να ενεργοποιήσετε τις ειδοποιήσεις, συνδεθείτε ξανά σε κάθε συσκευή",
"You have <a>disabled</a> URL previews by default.": "Έχετε <a>απενεργοποιημένη</a> από προεπιλογή την προεπισκόπηση συνδέσμων.",
"You have <a>enabled</a> URL previews by default.": "Έχετε <a>ενεργοποιημένη</a> από προεπιλογή την προεπισκόπηση συνδέσμων.",
"You may wish to login with a different account, or add this email to this account.": "Μπορεί να θέλετε να συνδεθείτε με διαφορετικό λογαριασμό, ή να προσθέσετε αυτή τη διεύθυνση ηλεκτρονικής αλληλογραφίας σε αυτόν τον λογαριασμό.",
"You need to be able to invite users to do that.": "Για να το κάνετε αυτό πρέπει να έχετε τη δυνατότητα να προσκαλέσετε χρήστες.",
"You seem to be uploading files, are you sure you want to quit?": "Φαίνεται ότι αποστέλετε αρχεία, είστε βέβαιοι ότι θέλετε να αποχωρήσετε;",
"You should not yet trust it to secure data": "Δεν πρέπει να το εμπιστεύεστε για να ασφαλίσετε δεδομένα",
"Your home server does not support device management.": "Ο διακομιστής δεν υποστηρίζει διαχείριση συσκευών.",
"Password too short (min %(MIN_PASSWORD_LENGTH)s).": "Ο κωδικός πρόσβασης είναι πολύ μικρός (ελ. %(MIN_PASSWORD_LENGTH)s).",
"User names may only contain letters, numbers, dots, hyphens and underscores.": "Τα ονόματα μπορεί να περιέχουν μόνο γράμματα, αριθμούς, τελείες, πάνω και κάτω παύλα.",
"Share message history with new users": "Διαμοιρασμός ιστορικού μηνυμάτων με τους νέους χρήστες",
"numbullet": "απαρίθμηση",
"You must join the room to see its files": "Πρέπει να συνδεθείτε στο δωμάτιο για να δείτε τα αρχεία του",
"Reject all %(invitedRooms)s invites": "Απόρριψη όλων των προσκλήσεων %(invitedRooms)s",
"Failed to invite the following users to the %(roomName)s room:": "Δεν ήταν δυνατή η πρόσκληση των παρακάτω χρηστών στο δωμάτιο %(roomName)s:",
"Deops user with given id": "Deop χρήστη με το συγκεκριμένο αναγνωριστικό",
"Drop here to tag %(section)s": "Απόθεση εδώ για ορισμό ετικέτας στο %(section)s",
"Join as <voiceText>voice</voiceText> or <videoText>video</videoText>.": "Συμμετάσχετε με <voiceText>φωνή</voiceText> ή <videoText>βίντεο</videoText>.",
"Joins room with given alias": "Συνδέεστε στο δωμάτιο με δοσμένο ψευδώνυμο",
"Show timestamps in 12 hour format (e.g. 2:30pm)": "Εμφάνιση χρονικών σημάνσεων σε 12ωρη μορφή ώρας (π.χ. 2:30 μ.μ.)",
"The signing key you provided matches the signing key you received from %(userId)s's device %(deviceId)s. Device marked as verified.": "Το κλειδί υπογραφής που δώσατε αντιστοιχεί στο κλειδί υπογραφής που λάβατε από τη συσκευή %(userId)s %(deviceId)s. Η συσκευή έχει επισημανθεί ως επιβεβαιωμένη.",
"To link to a room it must have <a>an address</a>.": "Για να συνδεθείτε σε ένα δωμάτιο πρέπει να έχετε <a>μια διεύθυνση</a>.",
"Your email address does not appear to be associated with a Matrix ID on this Homeserver.": "Η διεύθυνση της ηλ. αλληλογραφίας σας δεν φαίνεται να συσχετίζεται με μια ταυτότητα Matrix σε αυτόν τον Διακομιστή Φιλοξενίας.",
"Your password was successfully changed. You will not receive push notifications on other devices until you log back in to them": "Ο κωδικός πρόσβασής σας άλλαξε επιτυχώς. Δεν θα λάβετε ειδοποιήσεις push σε άλλες συσκευές μέχρι να συνδεθείτε ξανά σε αυτές",
"You will not be able to undo this change as you are promoting the user to have the same power level as yourself.": "Δεν θα μπορέσετε να αναιρέσετε αυτήν την αλλαγή καθώς προωθείτε τον χρήστη να έχει το ίδιο επίπεδο δύναμης με τον εαυτό σας.",
"Sent messages will be stored until your connection has returned.": "Τα απεσταλμένα μηνύματα θα αποθηκευτούν μέχρι να αακτηθεί η σύνδεσή σας.",
"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.": "Είστε βέβαιοι ότι θέλετε να καταργήσετε (διαγράψετε) αυτό το συμβάν; Σημειώστε ότι αν διαγράψετε το όνομα δωματίου ή αλλάξετε το θέμα, θα μπορούσε να αναιρέσει την αλλαγή.",
"This allows you to use this app with an existing Matrix account on a different home server.": "Αυτό σας επιτρέπει να χρησιμοποιήσετε την εφαρμογή με έναν υπάρχον λογαριασμό Matrix σε έναν διαφορετικό διακομιστή.",
"You can also set a custom identity server but this will typically prevent interaction with users based on email address.": "Μπορείτε επίσης να ορίσετε έναν προσαρμοσμένο διακομιστή ταυτοποίησης, αλλά αυτό συνήθως θα αποτρέψει την αλληλεπίδραση με τους χρήστες που βασίζονται στην ηλεκτρονική διεύθυνση αλληλογραφίας.",
"This will be your account name on the <span></span> homeserver, or you can pick a <a>different server</a>.": "Αυτό θα είναι το όνομα του λογαριασμού σας στον διακομιστή <span></span>, ή μπορείτε να επιλέξετε <a>διαφορετικό διακομιστή</a>.",
"If you already have a Matrix account you can <a>log in</a> instead.": "Αν έχετε ήδη λογαριασμό Matrix μπορείτε να <a>συνδεθείτε</a>.",
"Failed to load timeline position": "Δεν ήταν δυνατή η φόρτωση της θέσης του χρονολόγιου",
@ -599,9 +455,7 @@
"Changing password will currently reset any end-to-end encryption keys on all devices, making encrypted chat history unreadable, unless you first export your room keys and re-import them afterwards. In future this will be improved.": "Η αλλαγή του κωδικού πρόσβασης θα επαναφέρει τα κλειδιά κρυπτογράφησης από άκρο σε άκρο σε όλες τις συσκευές, καθιστώντας το κρυπτογραφημένο ιστορικό συζητήσεων μη αναγνώσιμο, εκτός και αν εξάγετε πρώτα τα κλειδιά και τα εισαγάγετε ξανά στο δωμάτιο. Στο μέλλον αυτή η διαδικασία θα βελτιωθεί.",
"Claimed Ed25519 fingerprint key": "Απαιτήθηκε κλειδί αποτυπώματος Ed25519",
"Displays action": "Εμφανίζει την ενέργεια",
"Resetting password will currently reset any end-to-end encryption keys on all devices, making encrypted chat history unreadable, unless you first export your room keys and re-import them afterwards. In future this will be improved.": "Η επαναφορά του κωδικού πρόσβασης θα επαναφέρει τα κλειδιά κρυπτογράφησης από άκρο σε άκρο σε όλες τις συσκευές, καθιστώντας το κρυπτογραφημένο ιστορικό συζητήσεων μη αναγνώσιμο, εκτός και αν εξάγετε πρώτα τα κλειδιά και τα εισαγάγετε ξανά στο δωμάτιο. Στο μέλλον αυτή η διαδικασία θα βελτιωθεί.",
"To use it, just wait for autocomplete results to load and tab through them.": "Για να το χρησιμοποιήσετε, απλά περιμένετε μέχρι να φορτωθούν τα αποτέλεσμα αυτόματης συμπλήρωσης. Έπειτα επιλέξτε ένα από αυτά χρησιμοποιώντας τον στηλοθέτη.",
"Unable to ascertain that the address this invite was sent to matches one associated with your account.": "Δεν είναι δυνατό να εξακριβωθεί ότι η διεύθυνση αυτής της πρόσκλησης στάλθηκε σε αντιστοιχία με εκείνη που σχετίζεται με το λογαριασμό σας.",
"Use compact timeline layout": "Χρήση συμπαγούς διάταξης χρονολογίου",
"(could not connect media)": "(αδυναμία σύνδεσης με το πολυμέσο)",
"WARNING: KEY VERIFICATION FAILED! The signing key for %(userId)s and device %(deviceId)s is \"%(fprint)s\" which does not match the provided key \"%(fingerprint)s\". This could mean your communications are being intercepted!": "ΠΡΟΕΙΔΟΠΟΙΗΣΗ: ΑΠΕΤΥΧΕ Η ΕΠΙΒΕΒΑΙΩΣΗ ΤΟΥ ΚΛΕΙΔΙΟΥ! Το κλειδί υπογραφής για τον χρήστη %(userId)s και συσκευή %(deviceId)s είναι \"%(fprint)s\" και δεν ταιριάζει με το δοσμένο κλειδί \"%(fingerprint)s\". Αυτό σημαίνει ότι η επικοινωνία σας μπορεί να έχει υποκλαπεί!",
@ -615,12 +469,8 @@
"You are currently blacklisting unverified devices; to send messages to these devices you must verify them.": "Αυτήν τη στιγμή βάζετε σε μαύρη λίστα μη επιβαιωμένες συσκευές. Για να στείλετε μηνύματα σε αυτές τις συσκευές, πρέπει να τις επιβεβαιώσετε.",
"We recommend you go through the verification process for each device to confirm they belong to their legitimate owner, but you can resend the message without verifying if you prefer.": "Σας συνιστούμε να ολοκληρώσετε τη διαδικασία επαλήθευσης για κάθε συσκευή και να επιβεβαιώσετε ότι ανήκουν στον νόμιμο κάτοχό της, αλλά εάν προτιμάτε μπορείτε να στείλετε ξανά το μήνυμα χωρίς επαλήθευση.",
"You are about to be taken to a third-party site so you can authenticate your account for use with %(integrationsUrl)s. Do you wish to continue?": "Θα μεταφερθείτε σε έναν ιστότοπου τρίτου για να πραγματοποιηθεί η πιστοποίηση του λογαριασμού σας με το %(integrationsUrl)s. Θα θέλατε να συνεχίσετε;",
"Disable Peer-to-Peer for 1:1 calls": "Απενεργοποίηση του ομότιμου (Peer-to-Peer) για κλήσεις έναν προς έναν",
"Do you want to set an email address?": "Θέλετε να ορίσετε μια διεύθυνση ηλεκτρονικής αλληλογραφίας;",
"This will allow you to reset your password and receive notifications.": "Αυτό θα σας επιτρέψει να επαναφέρετε τον κωδικό πρόσβαση σας και θα μπορείτε να λαμβάνετε ειδοποιήσεις.",
"Press <StartChatButton> to start a chat with someone": "Πατήστε <StartChatButton> για να ξεκινήσετε μια συνομιλία",
"You're not in any rooms yet! Press <CreateRoomButton> to make a room or <RoomDirectoryButton> to browse the directory": "Δεν είστε σε κανένα δωμάτιο! Πατήστε <CreateRoomButton> για να δημιουργήσετε ένα δωμάτιο ή <RoomDirectoryButton> για να δείτε το ευρετήριο",
"To return to your account in future you need to set a password": "Για να επιστρέψετε στον λογαριασμό σας μελλοντικα πρέπει να ορίσετε έναν κωδικό πρόσβασης",
"Skip": "Παράβλεψη",
"Start verification": "Έναρξη επιβεβαίωσης",
"Share without verifying": "Κοινή χρήση χωρίς επιβεβαίωση",
@ -628,7 +478,6 @@
"You added a new device '%(displayName)s', which is requesting encryption keys.": "Έχετε προσθέσει μια νέα συσκευή '%(displayName)s', η οποία ζητά κλειδιά κρυπτογράφησης.",
"Your unverified device '%(displayName)s' is requesting encryption keys.": "Η ανεπιβεβαίωτη συσκευή σας '%(displayName)s' ζητά κλειδιά κρυπτογράφησης.",
"Encryption key request": "Αίτημα κλειδιού κρυπτογράφησης",
"Updates": "Ενημερώσεις",
"Check for update": "Έλεγχος για ενημέρωση",
"Fetching third party location failed": "Η λήψη τοποθεσίας απέτυχε",
"A new version of Riot is available.": "Μία νέα έκδοση του Riot είναι διαθέσιμη.",
@ -645,10 +494,7 @@
"Friday": "Παρασκευή",
"Update": "Ενημέρωση",
"Riot does not know how to join a room on this network": "To Riot δεν γνωρίζει πως να συνδεθεί σε δωμάτια που ανήκουν σ' αυτό το δίκτυο",
"Add an email address above to configure email notifications": "Προσθέστε μια διεύθυνση ηλεκτρονικής αλληλογραφίας στο παραπάνω πεδίο, για να έχετε τη δυνατότητα να λαμβάνετε ειδοποιήσεις",
"Expand panel": "Μεγιστοποίηση καρτέλας",
"On": "Ενεργό",
"Filter room names": "Φιλτράρισμα δωματίων",
"Changelog": "Αλλαγές",
"Waiting for response from server": "Αναμονή απάντησης από τον διακομιστή",
"Leave": "Αποχώρηση",
@ -658,12 +504,10 @@
"To return to your account in future you need to <u>set a password</u>": "Για να επιστρέψετε στον λογαριασμό σας μελλοντικα πρέπει να ορίσετε έναν <u>κωδικό πρόσβασης</u>",
"Forget": "Παράλειψη",
"World readable": "Εμφανές σε όλους",
"Hide panel": "Απόκρυψη καρτέλας",
"You cannot delete this image. (%(code)s)": "Δεν μπορείτε να διαγράψετε αυτή την εικόνα. (%(code)s)",
"Cancel Sending": "Ακύρωση αποστολής",
"Warning": "Προειδοποίηση",
"This Room": "Στο δωμάτιο",
"The Home Server may be too old to support third party networks": "Ο διακομιστής μπορεί να είναι αρκετά παλιός για να υποστηρίζει δίκτυα τρίτων",
"Resend": "Αποστολή ξανά",
"Room not found": "Το δωμάτιο δεν βρέθηκε",
"Messages containing my display name": "Μηνύματα που περιέχουν το όνομα μου",
@ -681,14 +525,11 @@
"Members": "Μέλη",
"No update available.": "Δεν υπάρχει διαθέσιμη ενημέρωση.",
"Noisy": "Δυνατά",
"Failed to get protocol list from Home Server": "Δεν ήταν δυνατή η εύρεση των διαθέσιμων πρωτοκόλλων από το διακομιστή",
"Collecting app version information": "Συγκέντρωση πληροφοριών σχετικά με την έκδοση της εφαρμογής",
"Delete the room alias %(alias)s and remove %(name)s from the directory?": "Διαγραφή του ψευδώνυμου %(alias)s και αφαίρεση του %(name)s από το ευρετήριο;",
"This will allow you to return to your account after signing out, and sign in on other devices.": "Αυτό θα σας επιτρέψει να επιστρέψετε στον λογαριασμό σας αφού αποσυνδεθείτε και συνδεθείτε από άλλες συσκευές.",
"Keywords": "Λέξεις κλειδιά",
"Enable notifications for this account": "Ενεργοποίηση ειδοποιήσεων για τον λογαριασμό",
"Directory": "Ευρετήριο",
"Search for a room": "Αναζήτηση δωματίου",
"Messages containing <span>keywords</span>": "Μηνύματα που περιέχουν <span>λέξεις κλειδιά</span>",
"Error saving email notification preferences": "Σφάλμα κατά την αποθήκευση των προτιμήσεων",
"Tuesday": "Τρίτη",
@ -708,10 +549,7 @@
"All messages (noisy)": "Όλα τα μηνύματα (δυνατά)",
"Enable them now": "Ενεργοποίηση",
"Forward Message": "Προώθηση",
"Messages containing my user name": "Μηνύματα που περιέχουν το ψευδώνυμο μου",
"Collecting logs": "Συγκέντρωση πληροφοριών",
"more": "περισσότερα",
"Failed to get public room list": "Δεν ήταν δυνατή η λήψη της λίστας με τα δημόσια δωμάτια",
"(HTTP status %(httpStatus)s)": "(Κατάσταση HTTP %(httpStatus)s)",
"All Rooms": "Όλα τα δωμάτια",
"Wednesday": "Τετάρτη",
@ -742,22 +580,17 @@
"Low Priority": "Χαμηλή προτεραιότητα",
"What's New": "Τι νέο υπάρχει",
"Set Password": "Ορισμός κωδικού πρόσβασης",
"Enable audible notifications in web client": "Ενεργοποίηση ηχητικών ειδοποιήσεων",
"Off": "Ανενεργό",
"#example": "#παράδειγμα",
"Mentions only": "Μόνο αναφορές",
"Failed to remove tag %(tagName)s from room": "Δεν ήταν δυνατή η διαγραφή της ετικέτας %(tagName)s από το δωμάτιο",
"You can now return to your account after signing out, and sign in on other devices.": "Μπορείτε να επιστρέψετε στον λογαριασμό σας αφού αποσυνδεθείτε και συνδεθείτε από άλλες συσκευές.",
"Enable desktop notifications": "Ενεργοποίηση ειδοποιήσεων στην επιφάνεια εργασίας",
"Enable email notifications": "Ενεργοποίηση ειδοποιήσεων μέσω μηνυμάτων ηλ. αλληλογραφίας",
"Login": "Σύνδεση",
"No rooms to show": "Δεν υπάρχουν δωμάτια για εμφάνιση",
"Download this file": "Λήψη αρχείου",
"Failed to change settings": "Δεν ήταν δυνατή η αλλαγή των ρυθμίσεων",
"View Source": "Προβολή κώδικα",
"Unable to fetch notification target list": "Δεν ήταν δυνατή η εύρεση στόχων για τις ειδοποιήσεις",
"Quote": "Παράθεση",
"Collapse panel": "Ελαχιστοποίηση καρτέλας",
"With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "Με τον τρέχον περιηγητή, η εμφάνιση και η αίσθηση της εφαρμογής ενδέχεται να είναι εντελώς εσφαλμένη και ορισμένες ή όλες οι λειτουργίες ενδέχεται να μην λειτουργούν. Εάν θέλετε να το δοκιμάσετε ούτως ή άλλως μπορείτε να συνεχίσετε, αλλά είστε μόνοι σας σε ό, τι αφορά τα προβλήματα που μπορεί να αντιμετωπίσετε!",
"Checking for an update...": "Γίνεται έλεγχος για ενημέρωση...",
"There are advanced notifications which are not shown here": "Υπάρχουν προχωρημένες ειδοποιήσεις οι οποίες δεν εμφανίζονται εδώ",
@ -771,7 +604,6 @@
"Your device resolution": "Η ανάλυση της συσκευής σας",
"The information being sent to us to help make Riot.im better includes:": "Οι πληροφορίες που στέλνονται σε εμάς με σκοπό την βελτίωση του Riot.im περιλαμβάνουν:",
"Call Failed": "Η κλήση απέτυχε",
"Whether or not you're logged in (we don't record your user name)": "Εάν είστε συνδεδεμένος/η ή όχι (δεν καταγράφουμε το όνομα χρήστη σας)",
"e.g. %(exampleValue)s": "π.χ. %(exampleValue)s",
"Review Devices": "Ανασκόπηση συσκευών",
"Call Anyway": "Πραγματοποίηση Κλήσης όπως και να 'χει",
@ -784,7 +616,6 @@
"Who would you like to add to this community?": "Ποιον/α θα θέλατε να προσθέσετε σε αυτή την κοινότητα;",
"Warning: any person you add to a community will be publicly visible to anyone who knows the community ID": "Προσοχή: κάθε άτομο που προσθέτετε στην κοινότητα θε είναι δημοσίως ορατό σε οποιονδήποτε γνωρίζει το αναγνωριστικό της κοινότητας",
"Invite new community members": "Προσκαλέστε νέα μέλη στην κοινότητα",
"Name or matrix ID": "Όνομα ή αναγνωριστικό του matrix",
"Invite to Community": "Προσκαλέστε στην κοινότητα",
"Which rooms would you like to add to this community?": "Ποια δωμάτια θα θέλατε να προσθέσετε σε αυτή την κοινότητα;",
"Add rooms to the community": "Προσθήκη δωματίων στην κοινότητα",
@ -798,7 +629,6 @@
"Room name or alias": "Όνομα η ψευδώνυμο δωματίου",
"Restricted": "Περιορισμένο/η",
"Unable to create widget.": "Αδυναμία δημιουργίας γραφικού στοιχείου.",
"Reload widget": "Επαναφόρτωση γραφικού στοιχείου",
"You are not in this room.": "Δεν είστε μέλος αυτού του δωματίου.",
"You do not have permission to do that in this room.": "Δεν έχετε την άδεια να το κάνετε αυτό σε αυτό το δωμάτιο.",
"You are now ignoring %(userId)s": "Τώρα αγνοείτε τον/την %(userId)s",
@ -808,16 +638,10 @@
"%(widgetName)s widget modified by %(senderName)s": "Έγινε αλλαγή στο widget %(widgetName)s από τον/την %(senderName)s",
"%(widgetName)s widget added by %(senderName)s": "Προστέθηκε το widget %(widgetName)s από τον/την %(senderName)s",
"%(widgetName)s widget removed by %(senderName)s": "Το widget %(widgetName)s αφαιρέθηκε από τον/την %(senderName)s",
"%(names)s and %(count)s others are typing|other": "Ο/Η %(names)s και άλλοι/ες %(count)s πληκτρολογούν",
"%(names)s and %(count)s others are typing|one": "Ο/Η %(names)s και άλλος ένας πληκτρολογούν",
"Message Pinning": "Καρφίτσωμα Μηνυμάτων",
"Hide avatar changes": "Απόκρυψη αλλαγών εικονιδίων χρηστών",
"Hide display name changes": "Απόκρυψη αλλαγών εμφανιζόμενων ονομάτων",
"Hide avatars in user and room mentions": "Απόκρυψη εικονιδίων στις αναφορές χρηστών και δωματίων",
"Enable URL previews for this room (only affects you)": "Ενεργοποίηση προεπισκόπισης URL για αυτό το δωμάτιο (επηρεάζει μόνο εσάς)",
"Delete %(count)s devices|other": "Διαγραφή %(count)s συσκευών",
"Delete %(count)s devices|one": "Διαγραφή συσκευής",
"Select devices": "Επιλογή συσκευών",
"Cannot add any more widgets": "Δεν είναι δυνατή η προσθήκη άλλων γραφικών στοιχείων",
"The maximum permitted number of widgets have already been added to this room.": "Ο μέγιστος επιτρεπτός αριθμός γραφικών στοιχείων έχει ήδη προστεθεί σε αυτό το δωμάτιο.",
"Add a widget": "Προσθέστε ένα γραφικό στοιχείο",
@ -849,7 +673,6 @@
"Seen by %(displayName)s (%(userName)s) at %(dateTime)s": "Διαβάστηκε από τον/την %(displayName)s (%(userName)s) στις %(dateTime)s",
"Room Notification": "Ειδοποίηση Δωματίου",
"Notify the whole room": "Ειδοποιήστε όλο το δωμάτιο",
"Sets the room topic": "Ορίζει το θέμα του δωματίου",
"Add Email Address": "Προσθήκη Διεύθυνσης Ηλ. Ταχυδρομείου",
"Add Phone Number": "Προσθήκη Τηλεφωνικού Αριθμού",
"Whether or not you're logged in (we don't record your username)": "Χωρίς να έχει σημασία εάν είστε συνδεδεμένοι (δεν καταγράφουμε το όνομα χρήστη σας)",
@ -898,7 +721,6 @@
"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 />.": "Οι αναβαθμίσεις δωματίων συνήθως επηρεάζουν μόνο την επεξεργασία του δωματίου <i>από την πλευρά του διακομιστή</i>. Εάν έχετε προβλήματα με το πρόγραμμα-πελάτη Riot, παρακαλώ αρχειοθετήστε ένα πρόβλημα μέσω <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>Προσοχή</b>: Αναβαθμίζοντας ένα δωμάτιο <i>δεν θα μεταφέρει αυτόματα τα μέλη του δωματίου στη νέα έκδοση του δωματίου.</i> Θα αναρτήσουμε ένα σύνδεσμο προς το νέο δωμάτιο στη παλιά έκδοση του δωματίου - τα μέλη του δωματίου θα πρέπει να πατήσουν στον σύνδεσμο για να μπουν στο νέο δωμάτιο.",
"Please confirm that you'd like to go forward with upgrading this room from <oldVersion /> to <newVersion />.": "Παρακαλώ επιβεβαιώστε ότι θα θέλατε να προχωρήσετε με την αναβάθμιση του δωματίου από <oldVersion /> σε <newVersion />.",
"Upgrade": "Αναβάθμιση",
"Changes your display nickname in the current room only": "Αλλάζει το εμφανιζόμενο ψευδώνυμο μόνο στο παρόν δωμάτιο",
"Changes the avatar of the current room": "Αλλάζει το άβαταρ αυτού του δωματίου",
"Changes your avatar in this current room only": "Αλλάζει το άβαταρ σας μόνο στο παρόν δωμάτιο",

View file

@ -154,13 +154,8 @@
"To use it, just wait for autocomplete results to load and tab through them.": "To use it, just wait for autocomplete results to load and tab through them.",
"Upgrades a room to a new version": "Upgrades a room to a new version",
"You do not have the required permissions to use this command.": "You do not have the required permissions to use this command.",
"Room upgrade confirmation": "Room upgrade confirmation",
"Upgrading a room can be destructive and isn't always necessary.": "Upgrading a room can be destructive and isn't always necessary.",
"Room upgrades are usually recommended when a room version is considered <i>unstable</i>. Unstable room versions might have bugs, missing features, or security vulnerabilities.": "Room upgrades are usually recommended when a room version is considered <i>unstable</i>. Unstable room versions might have bugs, missing features, or security vulnerabilities.",
"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 />.": "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 />.",
"<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>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.",
"Please confirm that you'd like to go forward with upgrading this room from <oldVersion /> to <newVersion />.": "Please confirm that you'd like to go forward with upgrading this room from <oldVersion /> to <newVersion />.",
"Upgrade": "Upgrade",
"Error upgrading room": "Error upgrading room",
"Double check that your server supports the room version chosen and try again.": "Double check that your server supports the room version chosen and try again.",
"Changes your display nickname": "Changes your display nickname",
"Changes your display nickname in the current room only": "Changes your display nickname in the current room only",
"Changes the avatar of the current room": "Changes the avatar of the current room",
@ -730,6 +725,7 @@
"Camera": "Camera",
"Voice & Video": "Voice & Video",
"This room is not accessible by remote Matrix servers": "This room is not accessible by remote Matrix servers",
"<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>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.",
"Upgrade this room to the recommended room version": "Upgrade this room to the recommended room version",
"this room": "this room",
"View older messages in %(roomName)s.": "View older messages in %(roomName)s.",
@ -848,9 +844,9 @@
"If your other devices do not have the key for this message you will not be able to decrypt them.": "If your other devices do not have the key for this message you will not be able to decrypt them.",
"Key request sent.": "Key request sent.",
"<requestLink>Re-request encryption keys</requestLink> from your other devices.": "<requestLink>Re-request encryption keys</requestLink> from your other devices.",
"Undecryptable": "Undecryptable",
"This message cannot be decrypted": "This message cannot be decrypted",
"Encrypted by an unverified device": "Encrypted by an unverified device",
"Unencrypted message": "Unencrypted message",
"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",
"device id: ": "device id: ",
@ -994,6 +990,8 @@
"Use an identity server in Settings to receive invites directly in Riot.": "Use an identity server in Settings to receive invites directly in Riot.",
"Share this email in Settings to receive invites directly in Riot.": "Share this email in Settings to receive invites directly in Riot.",
"Do you want to chat with %(user)s?": "Do you want to chat with %(user)s?",
"<userName/> wants to chat": "<userName/> wants to chat",
"Start chatting": "Start chatting",
"Do you want to join %(roomName)s?": "Do you want to join %(roomName)s?",
"<userName/> invited you": "<userName/> invited you",
"Reject": "Reject",
@ -1009,6 +1007,7 @@
"Securely back up your keys to avoid losing them. <a>Learn more.</a>": "Securely back up your keys to avoid losing them. <a>Learn more.</a>",
"Not now": "Not now",
"Don't ask me again": "Don't ask me again",
"Options": "Options",
"%(count)s unread messages including mentions.|other": "%(count)s unread messages including mentions.",
"%(count)s unread messages including mentions.|one": "1 unread mention.",
"%(count)s unread messages.|other": "%(count)s unread messages.",
@ -1085,7 +1084,6 @@
"%(count)s verified Sign-In's|one": "1 verified Sign-In",
"Direct message": "Direct message",
"Unverify user": "Unverify user",
"Options": "Options",
"Remove from community": "Remove from community",
"Disinvite this user from community?": "Disinvite this user from community?",
"Remove this user from community?": "Remove this user from community?",
@ -1131,6 +1129,8 @@
"You sent a verification request": "You sent a verification request",
"Error decrypting video": "Error decrypting video",
"Show all": "Show all",
"Reactions": "Reactions",
"<reactors/><reactedWith> reacted with %(content)s</reactedWith>": "<reactors/><reactedWith> reacted with %(content)s</reactedWith>",
"<reactors/><reactedWith>reacted with %(shortName)s</reactedWith>": "<reactors/><reactedWith>reacted with %(shortName)s</reactedWith>",
"%(senderDisplayName)s changed the avatar for %(roomName)s": "%(senderDisplayName)s changed the avatar for %(roomName)s",
"%(senderDisplayName)s removed the room avatar.": "%(senderDisplayName)s removed the room avatar.",
@ -1445,6 +1445,13 @@
"Update any local room aliases to point to the new room": "Update any local room aliases to point to the new room",
"Stop users from speaking in the old version of the room, and post a message advising users to move to the new room": "Stop users from speaking in the old version of the room, and post a message advising users to move to the new room",
"Put a link back to the old room at the start of the new room so people can see old messages": "Put a link back to the old room at the start of the new room so people can see old messages",
"Automatically invite users": "Automatically invite users",
"Upgrade private room": "Upgrade private room",
"Upgrade public room": "Upgrade public room",
"Upgrading a room is an advanced action and is usually recommended when a room is unstable due to bugs, missing features or security vulnerabilities.": "Upgrading a room is an advanced action and is usually recommended when a room is unstable due to bugs, missing features or security vulnerabilities.",
"This usually only affects how the room is processed on the server. If you're having problems with your Riot, please <a>report a bug</a>.": "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>.",
"You'll upgrade this room from <oldVersion /> to <newVersion />.": "You'll upgrade this room from <oldVersion /> to <newVersion />.",
"Upgrade": "Upgrade",
"Sign out and remove encryption keys?": "Sign out and remove encryption keys?",
"Clear Storage and Sign Out": "Clear Storage and Sign Out",
"Send Logs": "Send Logs",
@ -1570,6 +1577,7 @@
"Report Content": "Report Content",
"Failed to set Direct Message status of room": "Failed to set Direct Message status of room",
"Failed to forget room %(errCode)s": "Failed to forget room %(errCode)s",
"Notification settings": "Notification settings",
"All messages (noisy)": "All messages (noisy)",
"All messages": "All messages",
"Mentions only": "Mentions only",
@ -1589,6 +1597,7 @@
"Take picture": "Take picture",
"Remove for everyone": "Remove for everyone",
"Remove for me": "Remove for me",
"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.",
"Custom Server Options": "Custom Server Options",

View file

@ -2,17 +2,12 @@
"Add a widget": "Add a widget",
"AM": "AM",
"PM": "PM",
"A text message has been sent to +%(msisdn)s. Please enter the verification code it contains": "A text message has been sent to +%(msisdn)s. Please enter the verification code it contains",
"%(targetName)s accepted an invitation.": "%(targetName)s accepted an invitation.",
"%(targetName)s accepted the invitation for %(displayName)s.": "%(targetName)s accepted the invitation for %(displayName)s.",
"Account": "Account",
"Access Token:": "Access Token:",
"Add a topic": "Add a topic",
"Add email address": "Add email address",
"Add phone number": "Add phone number",
"Admin": "Admin",
"VoIP": "VoIP",
"Missing Media Permissions, click here to request.": "Missing Media Permissions, click here to request.",
"No Microphones detected": "No Microphones detected",
"No Webcams detected": "No Webcams detected",
"No media permissions": "No media permissions",
@ -22,13 +17,11 @@
"Camera": "Camera",
"Advanced": "Advanced",
"Algorithm": "Algorithm",
"Hide removed messages": "Hide removed messages",
"Always show message timestamps": "Always show message timestamps",
"Authentication": "Authentication",
"%(items)s and %(lastItem)s": "%(items)s and %(lastItem)s",
"and %(count)s others...|other": "and %(count)s others...",
"and %(count)s others...|one": "and one other...",
"%(names)s and %(lastPerson)s are typing": "%(names)s and %(lastPerson)s are typing",
"A new password must be entered.": "A new password must be entered.",
"%(senderName)s answered the call.": "%(senderName)s answered the call.",
"An error has occurred.": "An error has occurred.",
@ -38,7 +31,6 @@
"Are you sure?": "Are you sure?",
"Are you sure you want to leave the room '%(roomName)s'?": "Are you sure you want to leave the room '%(roomName)s'?",
"Are you sure you want to reject the invitation?": "Are you sure you want to reject the invitation?",
"Are you sure you want to upload the following files?": "Are you sure you want to upload the following files?",
"Attachment": "Attachment",
"Autoplay GIFs and videos": "Autoplay GIFs and videos",
"%(senderName)s banned %(targetName)s.": "%(senderName)s banned %(targetName)s.",
@ -46,22 +38,17 @@
"Banned users": "Banned users",
"Bans user with given id": "Bans user with given id",
"Blacklisted": "Blacklisted",
"Bulk Options": "Bulk Options",
"Call Timeout": "Call Timeout",
"Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. Either use HTTPS or <a>enable unsafe scripts</a>.": "Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. Either use HTTPS or <a>enable unsafe scripts</a>.",
"Can't load user settings": "Can't load user settings",
"Change Password": "Change Password",
"%(senderName)s changed their profile picture.": "%(senderName)s changed their profile picture.",
"%(senderName)s changed the power level of %(powerLevelDiffText)s.": "%(senderName)s changed the power level of %(powerLevelDiffText)s.",
"%(senderDisplayName)s changed the room name to %(roomName)s.": "%(senderDisplayName)s changed the room name to %(roomName)s.",
"%(senderDisplayName)s removed the room name.": "%(senderDisplayName)s removed the room name.",
"%(senderDisplayName)s changed the topic to \"%(topic)s\".": "%(senderDisplayName)s changed the topic to \"%(topic)s\".",
"Changes to who can read history will only apply to future messages in this room": "Changes to who can read history will only apply to future messages in this room",
"Changes your display nickname": "Changes your display nickname",
"Changing password will currently reset any end-to-end encryption keys on all devices, making encrypted chat history unreadable, unless you first export your room keys and re-import them afterwards. In future this will be improved.": "Changing password will currently reset any end-to-end encryption keys on all devices, making encrypted chat history unreadable, unless you first export your room keys and re-import them afterwards. In future this will be improved.",
"Claimed Ed25519 fingerprint key": "Claimed Ed25519 fingerprint key",
"Clear Cache and Reload": "Clear Cache and Reload",
"Clear Cache": "Clear Cache",
"Click here to fix": "Click here to fix",
"Click to mute audio": "Click to mute audio",
"Click to mute video": "Click to mute video",
@ -70,15 +57,9 @@
"Click to unmute audio": "Click to unmute audio",
"Command error": "Command error",
"Commands": "Commands",
"Conference call failed.": "Conference call failed.",
"Conference calling is in development and may not be reliable.": "Conference calling is in development and may not be reliable.",
"Conference calls are not supported in encrypted rooms": "Conference calls are not supported in encrypted rooms",
"Conference calls are not supported in this client": "Conference calls are not supported in this client",
"Confirm password": "Confirm password",
"Confirm your new password": "Confirm your new password",
"Continue": "Continue",
"Could not connect to the integration server": "Could not connect to the integration server",
"Create an account": "Create an account",
"Create Room": "Create Room",
"Cryptography": "Cryptography",
"Current password": "Current password",
@ -86,10 +67,8 @@
"Custom level": "Custom level",
"/ddg is not a command": "/ddg is not a command",
"Deactivate Account": "Deactivate Account",
"Deactivate my account": "Deactivate my account",
"Decrypt %(text)s": "Decrypt %(text)s",
"Decryption error": "Decryption error",
"Delete": "Delete",
"Deops user with given id": "Deops user with given id",
"Default": "Default",
"Delete widget": "Delete widget",
@ -99,28 +78,17 @@
"device id: ": "device id: ",
"Device key:": "Device key:",
"Devices": "Devices",
"Devices will not yet be able to decrypt history from before they joined the room": "Devices will not yet be able to decrypt history from before they joined the room",
"Direct chats": "Direct chats",
"Disinvite": "Disinvite",
"Display name": "Display name",
"Displays action": "Displays action",
"Don't send typing notifications": "Don't send typing notifications",
"Download %(text)s": "Download %(text)s",
"Drop here to tag %(section)s": "Drop here to tag %(section)s",
"Ed25519 fingerprint": "Ed25519 fingerprint",
"Edit": "Edit",
"Email": "Email",
"Email address": "Email address",
"Email address (optional)": "Email address (optional)",
"Email, name or matrix ID": "Email, name or matrix ID",
"Emoji": "Emoji",
"Enable encryption": "Enable encryption",
"Encrypted messages will not be visible on clients that do not yet implement encryption": "Encrypted messages will not be visible on clients that do not yet implement encryption",
"Encrypted room": "Encrypted room",
"%(senderName)s ended the call.": "%(senderName)s ended the call.",
"End-to-end encryption information": "End-to-end encryption information",
"End-to-end encryption is in beta and may not be reliable": "End-to-end encryption is in beta and may not be reliable",
"Enter Code": "Enter Code",
"Error": "Error",
"Error decrypting attachment": "Error decrypting attachment",
"Event information": "Event information",
@ -140,15 +108,11 @@
"Failed to mute user": "Failed to mute user",
"Failed to reject invite": "Failed to reject invite",
"Failed to reject invitation": "Failed to reject invitation",
"Failed to save settings": "Failed to save settings",
"Failed to send email": "Failed to send email",
"Failed to send request.": "Failed to send request.",
"Failed to set avatar.": "Failed to set avatar.",
"Failed to set display name": "Failed to set display name",
"Failed to set up conference call": "Failed to set up conference call",
"Failed to toggle moderator status": "Failed to toggle moderator status",
"Failed to unban": "Failed to unban",
"Failed to upload file": "Failed to upload file",
"Failed to verify email address: make sure you clicked the link in the email": "Failed to verify email address: make sure you clicked the link in the email",
"Failure to create room": "Failure to create room",
"Favourite": "Favorite",
@ -156,14 +120,10 @@
"Fill screen": "Fill screen",
"Filter room members": "Filter room members",
"Forget room": "Forget room",
"Forgot your password?": "Forgot your password?",
"For security, this session has been signed out. Please sign in again.": "For security, this session has been signed out. Please sign in again.",
"For security, logging out will delete any end-to-end encryption keys from this browser. If you want to be able to decrypt your conversation history from future Riot sessions, please export your room keys for safe-keeping.": "For security, logging out will delete any end-to-end encryption keys from this browser. If you want to be able to decrypt your conversation history from future Riot sessions, please export your room keys for safe-keeping.",
"%(userId)s from %(fromPowerLevel)s to %(toPowerLevel)s": "%(userId)s from %(fromPowerLevel)s to %(toPowerLevel)s",
"Guest access is disabled on this Home Server.": "Guest access is disabled on this Home Server.",
"Guests cannot join this room even if explicitly invited.": "Guests cannot join this room even if explicitly invited.",
"Hangup": "Hangup",
"Hide read receipts": "Hide read receipts",
"Hide Text Formatting Toolbar": "Hide Text Formatting Toolbar",
"Historical": "Historical",
"Homeserver is": "Homeserver is",
@ -173,9 +133,7 @@
"Import E2E room keys": "Import E2E room keys",
"Incorrect username and/or password.": "Incorrect username and/or password.",
"Incorrect verification code": "Incorrect verification code",
"Interface Language": "Interface Language",
"Invalid alias format": "Invalid alias format",
"Invalid address format": "Invalid address format",
"Invalid Email Address": "Invalid Email Address",
"Invalid file%(extra)s": "Invalid file%(extra)s",
"%(senderName)s invited %(targetName)s.": "%(senderName)s invited %(targetName)s.",
@ -183,9 +141,7 @@
"Invited": "Invited",
"Invites": "Invites",
"Invites user with given id to current room": "Invites user with given id to current room",
"'%(alias)s' is not a valid format for an address": "'%(alias)s' is not a valid format for an address",
"'%(alias)s' is not a valid format for an alias": "'%(alias)s' is not a valid format for an alias",
"%(displayName)s is typing": "%(displayName)s is typing",
"Sign in with": "Sign in with",
"Join Room": "Join Room",
"%(targetName)s joined the room.": "%(targetName)s joined the room.",
@ -195,7 +151,6 @@
"Kick": "Kick",
"Kicks user with given id": "Kicks user with given id",
"Labs": "Labs",
"Ignored Users": "Ignored Users",
"Ignore": "Ignore",
"Unignore": "Unignore",
"User Options": "User Options",
@ -209,7 +164,6 @@
"%(targetName)s left the room.": "%(targetName)s left the room.",
"Publish this room to the public in %(domain)s's room directory?": "Publish this room to the public in %(domain)s's room directory?",
"Local addresses for this room:": "Local addresses for this room:",
"Logged in as:": "Logged in as:",
"Logout": "Logout",
"Low priority": "Low priority",
"%(senderName)s made future room history visible to all room members, from the point they are invited.": "%(senderName)s made future room history visible to all room members, from the point they are invited.",
@ -221,23 +175,18 @@
"Markdown is disabled": "Markdown is disabled",
"Markdown is enabled": "Markdown is enabled",
"matrix-react-sdk version:": "matrix-react-sdk version:",
"Disable Emoji suggestions while typing": "Disable Emoji suggestions while typing",
"Message not sent due to unknown devices being present": "Message not sent due to unknown devices being present",
"Missing room_id in request": "Missing room_id in request",
"Missing user_id in request": "Missing user_id in request",
"Mobile phone number": "Mobile phone number",
"Mobile phone number (optional)": "Mobile phone number (optional)",
"Moderator": "Moderator",
"Mute": "Mute",
"Name": "Name",
"Never send encrypted messages to unverified devices from this device": "Never send encrypted messages to unverified devices from this device",
"Never send encrypted messages to unverified devices in this room from this device": "Never send encrypted messages to unverified devices in this room from this device",
"New address (e.g. #foo:%(localDomain)s)": "New address (e.g. #foo:%(localDomain)s)",
"New password": "New password",
"New passwords don't match": "New passwords don't match",
"New passwords must match each other.": "New passwords must match each other.",
"none": "none",
"not set": "not set",
"not specified": "not specified",
"Notifications": "Notifications",
"(not supported by this browser)": "(not supported by this browser)",
@ -249,37 +198,28 @@
"No users have specific privileges in this room": "No users have specific privileges in this room",
"OK": "OK",
"olm version:": "olm version:",
"Once encryption is enabled for a room it cannot be turned off again (for now)": "Once encryption is enabled for a room it cannot be turned off again (for now)",
"Only people who have been invited": "Only people who have been invited",
"Operation failed": "Operation failed",
"Password": "Password",
"Password:": "Password:",
"Passwords can't be empty": "Passwords can't be empty",
"People": "People",
"Permissions": "Permissions",
"Phone": "Phone",
"%(senderName)s placed a %(callType)s call.": "%(senderName)s placed a %(callType)s call.",
"Please check your email and click on the link it contains. Once this is done, click continue.": "Please check your email and click on the link it contains. Once this is done, click continue.",
"Power level must be positive integer.": "Power level must be positive integer.",
"Prepends ¯\\_(ツ)_/¯ to a plain-text message": "Prepends ¯\\_(ツ)_/¯ to a plain-text message",
"Privacy warning": "Privacy warning",
"Privileged Users": "Privileged Users",
"Profile": "Profile",
"Reason": "Reason",
"Revoke Moderator": "Revoke Moderator",
"Revoke widget access": "Revoke widget access",
"Refer a friend to Riot:": "Refer a friend to Riot:",
"Register": "Register",
"%(targetName)s rejected the invitation.": "%(targetName)s rejected the invitation.",
"Reject invitation": "Reject invitation",
"Remote addresses for this room:": "Remote addresses for this room:",
"Remove Contact Information?": "Remove Contact Information?",
"%(senderName)s removed their display name (%(oldDisplayName)s).": "%(senderName)s removed their display name (%(oldDisplayName)s).",
"%(senderName)s removed their profile picture.": "%(senderName)s removed their profile picture.",
"Remove": "Remove",
"Remove %(threePid)s?": "Remove %(threePid)s?",
"%(senderName)s requested a VoIP conference.": "%(senderName)s requested a VoIP conference.",
"Resetting password will currently reset any end-to-end encryption keys on all devices, making encrypted chat history unreadable, unless you first export your room keys and re-import them afterwards. In future this will be improved.": "Resetting password will currently reset any end-to-end encryption keys on all devices, making encrypted chat history unreadable, unless you first export your room keys and re-import them afterwards. In future this will be improved.",
"Results from DuckDuckGo": "Results from DuckDuckGo",
"Return to login screen": "Return to login screen",
"Riot does not have permission to send you notifications - please check your browser settings": "Riot does not have permission to send you notifications - please check your browser settings",
@ -287,11 +227,9 @@
"riot-web version:": "riot-web version:",
"Room %(roomId)s not visible": "Room %(roomId)s not visible",
"Room Colour": "Room Color",
"Room name (optional)": "Room name (optional)",
"Rooms": "Rooms",
"Save": "Save",
"Scroll to bottom of page": "Scroll to bottom of page",
"Scroll to unread messages": "Scroll to unread messages",
"Search": "Search",
"Search failed": "Search failed",
"Searches DuckDuckGo for results": "Searches DuckDuckGo for results",
@ -301,16 +239,13 @@
"%(senderDisplayName)s sent an image.": "%(senderDisplayName)s sent an image.",
"%(senderName)s sent an invitation to %(targetDisplayName)s to join the room.": "%(senderName)s sent an invitation to %(targetDisplayName)s to join the room.",
"Server error": "Server error",
"Server may be unavailable or overloaded": "Server may be unavailable or overloaded",
"Server may be unavailable, overloaded, or search timed out :(": "Server may be unavailable, overloaded, or search timed out :(",
"Server may be unavailable, overloaded, or the file too big": "Server may be unavailable, overloaded, or the file too big",
"Server may be unavailable, overloaded, or you hit a bug.": "Server may be unavailable, overloaded, or you hit a bug.",
"Server unavailable, overloaded, or something else went wrong.": "Server unavailable, overloaded, or something else went wrong.",
"Session ID": "Session ID",
"%(senderName)s set a profile picture.": "%(senderName)s set a profile picture.",
"%(senderName)s set their display name to %(displayName)s.": "%(senderName)s set their display name to %(displayName)s.",
"Settings": "Settings",
"Show panel": "Show panel",
"Show timestamps in 12 hour format (e.g. 2:30pm)": "Show timestamps in 12 hour format (e.g. 2:30pm)",
"Signed Out": "Signed Out",
"Sign in": "Sign in",
@ -321,32 +256,19 @@
"Start Chat": "Start Chat",
"Submit": "Submit",
"Success": "Success",
"Tagged as: ": "Tagged as: ",
"The default role for new room members is": "The default role for new room members is",
"The main address for this room is": "The main address for this room is",
"The signing key you provided matches the signing key you received from %(userId)s's device %(deviceId)s. Device marked as verified.": "The signing key you provided matches the signing key you received from %(userId)s's device %(deviceId)s. Device marked as verified.",
"This email address is already in use": "This email address is already in use",
"This email address was not found": "This email address was not found",
"The email address linked to your account must be entered.": "The email address linked to your account must be entered.",
"The file '%(fileName)s' exceeds this home server's size limit for uploads": "The file '%(fileName)s' exceeds this home server's size limit for uploads",
"The file '%(fileName)s' failed to upload": "The file '%(fileName)s' failed to upload",
"The remote side failed to pick up": "The remote side failed to pick up",
"This Home Server does not support login using email address.": "This Home Server does not support login using email address.",
"This room has no local addresses": "This room has no local addresses",
"This room is not recognised.": "This room is not recognized.",
"These are experimental features that may break in unexpected ways": "These are experimental features that may break in unexpected ways",
"The visibility of existing history will be unchanged": "The visibility of existing history will be unchanged",
"This doesn't appear to be a valid email address": "This doesn't appear to be a valid email address",
"This is a preview of this room. Room interactions have been disabled": "This is a preview of this room. Room interactions have been disabled",
"This phone number is already in use": "This phone number is already in use",
"This room is not accessible by remote Matrix servers": "This room is not accessible by remote Matrix servers",
"This room's internal ID is": "This room's internal ID is",
"To reset your password, enter the email address linked to your account": "To reset your password, enter the email address linked to your account",
"To use it, just wait for autocomplete results to load and tab through them.": "To use it, just wait for autocomplete results to load and tab through them.",
"Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.",
"Tried to load a specific point in this room's timeline, but was unable to find it.": "Tried to load a specific point in this room's timeline, but was unable to find it.",
"Turn Markdown off": "Turn Markdown off",
"Turn Markdown on": "Turn Markdown on",
"%(senderName)s turned on end-to-end encryption (algorithm %(algorithm)s).": "%(senderName)s turned on end-to-end encryption (algorithm %(algorithm)s).",
"Unable to add email address": "Unable to add email address",
"Unable to remove contact information": "Unable to remove contact information",
@ -356,7 +278,6 @@
"Unable to capture screen": "Unable to capture screen",
"Unable to enable Notifications": "Unable to enable Notifications",
"Unable to load device list": "Unable to load device list",
"Unencrypted room": "Unencrypted room",
"unencrypted": "unencrypted",
"unknown device": "unknown device",
"unknown error code": "unknown error code",
@ -367,14 +288,10 @@
"Unrecognised room alias:": "Unrecognized room alias:",
"Upload avatar": "Upload avatar",
"Upload Failed": "Upload Failed",
"Upload Files": "Upload Files",
"Upload file": "Upload file",
"Usage": "Usage",
"Use compact timeline layout": "Use compact timeline layout",
"Use with caution": "Use with caution",
"User ID": "User ID",
"User Interface": "User Interface",
"User name": "User name",
"Users": "Users",
"Verification Pending": "Verification Pending",
"Verification": "Verification",
@ -388,34 +305,26 @@
"(could not connect media)": "(could not connect media)",
"(no answer)": "(no answer)",
"(unknown failure: %(reason)s)": "(unknown failure: %(reason)s)",
"(warning: cannot be disabled again!)": "(warning: cannot be disabled again!)",
"Warning!": "Warning!",
"WARNING: Device already verified, but keys do NOT MATCH!": "WARNING: Device already verified, but keys do NOT MATCH!",
"WARNING: KEY VERIFICATION FAILED! The signing key for %(userId)s and device %(deviceId)s is \"%(fprint)s\" which does not match the provided key \"%(fingerprint)s\". This could mean your communications are being intercepted!": "WARNING: KEY VERIFICATION FAILED! The signing key for %(userId)s and device %(deviceId)s is \"%(fprint)s\" which does not match the provided key \"%(fingerprint)s\". This could mean your communications are being intercepted!",
"Who can access this room?": "Who can access this room?",
"Who can read history?": "Who can read history?",
"Who would you like to add to this room?": "Who would you like to add to this room?",
"Who would you like to communicate with?": "Who would you like to communicate with?",
"%(senderName)s withdrew %(targetName)s's invitation.": "%(senderName)s withdrew %(targetName)s's invitation.",
"You are already in a call.": "You are already in a call.",
"You are trying to access %(roomName)s.": "You are trying to access %(roomName)s.",
"You cannot place a call with yourself.": "You cannot place a call with yourself.",
"You cannot place VoIP calls in this browser.": "You cannot place VoIP calls in this browser.",
"You do not have permission to post to this room": "You do not have permission to post to this room",
"You have been invited to join this room by %(inviterName)s": "You have been invited to join this room by %(inviterName)s",
"You have been logged out of all devices and will no longer receive push notifications. To re-enable notifications, sign in again on each device": "You have been logged out of all devices and will no longer receive push notifications. To re-enable notifications, sign in again on each device",
"You have <a>disabled</a> URL previews by default.": "You have <a>disabled</a> URL previews by default.",
"You have <a>enabled</a> URL previews by default.": "You have <a>enabled</a> URL previews by default.",
"You have no visible notifications": "You have no visible notifications",
"You need to be able to invite users to do that.": "You need to be able to invite users to do that.",
"You need to be logged in.": "You need to be logged in.",
"You need to enter a user name.": "You need to enter a user name.",
"Your email address does not appear to be associated with a Matrix ID on this Homeserver.": "Your email address does not appear to be associated with a Matrix ID on this Homeserver.",
"Your password has been reset": "Your password has been reset",
"Your password was successfully changed. You will not receive push notifications on other devices until you log back in to them": "Your password was successfully changed. You will not receive push notifications on other devices until you log back in to them",
"You seem to be in a call, are you sure you want to quit?": "You seem to be in a call, are you sure you want to quit?",
"You seem to be uploading files, are you sure you want to quit?": "You seem to be uploading files, are you sure you want to quit?",
"You should not yet trust it to secure data": "You should not yet trust it to secure data",
"You will not be able to undo this change as you are promoting the user to have the same power level as yourself.": "You will not be able to undo this change as you are promoting the user to have the same power level as yourself.",
"Sun": "Sun",
"Mon": "Mon",
@ -442,20 +351,8 @@
"Set a display name:": "Set a display name:",
"Upload an avatar:": "Upload an avatar:",
"This server does not support authentication with a phone number.": "This server does not support authentication with a phone number.",
"Missing password.": "Missing password.",
"Passwords don't match.": "Passwords don't match.",
"Password too short (min %(MIN_PASSWORD_LENGTH)s).": "Password too short (min %(MIN_PASSWORD_LENGTH)s).",
"This doesn't look like a valid email address.": "This doesn't look like a valid email address.",
"This doesn't look like a valid phone number.": "This doesn't look like a valid phone number.",
"User names may only contain letters, numbers, dots, hyphens and underscores.": "User names may only contain letters, numbers, dots, hyphens and underscores.",
"An unknown error occurred.": "An unknown error occurred.",
"I already have an account": "I already have an account",
"An error occurred: %(error_string)s": "An error occurred: %(error_string)s",
"Topic": "Topic",
"Make Moderator": "Make Moderator",
"Make this room private": "Make this room private",
"Share message history with new users": "Share message history with new users",
"Encrypt room": "Encrypt room",
"There are no visible files in this room": "There are no visible files in this room",
"Room": "Room",
"Connectivity to the server has been lost.": "Connectivity to the server has been lost.",
@ -464,15 +361,8 @@
"Active call": "Active call",
"bold": "bold",
"italic": "italic",
"strike": "strike",
"underline": "underline",
"code": "code",
"quote": "quote",
"bullet": "bullet",
"numbullet": "numbullet",
"Please select the destination room for this message": "Please select the destination room for this message",
"Start automatically after system login": "Start automatically after system login",
"Desktop specific": "Desktop specific",
"Analytics": "Analytics",
"Banned by %(displayName)s": "Banned by %(displayName)s",
"Options": "Options",
@ -490,9 +380,7 @@
"The export file will be protected with a passphrase. You should enter the passphrase here, to decrypt the file.": "The export file will be protected with a passphrase. You should enter the passphrase here, to decrypt the file.",
"You must join the room to see its files": "You must join the room to see its files",
"Reject all %(invitedRooms)s invites": "Reject all %(invitedRooms)s invites",
"Start new chat": "Start new chat",
"Failed to invite": "Failed to invite",
"Failed to invite user": "Failed to invite user",
"Failed to invite the following users to the %(roomName)s room:": "Failed to invite the following users to the %(roomName)s room:",
"Confirm Removal": "Confirm Removal",
"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.": "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.",
@ -503,7 +391,6 @@
"Device name": "Device name",
"Device key": "Device key",
"If it matches, press the verify button below. If it doesn't, then someone else is intercepting this device and you probably want to press the blacklist button instead.": "If it matches, press the verify button below. If it doesn't, then someone else is intercepting this device and you probably want to press the blacklist button instead.",
"In future this verification process will be more sophisticated.": "In future this verification process will be more sophisticated.",
"Verify device": "Verify device",
"I verify that the keys match": "I verify that the keys match",
"Unable to restore session": "Unable to restore session",
@ -519,38 +406,13 @@
"Verify...": "Verify...",
"ex. @bob:example.com": "ex. @bob:example.com",
"Add User": "Add User",
"To send messages, you must be a": "To send messages, you must be a",
"To invite users into the room, you must be a": "To invite users into the room, you must be a",
"To configure the room, you must be a": "To configure the room, you must be a",
"To kick users, you must be a": "To kick users, you must be a",
"To ban users, you must be a": "To ban users, you must be a",
"To remove other users' messages, you must be a": "To remove other users' messages, you must be a",
"To send events of type <eventType/>, you must be a": "To send events of type <eventType/>, you must be a",
"To change the room's avatar, you must be a": "To change the room's avatar, you must be a",
"To change the room's name, you must be a": "To change the room's name, you must be a",
"To change the room's main address, you must be a": "To change the room's main address, you must be a",
"To change the room's history visibility, you must be a": "To change the room's history visibility, you must be a",
"To change the permissions in the room, you must be a": "To change the permissions in the room, you must be a",
"To change the topic, you must be a": "To change the topic, you must be a",
"To modify widgets in the room, you must be a": "To modify widgets in the room, you must be a",
"This Home Server would like to make sure you are not a robot": "This Home Server would like to make sure you are not a robot",
"Sign in with CAS": "Sign in with CAS",
"Custom Server Options": "Custom Server Options",
"You can use the custom server options to sign into other Matrix servers by specifying a different Home server URL.": "You can use the custom server options to sign into other Matrix servers by specifying a different Home server URL.",
"This allows you to use this app with an existing Matrix account on a different home server.": "This allows you to use this app with an existing Matrix account on a different home server.",
"You can also set a custom identity server but this will typically prevent interaction with users based on email address.": "You can also set a custom identity server but this will typically prevent interaction with users based on email address.",
"Dismiss": "Dismiss",
"Please check your email to continue registration.": "Please check your email to continue registration.",
"Token incorrect": "Token incorrect",
"Please enter the code it contains:": "Please enter the code it contains:",
"powered by Matrix": "powered by Matrix",
"If you don't specify an email address, you won't be able to reset your password. Are you sure?": "If you don't specify an email address, you won't be able to reset your password. Are you sure?",
"You are registering with %(SelectedTeamName)s": "You are registering with %(SelectedTeamName)s",
"Default server": "Default server",
"Custom server": "Custom server",
"Home server URL": "Home server URL",
"Identity server URL": "Identity server URL",
"What does this mean?": "What does this mean?",
"Error decrypting audio": "Error decrypting audio",
"Error decrypting image": "Error decrypting image",
"Error decrypting video": "Error decrypting video",
@ -573,10 +435,7 @@
"Admin Tools": "Admin Tools",
"Alias (optional)": "Alias (optional)",
"Can't connect to homeserver - please check your connectivity, ensure your <a>homeserver's SSL certificate</a> is trusted, and that a browser extension is not blocking requests.": "Can't connect to homeserver - please check your connectivity, ensure your <a>homeserver's SSL certificate</a> is trusted, and that a browser extension is not blocking requests.",
"<a>Click here</a> to join the discussion!": "<a>Click here</a> to join the discussion!",
"Close": "Close",
"%(count)s new messages|one": "%(count)s new message",
"%(count)s new messages|other": "%(count)s new messages",
"Custom": "Custom",
"Decline": "Decline",
"Disable Notifications": "Disable Notifications",
@ -584,12 +443,8 @@
"Create new room": "Create new room",
"Room directory": "Room directory",
"Start chat": "Start chat",
"Create a new chat or reuse an existing one": "Create a new chat or reuse an existing one",
"Drop File Here": "Drop File Here",
"Encrypted by a verified device": "Encrypted by a verified device",
"Encrypted by an unverified device": "Encrypted by an unverified device",
"Encryption is enabled in this room": "Encryption is enabled in this room",
"Encryption is not enabled in this room": "Encryption is not enabled in this room",
"Error: Problem communicating with the given homeserver.": "Error: Problem communicating with the given homeserver.",
"Failed to fetch avatar URL": "Failed to fetch avatar URL",
"Failed to upload profile picture!": "Failed to upload profile picture!",
@ -599,12 +454,9 @@
"Incoming voice call from %(name)s": "Incoming voice call from %(name)s",
"Join as <voiceText>voice</voiceText> or <videoText>video</videoText>.": "Join as <voiceText>voice</voiceText> or <videoText>video</videoText>.",
"Last seen": "Last seen",
"Level:": "Level:",
"No display name": "No display name",
"Private Chat": "Private Chat",
"Public Chat": "Public Chat",
"Reason: %(reasonText)s": "Reason: %(reasonText)s",
"Rejoin": "Rejoin",
"Room contains unknown devices": "Room contains unknown devices",
"%(roomName)s does not exist.": "%(roomName)s does not exist.",
"%(roomName)s is not accessible at this time.": "%(roomName)s is not accessible at this time.",
@ -613,52 +465,31 @@
"Show Text Formatting Toolbar": "Show Text Formatting Toolbar",
"Start authentication": "Start authentication",
"The phone number entered looks invalid": "The phone number entered looks invalid",
"This invitation was sent to an email address which is not associated with this account:": "This invitation was sent to an email address which is not associated with this account:",
"This room": "This room",
"To link to a room it must have <a>an address</a>.": "To link to a room it must have <a>an address</a>.",
"Unable to ascertain that the address this invite was sent to matches one associated with your account.": "Unable to ascertain that the address this invite was sent to matches one associated with your account.",
"Undecryptable": "Undecryptable",
"Unencrypted message": "Unencrypted message",
"unknown caller": "unknown caller",
"Unnamed Room": "Unnamed Room",
"Unverified": "Unverified",
"Uploading %(filename)s and %(count)s others|zero": "Uploading %(filename)s",
"Uploading %(filename)s and %(count)s others|one": "Uploading %(filename)s and %(count)s other",
"Uploading %(filename)s and %(count)s others|other": "Uploading %(filename)s and %(count)s others",
"Upload new:": "Upload new:",
"%(userName)s (power %(powerLevelNumber)s)": "%(userName)s (power %(powerLevelNumber)s)",
"Username invalid: %(errMessage)s": "Username invalid: %(errMessage)s",
"Verified": "Verified",
"Would you like to <acceptText>accept</acceptText> or <declineText>decline</declineText> this invitation?": "Would you like to <acceptText>accept</acceptText> or <declineText>decline</declineText> this invitation?",
"You already have existing direct chats with this user:": "You already have existing direct chats with this user:",
"You have been banned from %(roomName)s by %(userName)s.": "You have been banned from %(roomName)s by %(userName)s.",
"You have been kicked from %(roomName)s by %(userName)s.": "You have been kicked from %(roomName)s by %(userName)s.",
"You may wish to login with a different account, or add this email to this account.": "You may wish to login with a different account, or add this email to this account.",
"You must <a>register</a> to use this functionality": "You must <a>register</a> to use this functionality",
"Your home server does not support device management.": "Your home server does not support device management.",
"(~%(count)s results)|one": "(~%(count)s result)",
"(~%(count)s results)|other": "(~%(count)s results)",
"New Password": "New Password",
"Device Name": "Device Name",
"Start chatting": "Start chatting",
"Start Chatting": "Start Chatting",
"Click on the button below to start chatting!": "Click on the button below to start chatting!",
"Username available": "Username available",
"Username not available": "Username not available",
"Something went wrong!": "Something went wrong!",
"This will be your account name on the <span></span> homeserver, or you can pick a <a>different server</a>.": "This will be your account name on the <span></span> homeserver, or you can pick a <a>different server</a>.",
"If you would like to create a Matrix account you can <a>register</a> now.": "If you would like to create a Matrix account you can <a>register</a> now.",
"If you already have a Matrix account you can <a>log in</a> instead.": "If you already have a Matrix account you can <a>log in</a> instead.",
"You are currently using Riot anonymously as a guest.": "You are currently using Riot anonymously as a guest.",
"Your browser does not support the required cryptography extensions": "Your browser does not support the required cryptography extensions",
"Not a valid Riot keyfile": "Not a valid Riot keyfile",
"Authentication check failed: incorrect password?": "Authentication check failed: incorrect password?",
"Disable Peer-to-Peer for 1:1 calls": "Disable Peer-to-Peer for 1:1 calls",
"Do you want to set an email address?": "Do you want to set an email address?",
"This will allow you to reset your password and receive notifications.": "This will allow you to reset your password and receive notifications.",
"Press <StartChatButton> to start a chat with someone": "Press <StartChatButton> to start a chat with someone",
"You're not in any rooms yet! Press <CreateRoomButton> to make a room or <RoomDirectoryButton> to browse the directory": "You're not in any rooms yet! Press <CreateRoomButton> to make a room or <RoomDirectoryButton> to browse the directory",
"To return to your account in future you need to set a password": "To return to your account in future you need to set a password",
"Skip": "Skip",
"Start verification": "Start verification",
"Share without verifying": "Share without verifying",
@ -666,26 +497,17 @@
"You added a new device '%(displayName)s', which is requesting encryption keys.": "You added a new device '%(displayName)s', which is requesting encryption keys.",
"Your unverified device '%(displayName)s' is requesting encryption keys.": "Your unverified device '%(displayName)s' is requesting encryption keys.",
"Encryption key request": "Encryption key request",
"Updates": "Updates",
"Check for update": "Check for update",
"Allow": "Allow",
"Cannot add any more widgets": "Cannot add any more widgets",
"Changes colour scheme of current room": "Changes color scheme of current room",
"Define the power level of a user": "Define the power level of a user",
"Do you want to load widget from URL:": "Do you want to load widget from URL:",
"Enable automatic language detection for syntax highlighting": "Enable automatic language detection for syntax highlighting",
"Hide join/leave messages (invites/kicks/bans unaffected)": "Hide join/leave messages (invites/kicks/bans unaffected)",
"Integrations Error": "Integrations Error",
"NOTE: Apps are not end-to-end encrypted": "NOTE: Apps are not end-to-end encrypted",
"Sets the room topic": "Sets the room topic",
"Sets the room name": "Sets the room name",
"The maximum permitted number of widgets have already been added to this room.": "The maximum permitted number of widgets have already been added to this room.",
"To get started, please pick a username!": "To get started, please pick a username!",
"Unable to create widget.": "Unable to create widget.",
"Unbans user with given id": "Unbans user with given id",
"You are not in this room.": "You are not in this room.",
"You do not have permission to do that in this room.": "You do not have permission to do that in this room.",
"Autocomplete Delay (ms):": "Autocomplete Delay (ms):",
"Loading device info...": "Loading device info...",
"Message removed by %(userId)s": "Message removed by %(userId)s",
"Example": "Example",
@ -695,15 +517,12 @@
"Featured Users:": "Featured Users:",
"Automatically replace plain text Emoji": "Automatically replace plain text Emoji",
"Failed to upload image": "Failed to upload image",
"Hide avatars in user and room mentions": "Hide avatars in user and room mentions",
"%(widgetName)s widget added by %(senderName)s": "%(widgetName)s widget added by %(senderName)s",
"%(widgetName)s widget removed by %(senderName)s": "%(widgetName)s widget removed by %(senderName)s",
"Robot check is currently unavailable on desktop - please use a <a>web browser</a>": "Robot check is currently unavailable on desktop - please use a <a>web browser</a>",
"Verifies a user, device, and pubkey tuple": "Verifies a user, device, and pubkey tuple",
"%(senderName)s changed the pinned messages for the room.": "%(senderName)s changed the pinned messages for the room.",
"Fetching third party location failed": "Fetching third party location failed",
"A new version of Riot is available.": "A new version of Riot is available.",
"Couldn't load home page": "Couldn't load home page",
"All notifications are currently disabled for all targets.": "All notifications are currently disabled for all targets.",
"Uploading report": "Uploading report",
"Sunday": "Sunday",
@ -712,15 +531,11 @@
"Notification targets": "Notification targets",
"Failed to set direct chat tag": "Failed to set direct chat tag",
"Today": "Today",
"Failed to get protocol list from Home Server": "Failed to get protocol list from Home Server",
"You are not receiving desktop notifications": "You are not receiving desktop notifications",
"Friday": "Friday",
"Update": "Update",
"What's New": "What's New",
"Add an email address above to configure email notifications": "Add an email address above to configure email notifications",
"Expand panel": "Expand panel",
"On": "On",
"Filter room names": "Filter room names",
"Changelog": "Changelog",
"Waiting for response from server": "Waiting for response from server",
"Leave": "Leave",
@ -729,13 +544,10 @@
"To return to your account in future you need to <u>set a password</u>": "To return to your account in future you need to <u>set a password</u>",
"Forget": "Forget",
"World readable": "World readable",
"#example": "#example",
"Hide panel": "Hide panel",
"You cannot delete this image. (%(code)s)": "You cannot delete this image. (%(code)s)",
"Cancel Sending": "Cancel Sending",
"Warning": "Warning",
"This Room": "This Room",
"The Home Server may be too old to support third party networks": "The Home Server may be too old to support third party networks",
"Noisy": "Noisy",
"Room not found": "Room not found",
"Messages containing my display name": "Messages containing my display name",
@ -760,8 +572,6 @@
"Keywords": "Keywords",
"Unpin Message": "Unpin Message",
"Enable notifications for this account": "Enable notifications for this account",
"Directory": "Directory",
"Failed to get public room list": "Failed to get public room list",
"Messages containing <span>keywords</span>": "Messages containing <span>keywords</span>",
"Error saving email notification preferences": "Error saving email notification preferences",
"Tuesday": "Tuesday",
@ -769,7 +579,6 @@
"Search…": "Search…",
"Remove %(name)s from the directory?": "Remove %(name)s from the directory?",
"Riot uses many advanced browser features, some of which are not available or experimental in your current browser.": "Riot uses many advanced browser features, some of which are not available or experimental in your current browser.",
"Enable desktop notifications": "Enable desktop notifications",
"Unnamed room": "Unnamed room",
"Remember, you can always set an email address in user settings if you change your mind.": "Remember, you can always set an email address in user settings if you change your mind.",
"All messages (noisy)": "All messages (noisy)",
@ -782,10 +591,7 @@
"Monday": "Monday",
"Remove from Directory": "Remove from Directory",
"Enable them now": "Enable them now",
"Messages containing my user name": "Messages containing my user name",
"Collecting logs": "Collecting logs",
"more": "more",
"Search for a room": "Search for a room",
"(HTTP status %(httpStatus)s)": "(HTTP status %(httpStatus)s)",
"All Rooms": "All Rooms",
"Wednesday": "Wednesday",
@ -818,26 +624,22 @@
"Low Priority": "Low Priority",
"Unable to fetch notification target list": "Unable to fetch notification target list",
"Set Password": "Set Password",
"Enable audible notifications in web client": "Enable audible notifications in web client",
"Off": "Off",
"Riot does not know how to join a room on this network": "Riot does not know how to join a room on this network",
"Mentions only": "Mentions only",
"Failed to remove tag %(tagName)s from room": "Failed to remove tag %(tagName)s from room",
"You can now return to your account after signing out, and sign in on other devices.": "You can now return to your account after signing out, and sign in on other devices.",
"Enable email notifications": "Enable email notifications",
"Login": "Login",
"No rooms to show": "No rooms to show",
"Download this file": "Download this file",
"Pin Message": "Pin Message",
"Failed to change settings": "Failed to change settings",
"View Source": "View Source",
"Collapse panel": "Collapse panel",
"With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!",
"Checking for an update...": "Checking for an update...",
"There are advanced notifications which are not shown here": "There are advanced notifications which are not shown here",
"The platform you're on": "The platform you're on",
"The version of Riot.im": "The version of Riot.im",
"Whether or not you're logged in (we don't record your user name)": "Whether or not you're logged in (we don't record your user name)",
"Your language of choice": "Your language of choice",
"Which officially provided instance you are using, if any": "Which officially provided instance you are using, if any",
"Whether or not you're using the Richtext mode of the Rich Text Editor": "Whether or not you're using the Richtext mode of the Rich Text Editor",
@ -857,7 +659,6 @@
"Answer Anyway": "Answer Anyway",
"Call": "Call",
"Answer": "Answer",
"A conference call could not be started because the intgrations server is not available": "A conference call could not be started because the integrations server is not available",
"Call in Progress": "Call in Progress",
"A call is currently being placed!": "A call is currently being placed!",
"A call is already in progress!": "A call is already in progress!",
@ -867,7 +668,6 @@
"Who would you like to add to this community?": "Who would you like to add to this community?",
"Warning: any person you add to a community will be publicly visible to anyone who knows the community ID": "Warning: any person you add to a community will be publicly visible to anyone who knows the community ID",
"Invite new community members": "Invite new community members",
"Name or matrix ID": "Name or matrix ID",
"Invite to Community": "Invite to Community",
"Which rooms would you like to add to this community?": "Which rooms would you like to add to this community?",
"Show these rooms to non-members on the community page and room list?": "Show these rooms to non-members on the community page and room list?",
@ -910,7 +710,6 @@
"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 />.": "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 />.",
"<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>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.",
"Please confirm that you'd like to go forward with upgrading this room from <oldVersion /> to <newVersion />.": "Please confirm that you'd like to go forward with upgrading this room from <oldVersion /> to <newVersion />.",
"Upgrade": "Upgrade",
"Changes your display nickname in the current room only": "Changes your display nickname in the current room only",
"Changes your avatar in this current room only": "Changes your avatar in this current room only",
"Gets or sets the room topic": "Gets or sets the room topic",

View file

@ -7,7 +7,6 @@
"Unable to capture screen": "Ne eblas registri ekranon",
"You cannot place a call with yourself.": "Vi ne povas voki vin mem.",
"Warning!": "Averto!",
"Sign in with CAS": "Saluti per CAS",
"Sign in with": "Saluti per",
"Sign in": "Saluti",
"For security, this session has been signed out. Please sign in again.": "Pro sekurecaj kialoj, la seanco finiĝis. Bonvolu resaluti.",
@ -38,19 +37,11 @@
"%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s %(time)s": "%(weekDayName)s, %(day)s %(monthName)s %(fullYear)s %(time)s",
"Who would you like to add to this community?": "Kiun vi volas aldoni al tiu ĉi komunumo?",
"Invite new community members": "Invitu novajn komunumanojn",
"Name or matrix ID": "Nomo aŭ Matrix-identigilo",
"Invite to Community": "Inviti al komunumo",
"Existing Call": "Jama voko",
"You are already in a call.": "Vi jam partoprenas vokon.",
"VoIP is unsupported": "VoIP ne estas subtenata",
"You cannot place VoIP calls in this browser.": "VoIP-vokoj ne fareblas en tiu ĉi foliumilo.",
"Conference calls are not supported in this client": "Grupaj vokoj ne fareblas en tiu ĉi kliento",
"Conference calls are not supported in encrypted rooms": "Grupaj vokoj ne fareblas en ĉifritaj ĉambroj",
"Conference calling is in development and may not be reliable.": "Grupaj vokoj ankoraŭ evoluas kaj povas malbone funkcii.",
"Failed to set up conference call": "Komenco de grupa voko malsukcesis",
"Conference call failed.": "Grupa voko malsukcesis.",
"The file '%(fileName)s' failed to upload": "Alŝuto de la dosiero '%(fileName)s' malsukcesis",
"The file '%(fileName)s' exceeds this home server's size limit for uploads": "La dosiero «%(fileName)s» estas tro granda por la hejma servilo",
"Warning: any person you add to a community will be publicly visible to anyone who knows the community ID": "Averto: ajna persono aldonita al komunumo estos publike videbla al iu ajn, kiu konas la identigilon de tiu komunumo",
"Which rooms would you like to add to this community?": "Kiujn ĉambrojn vi volas aldoni al ĉi tiu komunumo?",
"Show these rooms to non-members on the community page and room list?": "Montri tiujn ĉambrojn al malanoj en la komunuma paĝo kaj ĉambrolisto?",
@ -72,12 +63,9 @@
"Admin": "Administranto",
"Start a chat": "Komenci babilon",
"Who would you like to communicate with?": "Kun kiu vi volas komuniki?",
"Email, name or matrix ID": "Retpoŝtadreso, nomo, aŭ Matrix-identigilo",
"Start Chat": "Komenci babilon",
"Invite new room members": "Inviti novajn ĉambranojn",
"Who would you like to add to this room?": "Kiun vi ŝatus aldoni al tiu ĉi ĉambro?",
"Send Invites": "Sendi invitojn",
"Failed to invite user": "Malsukcesis inviti uzanton",
"Operation failed": "Ago malsukcesis",
"Failed to invite": "Invito malsukcesis",
"Failed to invite the following users to the %(roomName)s room:": "Malsukcesis inviti la jenajn uzantojn al la ĉambro %(roomName)s:",
@ -137,7 +125,6 @@
"(no answer)": "(sen respondo)",
"(unknown failure: %(reason)s)": "(nekonata eraro: %(reason)s)",
"%(senderName)s ended the call.": "%(senderName)s finis la vokon.",
"%(senderName)s placed a %(callType)s call.": "%(senderName)s faris vokon de speco: %(callType)s.",
"%(senderName)s sent an invitation to %(targetDisplayName)s to join the room.": "%(senderName)s sendis ĉambran inviton al %(targetDisplayName)s.",
"%(senderName)s made future room history visible to all room members, from the point they are invited.": "%(senderName)s videbligis estontan historion de la ĉambro al ĉiuj ĉambranoj, ekde la tempo de invito.",
"%(senderName)s made future room history visible to all room members, from the point they joined.": "%(senderName)s videbligis estontan historion de la ĉambro al ĉiuj ĉambranoj, ekde la tempo de aliĝo.",
@ -151,10 +138,6 @@
"%(widgetName)s widget modified by %(senderName)s": "Fenestraĵon %(widgetName)s ŝanĝis %(senderName)s",
"%(widgetName)s widget added by %(senderName)s": "Fenestraĵon %(widgetName)s aldonis %(senderName)s",
"%(widgetName)s widget removed by %(senderName)s": "Fenestraĵon %(widgetName)s forigis %(senderName)s",
"%(displayName)s is typing": "%(displayName)s tajpas",
"%(names)s and %(count)s others are typing|other": "%(names)s kaj %(count)s aliaj tajpas",
"%(names)s and %(count)s others are typing|one": "%(names)s kaj unu alia tajpas",
"%(names)s and %(lastPerson)s are typing": "%(names)s kaj %(lastPerson)s tajpas",
"Failure to create room": "Malsukcesis krei ĉambron",
"Server may be unavailable, overloaded, or you hit a bug.": "Servilo povas esti neatingebla, troŝarĝita, aŭ vi renkontis cimon.",
"Unnamed Room": "Sennoma Ĉambro",
@ -163,13 +146,7 @@
"Authentication check failed: incorrect password?": "Aŭtentiga kontrolo malsukcesis: ĉu pro malĝusta pasvorto?",
"Failed to join room": "Malsukcesis aliĝi al ĉambro",
"Message Pinning": "Fikso de mesaĝoj",
"Disable Emoji suggestions while typing": "Malŝalti mienetajn sugestojn dum tajpado",
"Use compact timeline layout": "Uzi densan okazordan aranĝon",
"Hide removed messages": "Kaŝi forigitajn mesaĝojn",
"Hide join/leave messages (invites/kicks/bans unaffected)": "Kaŝi envenajn/forlasajn mesaĝojn (sed ne invitajn/forpelajn/forbarajn)",
"Hide avatar changes": "Kaŝi profilbildajn ŝanĝojn",
"Hide display name changes": "Kaŝi ŝanĝojn de vidigaj nomoj",
"Hide read receipts": "Kaŝi legokonfrimojn",
"Show timestamps in 12 hour format (e.g. 2:30pm)": "Montri tempindikojn en 12-hora formo (ekz. 2:30 post.)",
"Always show message timestamps": "Ĉiam montri mesaĝajn tempindikojn",
"Autoplay GIFs and videos": "Memfare ludi GIF-bildojn kaj filmojn",
@ -183,12 +160,8 @@
"Send anyway": "Tamen sendi",
"Send": "Sendi",
"Enable automatic language detection for syntax highlighting": "Ŝalti memagan rekonon de lingvo por sintaksa markado",
"Hide avatars in user and room mentions": "Kaŝi profilbildojn en mencioj de uzantoj kaj babilejoj",
"Disable big emoji in chat": "Malŝalti grandajn mienetojn en babilo",
"Don't send typing notifications": "Ne elsendi sciigojn pri tajpado",
"Automatically replace plain text Emoji": "Memfare anstataŭigi tekstajn mienetojn",
"Mirror local video feed": "Speguli lokan filmon",
"Disable Peer-to-Peer for 1:1 calls": "Malŝalti samtavolajn duopajn vokojn",
"Never send encrypted messages to unverified devices from this device": "Neniam sendi neĉifritajn mesaĝojn al nekontrolitaj aparatoj de tiu ĉi aparato",
"Never send encrypted messages to unverified devices in this room from this device": "Neniam sendi ĉifritajn mesaĝojn al nekontrolitaj aparatoj en tiu ĉi ĉambro el tiu ĉi aparato",
"Enable inline URL previews by default": "Ŝalti entekstan antaŭrigardon al retadresoj",
@ -203,12 +176,9 @@
"Decline": "Rifuzi",
"Accept": "Akcepti",
"Error": "Eraro",
"A text message has been sent to +%(msisdn)s. Please enter the verification code it contains": "Teksta mesaĝo sendiĝis al +%(msisdn)s. Bonvolu enigi la entenatan kontrolan kodon",
"Incorrect verification code": "Malĝusta kontrola kodo",
"Enter Code": "Enigu kodon",
"Submit": "Sendi",
"Phone": "Telefono",
"Add phone number": "Aldoni telefonan numeron",
"Add": "Aldoni",
"Failed to upload profile picture!": "Malsukcesis alŝuti vian profilbildon!",
"Upload new:": "Alŝuti novan:",
@ -223,15 +193,12 @@
"New Password": "Nova pasvorto",
"Confirm password": "Konfirmi pasvorton",
"Change Password": "Ŝanĝi pasvorton",
"Your home server does not support device management.": "Via hejma servilo ne subtenas administradon de aparatoj.",
"Unable to load device list": "Listo de aparatoj ne legeblas",
"Authentication": "Aŭtentigo",
"Delete %(count)s devices|other": "Forigi %(count)s aparatojn",
"Delete %(count)s devices|one": "Forigi aparaton",
"Device ID": "Aparata identigilo",
"Device Name": "Aparata nomo",
"Last seen": "Laste vidita",
"Select devices": "Elekti aparatojn",
"Failed to set display name": "Malsukcesis agordi vidigan nomon",
"Disable Notifications": "Malŝalti sciigojn",
"Enable Notifications": "Ŝalti sciigojn",
@ -248,13 +215,10 @@
"%(senderName)s uploaded a file": "%(senderName)s alŝutis dosieron",
"Options": "Agordoj",
"Undecryptable": "Nemalĉifrebla",
"Encrypted by a verified device": "Ĉifrita de kontrolita aparato",
"Encrypted by an unverified device": "Ĉifrita de nekontrolita aparato",
"Unencrypted message": "Neĉifrita mesaĝo",
"Please select the destination room for this message": "Bonvolu elekti celan ĉambron por tiu mesaĝo",
"Blacklisted": "Senpova legi ĉifritajn mesaĝojn",
"Verified": "Kontrolita",
"Unverified": "Nekontrolita",
"device id: ": "aparata identigilo: ",
"Disinvite": "Malinviti",
"Kick": "Forpeli",
@ -288,37 +252,24 @@
"Revoke Moderator": "Forigi estrajn rajtojn",
"Make Moderator": "Kunestrigi",
"Admin Tools": "Estriloj",
"Level:": "Nivelo:",
"and %(count)s others...|other": "kaj %(count)s aliaj…",
"and %(count)s others...|one": "kaj unu alia…",
"Invited": "Invititaj",
"Filter room members": "Filtri ĉambranojn",
"%(userName)s (power %(powerLevelNumber)s)": "%(userName)s (potenco je %(powerLevelNumber)s)",
"Attachment": "Aldonaĵo",
"Upload Files": "Alŝuti dosierojn",
"Are you sure you want to upload the following files?": "Ĉu vi certe volas alŝuti la jenajn dosierojn?",
"Encrypted room": "Ĉifrita babilejo",
"Unencrypted room": "Neĉifrita babilejo",
"Hangup": "Fini vokon",
"Voice call": "Voĉvoko",
"Video call": "Vidvoko",
"Upload file": "Alŝuti dosieron",
"Show Text Formatting Toolbar": "Montri tekstaranĝan breton",
"You do not have permission to post to this room": "Mankas al vi permeso afiŝi en tiu ĉambro",
"Turn Markdown on": "Ŝalti Marksubon",
"Turn Markdown off": "Malŝalti Marksubon",
"Hide Text Formatting Toolbar": "Kaŝi tekstaranĝan breton",
"Server error": "Servila eraro",
"Server unavailable, overloaded, or something else went wrong.": "Servilo estas neatingebla, troŝarĝita, aŭ io alia misokazis.",
"Command error": "Komanda eraro",
"bold": "grasa",
"italic": "kursiva",
"strike": "trastrekita",
"underline": "substrekita",
"code": "kodo",
"quote": "citaĵo",
"bullet": "bulo",
"numbullet": "numerita",
"Markdown is disabled": "Marksubo estas malŝaltita",
"Markdown is enabled": "Marksubo estas ŝaltita",
"Unpin Message": "Malfiksi mesaĝon",
@ -343,24 +294,14 @@
"World readable": "Legebla de ĉiuj",
"Guests can join": "Gastoj povas aliĝi",
"No rooms to show": "Neniuj ĉambroj montreblas",
"Failed to set avatar.": "Malsukcesis agordi profilbildon.",
"Save": "Konservi",
"(~%(count)s results)|other": "(~%(count)s rezultoj)",
"(~%(count)s results)|one": "(~%(count)s rezulto)",
"Join Room": "Aliĝi al ĉambro",
"Upload avatar": "Alŝuti profilbildon",
"Remove avatar": "Forigi profilbildon",
"Settings": "Agordoj",
"Forget room": "Forgesi ĉambron",
"Search": "Serĉi",
"Show panel": "Montri panelon",
"Drop here to favourite": "Demetu tien ĉi por ŝati",
"Drop here to tag direct chat": "Demeti tien ĉi por marki rektan babilon",
"Drop here to restore": "Demeti tien ĉi por reigi",
"Drop here to demote": "Demeti tien ĉi por malpligravigi",
"Drop here to tag %(section)s": "Demeti tien ĉi por marki %(section)s",
"Press <StartChatButton> to start a chat with someone": "Premu <StartChatButton> por komenci babilon kun iu",
"You're not in any rooms yet! Press <CreateRoomButton> to make a room or <RoomDirectoryButton> to browse the directory": "Vi ankoraŭ estas en neniuj Babilejoj! Premu <CreateRoomButton> por krei Babilejon aŭ <RoomDirectoryButton> por esplori la Babilejujon",
"Community Invites": "Komunumaj invitoj",
"Invites": "Invitoj",
"Favourites": "Ŝatataj",
@ -368,55 +309,19 @@
"Rooms": "Ĉambroj",
"Low priority": "Malpli gravaj",
"Historical": "Estintaj",
"Unable to ascertain that the address this invite was sent to matches one associated with your account.": "Ne certigeblas, ke la adreso, kien ĉi tiu invito sendiĝis, kongruas kun tiu rilata al via konto.",
"This invitation was sent to an email address which is not associated with this account:": "Ĉi tiu invito sendiĝis al retpoŝtadreso, kiu ne rilatas al ĉi tiu konto:",
"You may wish to login with a different account, or add this email to this account.": "Vi povas saluti per alia konto, aŭ aldoni ĉi tiun retpoŝtadreson al tiu ĉi konto.",
"You have been invited to join this room by %(inviterName)s": "%(inviterName)s vin invitis al ĉi tiu ĉambro",
"Would you like to <acceptText>accept</acceptText> or <declineText>decline</declineText> this invitation?": "Ĉu vi volas <acceptText>akcepti</acceptText> aŭ <declineText>rifuzi</declineText> ĉi tiun inviton?",
"Reason: %(reasonText)s": "Kialo: %(reasonText)s",
"Rejoin": "Realiĝi",
"You have been kicked from %(roomName)s by %(userName)s.": "%(userName)s vin forpelis de %(roomName)s.",
"You have been kicked from this room by %(userName)s.": "%(userName)s vin forpelis de tiu ĉambro.",
"You have been banned from %(roomName)s by %(userName)s.": "%(userName)s vi forbaris de %(roomName)s.",
"You have been banned from this room by %(userName)s.": "%(userName)s vin forbaris de tiu ĉambro.",
"This room": "Ĉi tiu ĉambro",
"%(roomName)s does not exist.": "%(roomName)s ne ekzistas.",
"%(roomName)s is not accessible at this time.": "%(roomName)s ne estas atingebla nun.",
"You are trying to access %(roomName)s.": "Vi provas atingi %(roomName)s.",
"You are trying to access a room.": "Vi provas aliri ĉambron.",
"<a>Click here</a> to join the discussion!": "<a>Klaku ĉi tie</a> por aliĝi al la diskuto!",
"This is a preview of this room. Room interactions have been disabled": "Tio ĉi estas antaŭrigardo al la ĉambro. Ĉambraj interagoj estas malŝaltitaj",
"To change the room's avatar, you must be a": "Por ŝanĝi la ĉambran profilbildon, vi devas esti",
"To change the room's name, you must be a": "Por ŝanĝi la ĉambran nomon, videvas esti",
"To change the room's main address, you must be a": "Por ŝanĝi la ĉambran ĉefadreson, vi devas esti",
"To change the room's history visibility, you must be a": "Por ŝanĝi videblecon de la ĉambra historio, vi devas esti",
"To change the permissions in the room, you must be a": "Por ŝanĝi permesojn en la ĉambro, vi devas esti",
"To change the topic, you must be a": "Por ŝanĝi la temon, vi devas esti",
"To modify widgets in the room, you must be a": "Por ŝanĝi fenestraĵojn en la ĉambro, vi devas esti",
"Failed to unban": "Malsukcesis malforbari",
"Banned by %(displayName)s": "Forbarita de %(displayName)s",
"Privacy warning": "Priprivata averto",
"Changes to who can read history will only apply to future messages in this room": "Ŝanĝoj al videbleco de la historio nur efektiviĝos nur por estontaj mesaĝoj en ĉi tiu ĉambro",
"The visibility of existing history will be unchanged": "Videbleco de la jama historio restos senŝanĝa",
"unknown error code": "nekonata kodo de eraro",
"Failed to forget room %(errCode)s": "Malsukcesis forgesi ĉambron %(errCode)s",
"End-to-end encryption is in beta and may not be reliable": "Ĝiscela ĉifrado estas beta-versia kaj eble ne dependebla",
"You should not yet trust it to secure data": "Ankoraŭ ne fidu ĝin pri sekurigo de datumoj",
"Devices will not yet be able to decrypt history from before they joined the room": "Aparatoj ankoraŭ ne povos malĉifri historion de antaŭ ilia aliĝo",
"Once encryption is enabled for a room it cannot be turned off again (for now)": "Post ĉifrado ŝaltiĝos en ĉambro, ĝi ne malŝalteblos (ankoraŭ)",
"Encrypted messages will not be visible on clients that do not yet implement encryption": "Ĉifritaj mesaĝoj ne videblos en klinteoj, kiuj ankoraŭ ne subtenas ĉifradon",
"Enable encryption": "Ŝalti ĉifradon",
"(warning: cannot be disabled again!)": "(averto: ĝi ne malŝalteblas poste!)",
"Encryption is enabled in this room": "Ĉifrado estas ŝaltita en tiu ĉi ĉambro",
"Encryption is not enabled in this room": "Ĉifrado ne estas ŝaltita en tiu ĉi ĉambro",
"Privileged Users": "Privilegiuloj",
"No users have specific privileges in this room": "Neniuj uzantoj havas specialajn privilegiojn en tiu ĉi ĉambro",
"Banned users": "Forbaritaj uzantoj",
"This room is not accessible by remote Matrix servers": "Ĉi tiu ĉambro ne atingeblas por foraj serviloj de Matrix",
"Leave room": "Eliri ĉambron",
"Favourite": "Ŝatata",
"Tagged as: ": "Etikedita kiel: ",
"To link to a room it must have <a>an address</a>.": "Por esti ligebla, ĉambro devas havi <a>adreson</a>.",
"Guests cannot join this room even if explicitly invited.": "Gastoj ne povas aliĝi ĉi tiun ĉambron eĉ kun malimplica invito.",
"Click here to fix": "Klaku ĉi tie por riparo",
"Who can access this room?": "Kiu povas aliri ĉi tiun ĉambron?",
@ -430,30 +335,15 @@
"Members only (since they were invited)": "Nur ĉambranoj (ekde la invito)",
"Members only (since they joined)": "Nur ĉambranoj (ekde la aliĝo)",
"Permissions": "Permesoj",
"The default role for new room members is": "La implicita rolo de novaj ĉambranoj estas",
"To send messages, you must be a": "Por sendi mesaĝojn, vi devas esti",
"To invite users into the room, you must be a": "Por inviti uzantojn al la ĉambro, vi devas esti",
"To configure the room, you must be a": "Por agordi la ĉambron, vi devas esti",
"To kick users, you must be a": "Por forpeli uzantojn, vi devas esti",
"To ban users, you must be a": "Por forbari uzantojn, vi devas esti",
"To remove other users' messages, you must be a": "Por forigi mesaĝojn de aliaj uzantoj, vi devas esti",
"To send events of type <eventType/>, you must be a": "Por sendi okazojn de tipo <eventType/>, vi devas esti",
"Advanced": "Altnivela",
"This room's internal ID is": "Interna identigaĵo de tiu ĉi ĉambro estas",
"Add a topic": "Aldoni temon",
"Cancel": "Nuligi",
"Scroll to unread messages": "Rulumi al nelegitaj mesaĝoj",
"Jump to first unread message.": "Salti al unua nelegita mesaĝo.",
"Close": "Fermi",
"Invalid alias format": "Malvalida formo de kromnomo",
"'%(alias)s' is not a valid format for an alias": "'%(alias)s' ne estas valida formo de kromnomo",
"Invalid address format": "Malvalida formo de adreso",
"'%(alias)s' is not a valid format for an address": "%(alias)s ne estas valida formo de adreso",
"not specified": "nespecifita",
"not set": "neagordita",
"Remote addresses for this room:": "Foraj adresoj de ĉi tiu ĉambro:",
"Addresses": "Adresoj",
"The main address for this room is": "La ĉefadreso por ĉi tiu babilejo estas",
"Local addresses for this room:": "Lokaj adresoj por ĉi tiu ĉambro:",
"This room has no local addresses": "Ĉi tiu ĉambro ne havas lokajn adresojn",
"New address (e.g. #foo:%(localDomain)s)": "Nova adreso (ekz-e #io:%(localDomain)s)",
@ -490,34 +380,15 @@
"Leave": "Foriri",
"Register": "Registri",
"Add rooms to this community": "Aldoni ĉambrojn al ĉi tiu komunumo",
"Robot check is currently unavailable on desktop - please use a <a>web browser</a>": "Kontrolo kontraŭ robotoj ne disponeblas sur labortablo bonvolu uzi <a>retan foliumilon</a>",
"This Home Server would like to make sure you are not a robot": "Tiu ĉi hejma servilo volas certigi, ke vi ne estas roboto",
"You can use the custom server options to sign into other Matrix servers by specifying a different Home server URL.": "Vi povas uzi proprajn servilajn elektojn por saluti aliajn servilojn de Matrix per alia adreso de hejma servilo.",
"This allows you to use this app with an existing Matrix account on a different home server.": "Tio ĉi permesos al vi uzi ĉi tiun aplikaĵon kun jama konto de Matrix el alia hejma servilo.",
"You can also set a custom identity server but this will typically prevent interaction with users based on email address.": "Vi ankaŭ povas agordi propran identigan servilon, sed tio kutime malebligas interagadon kun uzantkontoj bazitaj sur retpoŝto.",
"To continue, please enter your password.": "Por daŭrigi, bonvolu enigi vian pasvorton.",
"Password:": "Pasvorto:",
"An email has been sent to %(emailAddress)s": "Retletero sendiĝis al %(emailAddress)s",
"Please check your email to continue registration.": "Bonvolu kontroli vian retpoŝton por daŭrigi la registriĝon.",
"Token incorrect": "Malĝusta ĵetono",
"A text message has been sent to %(msisdn)s": "Tekstmesaĝo sendiĝîs al %(msisdn)s",
"Please enter the code it contains:": "Bonvolu enigi la enhavatan kodon:",
"Start authentication": "Komenci aŭtentigon",
"Username on %(hs)s": "Salutnomo je %(hs)s",
"User name": "Salutnomo",
"Mobile phone number": "Telefona numero",
"Forgot your password?": "Ĉu vi forgesis vian pasvorton?",
"%(serverName)s Matrix ID": "%(serverName)s Matrix ID",
"Email address": "Retpoŝtadreso",
"If you don't specify an email address, you won't be able to reset your password. Are you sure?": "Se vi ne enigos retpoŝtadreson, vi ne povos restarigi vian pasvorton. Ĉu vi certas?",
"Email address (optional)": "Retpoŝtadreso (malnepra)",
"You are registering with %(SelectedTeamName)s": "Vi registriĝas kun %(SelectedTeamName)s",
"Mobile phone number (optional)": "Telefona numero (malnepra)",
"Default server": "Implicita servilo",
"Custom server": "Propra servilo",
"Home server URL": "Adreso de hejma servilo",
"Identity server URL": "URL de identiga servilo",
"What does this mean?": "Kion ĝi signifas?",
"Remove from community": "Forigi de komunumo",
"Disinvite this user from community?": "Ĉu malinviti ĉi tiun uzanton de komunumo?",
"Remove this user from community?": "Ĉu forigi ĉi tiun uzanton de komunumo?",
@ -537,19 +408,14 @@
"Something went wrong when trying to get your communities.": "Io misokazis dum legado de viaj komunumoj.",
"You're not currently a member of any communities.": "Vi nuntempe apartenas al neniu komunumo.",
"Unknown Address": "Nekonata adreso",
"NOTE: Apps are not end-to-end encrypted": "RIMARKO: Aplikaĝoj ne estas ĝiscele ĉifritaj",
"Do you want to load widget from URL:": "Ĉu vi volas enlegi fenestraĵon el URL:",
"Allow": "Permesi",
"Delete Widget": "Forigi fenestraĵon",
"Delete widget": "Forigi fenestraĵon",
"Revoke widget access": "Malvalidigi atingon de fenestraĵo",
"Create new room": "Krei novan ĉambron",
"Verify...": "Kontroli…",
"No results": "Neniuj rezultoj",
"Delete": "Forigi",
"Communities": "Komunumoj",
"Home": "Hejmo",
"Integrations Error": "Integra eraro",
"Could not connect to the integration server": "Malsukcesis konektiĝi al la kuniga servilo",
"Manage Integrations": "Administri integrojn",
"%(nameList)s %(transitionList)s": "%(nameList)s %(transitionList)s",
@ -606,7 +472,6 @@
"%(items)s and %(lastItem)s": "%(items)s kaj %(lastItem)s",
"collapse": "maletendi",
"expand": "etendi",
"Custom of %(powerLevel)s": "Propra nivelo %(powerLevel)s",
"Custom level": "Propra nivelo",
"Room directory": "Ĉambra dosierujo",
"Username not available": "Uzantonomo ne disponeblas",
@ -614,8 +479,6 @@
"Username available": "Uzantonomo disponeblas",
"To get started, please pick a username!": "Por komenci, bonvolu elekti uzantonomon!",
"Incorrect username and/or password.": "Malĝusta uzantnomo kaj/aŭ pasvorto.",
"User names may only contain letters, numbers, dots, hyphens and underscores.": "Salutnomoj enhavu nur literojn, numerojn, punktojn, streketojn, kaj substrekojn.",
"You need to enter a user name.": "Vi devas enigi salutnomon.",
"Start chat": "Komenci babilon",
"And %(count)s more...|other": "Kaj %(count)s pliaj…",
"ex. @bob:example.com": "ekz-e @nomo:ekzemplo.net",
@ -625,12 +488,6 @@
"email address": "retpoŝtadreso",
"Try using one of the following valid address types: %(validTypesList)s.": "Provu unu el la sekvaj validaj tipoj de adreso: %(validTypesList)s.",
"You have entered an invalid address.": "Vi enigis malvalidan adreson.",
"Create a new chat or reuse an existing one": "Kreu novan babilon aŭ aliĝu al jama",
"Start new chat": "Komenci novan babilon",
"You already have existing direct chats with this user:": "Vi jam havas rekte babilas kun ĉi tiu uzanto:",
"Start chatting": "Komenci babilon",
"Click on the button below to start chatting!": "Alklaku la butonon sube por komenci babilon!",
"Start Chatting": "Komenci babilon",
"Confirm Removal": "Konfirmi forigon",
"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.": "Ĉu vi certe volas forigi ĉi tiun okazaĵon? Per ŝanĝo de la ĉambra nomo aŭ temo, la ŝanĝo eble malfariĝos.",
"Community IDs may only contain characters a-z, 0-9, or '=_-./'": "Komunuma identigilo povas enhavi nur signojn a-z, 0-9, aŭ '=_-./'",
@ -642,10 +499,6 @@
"example": "ekzemplo",
"Create": "Krei",
"Create Room": "Krei ĉambron",
"Room name (optional)": "Ĉambra nomo (malnepra)",
"Advanced options": "Specialaj agordoj",
"Block users on other matrix homeservers from joining this room": "Forbari uzantojn el aliaj hejmserviloj for de ĉi tiu ĉambro",
"This setting cannot be changed later!": "Tiu ĉi agordo ne ŝanĝeblas poste!",
"Unknown error": "Nekonata eraro",
"Incorrect password": "Malĝusta pasvorto",
"Deactivate Account": "Malaktivigi konton",
@ -653,7 +506,6 @@
"Device name": "Aparata nomo",
"Device key": "Aparata ŝlosilo",
"If it matches, press the verify button below. If it doesn't, then someone else is intercepting this device and you probably want to press the blacklist button instead.": "Se ĝi kongruas, premu la kontrolan butonon sube. Se ne, tiuokaze iu alia interkaptas ĉi tiun aparaton, kaj eble vi premu la malpermesan butonon anstataŭe.",
"In future this verification process will be more sophisticated.": "Ni planas plifaciligi la kontrolan procedon estontece.",
"Verify device": "Kontroli aparaton",
"I verify that the keys match": "Mi kontrolas, ke la ŝlosiloj kongruas",
"An error has occurred.": "Okazis eraro.",
@ -690,10 +542,6 @@
"Custom": "Propra",
"Alias (optional)": "Kromnomo (malnepra)",
"Name": "Nomo",
"Topic": "Temo",
"Make this room private": "Privatigi ĉi tiun ĉambron",
"Share message history with new users": "Kunhavi mesaĝan historion kun novaj uzantoj",
"Encrypt room": "Ĉifri ĉambron",
"You must <a>register</a> to use this functionality": "Vi devas <a>registriĝî</a> por uzi tiun ĉi funkcion",
"You must join the room to see its files": "Vi devas aliĝi al la ĉambro por vidi tie dosierojn",
"There are no visible files in this room": "En ĉi tiu ĉambro estas neniaj videblaj dosieroj",
@ -728,7 +576,6 @@
"Long Description (HTML)": "Longa priskribo (HTML)",
"Description": "Priskribo",
"Community %(groupId)s not found": "Komunumo %(groupId)s ne troviĝis",
"This Home server does not support communities": "Tiu ĉi hejma servilo ne subtenas komunumojn",
"Failed to load %(groupId)s": "Malsukcesis enlegi %(groupId)s",
"Reject invitation": "Rifuzi inviton",
"Are you sure you want to reject the invitation?": "Ĉu vi certe volas rifuzi la inviton?",
@ -748,20 +595,15 @@
"Message not sent due to unknown devices being present": "Mesaĝo ne sendita pro ĉeesto de nekonataj aparatoj",
"Connectivity to the server has been lost.": "Konekto al la servilo perdiĝis.",
"Sent messages will be stored until your connection has returned.": "Senditaj mesaĝoj konserviĝos ĝis via konekto refunkcios.",
"%(count)s new messages|other": "%(count)s novaj mesaĝoj",
"%(count)s new messages|one": "%(count)s nova mesaĝo",
"Active call": "Aktiva voko",
"There's no one else here! Would you like to <inviteText>invite others</inviteText> or <nowarnText>stop warning about the empty room</nowarnText>?": "Neniu alia ĉeestas! Ĉu vi ŝatus <inviteText>inviti aliajn</inviteText> aŭ <nowarnText>ĉesigi avertadon pri la malplena ĉambro</nowarnText>?",
"You seem to be uploading files, are you sure you want to quit?": "Ŝajne vi alŝutas dosierojn nun; ĉu vi tamen volas foriri?",
"You seem to be in a call, are you sure you want to quit?": "Ŝajne vi vokas nun; ĉu vi tamen volas foriri?",
"Failed to upload file": "Malsukcesis alŝuti dosieron",
"Server may be unavailable, overloaded, or the file too big": "Aŭ la servilo estas neatingebla aŭ troŝargita, aŭ la dosiero estas tro granda",
"Search failed": "Serĉo malsukcesis",
"Server may be unavailable, overloaded, or search timed out :(": "Aŭ la servilo estas neatingebla aŭ troŝargita, aŭ la serĉo eltempiĝis :(",
"No more results": "Neniuj pliaj rezultoj",
"Unknown room %(roomId)s": "Nekonata ĉambro %(roomId)s",
"Room": "Ĉambro",
"Failed to save settings": "Malsukcesis konservi agordojn",
"Failed to reject invite": "Malsukcesis rifuzi inviton",
"Fill screen": "Plenigi ekranon",
"Click to unmute video": "Klaku por ŝalti vidon",
@ -776,57 +618,32 @@
"Uploading %(filename)s and %(count)s others|one": "Alŝutanta dosieron %(filename)s kaj %(count)s alian",
"Light theme": "Hela haŭto",
"Dark theme": "Malhela haŭto",
"Status.im theme": "Temo de status.im",
"Can't load user settings": "Agordoj de uzanto ne enlegeblas",
"Server may be unavailable or overloaded": "Servilo eble estas neatingebla aŭ troŝarĝita",
"Sign out": "Adiaŭi",
"For security, logging out will delete any end-to-end encryption keys from this browser. If you want to be able to decrypt your conversation history from future Riot sessions, please export your room keys for safe-keeping.": "Pro sekureco, adiaŭo forigos ĉiujn ĝiscele ĉifrajn ŝlosilojn de tiu ĉi foliumilo. Se vi volas malĉifri vian babilan historion el estontaj seancoj de Riot, bonvolu elporti kaj bone reteni viajn ĉambrojn ŝlosilojn.",
"Success": "Sukceso",
"Your password was successfully changed. You will not receive push notifications on other devices until you log back in to them": "Via pasvorto sukcese ŝanĝiĝis. Vi ne ricevos puŝatentigojn je aliaj aparatoj ĝis tiam, kiam vi resalutos per ili",
"Remove Contact Information?": "Ĉu forigi kontaktajn informojn?",
"Remove %(threePid)s?": "Ĉu forigi %(threePid)s?",
"Unable to remove contact information": "Kontaktaj informoj ne forigeblas",
"Refer a friend to Riot:": "Rekomendi programon Riot al konato:",
"Interface Language": "Fasada lingvo",
"User Interface": "Fasado por uzantoj",
"Autocomplete Delay (ms):": "Prokrasto de aŭtomata finado (ms):",
"<not supported>": "<nesubtenata>",
"Import E2E room keys": "Enporti ĝiscele ĉifrajn ĉambrajn ŝlosilojn",
"Cryptography": "Kriptografio",
"Device ID:": "Aparata identigilo:",
"Device key:": "Aparata ŝlosilo:",
"Ignored Users": "Malatentataj uzantoj",
"Analytics": "Analizo",
"Riot collects anonymous analytics to allow us to improve the application.": "Riot kolektas sennomaj analizajn datumojn por helpi plibonigadon de la programo.",
"Labs": "Eksperimentaj funkcioj",
"These are experimental features that may break in unexpected ways": "Tiu ĉi funkcioj estas eksperimentaj, kaj povas misfunkcii diversmaniere",
"Use with caution": "Uzu atenteme",
"Deactivate my account": "Malaktivigi mian konton",
"Clear Cache": "Vakigi kaŝmemoron",
"Clear Cache and Reload": "Vakigi kaŝmemoron kaj relegi",
"Updates": "Ĝisdatigoj",
"Check for update": "Kontroli ĝisdatigojn",
"Reject all %(invitedRooms)s invites": "Rifuzi ĉiujn %(invitedRooms)s invitojn",
"Bulk Options": "Amasaj agordoj",
"Desktop specific": "Specialaj al labortablo",
"Start automatically after system login": "Memfare ruli post operaciuma saluto",
"No media permissions": "Neniuj permesoj pri aŭdvidaĵoj",
"You may need to manually permit Riot to access your microphone/webcam": "Eble vi devos permane permesi al Riot atingon de viaj mikrofono/kamerao",
"Missing Media Permissions, click here to request.": "Mankas permesoj pri aŭdvidaĵoj; klaku ĉi tie por peti ilin.",
"No Microphones detected": "Neniu mikrofono troviĝis",
"No Webcams detected": "Neniu kamerao troviĝis",
"Default Device": "Implicita aparato",
"Microphone": "Mikrofono",
"Camera": "Kamerao",
"VoIP": "Rettelefonado",
"Email": "Retpoŝto",
"Add email address": "Aldoni retpoŝtadreson",
"Notifications": "Sciigoj",
"Profile": "Profilo",
"Display name": "Vidiga nomo",
"Account": "Konto",
"To return to your account in future you need to set a password": "Por reveni al via konto estontece, vi devas agordi pasvorton",
"Logged in as:": "Salutinta kiel:",
"Access Token:": "Atinga ĵetono:",
"click to reveal": "klaku por malkovri",
"Homeserver is": "Hejmservilo estas",
@ -838,49 +655,29 @@
"The email address linked to your account must be entered.": "Vi devas enigi retpoŝtadreson ligitan al via konto.",
"A new password must be entered.": "Vi devas enigi novan pasvorton.",
"New passwords must match each other.": "Novaj pasvortoj devas kongrui.",
"Resetting password will currently reset any end-to-end encryption keys on all devices, making encrypted chat history unreadable, unless you first export your room keys and re-import them afterwards. In future this will be improved.": "Restarigo de pasvorto nun nuligos ĝiscele ĉifrajn ŝlosilojn sur ĉiuj aparatoj, farante babilan historion nelegebla, krom se vi unue elportos viajn ĉambrajn ŝlosilojn kaj reenportos ilin poste. Estontece tio ĉi plifaciliĝos.",
"An email has been sent to %(emailAddress)s. Once you've followed the link it contains, click below.": "Retletero sendiĝis al %(emailAddress)s. Irinte al la ligilo en tiu mesaĝo, klaku sube.",
"I have verified my email address": "Mi kontrolis mian retpoŝtadreson",
"Your password has been reset": "Via pasvorto restariĝis",
"You have been logged out of all devices and will no longer receive push notifications. To re-enable notifications, sign in again on each device": "Vi aŭtomate adiaŭis ĉiujn aparatojn kaj ne ricevos plu puŝsciigojn. Por reŝalti sciigojn, saluti denove per ĉiu aparato",
"Return to login screen": "Reiri al saluta paĝo",
"To reset your password, enter the email address linked to your account": "Por restarigi vian pasvorton, enigu la retpoŝtadreson ligitan al via konto",
"New password": "Nova pasvorto",
"Confirm your new password": "Konfirmu vian novan pasvorton",
"Send Reset Email": "Sendi restarigan retleteron",
"Create an account": "Krei konton",
"This Home Server does not support login using email address.": "Tiu ĉi hejma servilo ne subtenas saluton per retpoŝtadreso.",
"Please note you are logging into the %(hs)s server, not matrix.org.": "Rimarku ke vi salutas la servilon %(hs)s, ne matrix.org.",
"Guest access is disabled on this Home Server.": "Gasta atingo estas malŝaltita en tiu ĉi hejma servilo.",
"The phone number entered looks invalid": "Tiu ĉi telefona numero ŝajnas malvalida",
"This homeserver doesn't offer any login flows which are supported by this client.": "Tiu ĉi hejmservilo ne proponas salutajn fluojn subtenatajn de tiu ĉi kliento.",
"Error: Problem communicating with the given homeserver.": "Eraro: Estas problemo en komunikado kun la hejmservilo.",
"Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. Either use HTTPS or <a>enable unsafe scripts</a>.": "Hejmservilo ne alkonekteblas per HTTP kun HTTPS URL en via adresbreto. Aŭ uzu HTTPS aŭ <a>ŝaltu malsekurajn skriptojn</a>.",
"Can't connect to homeserver - please check your connectivity, ensure your <a>homeserver's SSL certificate</a> is trusted, and that a browser extension is not blocking requests.": "Ne eblas konekti al hejmservilo bonvolu kontroli vian konekton, certigi ke <a>la SSL-atestilo de via hejmservilo</a> estas fidata, kaj ke neniu foliumila kromprogramo baras petojn.",
"Sign in to get started": "Komencu per saluto",
"Failed to fetch avatar URL": "Malsukcesis venigi adreson de profilbildo",
"Set a display name:": "Agordi vidigan nomon:",
"Upload an avatar:": "Alŝuti profilbildon:",
"This server does not support authentication with a phone number.": "Ĉi tiu servilo ne subtenas aŭtentigon per telefona numero.",
"Missing password.": "Mankas pasvorto.",
"Passwords don't match.": "Pasvortoj ne kongruas.",
"Password too short (min %(MIN_PASSWORD_LENGTH)s).": "Pasvorto estas tro mallonga (malplejlonge %(MIN_PASSWORD_LENGTH)s).",
"This doesn't look like a valid email address.": "Tio ĉi ne ŝajnas esti valida retpoŝtadreso.",
"This doesn't look like a valid phone number.": "Tio ĉi ne ŝajnas esti valida telefona numero.",
"An unknown error occurred.": "Okazis nekonata eraro.",
"I already have an account": "Mi jam havas konton",
"Displays action": "Montras agon",
"Bans user with given id": "Forbaras uzanton kun la donita identigilo",
"Unbans user with given id": "Malforbaras uzanton kun la donita identigilo",
"Define the power level of a user": "Difini la potencan nivelon de uzanto",
"Deops user with given id": "Senestrigas uzanton kun donita identigilo",
"Invites user with given id to current room": "Invitas uzanton per identigilo al la nuna ĉambro",
"Joins room with given alias": "Aliĝas al ĉambro per kromnomo",
"Sets the room topic": "Agordas la babilejan temon",
"Kicks user with given id": "Forpelas uzanton kun la donita identigilo",
"Changes your display nickname": "Ŝanĝas vian vidigan nomon",
"Searches DuckDuckGo for results": "Serĉas rezultojn per DuckDuckGo",
"Changes colour scheme of current room": "Ŝanĝas kolorskemon de la nuna ĉambro",
"Verifies a user, device, and pubkey tuple": "Kontrolas opon de uzanto, aparato, kaj publika ŝlosilo",
"Ignores a user, hiding their messages from you": "Malatentas uzanton, kaŝante ĝiajn mesaĝojn de vi",
"Stops ignoring a user, showing their messages going forward": "Ĉesas malatenti uzanton, montronte ĝiajn pluajn mesaĝojn",
@ -922,7 +719,6 @@
"Unblacklist": "Repermesi legadon de ĉifritaj mesaĝoj",
"none": "neniu",
"The version of Riot.im": "Tiu ĉi versio de Riot.im",
"Whether or not you're logged in (we don't record your user name)": "Ĉu vi salutis aŭ ne (ni ne registras vian salutnomon)",
"Your language of choice": "Via preferata lingvo",
"The information being sent to us to help make Riot.im better includes:": "Informoj sendataj al ni por plibonigi la servon Riot.im inkluzivas:",
"%(oldDisplayName)s changed their display name to %(displayName)s.": "%(oldDisplayName)s ŝanĝis sian vidigan nomon al %(displayName)s.",
@ -940,13 +736,11 @@
"Whether or not you're using the Richtext mode of the Rich Text Editor": "Ĉu vi uzas la riĉtekstan reĝimon de la riĉteksta redaktilo aŭ ne",
"Where this page includes identifiable information, such as a room, user or group ID, that data is removed before being sent to the server.": "Kiam ĉi tiu paĝo enhavas identigeblajn informojn, ekzemple ĉambron, uzantan aŭ grupan identigilon, ili estas formetataj antaŭ ol sendado al la servilo.",
"%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s": "%(weekDayName)s, %(day)s %(monthName)s %(fullYear)s",
"Disable Community Filter Panel": "Malŝalti komunuman filtran breton",
"Failed to add tag %(tagName)s to room": "Malsukcesis aldoni etikedon %(tagName)s al ĉambro",
"Submit debug logs": "Sendi sencimigan protokolon",
"Fetching third party location failed": "Malsukcesis trovi lokon de ekstera liveranto",
"A new version of Riot is available.": "Nova versio de Riot haveblas.",
"I understand the risks and wish to continue": "Mi komprenas la riskojn kaj volas daŭrigi",
"Couldn't load home page": "Malsukcesis enlegi hejmpaĝon",
"Send Account Data": "Sendi kontajn informojn",
"Advanced notification settings": "Specialaj agordoj de sciigoj",
"Uploading report": "Alŝutante raporton",
@ -959,11 +753,7 @@
"Friday": "Vendredo",
"Update": "Ĝisdatigi",
"What's New": "Kio novas",
"Add an email address above to configure email notifications": "Aldonu retadreson supre por agordi retpoŝtajn sciigojn",
"Expand panel": "Etendi panelon",
"On": "Ek",
"%(count)s Members|other": "%(count)s Membroj",
"Filter room names": "Filtri nomojn de ĉambroj",
"Changelog": "Protokolo de ŝanĝoj",
"Waiting for response from server": "Atendante respondon el la servilo",
"Send Custom Event": "Sendi propran okazon",
@ -971,12 +761,9 @@
"delete the alias.": "forigi la kromnomon.",
"To return to your account in future you need to <u>set a password</u>": "Por reveni al via konto estonte, vi devas <u>agordi pasvorton</u>",
"Forget": "Forgesi",
"#example": "#ekzemplo",
"Hide panel": "Kaŝi panelon",
"You cannot delete this image. (%(code)s)": "Vi ne povas forigi tiun ĉi bildon. (%(code)s)",
"Cancel Sending": "Nuligi sendon",
"This Room": "Ĉi tiu ĉambro",
"The Home Server may be too old to support third party networks": "La hejmservilo povas esti tro malnova por subteni retojn de eksteraj liverantoj",
"Noisy": "Brua",
"Room not found": "Ĉambro ne troviĝis",
"Messages containing my display name": "Mesaĝoj enhavantaj mian vidigan nomon",
@ -986,7 +773,6 @@
"Failed to update keywords": "Malsukcesis ĝisdatigi la ŝlosilvortojn",
"remove %(name)s from the directory.": "forigi %(name)s de la ujo.",
"Notifications on the following keywords follow rules which cant be displayed here:": "La sciigoj de la jenaj ŝlosilvortoj sekvas regulojn kiuj ne povas esti montrataj ĉi tie:",
"<safariLink>Safari</safariLink> and <operaLink>Opera</operaLink> work too.": "Ankaŭ <safariLink>Safario</safariLink> kaj <operaLink>Opero</operaLink> funkcias.",
"Please set a password!": "Bonvolu agordi pasvorton!",
"You have successfully set a password!": "Vi sukcese agordis pasvorton!",
"An error occurred whilst saving your email notification preferences.": "Konservo de agordoj pri retpoŝtaj sciigoj eraris.",
@ -997,14 +783,11 @@
"Members": "Anoj",
"No update available.": "Neniuj ĝisdatigoj haveblas.",
"Resend": "Resendi",
"Failed to get protocol list from Home Server": "Malsukcesis akiri liston de protokoloj el la hejmservilo",
"Collecting app version information": "Kolektanta informon pri versio de la aplikaĵo",
"Delete the room alias %(alias)s and remove %(name)s from the directory?": "Ĉu forigi la ĉambran kromnomon %(alias)s kaj forigi %(name)s de la ujo?",
"This will allow you to return to your account after signing out, and sign in on other devices.": "Ĉi tio permesos al vi reveni al via konto post adiaŭo, kaj saluti kun aliaj aparatoj.",
"Enable notifications for this account": "Ŝalti sciigojn por tiu ĉi konto",
"Directory": "Dosierujo",
"Invite to this community": "Inviti al tiu ĉi komunumo",
"Failed to get public room list": "Malsukcesis akiri liston de publikaj ĉambroj",
"Messages containing <span>keywords</span>": "Mesaĝoj enhavantaj <span>ŝlosilovortojn</span>",
"Error saving email notification preferences": "Konservo de preferoj pri retpoŝtaj sciigoj eraris",
"Tuesday": "Mardo",
@ -1025,14 +808,11 @@
"Monday": "Lundo",
"Remove from Directory": "Forigi de ujo",
"Enable them now": "Ŝalti ilin nun",
"Messages containing my user name": "Mesaĝoj enhavantaj mian salutnomon",
"Toolbox": "Ilaro",
"Collecting logs": "Kolektante protokolon",
"more": "pli",
"You must specify an event type!": "Vi devas specifi tipon de okazo!",
"(HTTP status %(httpStatus)s)": "(stato de HTTP %(httpStatus)s)",
"Invite to this room": "Inviti al ĉi tiu ĉambro",
"Please install <chromeLink>Chrome</chromeLink> or <firefoxLink>Firefox</firefoxLink> for the best experience.": "Bonvolu instali <chromeLink>Ĥromon</chromeLink> aŭ <firefoxLink>Fajrovulpon</firefoxLink> por plej bona sperto.",
"Wednesday": "Merkredo",
"You cannot delete this message. (%(code)s)": "Vi ne povas forigi tiun ĉi mesaĝon. (%(code)s)",
"Quote": "Citi",
@ -1051,7 +831,6 @@
"Unable to look up room ID from server": "Ĉambra identigilo ne akireblas de la servilo",
"Couldn't find a matching Matrix room": "Malsukcesis trovi kongruan ĉambron en Matrix",
"All Rooms": "Ĉiuj ĉambroj",
"Search for a room": "Serĉi ĉambron",
"Thursday": "Ĵaŭdo",
"Forward Message": "Plusendi mesaĝon",
"Back": "Reen",
@ -1066,36 +845,29 @@
"Messages in group chats": "Mesaĝoj en grupaj babiloj",
"Yesterday": "Hieraŭ",
"Error encountered (%(errorDetail)s).": "Okazis eraro (%(errorDetail)s).",
"Login": "Saluti",
"Low Priority": "Malalta prioritato",
"Unable to fetch notification target list": "Malsukcesis akiri la liston de celoj por sciigoj",
"Set Password": "Agordi pasvorton",
"Enable audible notifications in web client": "Ŝalti aŭdeblajn sciigojn en la retkliento",
"Off": "For",
"Riot does not know how to join a room on this network": "Riot ne scias aliĝi al ĉambroj en tiu ĉi reto",
"Mentions only": "Nur mencioj",
"Failed to remove tag %(tagName)s from room": "Malsukcesis forigi etikedon %(tagName)s el la ĉambro",
"You can now return to your account after signing out, and sign in on other devices.": "Vi nun rajtas reveni al via konto post adiaŭo, kaj saluti per ĝi kun aliaj aparatoj.",
"Enable desktop notifications": "Ŝalti labortablajn sciigojn",
"Enable email notifications": "Ŝalti retpoŝtajn sciigojn",
"Event Type": "Tipo de okazo",
"Download this file": "Elŝuti ĉi tiun dosieron",
"Pin Message": "Fiksi mesaĝon",
"Thank you!": "Dankon!",
"View Community": "Vidi Komunumon",
"%(count)s Members|one": "%(count)s Membro",
"Developer Tools": "Evoluigiloj",
"View Source": "Vidi fonton",
"Event Content": "Enhavo de okazo",
"Collapse panel": "Maletendi panelon",
"With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "Kun via nuna foliumilo, la aspekto kaj funkciado de la aplikaĵo povas esti tute malĝusta, kaj kelkaj aŭ ĉiu funkcioj eble ne tute funkcios. Se vi tamen volas provi, vi povas daŭrigi, sed vi ricevos nenian subtenon se vi renkontos problemojn!",
"Checking for an update...": "Serĉanta ĝisdatigojn…",
"There are advanced notifications which are not shown here": "Ekzistas specialaj sciigoj, kiuj ne montriĝas ĉi tie",
"Logs sent": "Protokolo sendiĝis",
"GitHub issue link:": "Ligilo al raporto ĉe GitHub:",
"Debug logs contain application usage data including your username, the IDs or aliases of the rooms or groups you have visited and the usernames of other users. They do not contain messages.": "Sencimigaj protokoloj enhavas informojn pri uzo de aplikaĵo, inkluzive vian uzantonomon, la identigilojn aŭ nomojn de la ĉambroj aŭ grupoj kiujn vi vizitis, kaj la uzantonomojn de aliaj uzantoj. Ili ne enhavas mesaĝojn.",
"Failed to send logs: ": "Malsukcesis sendi protokolon: ",
"Notes:": "Rimarkoj:",
"Preparing to send logs": "Pretiganta sendon de protokolo",
"e.g. %(exampleValue)s": "ekz. %(exampleValue)s",
"Every page you use in the app": "Ĉiu paĝo kiun vi uzas en la aplikaĵo",
@ -1108,8 +880,6 @@
"Send analytics data": "Sendi statistikajn datumojn",
"Key request sent.": "Demando de ŝlosilo sendita.",
"<requestLink>Re-request encryption keys</requestLink> from your other devices.": "<requestLink>Redemandi ĉifroŝlosilojn</requestLink> el viaj aliaj aparatoj.",
"Encrypting": "Ĉifranta",
"Encrypted, not sent": "Ĉifrita, ne sendita",
"If your other devices do not have the key for this message you will not be able to decrypt them.": "Se viaj aliaj aparatoj ne havas la ŝlosilon por ĉi tiu mesaĝo, vi ne povos malĉifri ĝin.",
"Permission Required": "Necesas permeso",
"Registration Required": "Necesas registriĝo",
@ -1123,8 +893,6 @@
"%(senderName)s set the main address for this room to %(address)s.": "%(senderName)s agordis la ĉefan adreson por la ĉambro al %(address)s.",
"%(senderName)s removed the main address for this room.": "%(senderName)s forigis la ĉefan adreson de la ĉambro.",
"Please <a>contact your service administrator</a> to continue using the service.": "Bonvolu <a>kontakti administranton de la servo</a> por daŭre uzadi la servon.",
"Pin unread rooms to the top of the room list": "Fiksi nelegitajn ĉambrojn supre de la listo",
"Pin rooms I'm mentioned in to the top of the room list": "Fiksi ĉambrojn kun mencioj de mia nomo supre de la listo",
"A call is currently being placed!": "Alia voko nun dumas!",
"Unable to load! Check your network connectivity and try again.": "Ne eblas ŝargi! Kontrolu vian retan konekton kaj reprovu.",
"Failed to invite users to the room:": "Malsukcesis inviti uzantojn al la ĉambro:",
@ -1161,8 +929,6 @@
"There was an error joining the room": "Aliĝo al la ĉambro eraris",
"Sorry, your homeserver is too old to participate in this room.": "Pardonon, via hejmservilo estas tro malnova por partoprenado en la ĉambro.",
"Please contact your homeserver administrator.": "Bonvolu kontakti la administranton de via hejmservilo.",
"Increase performance by only loading room members on first view": "Plibonigu efikecon per nur unuafoja enlego de ĉambranoj",
"Backup of encryption keys to server": "Savkopio de ĉifroŝlosiloj al servilo",
"Show a reminder to enable Secure Message Recovery in encrypted rooms": "Montri memorigilon por ŝalti Sekuran Ricevon de Mesaĝoj en ĉifrataj ĉambroj",
"Show developer tools": "Montri verkistajn ilojn",
"Messages containing @room": "Mesaĝoj enhavantaj @room",
@ -1175,10 +941,8 @@
"Unable to reply": "Ne eblas respondi",
"<a>In reply to</a> <pill>": "<a>Respondanta al</a> <pill>",
"Share Message": "Diskonigi",
"Search for a room like #example": "Serĉi ĉambron kiel #example",
"<showDevicesText>Show devices</showDevicesText>, <sendAnywayText>send anyway</sendAnywayText> or <cancelText>cancel</cancelText>.": "<showDevicesText>Montri aparatojn</showDevicesText>, <sendAnywayText>tamen sendi</sendAnywayText> aŭ <cancelText>nuligi</cancelText>.",
"Whether or not you're logged in (we don't record your username)": "Ĉu vi salutis aŭ ne (ni ne registras vian uzantonomon)",
"A conference call could not be started because the intgrations server is not available": "Ne eblis komenci grupvokon, ĉar la integriga servilo ne disponeblas",
"You do not have permission to start a conference call in this room": "Vi ne havas permeson komenci grupvokon en ĉi tiu ĉambro",
"The file '%(fileName)s' exceeds this homeserver's size limit for uploads": "La dosiero '%(fileName)s' superas la grandecan limon de ĉi tiu hejmservilo",
"Prepends ¯\\_(ツ)_/¯ to a plain-text message": "Antaŭmetas ¯\\_(ツ)_/¯ al platteksta mesaĝo",
@ -1271,7 +1035,6 @@
"Key backup": "Sekurkopio de ŝlosilo",
"Security & Privacy": "Sekureco & Privateco",
"Voice & Video": "Voĉo kaj vido",
"Upgrade room to version %(ver)s": "Ĝisdatigi ĉambron al versio %(ver)s",
"Room information": "Ĉambraj informoj",
"Internal room ID:": "Ena ĉambra identigilo:",
"Room version": "Ĉambra versio",
@ -1306,7 +1069,6 @@
"Seen by %(displayName)s (%(userName)s) at %(dateTime)s": "Vidita de %(displayName)s (%(userName)s) je %(dateTime)s",
"Share room": "Kunhavigi ĉambron",
"System Alerts": "Sistemaj avertoj",
"Joining room...": "Aliĝante al ĉambro...",
"Not now": "Ne nun",
"Don't ask me again": "Ne demandu min denove",
"Main address": "Ĉefa adreso",
@ -1317,12 +1079,9 @@
"Room Topic": "Temo de ĉambro",
"Yes, I want to help!": "Jes. Mi volas helpi!",
"Failed to remove widget": "Malsukcesis forigi fenestraĵon",
"Reload widget": "Reŝargi fenestraĵon",
"Picture": "Bildo",
"Join": "Aliĝi",
"Invite anyway": "Tamen inviti",
"To continue, please enter your password:": "Por daŭrigi, bonvoluenigi vian pasvorton:",
"password": "pasvorto",
"Updating Riot": "Ĝisdatigante Riot",
"Go back": "Reen iri",
"Room Settings - %(roomName)s": "Ĉambraj agordoj — %(roomName)s",
@ -1344,17 +1103,13 @@
"Server Name": "Nomo de servilo",
"Username": "Uzantonomo",
"Not sure of your password? <a>Set a new one</a>": "Ĉu vi ne certas pri via pasvorto? <a>Agordu novan</a>",
"Sign in to your Matrix account": "Saluti per via Matrix-konto",
"Sign in to your Matrix account on %(serverName)s": "Saluti per via Matrix-konto sur %(serverName)s",
"Change": "Ŝanĝi",
"Create your Matrix account": "Krei vian Matrix-konton",
"Create your Matrix account on %(serverName)s": "Krei vian Matrix-konton sur %(serverName)s",
"Email (optional)": "Retpoŝto (malnepra)",
"Phone (optional)": "Telefono (malnepra)",
"Confirm": "Konfirmi",
"Use an email address to recover your account. Other users can invite you to rooms using your contact details.": "Uzu retpoŝtadreson por restaŭri vian konton. Aliaj uzantoj povas inviti vin al ĉambroj uzante viajn kontaktdetalojn.",
"Other servers": "Aliaj serviloj",
"Enter custom server URLs <a>What does this mean?</a>": "Enigi propran servil-URL-ojn. <a>Kion signifas ĉi tion?</a>",
"Homeserver URL": "Hejmservila URL",
"Identity Server URL": "URL de identiga servilo",
"Free": "Senpaga",
@ -1368,11 +1123,9 @@
"This homeserver does not support communities": "Ĉi tiu hejmservilo ne subtenas komunumojn",
"%(count)s of your messages have not been sent.|other": "Kelkaj viaj mesaĝoj ne sendiĝis.",
"%(count)s of your messages have not been sent.|one": "Via mesaĝo ne sendiĝis.",
"File is too big. Maximum file size is %(fileSize)s": "Dosiero estas tro granda. Maksimuma dosiergrandeco estas %(fileSize)s",
"Clear filter": "Vakigi filtrilon",
"Guest": "Gasto",
"Could not load user profile": "Ne povis ŝargi uzantan profilon",
"Your Matrix account": "Via Matrix-konto",
"Your Matrix account on %(serverName)s": "Via Matrix-konto sur %(serverName)s",
"A verification email will be sent to your inbox to confirm setting your new password.": "Kontrola retpoŝtmesaĝo estos sendita al via enirkesto por kontroli agordadon de via nova pasvorto.",
"Sign in instead": "Anstataŭe saluti",
@ -1380,7 +1133,6 @@
"Set a new password": "Agordi novan pasvorton",
"General failure": "Ĝenerala fiasko",
"Create account": "Krei konton",
"You need to enter a username.": "Necesas, ke vi enigu uzantonomon.",
"Create your account": "Krei vian konton",
"Great! This passphrase looks strong enough.": "Bonege! Ĉi tiu pasfrazo ŝajnas sufiĉe forta.",
"Keep going...": "Daŭrigu…",
@ -1406,7 +1158,6 @@
"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 />.": "Ĉambraj gradaltigoj efikas nur sur <i>servil-flanka</i> funkciado de la ĉambro. Se vi havas problemon kun via kliento (Riot), bonvolu raparti problemon per <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>Averto</b>: Gradaltigo de ĉambro <i>ne transmetos ĉiujn ĉambranojn al la nova versio de la ĉambro.</i> Ni afiŝos ligilon al la nova ĉambro en la malnova versio de la ĉambro ĉambranoj devos tien klaki por aliĝi al la nova ĉambro.",
"Please confirm that you'd like to go forward with upgrading this room from <oldVersion /> to <newVersion />.": "Bonvolu konfirmi, ke vi certe volas gradaltigi ĉi tiun ĉambron de <oldVersion /> al <newVersion />.",
"Upgrade": "Gradaltigi",
"Changes your display nickname in the current room only": "Ŝanĝas vian vidigan nomon nur en la nuna ĉambro",
"Changes your avatar in this current room only": "Ŝanĝas vian profilbildon nur en la nuna ĉambro",
"Gets or sets the room topic": "Ekhavas aŭ agordas la temon de la ĉambro",
@ -1434,8 +1185,6 @@
"The user's homeserver does not support the version of the room.": "Hejmservilo de ĉi tiu uzanto ne subtenas la version de la ĉambro.",
"No need for symbols, digits, or uppercase letters": "Ne necesas simboloj, ciferoj, aŭ majuskloj",
"Render simple counters in room header": "Bildigi simplajn kalkulilojn en la ĉapo de la fenestro",
"Edit messages after they have been sent (refresh to apply changes)": "Redakti mesaĝojn senditajn (aktualigu por apliki ŝanĝojn)",
"React to messages with emoji (refresh to apply changes)": "Reagi al mesaĝoj per bildsignoj (aktualigu por apliki ŝanĝojn)",
"Enable Emoji suggestions while typing": "Ŝalti proponojn de bildsignoj dum tajpado",
"Show a placeholder for removed messages": "Meti kovrilon anstataŭ forigitajn mesaĝojn",
"Show join/leave messages (invites/kicks/bans unaffected)": "Montri mesaĝojn pri aliĝo/foriro (neteme pri invitoj/forpeloj/forbaroj)",
@ -1492,7 +1241,6 @@
"Verification code": "Kontrola kodo",
"Deactivating your account is a permanent action - be careful!": "Malaktivigo de via konto estas nemalfarebla atentu!",
"If you've submitted a bug via GitHub, debug logs can help us track down the problem. Debug logs contain application usage data including your username, the IDs or aliases of the rooms or groups you have visited and the usernames of other users. They do not contain messages.": "Se vi raportis eraron per GitHub, senerariga protokolo povas helpi al ni spuri la problemon. Senerariga protokolo povas enhavi datumojn pri uzo de la aplikaĵo, inkluzive vian uzantnomon, identigilojn aŭ nomojn de la vizititaj ĉambroj aŭ grupoj, kaj uzantnomojn de aliaj uzantoj. Ili ne enhavas mesaĝojn.",
"Close button should minimize window to tray": "Ferma butono devas nur plejetigi la fenestron",
"Accept all %(invitedRooms)s invites": "Akcepti ĉiujn %(invitedRooms)s invitojn",
"Missing media permissions, click the button below to request.": "Mankas aŭdovidaj permesoj; klaku al la suba butono por peti.",
"Request media permissions": "Peti aŭdovidajn permesojn",
@ -1502,7 +1250,6 @@
"Account management": "Administrado de kontoj",
"This event could not be displayed": "Ĉi tiu okazo ne povis montriĝi",
"Please install <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, or <safariLink>Safari</safariLink> for the best experience.": "Bonvolu instali <chromeLink>Ĥromon</chromeLink>, <firefoxLink>Fajrfokson</firefoxLink>, aŭ <safariLink>Safarion</safariLink> por la plej bonaj spertoj.",
"If this is unexpected, please contact your system administrator or technical support representative.": "Se estas neatendite, bonvolu kontakti vian sisteman administranton aŭ teĥnikan subtenanton.",
"You are an administrator of this community. You will not be able to rejoin without an invite from another administrator.": "Vi estas administranto de tiu ĉi komunumo. Sen invito de alia administranto vi ne povos realiĝi.",
"Changes made to your community <bold1>name</bold1> and <bold2>avatar</bold2> might not be seen by other users for up to 30 minutes.": "Ŝanĝoj al viaj komunumaj <bold1>nomo</bold1> kaj <bold2>profilbildo</bold2> eble ne montriĝos al aliaj uzantoj ĝis 30 minutoj.",
"Who can join this community?": "Kiu povas aliĝi al tiu ĉi komunumo?",
@ -1518,12 +1265,9 @@
"There was an error removing that alias. It may no longer exist or a temporary error occurred.": "Forigo de tiu kromnomo eraris. Aŭ ĝi ne plu ekzistas, aŭ io misfunkciis.",
"In encrypted rooms, like this one, URL previews are disabled by default to ensure that your homeserver (where the previews are generated) cannot gather information about links you see in this room.": "En ĉifritaj ĉambroj, kiel ĉi tiu, antaŭrigardoj al URL-oj estas implicite malŝaltitaj por certigi, ke via hejmservilo (kie la antaŭrigardoj estas generataj) ne povas kolekti informojn pri ligiloj en ĉi tiu ĉambro.",
"When someone puts a URL in their message, a URL preview can be shown to give more information about that link such as the title, description, and an image from the website.": "Kiam iu metas URL-on en sian mesaĝon, antaŭrigardo al tiu URL povas montriĝi, por doni pliajn informojn pri tiu ligilo, kiel ekzemple la titolon, priskribon, kaj bildon el la retejo.",
"Agree or Disagree": "Konsenti aŭ malkonsenti",
"Like or Dislike": "Ŝati aŭ malŝati",
"<reactors/><reactedWith>reacted with %(shortName)s</reactedWith>": "<reactors/><reactedWith>reagis per %(shortName)s</reactedWith>",
"This room is a continuation of another conversation.": "Ĉi tiu ĉambro estas daŭrigo de alia interparolo.",
"Click here to see older messages.": "Klaku ĉi tien por vidi pli malnovajn mesaĝojn.",
"Edited at %(date)s": "Redaktita je %(date)s",
"edited": "redaktita",
"Failed to load group members": "Malsukcesis enlegi grupanojn",
"Please help improve Riot.im by sending <UsageDataLink>anonymous usage data</UsageDataLink>. This will use a cookie (please see our <PolicyLink>Cookie Policy</PolicyLink>).": "Bonvolu helpi plibonigi projekton Riot.im per sendado de <UsageDataLink>sennomaj datumoj pri uzado</UsageDataLink>. Tio funkciados per kuketo (bonvolu vidi nian <PolicyLink>Politikon pri kuketoj</PolicyLink>).",
@ -1531,7 +1275,6 @@
"Please <a>contact your service administrator</a> to get this limit increased.": "Bonvolu <a>kontakti vian administranton</a> por plialtigi ĉi tiun limon.",
"This homeserver has hit its Monthly Active User limit so <b>some users will not be able to log in</b>.": "Ĉi tiu hejmservilo atingis sian monatan limon de aktivaj uzantoj, do <b>iuj uzantoj ne povos saluti</b>.",
"This homeserver has exceeded one of its resource limits so <b>some users will not be able to log in</b>.": "Ĉi tiu hejmservilo pasis trans unu el siaj rimedaj limoj, do <b>iuj uzantoj ne povos saluti</b>.",
"Warning: This widget might use cookies.": "Averto: Tiu ĉi fenestraĵo eble uzos kuketojn.",
"An error ocurred whilst trying to remove the widget from the room": "Forigo de la fenestraĵo el la ĉambro eraris",
"Minimize apps": "Plejetigi aplikaĵojn",
"Maximize apps": "Plejgrandigi aplikaĵojn",
@ -1560,13 +1303,10 @@
"Re-join": "Re-aliĝi",
"You were banned from %(roomName)s by %(memberName)s": "%(memberName)s vin forbaris de %(roomName)s",
"Something went wrong with your invite to %(roomName)s": "Io misokazis al via invito al %(roomName)s",
"%(errcode)s was returned while trying to valide your invite. You could try to pass this information on to a room admin.": "Okazis eraro %(errcode)s dum kontrolado de via invito. Eble transdonu tiun informon al ĉambrestro.",
"You can only join it with a working invite.": "Vi povas aliĝi nur kun funkcianta invito.",
"You can still join it because this is a public room.": "Tamen vi povas aliĝi, ĉar ĉi tiu ĉambro estas publika.",
"Join the discussion": "Aliĝi al la diskuto",
"Try to join anyway": "Tamen provi aliĝi",
"This invite to %(roomName)s wasn't sent to your account": "Ĉi tiu invito al %(roomName)s ne sendiĝis al via konto",
"Sign in with a different account, ask for another invite, or add the e-mail address %(email)s to this account.": "Salutu per alia konto, petu inviton, aŭ aldonu la retpoŝtadreson %(email)s al tiu ĉi konto.",
"Do you want to chat with %(user)s?": "Ĉu vi volas babili kun %(user)s?",
"Do you want to join %(roomName)s?": "Ĉu vi volas aliĝi al %(roomName)s?",
"<userName/> invited you": "<userName/> vin invitis",
@ -1605,7 +1345,6 @@
"The room upgrade could not be completed": "Gradaltigo de la ĉambro ne povis finiĝi",
"Upgrade this room to version %(version)s": "Gradaltigi ĉi tiun ĉambron al versio %(version)s",
"Upgrade Room Version": "Gradaltigi version de la ĉambro",
"Upgrading this room requires closing down the current instance of the room and creating a new room it its place. To give room members the best possible experience, we will:": "Gradaltigo de ĉi tiu ĉambro bezonas ĝian fermon kaj anstataŭigon per ĉambro nova. Por plejbonigi la sperton de uzantoj, ni:",
"Create a new room with the same name, description and avatar": "Kreos novan ĉàmbron kun la sama nomo, priskribo, kaj profilbildo",
"Update any local room aliases to point to the new room": "Religos ĉiujn lokajn kromnomojn al la nova ĉambro",
"Stop users from speaking in the old version of the room, and post a message advising users to move to the new room": "Haltigos parolojn al la malnova versio de al ĉambro, kaj konsilos uzantojn pri la nova per mesaĝo",
@ -1635,7 +1374,6 @@
"Collapse Reply Thread": "Maletendi respondan fadenon",
"This homeserver would like to make sure you are not a robot.": "Ĉi tiu hejmservilo volas certigi, ke vi ne estas roboto.",
"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.": "Vi povas uzi proprajn servilajn elektojn por saluti aliajn servilojn de Matrix per alia hejmservila URL. Tio ebligos uzi ĉi tiun aplikaĵon kun jama Matrix-konto en alia hejmservilo.",
"You can also set a custom identity server, but you won't be able to invite users by email address, or be invited by email address yourself.": "Vi povas ankaŭ agordi propran identigan servilon, sed vi ne eblos inviti uzantojn per retpoŝtadresoj, nek tiel invitiĝi.",
"Please review and accept all of the homeserver's policies": "Bonvolu tralegi kaj akcepti ĉioman politikon de ĉi tiu hejmservilo",
"Please review and accept the policies of this homeserver:": "Bonvolu tralegi kaj akcepti la politikon de ĉi tiu hejmservilo:",
"Unable to validate homeserver/identity server": "Ne povas kontroli hejmservilon aŭ identigan servilon",
@ -1702,11 +1440,6 @@
"Show recently visited rooms above the room list": "Montri freŝe vizititajn ĉambrojn super la listo de ĉambroj",
"Show hidden events in timeline": "Montri kaŝitajn okazojn en historio",
"Low bandwidth mode": "Reĝimo de malmulta kapacito",
"No integrations server configured": "Neniu kuniga servilo agordita",
"This Riot instance does not have an integrations server configured.": "Ĉi tiu rulo de Riot ne havas agorditan kunigan servilon.",
"Connecting to integrations server...": "Konektiĝante al kuniga servilo…",
"Cannot connect to integrations server": "Ne povas konektiĝi al kuniga servilo",
"The integrations server is offline or it cannot reach your homeserver.": "La kuniga servilo aŭ estas eksterreta aŭ ne povas atingi vian hejmservilon.",
"Connect this device to Key Backup": "Konekti ĉi tiun aparaton al Savkopiado de ŝlosiloj",
"Start using Key Backup": "Ekuzi Savkopiadon de ŝlosiloj",
"Timeline": "Historio",
@ -1719,14 +1452,6 @@
"Set a new custom sound": "Agordi novan propran sonon",
"Browse": "Foliumi",
"Some devices for this user are not trusted": "Iuj aparatoj de tiu ĉi uzanto ne estas fidataj",
"Failed to connect to integrations server": "Malsukcesis konektiĝi al kuniga servilo",
"No integrations server is configured to manage stickers with": "Neniu kuniga servilo estas agordita por mastrumi glumarkojn",
"Agree": "Konsenti",
"Disagree": "Malkonsenti",
"Happy": "Kontenta",
"Party Popper": "Festilo",
"Confused": "Konfuza",
"Eyes": "Okuloj",
"Show all": "Montri ĉiujn",
"Edited at %(date)s. Click to view edits.": "Redaktita je %(date)s. Klaku por vidi redaktojn.",
"That doesn't look like a valid email address": "Tio ne ŝajnas esti valida retpoŝtadreso",
@ -1823,8 +1548,6 @@
"Use lowercase letters, numbers, dashes and underscores only": "Uzu nur malgrandajn leterojn, numerojn, streketojn kaj substrekojn",
"Enter username": "Enigu uzantonomon",
"Some characters not allowed": "Iuj signoj ne estas permesitaj",
"Use an email address to recover your account.": "Uzu retpoŝtadreson por rehavi vian konton.",
"Other users can invite you to rooms using your contact details.": "Aliaj uzantoj povas inviti vin al ĉambroj per viaj kontaktaj detaloj.",
"Find other public servers or use a custom server": "Trovi aliajn publikajn servilojn aŭ uzi propran",
"Terms and Conditions": "Uzokondiĉoj",
"To continue using the %(homeserverDomain)s homeserver you must review and agree to our terms and conditions.": "Por daŭre uzadi la hejmservilon %(homeserverDomain)s, vi devas tralegi kaj konsenti niajn uzokondiĉojn.",
@ -1911,10 +1634,8 @@
"Be found by phone or email": "Troviĝu per telefonnumero aŭ retpoŝtadreso",
"Use bots, bridges, widgets and sticker packs": "Uzu robotojn, pontojn, fenestraĵojn, kaj glumarkarojn",
"Terms of Service": "Uzokondiĉoj",
"To continue you need to accept the Terms of this service.": "Por pluiĝi, vi devas akcepti la uzokondiĉojn.",
"Service": "Servo",
"Summary": "Resumo",
"Terms": "Kondiĉoj",
"This account has been deactivated.": "Tiu ĉi konto malaktiviĝis.",
"Call failed due to misconfigured server": "Voko malsukcesis pro misagordita servilo",
"Please ask the administrator of your homeserver (<code>%(homeserverDomain)s</code>) to configure a TURN server in order for calls to work reliably.": "Bonvolu peti la administranton de via hejmservilo (<code>%(homeserverDomain)s</code>) agordi TURN-servilon, por ke vokoj funkciu dependeble.",
@ -1934,7 +1655,6 @@
"Actions": "Agoj",
"Use an identity server to invite by email. Click continue to use the default identity server (%(defaultIdentityServerName)s) or manage in Settings.": "Uzu identigan servilon por inviti retpoŝte. Klaku al «daŭrigi» por uzi la norman identigan servilon (%(defaultIdentityServerName)s) aŭ administru tion en Agordoj.",
"Displays list of commands with usages and descriptions": "Montras liston de komandoj kun priskribo de uzo",
"Use the new, faster, but still experimental composer for writing messages (requires refresh)": "Uzi la novan, pli rapidan, sed ankoraŭ eksperimentan komponilon de mesaĝoj (bezonas aktualigon)",
"Send read receipts for messages (requires compatible homeserver to disable)": "Sendi legokonfirmojn de mesaĝoj (bezonas akordan hejmservilon por malŝalto)",
"Accept <policyLink /> to continue:": "Akceptu <policyLink /> por daŭrigi:",
"Identity Server URL must be HTTPS": "URL de identiga servilo devas esti HTTPS-a",
@ -1985,10 +1705,8 @@
"Italics": "Kursive",
"Strikethrough": "Trastrekite",
"Code block": "Kodujo",
"No Identity Server is configured so you cannot add add an email address in order to reset your password in the future.": "Neniu identiga servilo estas agordita, do vi ne povas aldoni retpoŝtadreson por restarigi ose vian pasvorton.",
"Set an email for account recovery. Use email or phone to optionally be discoverable by existing contacts.": "Agordi retpoŝtadreson por rehavo de konto. Uzu retpoŝton aŭ telefonon por laŭelekte troviĝi de jamaj kontaktoj.",
"Set an email for account recovery. Use email to optionally be discoverable by existing contacts.": "Agordi retpoŝtadreson por rehavo de konto. Uzu retpoŝton por laŭelekte troviĝi de jamaj kontaktoj.",
"No Identity Server is configured: no email addreses can be added. You will be unable to reset your password.": "Neniu identiga servilo estas agordita: ne eblas aldoni retpoŝtadresojn. Vi ne povos restarigi vian pasvorton.",
"Explore": "Esplori",
"Filter": "Filtri",
"Filter rooms…": "Filtri ĉambrojn…",
@ -2003,8 +1721,6 @@
"Trust": "Fido",
"%(name)s (%(userId)s)": "%(name)s (%(userId)s)",
"Multiple integration managers": "Pluraj kunigiloj",
"Use the new, consistent UserInfo panel for Room Members and Group Members": "Uzi la novan, koheran informan panelon por ĉambranoj kaj grupanoj",
"Send verification requests in direct message": "Sendi kontrolajn petojn per rekta mesaĝo",
"Use the new, faster, composer for writing messages": "Uzi la novan, pli rapidan verkilon de mesaĝoj",
"Show previews/thumbnails for images": "Montri antaŭrigardojn/bildetojn je bildoj",
"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.": "Vi <b>forigu viajn personajn datumojn</b> de identiga servilo <idserver /> antaŭ ol vi malkonektiĝos. Bedaŭrinde, identiga servilo <idserver /> estas nuntempe eksterreta kaj ne eblas ĝin atingi.",
@ -2012,15 +1728,7 @@
"check your browser plugins for anything that might block the identity server (such as Privacy Badger)": "kontrolu kromprogramojn de via foliumilo je ĉio, kio povus malhelpi konekton al la identiga servilo (ekzemple «Privacy Badger»)",
"contact the administrators of identity server <idserver />": "kontaktu la administrantojn de la identiga servilo <idserver />",
"wait and try again later": "atendu kaj reprovu pli poste",
"Failed to update integration manager": "Malsukcesis ĝisdatigi kunigilon",
"Integration manager offline or not accessible.": "Kunigilo estas eksterreta aŭ alie neatingebla",
"Terms of service not accepted or the integration manager is invalid.": "Aŭ zokondiĉoj ne akceptiĝis, aŭ la kunigilo estas nevalida.",
"Integration manager has no terms of service": "Kunigilo havas neniujn uzokondiĉojn",
"The integration manager you have chosen does not have any terms of service.": "La elektita kunigilo havas neniujn uzokondiĉojn.",
"You are currently using <b>%(serverName)s</b> to manage your bots, widgets, and sticker packs.": "Vi nun mastrumas viajn robotojn, fenestaĵojn, kaj glumarkarojn per <b>%(serverName)s</b>.",
"Add which integration manager you want to manage your bots, widgets, and sticker packs.": "Aldonu kiun kunigilon vi volas por mastrumi viajn robotojn, fenestraĵojn, kaj glumarkarojn.",
"Integration Manager": "Kunigilo",
"Enter a new integration manager": "Metu novan kunigilon",
"Clear cache and reload": "Vakigi kaŝmemoron kaj relegi",
"Show tray icon and minimize window to it on close": "Montri pletan bildsimbolon kaj tien plejetigi la fenestron je fermo",
"Read Marker lifetime (ms)": "Vivodaŭro de legomarko (ms)",
@ -2029,7 +1737,7 @@
"Unable to share email address": "Ne povas havigi vian retpoŝtadreson",
"Your email address hasn't been verified yet": "Via retpoŝtadreso ankoraŭ ne kontroliĝis",
"Click the link in the email you received to verify and then click continue again.": "Klaku la ligilon en la ricevita retletero por kontroli, kaj poste reklaku al «daŭrigi».",
"Verify the link in your inbox": "Kontrolu la ligilon en via ricevujo.",
"Verify the link in your inbox": "Kontrolu la ligilon en via ricevujo",
"Complete": "Fini",
"Revoke": "Senvalidigi",
"Share": "Havigi",
@ -2056,8 +1764,6 @@
"%(count)s unread messages.|one": "1 nelegita mesaĝo.",
"Unread mentions.": "Nelegitaj mencioj.",
"Unread messages.": "Nelegitaj mesaĝoj.",
"Trust & Devices": "Fido kaj Aparatoj",
"Direct messages": "Rektaj mesaĝoj",
"Failed to deactivate user": "Malsukcesis malaktivigi uzanton",
"This client does not support end-to-end encryption.": "Ĉi tiu kliento ne subtenas tutvojan ĉifradon.",
"Messages in this room are not end-to-end encrypted.": "Mesaĝoj en ĉi tiu ĉambro ne estas tutvoje ĉifrataj.",
@ -2109,7 +1815,6 @@
"Reporting this message will send its unique 'event ID' to the administrator of your homeserver. If messages in this room are encrypted, your homeserver administrator will not be able to read the message text or view any files or images.": "Per raporto de ĝi tiu mesaĝo vi sendos ĝian unikan «eventan identigilon» al la administranto de via hejmservilo. Se mesaĝoj en ĉi tiu ĉambro estas ĉifrataj, la administranto de via hejmservilo ne povos legi la tekston de la mesaĝo, nek rigardi dosierojn aŭ bildojn.",
"Send report": "Sendi raporton",
"Command Help": "Helpo pri komando",
"Integrations Manager": "Kunigilo",
"To continue you need to accept the terms of this service.": "Por pluigi, vi devas akcepti la uzokondiĉojn de ĉi tiu servo.",
"Document": "Dokumento",
"Report Content": "Raporti enhavon",
@ -2127,5 +1832,40 @@
"Emoji Autocomplete": "Memkompletigo de mienetoj",
"Notification Autocomplete": "Memkompletigo de sciigoj",
"Room Autocomplete": "Memkompletigo de ĉambroj",
"User Autocomplete": "Memkompletigo de uzantoj"
"User Autocomplete": "Memkompletigo de uzantoj",
"Custom (%(level)s)": "Propra (%(level)s)",
"%(senderName)s placed a voice call.": "%(senderName)s metis voĉvokon.",
"%(senderName)s placed a voice call. (not supported by this browser)": "%(senderName)s metis voĉvokon. (mankas subteno en ĉi tiu foliumilo)",
"%(senderName)s placed a video call.": "%(senderName)s metis vidvokon.",
"%(senderName)s placed a video call. (not supported by this browser)": "%(senderName)s metis vidvokon. (mankas subteno en ĉi tiu foliumilo)",
"Try out new ways to ignore people (experimental)": "Elprovi novajn manierojn malatenti homojn (eksperimente)",
"Send verification requests in direct message, including a new verification UX in the member panel.": "Sendadi kontrolajn petojn per rektaj mesaĝoj, inkluzive novan kontrolan ilaron en la membra panelo.",
"Match system theme": "Similiĝi la sisteman haŭton",
"My Ban List": "Mia listo de forbaroj",
"This is your list of users/servers you have blocked - don't leave the room!": "Ĉi tio estas la listo de uzantoj/serviloj, kiujn vi forbaris ne eliru el la ĉambro!",
"Decline (%(counter)s)": "Malakcepti (%(counter)s)",
"Clear notifications": "Vakigi sciigojn",
"Error subscribing to list": "Eraris abono al listo",
"Please verify the room ID or alias and try again.": "Bonvolu kontroli la identigilon aŭ kromnomon de la ĉambro kaj reprovu.",
"Error removing ignored user/server": "Eraris forigo de la malatentata uzanto/servilo",
"Error unsubscribing from list": "Eraris malabono de la listo",
"Please try again or view your console for hints.": "Bonvolu reprovi aŭ serĉi helpilojn en via konzolo.",
"You have not ignored anyone.": "Vi neniun malatentis.",
"You are not subscribed to any lists": "Vi neniun liston abonis.",
"Unsubscribe": "Malaboni",
"View rules": "Montri regulojn",
"You are currently subscribed to:": "Vi nun abonas:",
"⚠ These settings are meant for advanced users.": "⚠ Ĉi tiuj agordoj celas spertajn uzantojn.",
"Subscribed lists": "Abonataj listoj",
"Subscribe": "Aboni",
"Your display name": "Via vidiga nomo",
"Your avatar URL": "URL de via profilbildo",
"Your user ID": "Via identigilo de uzanto",
"Your theme": "Via haŭto",
"Riot URL": "URL de Riot",
"Room ID": "Identigilo de ĉambro",
"Widget ID": "Identigilo de fenestraĵo",
"Widgets do not use message encryption.": "Fenestraĵoj ne uzas ĉifradon de mesaĝoj.",
"Widget added by": "Fenestraĵon aldonis",
"This widget may use cookies.": "Ĉi tiu fenestraĵo povas uzi kuketojn."
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -16,10 +16,7 @@
"Update": "به‌روزرسانی",
"Notifications": "آگاه‌سازی‌ها",
"What's New": "تازه‌ها",
"Add an email address above to configure email notifications": "آدرس ایمیلتان را به بالا بیفزایید تا بتوانید آگاه‌سازی با ایمیل را مدیریت کنید",
"Expand panel": "پنل را بگشا",
"On": "روشن",
"Filter room names": "جستجو در گپ‌ها",
"Changelog": "تغییراتِ به‌وجودآمده",
"Waiting for response from server": "در انتظار پاسخی از سمت سرور",
"Leave": "خروج",
@ -31,7 +28,6 @@
"Forget": "فراموش کن",
"World readable": "خواندن جهانی",
"Mute": "سکوت",
"Hide panel": "پنل را پنهان کن",
"You cannot delete this image. (%(code)s)": "شما نمی‌توانید این تصویر را پاک کنید. (%(code)s)",
"Cancel Sending": "فرستادن را لغو کن",
"Warning": "هشدار",
@ -39,7 +35,6 @@
"Resend": "بازفرست",
"Error saving email notification preferences": "خطا در ذخیره‌سازی ترجیحات آگاهسازی با ایمیل",
"Downloading update...": "در حال بارگیریِ به‌روزرسانی...",
"#example": "#نمونه",
"Remember, you can always set an email address in user settings if you change your mind.": "به خاطر داشته باشید که اگر نظرتان عوض شد می‌توانید از بخش تنظیمات یک ایمیل را به اکانتتان متصل کنید.",
"Unavailable": "غیرقابل‌دسترسی",
"View Decrypted Source": "دیدن منبع رمزگشایی شده",
@ -55,14 +50,11 @@
"Members": "اعضا",
"No update available.": "هیچ به روزرسانی جدیدی موجود نیست.",
"Noisy": "پرسروصدا",
"Failed to get protocol list from Home Server": "دریافت لیست پروتکل‌ها از کارگزار مبدا موفقیت‌آمیز نبود",
"Collecting app version information": "درحال جمع‌آوری اطلاعات نسخه‌ی برنامه",
"Delete the room alias %(alias)s and remove %(name)s from the directory?": "آیا مطمئنید که می‌خواهید نام مستعار گپ %(alias)s را پاک و %(name)s را از فهرست حذف کنید؟",
"This will allow you to return to your account after signing out, and sign in on other devices.": "این به شما اجازه خواهد داد که پس از خروج به اکانت خود بازگردید و از سایر دستگاه‌ها وارد شوید.",
"Cancel": "لغو",
"Enable notifications for this account": "آگاه سازی با رایانامه را برای این اکانت فعال کن",
"Directory": "فهرست گپ‌گاه‌ها",
"Failed to get public room list": "گرفتن لیست گپ‌گاه‌های عمومی موفقیت‌آمیز نبود",
"Messages containing <span>keywords</span>": "پیا‌م‌های دارای <span> این کلیدواژه‌ها </span>",
"Room not found": "گپ یافت نشد",
"Tuesday": "سه‌شنبه",
@ -82,10 +74,7 @@
"Monday": "دوشنبه",
"All messages (noisy)": "همه‌ی پیام‌ها(بلند)",
"Enable them now": "همین حالا فعالشان کن",
"Messages containing my user name": "پیام‌های شامل نامِ کاربری من",
"Collecting logs": "درحال جمع‌آوری گزارش‌ها",
"more": "بیشتر",
"Search for a room": "جستجوی برای یک گپ",
"Search": "جستجو",
"(HTTP status %(httpStatus)s)": "(HTTP وضعیت %(httpStatus)s)",
"Failed to forget room %(errCode)s": "فراموش کردن گپ‌گاه %(errCode)s موفقیت‌آمیز نبود",
@ -123,7 +112,6 @@
"Unable to fetch notification target list": "ناتوانی در تطبیق لیست آگاه‌سازی‌های هدف",
"Set Password": "پسوردتان را انتخاب کنید",
"An error occurred whilst saving your email notification preferences.": "خطایی در حین ذخیره‌ی ترجیجات شما درباره‌ی رایانامه رخ داد.",
"Enable audible notifications in web client": "آگاه‌سازی صدادار را در کارگزار وب فعال کن",
"Off": "خاموش",
"Riot does not know how to join a room on this network": "رایوت از چگونگی ورود به یک گپ در این شبکه اطلاعی ندارد",
"Mentions only": "فقط نام‌بردن‌ها",
@ -131,16 +119,13 @@
"Remove": "حذف کن",
"You can now return to your account after signing out, and sign in on other devices.": "اکنون می‌توانید پس از خروج به اکانتتان بازگردید و با دستگاه‌های دیگری وارد شوید.",
"Continue": "ادامه",
"Enable desktop notifications": "آگاه‌سازی دسکتاپ را فعال کن",
"Enable email notifications": "آگاه‌سازی با رایانامه را فعال کن",
"Login": "ورود",
"No rooms to show": "هیچ گپی برای نشان دادن موجود نیست",
"Download this file": "بارگیری کن",
"Failed to change settings": "تغییر تنظیمات موفقیت‌آمیز نبود",
"Failed to change password. Is your password correct?": "خطا در تغییر گذرواژه. آیا از درستی گذرواژه‌تان اطمینان دارید؟",
"View Source": "دیدن منبع",
"Custom Server Options": "تنظیمات سفارشی برای سرور",
"Collapse panel": "پنل را ببند",
"With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "با مرورگر کنونی شما، ظاهر و حس استفاده از برنامه ممکن است کاملا اشتباه باشد و برخی یا همه‌ی ویژگی‌ها ممکن است کار نکنند. می‌توانید به استفاده ادامه دهید اما مسئولیت هر مشکلی که به آن بربخورید بر عهده‌ی خودتان است!",
"Checking for an update...": "درحال بررسی به‌روزرسانی‌ها...",
"There are advanced notifications which are not shown here": "آگاه‌سازی‌های پیشرفته‌ای هستند که در اینجا نشان داده نشده‌اند",

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -9,12 +9,7 @@
"VoIP is unsupported": "Sen soporte para VoIP",
"You cannot place VoIP calls in this browser.": "Non pode establecer chamadas VoIP neste navegador.",
"You cannot place a call with yourself.": "Non pode facer unha chamada a si mesmo.",
"Conference calls are not supported in this client": "Non pode establecer chamadas de reunión neste cliente",
"Conference calls are not supported in encrypted rooms": "Nas salas cifradas non se pode establecer chamadas de reunión",
"Warning!": "Aviso!",
"Conference calling is in development and may not be reliable.": "As chamadas de reunión poderían non ser totalmente estables xa que están en desenvolvemento.",
"Failed to set up conference call": "Fallo ao establecer a chamada de reunión",
"Conference call failed.": "Fallo na chamada de reunión.",
"Call Failed": "Fallou a chamada",
"There are unknown devices in this room: if you proceed without verifying them, it will be possible for someone to eavesdrop on your call.": "Hai dispositivos descoñecidos en esta sala: se segue adiante sen verificalos, pode ser posible que alguén bote un ollo a súa chamada.",
"Review Devices": "Revisar dispositivos",
@ -23,8 +18,6 @@
"Call": "Chamar",
"Answer": "Resposta",
"Call Timeout": "Tempo de resposta de chamada",
"The file '%(fileName)s' failed to upload": "Non se puido subir o ficheiro '%(fileName)s'",
"The file '%(fileName)s' exceeds this home server's size limit for uploads": "O ficheiro '%(fileName)s' excede o límite de tamaño establecido para este servidor",
"Upload Failed": "Fallou o envío",
"Sun": "Dom",
"Mon": "Lun",
@ -53,7 +46,6 @@
"Who would you like to add to this community?": "A quen quere engadir a esta comunidade?",
"Warning: any person you add to a community will be publicly visible to anyone who knows the community ID": "Aviso: calquera persoa que engada a unha comunidade estará publicamente visible para calquera que coñeza a ID da comunidade",
"Invite new community members": "Convidará comunidade a novos participantes",
"Name or matrix ID": "Nome ou ID matrix",
"Invite to Community": "Convidar á comunidade",
"Which rooms would you like to add to this community?": "Que salas desexaría engadir a esta comunidade?",
"Show these rooms to non-members on the community page and room list?": "Quere que estas salas se lle mostren a outros membros de fóra da comunidade na lista de salas?",
@ -75,12 +67,9 @@
"Admin": "Administrador",
"Start a chat": "Iniciar unha conversa",
"Who would you like to communicate with?": "Con quen desexa comunicarse?",
"Email, name or matrix ID": "Correo, nome ou ID matrix",
"Start Chat": "Iniciar conversa",
"Invite new room members": "Convidar a novos participantes",
"Who would you like to add to this room?": "A quen desexaría engadir a esta sala?",
"Send Invites": "Enviar convites",
"Failed to invite user": "Fallo ao convidar usuaria",
"Operation failed": "Fallou a operación",
"Failed to invite": "Fallou o convite",
"Failed to invite the following users to the %(roomName)s room:": "Houbo un fallo convidando os seguintes usuarios á sala %(roomName)s:",
@ -140,7 +129,6 @@
"(no answer)": "(sen resposta)",
"(unknown failure: %(reason)s)": "(fallo descoñecido: %(reason)s)",
"%(senderName)s ended the call.": "%(senderName)s rematou a chamada.",
"%(senderName)s placed a %(callType)s call.": "%(senderName)s estableceu unha chamada %(callType)s.",
"%(senderName)s sent an invitation to %(targetDisplayName)s to join the room.": "%(senderName)s enviou un convite a %(targetDisplayName)s para unirse a sala.",
"%(senderName)s made future room history visible to all room members, from the point they are invited.": "%(senderName)s fixo o historial da sala visible para todos os participantes, desde o punto en que foron convidadas.",
"%(senderName)s made future room history visible to all room members, from the point they joined.": "%(senderName)s estableceu o historial futuro visible a todos os participantes, desde o punto en que se uniron.",
@ -154,10 +142,6 @@
"%(widgetName)s widget modified by %(senderName)s": "O trebello %(widgetName)s modificado por %(senderName)s",
"%(widgetName)s widget added by %(senderName)s": "O trebello %(widgetName)s engadido por %(senderName)s",
"%(widgetName)s widget removed by %(senderName)s": "%(widgetName)s eliminado por %(senderName)s",
"%(displayName)s is typing": "%(displayName)s está a escribir",
"%(names)s and %(count)s others are typing|other": "%(names)s e %(count)s outras están a escribir",
"%(names)s and %(count)s others are typing|one": "%(names)s e outra está a escribir",
"%(names)s and %(lastPerson)s are typing": "%(names)s e %(lastPerson)s están a escribir",
"Failure to create room": "Fallou a creación da sala",
"Server may be unavailable, overloaded, or you hit a bug.": "O servidor podería non estar dispoñible, con sobrecarga ou ter un fallo.",
"Send anyway": "Enviar de todos os xeitos",
@ -168,22 +152,12 @@
"Authentication check failed: incorrect password?": "Fallou a comprobación de autenticación: contrasinal incorrecto?",
"Failed to join room": "Non se puido unir a sala",
"Message Pinning": "Fixando mensaxe",
"Disable Emoji suggestions while typing": "Desactivar a suxestión de Emoji mentres escribe",
"Use compact timeline layout": "Utilizar a disposición compacta da liña temporal",
"Hide removed messages": "Ocultar mensaxes eliminadas",
"Hide join/leave messages (invites/kicks/bans unaffected)": "Ocultar mensaxes de unión/saída (convites/expulsións/bloqueos non afectados)",
"Hide avatar changes": "Ocultar cambios no avatar",
"Hide display name changes": "Ocultar cambios no nome público",
"Hide read receipts": "Ocultar avisos de recepción",
"Show timestamps in 12 hour format (e.g. 2:30pm)": "Mostrar marcas de tempo con formato 12 horas (ex. 2:30pm)",
"Always show message timestamps": "Mostrar sempre marcas de tempo",
"Autoplay GIFs and videos": "Reprodución automática de GIFs e vídeos",
"Enable automatic language detection for syntax highlighting": "Activar a detección automática de idioma para o resalte da sintaxe",
"Hide avatars in user and room mentions": "Ocultar avatares nas mencións de usuarios e salas",
"Disable big emoji in chat": "Desactivar emojis grandes nas conversas",
"Don't send typing notifications": "Non enviar notificacións de escritura",
"Automatically replace plain text Emoji": "Substituír automaticamente Emoji en texto plano",
"Disable Peer-to-Peer for 1:1 calls": "Desactivar Peer-to-Peer para chamadas 1:1",
"Never send encrypted messages to unverified devices from this device": "Nunca enviar mensaxes cifradas aos dispositivos que non estean verificados neste dispositivo",
"Never send encrypted messages to unverified devices in this room from this device": "Nunca enviar mensaxes cifradas aos dispositivos que non estean verificados nesta sala desde este dispositivo",
"Enable inline URL previews by default": "Activar por defecto as vistas previas en liña de URL",
@ -198,12 +172,9 @@
"Decline": "Rexeitar",
"Accept": "Aceptar",
"Error": "Fallo",
"A text message has been sent to +%(msisdn)s. Please enter the verification code it contains": "Enviouse unha mensaxe de texto a +%(msisdn)s. Por favor, introduza o código de verificación que contén",
"Incorrect verification code": "Código de verificación incorrecto",
"Enter Code": "Introduza o código",
"Submit": "Enviar",
"Phone": "Teléfono",
"Add phone number": "Engada número de teléfono",
"Add": "Engadir",
"Failed to upload profile picture!": "Fallo ao subir a imaxe de perfil!",
"Upload new:": "Subir nova:",
@ -219,15 +190,12 @@
"New Password": "Novo contrasinal",
"Confirm password": "Confirme o contrasinal",
"Change Password": "Cambiar contrasinal",
"Your home server does not support device management.": "O seu servidor non soporta a xestión de dispositivos.",
"Unable to load device list": "Non se puido cargar a lista de dispositivos",
"Authentication": "Autenticación",
"Delete %(count)s devices|other": "Eliminar %(count)s dispositivos",
"Delete %(count)s devices|one": "Eliminar dispositivo",
"Device ID": "ID de dispositivo",
"Device Name": "Nome do dispositivo",
"Last seen": "Visto por última vez",
"Select devices": "Escolla dispositivos",
"Failed to set display name": "Fallo ao establecer o nome público",
"Disable Notifications": "Desactivar notificacións",
"Enable Notifications": "Activar ass notificacións",
@ -246,13 +214,10 @@
"%(senderName)s uploaded a file": "%(senderName)s subiu un ficheiro",
"Options": "Axustes",
"Undecryptable": "Non descifrable",
"Encrypted by a verified device": "Cifrado por un dispositivo verificado",
"Encrypted by an unverified device": "Cifrado por un dispositivo non verificado",
"Unencrypted message": "Mensaxe non cifrada",
"Please select the destination room for this message": "Escolla por favor a sala de destino para esta mensaxe",
"Blacklisted": "Omitidos",
"Verified": "Verificados",
"Unverified": "Non verificados",
"device id: ": "id dispositivo: ",
"Disinvite": "Retirar convite",
"Kick": "Expulsar",
@ -283,17 +248,12 @@
"Revoke Moderator": "Quitar Moderador",
"Make Moderator": "Facer Moderador",
"Admin Tools": "Ferramentas de administración",
"Level:": "Nivel:",
"and %(count)s others...|other": "e %(count)s outras...",
"and %(count)s others...|one": "e outra máis...",
"Invited": "Convidada",
"Filter room members": "Filtrar os participantes da conversa",
"%(userName)s (power %(powerLevelNumber)s)": "%(userName)s (permiso %(powerLevelNumber)s)",
"Attachment": "Anexo",
"Upload Files": "Subir ficheiros",
"Are you sure you want to upload the following files?": "Está segura de que quere subir os seguintes ficheiros?",
"Encrypted room": "Sala cifrada",
"Unencrypted room": "Sala non cifrada",
"Hangup": "Quedada",
"Voice call": "Chamada de voz",
"Video call": "Chamada de vídeo",
@ -304,20 +264,12 @@
"Send an encrypted message…": "Enviar unha mensaxe cifrada…",
"Send a message (unencrypted)…": "Enviar unha mensaxe (non cifrada)…",
"You do not have permission to post to this room": "Non ten permiso para comentar nesta sala",
"Turn Markdown on": "Activar Markdown",
"Turn Markdown off": "Desactivar Markdown",
"Hide Text Formatting Toolbar": "Agochar barra de formato de texto",
"Server error": "Fallo no servidor",
"Server unavailable, overloaded, or something else went wrong.": "Servidor non dispoñible, sobrecargado, ou outra cousa puido fallar.",
"Command error": "Erro na orde",
"bold": "remarcado",
"italic": "cursiva",
"strike": "raiado",
"underline": "subliñado",
"code": "código",
"quote": "cita",
"bullet": "lista",
"numbullet": "lista numerada",
"Markdown is disabled": "Markdown desactivado",
"Markdown is enabled": "Markdown activado",
"Unpin Message": "Desfixar mensaxe",
@ -343,25 +295,15 @@
"Unnamed room": "Sala sen nome",
"World readable": "Visible por todos",
"Guests can join": "Convidados pódense unir",
"Failed to set avatar.": "Fallo ao establecer o avatar.",
"Save": "Gardar",
"(~%(count)s results)|other": "(~%(count)s resultados)",
"(~%(count)s results)|one": "(~%(count)s resultado)",
"Join Room": "Unirse a sala",
"Upload avatar": "Subir avatar",
"Remove avatar": "Quitar avatar",
"Settings": "Axustes",
"Forget room": "Esquecer sala",
"Search": "Busca",
"Show panel": "Mostra panel",
"Drop here to favourite": "Solte aquí para favorito",
"Drop here to tag direct chat": "Solte aquí para etiquetar chat directo",
"Drop here to restore": "Solte aquí para restablecer",
"Drop here to tag %(section)s": "Solte aquí para etiquetar %(section)s",
"You will not be able to undo this change as you are demoting yourself, if you are the last privileged user in the room it will be impossible to regain privileges.": "Non poderá desfacer este cambio xa que está a diminuír a súa autoridade, se é a única persoa con autorización na sala será imposible volver a obter privilexios.",
"Drop here to demote": "Arrastre aquí para degradar",
"Press <StartChatButton> to start a chat with someone": "Pulse <StartChatButton> para iniciar a conversa con alguén",
"You're not in any rooms yet! Press <CreateRoomButton> to make a room or <RoomDirectoryButton> to browse the directory": "Aínda non está en ningunha sala! Pulse <CreateRoomButton> para crear unha sala ou <RoomDirectoryButton> para buscar no directorio",
"Community Invites": "Convites da comunidade",
"Invites": "Convites",
"Favourites": "Favoritas",
@ -369,54 +311,19 @@
"Rooms": "Salas",
"Low priority": "Baixa prioridade",
"Historical": "Historial",
"This invitation was sent to an email address which is not associated with this account:": "Este convite foi enviado a un enderezo de correo que non está asociado con esta conta:",
"You may wish to login with a different account, or add this email to this account.": "Pode que desexe conectarse con outra conta, ou engadir este enderezo a súa conta.",
"You have been invited to join this room by %(inviterName)s": "Foi convidada por %(inviterName)s a unirse a esta sala",
"Would you like to <acceptText>accept</acceptText> or <declineText>decline</declineText> this invitation?": "Quere <acceptText>aceptar</acceptText> ou <declineText>rexeitar</declineText> este convite?",
"Reason: %(reasonText)s": "Razón: %(reasonText)s",
"Rejoin": "Volver a unirse",
"You have been kicked from %(roomName)s by %(userName)s.": "Foi expulsada de %(roomName)s por %(userName)s.",
"You have been kicked from this room by %(userName)s.": "Foi expulsada desta sala por %(userName)s.",
"You have been banned from %(roomName)s by %(userName)s.": "Non se lle permite acceder a %(roomName)s por %(userName)s.",
"You have been banned from this room by %(userName)s.": "Non se lle permite o acceso a esta sala por %(userName)s.",
"This room": "Esta sala",
"%(roomName)s does not exist.": "%(roomName)s non existe.",
"%(roomName)s is not accessible at this time.": "%(roomName)s non está accesible neste momento.",
"You are trying to access %(roomName)s.": "Está intentando acceder a %(roomName)s.",
"You are trying to access a room.": "Está intentando acceder a unha sala.",
"<a>Click here</a> to join the discussion!": "<a>Pulse aquí</a> para unirse a conversa!",
"This is a preview of this room. Room interactions have been disabled": "Esta é unha vista previa desta sala. Desactiváronse as interaccións coa sala",
"To change the room's avatar, you must be a": "Para cambiar o avatar da sala, debe ser",
"To change the room's name, you must be a": "Para cambiar o nome da sala, debe ser",
"To change the room's main address, you must be a": "Para cambiar o enderezo principal da sala, debe ser",
"To change the room's history visibility, you must be a": "Para cambiar a visibilidade do histórico da sala, debe ser",
"To change the permissions in the room, you must be a": "Para cambiar os permisos na sala, debe ser",
"To change the topic, you must be a": "Para cambiar o asunto, debe ser",
"To modify widgets in the room, you must be a": "Para modificar os trebellos da sala, debe ser",
"Failed to unban": "Fallou eliminar a prohibición",
"Banned by %(displayName)s": "Non aceptado por %(displayName)s",
"Privacy warning": "Aviso de intimidade",
"Changes to who can read history will only apply to future messages in this room": "Os cambios sobre quen pode ler o histórico serán de aplicación para as futuras mensaxes nesta sala",
"The visibility of existing history will be unchanged": "A visibilidade do histórico existente non cambiará",
"unknown error code": "código de fallo descoñecido",
"Failed to forget room %(errCode)s": "Fallo ao esquecer sala %(errCode)s",
"End-to-end encryption is in beta and may not be reliable": "O cifrado de par-a-par está en beta e podería non ser fiable",
"You should not yet trust it to secure data": "Polo de agora non debería confiarlle datos seguros",
"Devices will not yet be able to decrypt history from before they joined the room": "Os dispositivos non poderán descifrar o histórico anterior a que se uniron a sala",
"Once encryption is enabled for a room it cannot be turned off again (for now)": "Unha vez activou o cifrado para unha sala non se poderá desactivar (por agora)",
"Encrypted messages will not be visible on clients that do not yet implement encryption": "As mensaxes cifradas non será visibles en clientes que non aínda non teñan implementado o cifrado",
"Enable encryption": "Activar o cifrado",
"(warning: cannot be disabled again!)": "(aviso: non se pode desactivar!)",
"Encryption is enabled in this room": "O cifrado está activado nesta sala",
"Encryption is not enabled in this room": "Non se activou o cifrado nesta sala",
"Privileged Users": "Usuarios con privilexios",
"No users have specific privileges in this room": "Non hai usuarios con privilexios específicos nesta sala",
"Banned users": "Usuarios excluídos",
"This room is not accessible by remote Matrix servers": "Esta sala non é accesible por servidores Matrix remotos",
"Leave room": "Deixar a sala",
"Favourite": "Favorita",
"Tagged as: ": "Etiquetada como: ",
"To link to a room it must have <a>an address</a>.": "Para ligar a unha sala deberá ter <a>un enderezo</a>.",
"Guests cannot join this room even if explicitly invited.": "Os convidados non se poden unir a esta sala inda que fosen convidados explicitamente.",
"Click here to fix": "Pulse aquí para solución",
"Who can access this room?": "Quen pode acceder a esta sala?",
@ -430,30 +337,15 @@
"Members only (since they were invited)": "Só membros (desde que foron convidados)",
"Members only (since they joined)": "Só membros (desde que se uniron)",
"Permissions": "Permisos",
"The default role for new room members is": "O rol por defecto na sala para novos participantes é",
"To send messages, you must be a": "Para enviar mensaxes, deberá ser",
"To invite users into the room, you must be a": "Para convidar a usuarios a esta sala, debe ser",
"To configure the room, you must be a": "Para configurar a sala, debe ser",
"To kick users, you must be a": "Para expulsar usuarios, debe ser",
"To ban users, you must be a": "Para prohibir usuarios, debe ser",
"To remove other users' messages, you must be a": "Para eliminar mensaxes doutras usuarios, debe ser",
"To send events of type <eventType/>, you must be a": "Para enviar eventos de tipo <eventType/>, debe ser",
"Advanced": "Avanzado",
"This room's internal ID is": "O ID interno desta sala é",
"Add a topic": "Engadir asunto",
"Cancel": "Cancelar",
"Scroll to unread messages": "Desprazarse ate mensaxes non lidas",
"Jump to first unread message.": "Ir a primeira mensaxe non lida.",
"Close": "Pechar",
"Invalid alias format": "Formato de alias non válido",
"'%(alias)s' is not a valid format for an alias": "'%(alias)s' non é un formato válido para un alias",
"Invalid address format": "Formato de enderezo non válido",
"'%(alias)s' is not a valid format for an address": "'%(alias)s' non é un formato válido par un enderezo",
"not specified": "non indicado",
"not set": "non establecido",
"Remote addresses for this room:": "Enderezos remotos para esta sala:",
"Addresses": "Enderezos",
"The main address for this room is": "O enderezo principal para esta sala é",
"Local addresses for this room:": "O enderezo local para esta sala:",
"This room has no local addresses": "Esta sala non ten enderezos locais",
"New address (e.g. #foo:%(localDomain)s)": "Novos enderezos (ex. #foo:%(localDomain)s)",
@ -482,16 +374,9 @@
"Removed or unknown message type": "Tipo de mensaxe descoñecida ou eliminada",
"Message removed by %(userId)s": "Mensaxe eliminada por %(userId)s",
"Message removed": "Mensaxe eliminada",
"Robot check is currently unavailable on desktop - please use a <a>web browser</a>": "Comprobación por Robot non está dispoñible en escritorio - por favor utilice un <a>navegador web</a>",
"This Home Server would like to make sure you are not a robot": "Este servidor quere asegurarse de que vostede non é un robot",
"Sign in with CAS": "Conectarse con CAS",
"Custom Server Options": "Opcións personalizadas do servidor",
"You can use the custom server options to sign into other Matrix servers by specifying a different Home server URL.": "Pode utilizar as opcións personalizadas do servidor para conectarse a outros servidores Matrix indicando un URL de servidor de inicio diferente.",
"This allows you to use this app with an existing Matrix account on a different home server.": "Así pode utilizar este aplicativo con unha conta Matrix existente en un servidor de inicio diferente.",
"You can also set a custom identity server but this will typically prevent interaction with users based on email address.": "Tamén pode establecer un servidor de identidade personalizado pero isto normalmente dificulta a interacción con usuarios baseándose non enderezo de correo.",
"Dismiss": "Rexeitar",
"To continue, please enter your password.": "Para continuar, por favor introduza o seu contrasinal.",
"Password:": "Contrasinal:",
"An email has been sent to %(emailAddress)s": "Enviouse un correo a %(emailAddress)s",
"Please check your email to continue registration.": "Comprobe o seu correo para continuar co rexistro.",
"Token incorrect": "Testemuño incorrecto",
@ -499,24 +384,11 @@
"Please enter the code it contains:": "Por favor introduza o código que contén:",
"Start authentication": "Inicie a autenticación",
"powered by Matrix": "funciona grazas a Matrix",
"Username on %(hs)s": "Nome de usuaria en %(hs)s",
"User name": "Nome de usuaria",
"Mobile phone number": "Número de teléfono móbil",
"Forgot your password?": "Esqueceu o contrasinal?",
"%(serverName)s Matrix ID": "Matrix ID en %(serverName)s",
"Sign in with": "Conectarse con",
"Email address": "Enderezo de correo",
"Sign in": "Conectar",
"If you don't specify an email address, you won't be able to reset your password. Are you sure?": "Se non indica un enderezo de correo non poderá restablecer o contrasinal, está seguro?",
"Email address (optional)": "Enderezo de correo (opcional)",
"You are registering with %(SelectedTeamName)s": "Estase a rexistrar con %(SelectedTeamName)s",
"Mobile phone number (optional)": "Número de teléfono móbil (opcional)",
"Register": "Rexistrar",
"Default server": "Servidor por defecto",
"Custom server": "Servidor personalizado",
"Home server URL": "URL do servidor de inicio",
"Identity server URL": "URL do servidor de identidade",
"What does this mean?": "Que significa isto?",
"Remove from community": "Eliminar da comunidade",
"Disinvite this user from community?": "Retirar o convite a comunidade a esta usuaria?",
"Remove this user from community?": "Quitar a esta usuaria da comunidade?",
@ -537,13 +409,10 @@
"Something went wrong when trying to get your communities.": "Algo fallou ao intentar obter as súas comunidades.",
"You're not currently a member of any communities.": "Ate o momento non é membro de ningunha comunidade.",
"Unknown Address": "Enderezo descoñecido",
"NOTE: Apps are not end-to-end encrypted": "NOTA: As Apps non están cifradas de par-a-par",
"Do you want to load widget from URL:": "Quere cargar o trebello da URL:",
"Allow": "Permitir",
"Delete Widget": "Eliminar trebello",
"Deleting a widget removes it for all users in this room. Are you sure you want to delete this widget?": "Quitando un trebello elimínao para todas os usuarios desta sala. Está seguro de querer eliminar este trebello?",
"Delete widget": "Eliminar trebello",
"Revoke widget access": "Retirar acceso ao trebello",
"Minimize apps": "Minimizar apps",
"Edit": "Editar",
"Create new room": "Crear unha nova sala",
@ -552,10 +421,8 @@
"Unverify": "Retirar verificación",
"Verify...": "Verificar...",
"No results": "Sen resultados",
"Delete": "Eliminar",
"Communities": "Comunidades",
"Home": "Inicio",
"Integrations Error": "Fallo nas integracións",
"Could not connect to the integration server": "Non se puido conectar ao servidor de integración",
"Manage Integrations": "Xestionar integracións",
"%(nameList)s %(transitionList)s": "%(nameList)s %(transitionList)s",
@ -612,7 +479,6 @@
"%(items)s and %(lastItem)s": "%(items)s e %(lastItem)s",
"collapse": "comprimir",
"expand": "expandir",
"Custom of %(powerLevel)s": "Personalización de %(powerLevel)s",
"Custom level": "Nivel personalizado",
"Room directory": "Directorio de salas",
"Start chat": "Iniciar conversa",
@ -624,12 +490,6 @@
"email address": "enderezo de correo",
"Try using one of the following valid address types: %(validTypesList)s.": "Intentar utilizar algún dos seguintes tipos de enderezo válidos: %(validTypesList)s.",
"You have entered an invalid address.": "Introduciu un enderezo non válido.",
"Create a new chat or reuse an existing one": "Crear un novo chat ou reutilizar un xa existente",
"Start new chat": "Iniciar un novo chat",
"You already have existing direct chats with this user:": "Xa ten unha conversa directa con esta usuaria:",
"Start chatting": "Iniciar a conversar",
"Click on the button below to start chatting!": "Pulse non botón inferior para iniciar a conversar!",
"Start Chatting": "Iniciar a conversa",
"Confirm Removal": "Confirme a retirada",
"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.": "Está certa de que quere quitar (eliminar) este evento? Saiba que si elimina un nome de sala ou cambia o asunto, podería desfacer o cambio.",
"Community IDs may only contain characters a-z, 0-9, or '=_-./'": "Os ID de comunidade só poden conter caracteres a-z, 0-9, or '=_-./'",
@ -642,19 +502,13 @@
"example": "exemplo",
"Create": "Crear",
"Create Room": "Crear sala",
"Room name (optional)": "Nome da sala (opcional)",
"Advanced options": "Axustes avanzados",
"Block users on other matrix homeservers from joining this room": "Evitar que usuarios doutros servidores matrix se unan a esta sala",
"This setting cannot be changed later!": "Esta preferencia non se pode cambiar máis tarde!",
"Unknown error": "Fallo descoñecido",
"Incorrect password": "Contrasinal incorrecto",
"Deactivate Account": "Desactivar conta",
"Unable to ascertain that the address this invite was sent to matches one associated with your account.": "Non se pode determinar si o enderezo ao que foi enviado este convite coincide con un dos asociados a súa conta.",
"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:": "Para verificar que se pode confiar neste dispositivo, contacte co seu dono utilizando algún outro medio (ex. en persoa ou chamada de teléfono) e pregúntelle se a clave que ven nos axustes de usuario do se dispositivo coincide coa clave inferior:",
"Device name": "Nome do dispositivo",
"Device key": "Chave do dispositivo",
"If it matches, press the verify button below. If it doesn't, then someone else is intercepting this device and you probably want to press the blacklist button instead.": "Se concorda, pulse o botón verificar. Si non, entón alguén está interceptando este dispositivo e probablemente vostede desexe pulsar o botón lista negra.",
"In future this verification process will be more sophisticated.": "No futuro este proceso de verificación será máis sofisticado.",
"Verify device": "Verificar dispositivo",
"I verify that the keys match": "Certifico que coinciden as chaves",
"An error has occurred.": "Algo fallou.",
@ -676,7 +530,6 @@
"Unable to verify email address.": "Non se puido verificar enderezo de correo electrónico.",
"This will allow you to reset your password and receive notifications.": "Isto permitiralle restablecer o seu contrasinal e recibir notificacións.",
"Skip": "Saltar",
"User names may only contain letters, numbers, dots, hyphens and underscores.": "Os nomes de usuaria só poden conter letras, números, puntos e guión alto e baixo.",
"Username not available": "Nome de usuaria non dispoñible",
"Username invalid: %(errMessage)s": "Nome de usuaria non válido: %(errMessage)s",
"An error occurred: %(error_string)s": "Algo fallou: %(error_string)s",
@ -694,10 +547,6 @@
"Custom": "Personalizada",
"Alias (optional)": "Alias (opcional)",
"Name": "Nome",
"Topic": "Asunto",
"Make this room private": "Facer que esta sala sexa privada",
"Share message history with new users": "Compartir o histórico de mensaxes cos novos usuarios",
"Encrypt room": "Cifrar a sala",
"You must <a>register</a> to use this functionality": "Debe <a>rexistrarse</a> para utilizar esta función",
"You must join the room to see its files": "Debe unirse a sala para ver os seus ficheiros",
"There are no visible files in this room": "Non hai ficheiros visibles nesta sala",
@ -734,7 +583,6 @@
"Long Description (HTML)": "Descrición longa (HTML)",
"Description": "Descrición",
"Community %(groupId)s not found": "Non se atopou a comunidade %(groupId)s",
"This Home server does not support communities": "Este servidor non soporta comunidades",
"Failed to load %(groupId)s": "Fallo ao cargar %(groupId)s",
"Reject invitation": "Rexeitar convite",
"Are you sure you want to reject the invitation?": "Seguro que desexa rexeitar o convite?",
@ -760,20 +608,15 @@
"Warning": "Aviso",
"Connectivity to the server has been lost.": "Perdeuse a conexión ao servidor.",
"Sent messages will be stored until your connection has returned.": "As mensaxes enviadas gardaranse ate que retome a conexión.",
"%(count)s new messages|other": "%(count)s novas mensaxes",
"%(count)s new messages|one": "%(count)s nova mensaxe",
"Active call": "Chamada activa",
"There's no one else here! Would you like to <inviteText>invite others</inviteText> or <nowarnText>stop warning about the empty room</nowarnText>?": "Non hai ninguén por aquí! Desexa convidar <inviteText>a outras</inviteText> ou <nowarnText>deixar de informar sobre a sala baldeira</nowarnText>?",
"You seem to be uploading files, are you sure you want to quit?": "Semella estar a subir ficheiros, seguro que desexa deixalo?",
"You seem to be in a call, are you sure you want to quit?": "Semella estar en unha chamada, seguro que quere saír?",
"Failed to upload file": "Fallo ao subir ficheiro",
"Server may be unavailable, overloaded, or the file too big": "O servidor podería non estar dispoñible, sobrecargado ou o ficheiro ser demasiado grande",
"Search failed": "Fallou a busca",
"Server may be unavailable, overloaded, or search timed out :(": "O servidor podería non estar dispoñible, sobrecargado, ou caducou a busca :(",
"No more results": "Sen máis resultados",
"Unknown room %(roomId)s": "Sala descoñecida %(roomId)s",
"Room": "Sala",
"Failed to save settings": "Fallo ao gardar os axustes",
"Failed to reject invite": "Fallo ao rexeitar o convite",
"Fill screen": "Encher pantalla",
"Click to unmute video": "Pulse para escoitar vídeo",
@ -788,60 +631,35 @@
"Uploading %(filename)s and %(count)s others|one": "Subindo %(filename)s e %(count)s máis",
"Light theme": "Decorado claro",
"Dark theme": "Decorado escuro",
"Status.im theme": "Decorado Status.im",
"Can't load user settings": "Non se puideron cargar os axustes de usuaria",
"Server may be unavailable or overloaded": "O servidor podería non está dispoñible ou sobrecargado",
"Sign out": "Desconectar",
"For security, logging out will delete any end-to-end encryption keys from this browser. If you want to be able to decrypt your conversation history from future Riot sessions, please export your room keys for safe-keeping.": "Por seguridade, ao desconectarse borrará todas as chaves de cifrado par-a-par ste navegador. Se quere poder descifrar o historial da conversa en futuras sesións en Riot, por favor exporte as chaves da sala e gárdeas en lugar seguro.",
"Failed to change password. Is your password correct?": "Fallo ao cambiar o contrasinal. É correcto o contrasinal?",
"Success": "Parabéns",
"Your password was successfully changed. You will not receive push notifications on other devices until you log back in to them": "O seu contrasinal cambiouse correctamente. Non recibirá notificacións tipo push en outros dispositivos ate que se conecte novamente en eles",
"Remove Contact Information?": "Eliminar información do contacto?",
"Remove %(threePid)s?": "Eliminar %(threePid)s?",
"Unable to remove contact information": "Non se puido eliminar a información do contacto",
"Refer a friend to Riot:": "Convide a un amigo a Riot:",
"Interface Language": "Idioma da Interface",
"User Interface": "Interface de usuaria",
"Autocomplete Delay (ms):": "Atraso no autocompletado (ms):",
"<not supported>": "<non soportado>",
"Import E2E room keys": "Importar chaves E2E da sala",
"Cryptography": "Criptografía",
"Device ID:": "ID de dispositivo:",
"Device key:": "Chave do dispositivo:",
"Ignored Users": "Usuarios ignorados",
"Analytics": "Analytics",
"Riot collects anonymous analytics to allow us to improve the application.": "Riot recolle información analítica anónima para permitirnos mellorar o aplicativo.",
"Privacy is important to us, so we don't collect any personal or identifiable data for our analytics.": "A intimidade impórtanos, así que non recollemos información personal ou identificable nos datos dos nosos análises.",
"Learn more about how we use analytics.": "Saber máis sobre como utilizamos analytics.",
"Labs": "Labs",
"These are experimental features that may break in unexpected ways": "Estas son características experimentais que poderían dar lugar a fallos non agardados",
"Use with caution": "Utilice con precaución",
"Deactivate my account": "Desactivar a miña conta",
"Clear Cache": "Limpar caché",
"Clear Cache and Reload": "Limpar caché e recargar",
"Updates": "Actualizacións",
"Check for update": "Comprobar actualización",
"Reject all %(invitedRooms)s invites": "Rexeitar todos os %(invitedRooms)s convites",
"Bulk Options": "Opcións en bloque",
"Desktop specific": "Configuracións de escritorio",
"Start automatically after system login": "Iniciar automaticamente despois de iniciar sesión",
"No media permissions": "Sen permisos de medios",
"You may need to manually permit Riot to access your microphone/webcam": "Igual ten que permitir manualmente a Riot acceder ao seus micrófono e cámara",
"Missing Media Permissions, click here to request.": "Faltan permisos de medios, pulse aquí para solicitalos.",
"No Microphones detected": "Non se detectaron micrófonos",
"No Webcams detected": "Non se detectaron cámaras",
"Default Device": "Dispositivo por defecto",
"Microphone": "Micrófono",
"Camera": "Cámara",
"VoIP": "VoIP",
"Email": "Correo electrónico",
"Add email address": "Engadir enderezo correo electrónico",
"Notifications": "Notificacións",
"Profile": "Perfil",
"Display name": "Nome mostrado",
"Account": "Conta",
"To return to your account in future you need to set a password": "Estableza un contrasinal para volver a súa conta con posterioridade",
"Logged in as:": "Conectada como:",
"Access Token:": "Testemuño de acceso:",
"click to reveal": "pulse para revelar",
"Homeserver is": "O servidor de inicio é",
@ -854,50 +672,29 @@
"A new password must be entered.": "Debe introducir un novo contrasinal.",
"New passwords must match each other.": "Os novos contrasinais deben ser coincidentes.",
"Data from an older version of Riot has been detected. This will have caused end-to-end cryptography to malfunction in the older version. End-to-end encrypted messages exchanged recently whilst using the older version may not be decryptable in this version. This may also cause messages exchanged with this version to fail. If you experience problems, log out and back in again. To retain message history, export and re-import your keys.": "Detectáronse datos de una versión anterior de Riot. Isto causará un mal funcionamento da criptografía extremo-a-extremo na versión antiga. As mensaxes cifradas extremo-a-extremo intercambiadas mentres utilizaba a versión anterior poderían non ser descifrables en esta versión. Isto tamén podería causar que mensaxes intercambiadas con esta versión tampouco funcionasen. Se ten problemas, desconéctese e conéctese de novo. Para manter o historial de mensaxes, exporte e reimporte as súas chaves.",
"Resetting password will currently reset any end-to-end encryption keys on all devices, making encrypted chat history unreadable, unless you first export your room keys and re-import them afterwards. In future this will be improved.": "O restablecemento do contrasinal restablecerá tamén as chaves de cifrado extremo-a-extremo en todos os dispositivos, facendo o historial de chat cifrado non lexible, a menos que primeiro exporte as chaves da sala e as reimporte posteriormente. No futuro melloraremos isto.",
"An email has been sent to %(emailAddress)s. Once you've followed the link it contains, click below.": "Enviouse un correo a %(emailAddress)s. Unha vez siga a ligazón que contén, pulse abaixo.",
"I have verified my email address": "Validei o meu enderezo de correo electrónico",
"Your password has been reset": "Restableceuse o seu contrasinal",
"You have been logged out of all devices and will no longer receive push notifications. To re-enable notifications, sign in again on each device": "Foi desconectado de todos os seus dispositivos e xa non recibirá notificacións push. Para reactivar as notificacións, conéctese de novo en cada dispositivo",
"Return to login screen": "Volver a pantalla de conexión",
"To reset your password, enter the email address linked to your account": "Para restablecer o seu contrasinal, introduza o enderezo de correo electrónico ligado a súa conta",
"New password": "Novo contrasinal",
"Confirm your new password": "Confirme o seu novo contrasinal",
"Send Reset Email": "Enviar correo electrónico de restablecemento",
"Create an account": "Crear unha conta",
"This Home Server does not support login using email address.": "Este servidor non soporta a conexión utilizando un enderezo de correo electrónico.",
"Incorrect username and/or password.": "Nome de usuaria ou contrasinal non válidos.",
"Please note you are logging into the %(hs)s server, not matrix.org.": "Teña en conta que se está a conectar ao servidor %(hs)s, non a matrix.org.",
"Guest access is disabled on this Home Server.": "O acceso de convidados está desactivado neste servidor de inicio.",
"The phone number entered looks invalid": "O número de teléfono introducido non semella ser válido",
"This homeserver doesn't offer any login flows which are supported by this client.": "Este servidor non ofrece ningún sistema de conexión que soporte este cliente.",
"Error: Problem communicating with the given homeserver.": "Fallo: problema ao comunicarse con servidor proporcionado.",
"Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. Either use HTTPS or <a>enable unsafe scripts</a>.": "Non se pode conectar ao servidor vía HTTP cando na barra de enderezos do navegador está HTTPS. Utilice HTTPS ou <a>active scripts non seguros</a>.",
"Can't connect to homeserver - please check your connectivity, ensure your <a>homeserver's SSL certificate</a> is trusted, and that a browser extension is not blocking requests.": "Non se conectou ao servidor - por favor comprobe a conexión, asegúrese de que o<a>certificado SSL do servidor</a> sexa de confianza, e que ningún engadido do navegador estea bloqueando as peticións.",
"Sign in to get started": "Conéctese para iniciar",
"Failed to fetch avatar URL": "Fallo ao obter o URL do avatar",
"Set a display name:": "Establecer nome público:",
"Upload an avatar:": "Suba un avatar:",
"This server does not support authentication with a phone number.": "O servidor non soporta a autenticación con número de teléfono.",
"Missing password.": "Falta contrasinal.",
"Passwords don't match.": "Non coinciden os contrasinais.",
"Password too short (min %(MIN_PASSWORD_LENGTH)s).": "Contrasinal demasiado curto (min %(MIN_PASSWORD_LENGTH)s).",
"This doesn't look like a valid email address.": "Non semella ser un enderezo de correo electrónico válido.",
"This doesn't look like a valid phone number.": "Non semella ser un número de teléfono válido.",
"You need to enter a user name.": "É preciso que introduza un nome de usuaria.",
"An unknown error occurred.": "Aconteceu un erro descoñecido.",
"I already have an account": "Xa teño unha conta",
"Displays action": "Mostra acción",
"Bans user with given id": "Prohibe a usuaria co ID indicado",
"Unbans user with given id": "Permite de novo a usuaria co ID proporcionado",
"Define the power level of a user": "Define o nivel de permisos de unha usuaria",
"Invites user with given id to current room": "Convida a usuaria co id proporcionado a sala actual",
"Joins room with given alias": "Únese a sala co alias proporcionado",
"Sets the room topic": "Establece o asunto da sala",
"Kicks user with given id": "Expulsa usuaria co id proporcionado",
"Changes your display nickname": "Cambia o alcume mostrado",
"Searches DuckDuckGo for results": "Buscar en DuckDuckGo por resultados",
"Changes colour scheme of current room": "Cambia o esquema de cores da sala actual",
"Verifies a user, device, and pubkey tuple": "Valida o conxunto de usuaria, dispositivo e chave pública",
"Ignores a user, hiding their messages from you": "Ignora unha usuaria, agochándolle as súas mensaxes",
"Stops ignoring a user, showing their messages going forward": "Deixa de ignorar unha usuaria, mostrándolles as súas mensaxes a partir de agora",
@ -940,7 +737,6 @@
"Where this page includes identifiable information, such as a room, user or group ID, that data is removed before being sent to the server.": "Se esta páxina inclúe información identificable como ID de grupo, usuario ou sala, estes datos son eliminados antes de ser enviados ao servidor.",
"The platform you're on": "A plataforma na que está",
"The version of Riot.im": "A versión de Riot.im",
"Whether or not you're logged in (we don't record your user name)": "Se está ou non conectado/a (non gardamos os nomes de usuarios)",
"Your language of choice": "A súa preferencia de idioma",
"Which officially provided instance you are using, if any": "Se a houbese, que instancia oficial está a utilizar",
"Whether or not you're using the Richtext mode of the Rich Text Editor": "Se utiliza o modo Richtext ou non do editor de texto enriquecido",
@ -954,17 +750,13 @@
"Failed to set direct chat tag": "Fallo ao establecer etiqueta do chat directo",
"Failed to remove tag %(tagName)s from room": "Fallo ao eliminar a etiqueta %(tagName)s da sala",
"Failed to add tag %(tagName)s to room": "Fallo ao engadir a etiqueta %(tagName)s a sala",
"Disable Community Filter Panel": "Deshabilitar o panel de filtro de comunidades",
"Your key share request has been sent - please check your other devices for key share requests.": "Enviouse a solicitude de compartir chave - por favor comprobe as peticións de compartir chaves nos seus outros dispositivos.",
"Key share requests are sent to your other devices automatically. If you rejected or dismissed the key share request on your other devices, click here to request the keys for this session again.": "As peticións de compartir chaves envíanse de xeito automático aos seus outros dispositivos. Se rexeita o obvia estas peticións nos outros dispositivos, pulse aquí para solicitar novamente as chaves para esta sesión.",
"If your other devices do not have the key for this message you will not be able to decrypt them.": "Se os seus outros dispositivos non teñen as chaves para este mensaxe non poderán descifrala.",
"Key request sent.": "Petición de chave enviada.",
"<requestLink>Re-request encryption keys</requestLink> from your other devices.": "<requestLink>Volver a pedir chaves de cifrado</requestLink> desde os outros dispositivos.",
"%(user)s is a %(userRole)s": "%(user)s é %(userRole)s",
"Flair": "Aura",
"Showing flair for these communities:": "Mostrar a aura para estas comunidades:",
"Flair will appear if enabled in room settings": "A aura aparecerá se está activada nas preferencias da sala",
"Flair will not appear": "A aura non aparecerá",
"Display your community flair in rooms configured to show it.": "Mostrar a aura da súa comunidade nas salas configuradas para que a mostren.",
"Did you know: you can use communities to filter your Riot.im experience!": "Sabía que pode utilizar as comunidades para mellorar a súa experiencia con Riot.im!",
"To set up a filter, drag a community avatar over to the filter panel on the far left hand side of the screen. You can click on an avatar in the filter panel at any time to see only the rooms and people associated with that community.": "Para establecer un filtro, arrastre un avatar da comunidade sobre o panel de filtros na parte esquerda da pantalla. Pode pulsar nun avatar no panel de filtrado en calquera momento para ver só salas e xente asociada a esa comunidade.",
@ -976,36 +768,28 @@
"Changes made to your community <bold1>name</bold1> and <bold2>avatar</bold2> might not be seen by other users for up to 30 minutes.": "Os cambios realizados a súa comunidade <bold1>name</bold1> e <bold2>avatar</bold2> poida que non os vexan outros usuarios ate dentro de 30 minutos.",
"Join this community": "Únase a esta comunidade",
"Leave this community": "Deixar esta comunidade",
"Debug Logs Submission": "Envío de rexistro de depuración",
"If you've submitted a bug via GitHub, debug logs can help us track down the problem. Debug logs contain application usage data including your username, the IDs or aliases of the rooms or groups you have visited and the usernames of other users. They do not contain messages.": "Si enviou un reporte de fallo a través de GitHub, os informes poden axudarnos a examinar o problema. Os informes de fallo conteñen datos do uso do aplicativo incluíndo o seu nome de usuaria, os IDs ou alcumes das salas e grupos que visitou e os nomes de usuaria de outras persoas. Non conteñen mensaxes.",
"Submit debug logs": "Enviar informes de depuración",
"Opens the Developer Tools dialog": "Abre o cadro de Ferramentas de desenvolvemento",
"Stickerpack": "Iconas",
"You don't currently have any stickerpacks enabled": "Non ten paquetes de iconas activados",
"Add a stickerpack": "Engadir un paquete de iconas",
"Hide Stickers": "Agochar iconas",
"Show Stickers": "Mostrar iconas",
"Who can join this community?": "Quen pode unirse a esta comunidade?",
"Everyone": "Todo o mundo",
"Fetching third party location failed": "Fallo ao obter a localización de terceiros",
"A new version of Riot is available.": "Está dispoñible unha nova versión de Riot.",
"Couldn't load home page": "Non se cargou a páxina de inicio",
"Send Account Data": "Enviar datos da conta",
"All notifications are currently disabled for all targets.": "Todas as notificacións están desactivadas para todos os destinos.",
"Uploading report": "Informe da subida",
"Sunday": "Domingo",
"Notification targets": "Obxectivos das notificacións",
"Today": "Hoxe",
"Failed to get protocol list from Home Server": "Fallo ao obter a lista de protocolo desde o servidor",
"You are not receiving desktop notifications": "Non está a recibir notificacións de escritorio",
"Friday": "Venres",
"Update": "Actualizar",
"What's New": "Que hai de novo",
"Add an email address above to configure email notifications": "Engada un enderezo de correo electrónico para configurar as notificacións",
"Expand panel": "Expandir panel",
"On": "On",
"%(count)s Members|other": "%(count)s participantes",
"Filter room names": "Filtrar nomes de sala",
"Changelog": "Rexistro de cambios",
"Waiting for response from server": "Agardando pola resposta do servidor",
"Send Custom Event": "Enviar evento personalizado",
@ -1014,12 +798,9 @@
"delete the alias.": "borrar alcume.",
"To return to your account in future you need to <u>set a password</u>": "Para volver a súa conta no futuro debe <u>establecer un contrasinal>/u>",
"Forget": "Esquecer",
"#example": "#exemplo",
"Hide panel": "Agochar panel",
"You cannot delete this image. (%(code)s)": "Non pode eliminar esta imaxe. (%(code)s)",
"Cancel Sending": "Cancelar o envío",
"This Room": "Esta sala",
"The Home Server may be too old to support third party networks": "O servidor de inicio podería ser demasiado antigo como para aceptar redes de terceiros",
"Noisy": "Ruidoso",
"Error saving email notification preferences": "Fallo ao cargar os axustes de notificacións",
"Messages containing my display name": "Mensaxes que conteñen o meu nome público",
@ -1027,15 +808,12 @@
"Unavailable": "Non dispoñible",
"View Decrypted Source": "Ver a fonte descifrada",
"Failed to update keywords": "Fallo ao actualizar as palabras chave",
"Notes:": "Notas:",
"remove %(name)s from the directory.": "eliminar %(name)s do directorio.",
"Notifications on the following keywords follow rules which cant be displayed here:": "Notificacións das regras de seguimento das seguintes palabras que non se mostrarán aquí:",
"<safariLink>Safari</safariLink> and <operaLink>Opera</operaLink> work too.": "<safariLink>Safari</safariLink> e <operaLink>Opera</operaLink> tamén funcionan.",
"Please set a password!": "Por favor estableza un contrasinal!",
"You have successfully set a password!": "Mudou con éxito o seu contrasinal!",
"An error occurred whilst saving your email notification preferences.": "Algo fallou mentres se gardaban as súas preferencias de notificación.",
"Explore Room State": "Explorar estado da sala",
"Search for a room": "Buscar unha sala",
"Source URL": "URL fonte",
"Messages sent by bot": "Mensaxes enviadas por bot",
"Filter results": "Filtrar resultados",
@ -1048,9 +826,7 @@
"This will allow you to return to your account after signing out, and sign in on other devices.": "Isto permitiralle volver a súa conta tras desconectarse, e conectarse en outros dispositivos.",
"Keywords": "Palabras chave",
"Enable notifications for this account": "Activar notificacións para esta conta",
"Directory": "Directorio",
"Invite to this community": "Convidar a esta comunidade",
"Failed to get public room list": "Fallo ao obter a lista de salas públicas",
"Messages containing <span>keywords</span>": "Mensaxes que conteñen <span>palabras chave</span>",
"Room not found": "Non se atopou a sala",
"Tuesday": "Martes",
@ -1060,7 +836,6 @@
"Riot uses many advanced browser features, some of which are not available or experimental in your current browser.": "Riot utiliza características avanzadas do navegador, algunhas das cales non están dispoñibles ou son experimentais no seu navegador actual.",
"Developer Tools": "Ferramentas para desenvolver",
"Preparing to send logs": "Preparándose para enviar informe",
"Enable desktop notifications": "Activar as notificacións de escritorio",
"Remember, you can always set an email address in user settings if you change your mind.": "Lembre que sempre poderá poñer un enderezo de correo nos axustes de usuario se cambiase de idea.",
"Explore Account Data": "Explorar datos da conta",
"All messages (noisy)": "Todas as mensaxes (alto)",
@ -1073,16 +848,12 @@
"Monday": "Luns",
"Remove from Directory": "Eliminar do directorio",
"Enable them now": "Activalos agora",
"Messages containing my user name": "Mensaxes que conteñen o meu nome de usuaria",
"Toolbox": "Ferramentas",
"Collecting logs": "Obtendo rexistros",
"more": "máis",
"GitHub issue link:": "Ligazón ao reporte en GitHub:",
"You must specify an event type!": "Debe indicar un tipo de evento!",
"(HTTP status %(httpStatus)s)": "(Estado HTTP %(httpStatus)s)",
"All Rooms": "Todas as Salas",
"State Key": "Chave do estado",
"Please install <chromeLink>Chrome</chromeLink> or <firefoxLink>Firefox</firefoxLink> for the best experience.": "Por favor instale <chromeLink>Chrome</chromeLink> ou <firefoxLink>Firefox</firefoxLink> para a mellor experiencia de usuaria.",
"Wednesday": "Mércores",
"Quote": "Cita",
"Send logs": "Enviar informes",
@ -1115,11 +886,9 @@
"Messages in group chats": "Mensaxes en grupos de chat",
"Yesterday": "Onte",
"Error encountered (%(errorDetail)s).": "Houbo un erro (%(errorDetail)s).",
"Login": "Conectar",
"Low Priority": "Baixa prioridade",
"Unable to fetch notification target list": "Non se puido procesar a lista de obxectivo de notificacións",
"Set Password": "Establecer contrasinal",
"Enable audible notifications in web client": "Activar as notificacións audibles no cliente web",
"Off": "Off",
"Riot does not know how to join a room on this network": "Riot non sabe como conectar cunha sala nesta rede",
"Mentions only": "Só mencións",
@ -1130,12 +899,10 @@
"Pin Message": "Fixar mensaxe",
"Failed to change settings": "Fallo ao cambiar os axustes",
"View Community": "Ver Comunidade",
"%(count)s Members|one": "%(count)s participante",
"Event sent!": "Evento enviado!",
"View Source": "Ver fonte",
"Event Content": "Contido do evento",
"Thank you!": "Grazas!",
"Collapse panel": "Agochar panel",
"With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "Co seu navegador actual a aparencia e uso do aplicativo poderían estar totalmente falseadas, e algunhas características poderían non funcionar. Se quere pode continuar, pero debe ser consciente de que poden haber fallos!",
"Checking for an update...": "Comprobando as actualizacións...",
"There are advanced notifications which are not shown here": "Existen notificacións avanzadas que non se mostran aquí",
@ -1145,14 +912,10 @@
"Your device resolution": "Resolución do dispositivo",
"Missing roomId.": "Falta o ID da sala.",
"Always show encryption icons": "Mostra sempre iconas de cifrado",
"At this time it is not possible to reply with a file so this will be sent without being a reply.": "Neste intre non é posible responder con un ficheiro así que este será enviado sen ser considerado resposta.",
"Unable to reply": "Non puido responder",
"At this time it is not possible to reply with an emote.": "Neste intre non é posible responder con un emote.",
"Popout widget": "trebello emerxente",
"Picture": "Imaxe",
"Unable to load event that was replied to, it either does not exist or you do not have permission to view it.": "Non se cargou o evento ao que respondía, ou non existe ou non ten permiso para velo.",
"Riot bugs are tracked on GitHub: <a>create a GitHub issue</a>.": "Os fallos de Riot séguense en GitHub: <a>crear un informe en GitHub</a>.",
"Log out and remove encryption keys?": "Desconectar e eliminar as chaves de cifrado?",
"Send Logs": "Enviar informes",
"Clear Storage and Sign Out": "Limpar o almacenamento e Desconectar",
"Refresh": "Actualizar",
@ -1162,22 +925,15 @@
"e.g. %(exampleValue)s": "p.ex. %(exampleValue)s",
"Send analytics data": "Enviar datos de análises",
"Enable widget screenshots on supported widgets": "Activar as capturas de trebellos para aqueles que as permiten",
"Encrypting": "Cifrando",
"Encrypted, not sent": "Cifrado, sen enviar",
"Share Link to User": "Compartir a ligazón co usuario",
"Share room": "Compartir sala",
"To notify everyone in the room, you must be a": "Para avisar a todos os da sala ten que ser",
"Muted Users": "Usuarios silenciados",
"Please help improve Riot.im by sending <UsageDataLink>anonymous usage data</UsageDataLink>. This will use a cookie (please see our <PolicyLink>Cookie Policy</PolicyLink>).": "Mellore Riot.im enviando <UsageDataLink>os datos anónimos de uso</UsageDataLink>. Iso suporá o emprego dunha cookie (véxase a nosa <PolicyLink>Política de Cookies</PolicyLink>).",
"Please help improve Riot.im by sending <UsageDataLink>anonymous usage data</UsageDataLink>. This will use a cookie.": "Mellore Riot.im enviando <UsageDataLink>o uso de datos anónimo</UsageDataLink>. Iso usará unha cookie.",
"Yes, I want to help!": "Si, quero axuda",
"Warning: This widget might use cookies.": "Aviso: este trebello podería usar algunha cookie.",
"Reload widget": "Volver a cargar o trebello",
"Failed to indicate account erasure": "Non se deu indicado a eliminación de conta",
"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>": "Iso fará que a súa deixe de ter uso de xeito permanente. Non poderá acceder e ninguén vai a poder volver a rexistrar esa mesma ID de usuario. Suporá que saía de todas as salas de conversas nas que estaba e eliminará os detalles da súa conta do servidores de identificación.<b>Isto non se poderá desfacer</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.": "Desactivando a súa conta <b>non supón que por defecto esquezamos as súas mensaxes enviadas.</b> Se quere que nos esquezamos das súas mensaxes, prema na caixa de embaixo.",
"To continue, please enter your password:": "Para continuar introduza o seu contrasinal:",
"password": "contrasinal",
"Message visibility in Matrix is similar to email. Our forgetting your messages means that messages you have sent will not be shared with any new or unregistered users, but registered users who already have access to these messages will still have access to their copy.": "A visibilidade das mensaxes en Matrix é parecida ás dos correos electrónicos. Que esquezamos as súas mensaxes significa que as súas mensaxes non se van a compartir con ningún novo membro ou usuario que non estea rexistrado. Mais aqueles usuarios que xa tiveron acceso a estas mensaxes si que seguirán tendo acceso as súas propias copias desas mensaxes.",
"Please forget all messages I have sent when my account is deactivated (<b>Warning:</b> this will cause future users to see an incomplete view of conversations)": "Esquezan todas as mensaxes que eu enviara no momento en que elimine a miña conta. (<b>Aviso</b>: iso suporá que os seguintes participantes só verán unha versión incompleta das conversas.)",
"Share Room": "Compartir sala",
@ -1195,14 +951,10 @@
"Review terms and conditions": "Revise os termos e condicións",
"No Audio Outputs detected": "Non se detectou unha saída de audio",
"Audio Output": "Saída de audio",
"Try the app first": "Probe a aplicación primeiro",
"Jitsi Conference Calling": "Chamada para conferencia con Jitsi",
"A conference call could not be started because the intgrations server is not available": "Non se puido comezar a chamada por mor de que o servidor de integración non está activo",
"Call in Progress": "Chamada en progreso",
"A call is already in progress!": "Xa hai unha chamada en progreso!",
"Permission Required": "Precísase de permisos",
"You do not have permission to start a conference call in this room": "Non ten permisos para comezar unha chamada de conferencia nesta sala",
"Show empty room list headings": "Amosar a cabeceira da lista de salas baleiras",
"This event could not be displayed": "Non se puido amosar este evento",
"Demote yourself?": "Baixarse a si mesmo de rango?",
"Demote": "Baixar de rango",
@ -1212,21 +964,16 @@
"block-quote": "bloque de citas",
"bulleted-list": "lista de puntos",
"numbered-list": "lista numérica",
"You have no historical rooms": "Ton ten salas anteriores",
"In encrypted rooms, like this one, URL previews are disabled by default to ensure that your homeserver (where the previews are generated) cannot gather information about links you see in this room.": "Nas salas cifradas, como é esta, está desactivado por defecto a previsualización das URL co fin de asegurarse de que o servidor local (que é onde se gardan as previsualizacións) non poida recoller información sobre das ligazóns que se ven nesta sala.",
"When someone puts a URL in their message, a URL preview can be shown to give more information about that link such as the title, description, and an image from the website.": "Cando alguén pon unha URL na mensaxe, esta previsualízarase para que así se coñezan xa cousas delas como o título, a descrición ou as imaxes que inclúe ese sitio web.",
"The email field must not be blank.": "Este campo de correo non pode quedar en branco.",
"The user name field must not be blank.": "O campo de nome de usuario non pode quedar en branco.",
"The phone number field must not be blank.": "O número de teléfono non pode quedar en branco.",
"The password field must not be blank.": "O campo do contrasinal non pode quedar en branco.",
"You can't send any messages until you review and agree to <consentLink>our terms and conditions</consentLink>.": "Non vai poder enviar mensaxes ata que revise e acepte <consentLink>os nosos termos e condicións</consentLink>.",
"A call is currently being placed!": "Xa se estableceu a chamada!",
"Sorry, your homeserver is too old to participate in this room.": "Lametámolo, o seu servidor de inicio é vello de máis para participar en esta sala.",
"Please contact your homeserver administrator.": "Por favor, contacte coa administración do seu servidor.",
"Increase performance by only loading room members on first view": "Aumente o rendemento cargando só membros da sala na vista inicial",
"System Alerts": "Alertas do Sistema",
"Internal room ID: ": "ID interno da sala: ",
"Room version number: ": "Número de versión da sala: ",
"Please <a>contact your service administrator</a> to continue using the service.": "Por favor <a>contacte coa administración do servizo</a> para seguir utilizando o servizo.",
"This homeserver has hit its Monthly Active User limit.": "Este servidor acadou o límite mensual de usuarias activas.",
"This homeserver has exceeded one of its resource limits.": "Este servidor excedeu un dos seus límites de recursos.",
@ -1237,9 +984,6 @@
"An error ocurred whilst trying to remove the widget from the room": "Algo fallou mentras se intentaba eliminar o widget da sala",
"Your message wasn't sent because this homeserver has hit its Monthly Active User Limit. Please <a>contact your service administrator</a> to continue using the service.": "A súa mensaxe non foi enviada porque este servidor acadou o Límite Mensual de Usuaria Activa. Por favor <a>contacte coa administración do servizo</a> para continuar utilizando o servizo.",
"Your message wasn't sent because this homeserver has exceeded a resource limit. Please <a>contact your service administrator</a> to continue using the service.": "A súa mensaxe non foi enviada porque o servidor superou o límite de recursos. Por favor <a>contacte coa administración do servizo</a> para continuar utilizando o servizo.",
"Lazy loading members not supported": "A cargar preguiceira de membros non está soportada",
"Lazy loading is not supported by your current homeserver.": "A carga preguiceira non está soportada polo servidor actual.",
"Legal": "Legal",
"Please <a>contact your service administrator</a> to continue using this service.": "Por favor <a>contacte coa administración do servizo</a> para continuar utilizando o servizo.",
"You can also set a custom identity server, but you won't be able to invite users by email address, or be invited by email address yourself.": "Tamén podes fixar un servidor de identidade, pero non poderás invitar a usuarios polo enderezo de correo, e tampouco que te inviten."
"Please <a>contact your service administrator</a> to continue using this service.": "Por favor <a>contacte coa administración do servizo</a> para continuar utilizando o servizo."
}

View file

@ -16,14 +16,7 @@
"VoIP is unsupported": "שיחה מעל IP לא נתמכת",
"You cannot place VoIP calls in this browser.": "אין אפשרות ליצור שיחה מעל IP בדפדפן זה.",
"You cannot place a call with yourself.": "אין אפשרות ליצור שיחה עם עצמך.",
"Conference calls are not supported in this client": "שיחות וועידה לא נתמכות בתכנה הזו",
"Conference calls are not supported in encrypted rooms": "שיחות וועידה לא נתמכות בחדרים מוצפנים",
"Warning!": "אזהרה!",
"Conference calling is in development and may not be reliable.": "שיחות וועידה נמצאות תחת פיתוח ועלולות להיות לא אמינות.",
"Failed to set up conference call": "כישלון ביצירת שיחת וועידה",
"Conference call failed.": "שיחת וועידה נכשלה.",
"The file '%(fileName)s' failed to upload": "העלאת הקובץ '%(fileName)s' נכשלה",
"The file '%(fileName)s' exceeds this home server's size limit for uploads": "הקובץ '%(fileName)s' גדול מהגבלת ההעלאה של שרת הבית",
"Upload Failed": "העלאה נכשלה",
"Sun": "ראשון",
"Mon": "שני",
@ -49,7 +42,6 @@
"Who would you like to add to this community?": "מי תרצה להוסיף לקהילה?",
"Warning: any person you add to a community will be publicly visible to anyone who knows the community ID": "אזהרה: כל אחד שיודע את מזהה הקהילה יוכל לראות את האנשים המוזמנים לקהילה",
"Invite new community members": "הזמן חברי קהילה חדשים",
"Name or matrix ID": "שם או מזהה מטריקס",
"Invite to Community": "הזמן לקהילה",
"Which rooms would you like to add to this community?": "אילו חדרים תרצה להוסיף לקהילה?",
"Show these rooms to non-members on the community page and room list?": "הצג חדרים אלה לחסרי-חשבון על דף הקהילה ורשימת החדרים?",
@ -88,7 +80,6 @@
"No rooms to show": "אין חדרים להצגה",
"Fetching third party location failed": "נסיון להביא מיקום צד שלישי נכשל",
"A new version of Riot is available.": "יצאה גרסה חדשה של Riot.",
"Couldn't load home page": "כשל בטעינת דף הבית",
"Send Account Data": "שלח נתוני משתמש",
"All notifications are currently disabled for all targets.": "התראות מנוטרלות לכלל המערכת.",
"Uploading report": "מעדכן דוח",
@ -102,11 +93,7 @@
"Friday": "שישי",
"Update": "עדכון",
"What's New": "מה חדש",
"Add an email address above to configure email notifications": "הוסף כתובת דואר אלקטורני למעלה בכדי להגדיר התראות",
"Expand panel": "הרחב מסגרת",
"On": "דלוק",
"%(count)s Members|other": " םישמתשמ %(count)s",
"Filter room names": "סנן שמות חדרים",
"Changelog": "דו\"ח שינויים",
"Waiting for response from server": "ממתין לתשובה מהשרת",
"Send Custom Event": "שלח אירוע מותאם אישית",
@ -115,12 +102,9 @@
"delete the alias.": "מחיקת כינוי.",
"To return to your account in future you need to <u>set a password</u>": "להשתמש בחשבונך בעתיד, עליך <u>להגדיר סיסמא</u>",
"Forget": "שכח",
"#example": "#דוגמא",
"Hide panel": "הסתר מסגרת",
"You cannot delete this image. (%(code)s)": "אי אפשר למחוק את התמונה. (%(code)s)",
"Cancel Sending": "ביטול שליחה",
"This Room": "החדר הזה",
"The Home Server may be too old to support third party networks": "שרת הבית ישן ואינו יכול לתמוך ברשתות צד שלישי",
"Noisy": "רועש",
"Error saving email notification preferences": "שגיאה בעת שמירת הגדרות התראה באמצעות הדואר האלקטרוני",
"Messages containing my display name": "הודעות המכילות את שם התצוגה שלי",
@ -128,10 +112,8 @@
"Unavailable": "לא זמין",
"View Decrypted Source": "הצג מקור מפוענח",
"Failed to update keywords": "נכשל עדכון מילים",
"Notes:": "הערות:",
"remove %(name)s from the directory.": "הסר את %(name)s מהרשימה.",
"Notifications on the following keywords follow rules which cant be displayed here:": "התראה על מילות המפתח הבאות עוקבת אחר החוקים שאינם יכולים להיות מוצגים כאן:",
"<safariLink>Safari</safariLink> and <operaLink>Opera</operaLink> work too.": "<safariLink>Safari</safariLink> וגם <operaLink>Opera</operaLink> עובדים.",
"Please set a password!": "נא להגדיר סיסמא!",
"You have successfully set a password!": "שינוי סיסמא בוצע בהצלחה!",
"An error occurred whilst saving your email notification preferences.": "קרתה שגיאה בזמן שמירת הגדרות התראה באמצעות הדואר האלקטרוני.",
@ -142,15 +124,12 @@
"Members": "חברים",
"No update available.": "אין עדכון זמין.",
"Resend": "שלח מחדש",
"Failed to get protocol list from Home Server": "נכשל בעת נסיון קבלת רשימת פרוטוקולים משרת הבית",
"Collecting app version information": "אוסף מידע על גרסת היישום",
"Delete the room alias %(alias)s and remove %(name)s from the directory?": "מחק כינוי %(alias)s של החדר והסר את %(name)s מהרשימה?",
"This will allow you to return to your account after signing out, and sign in on other devices.": "זה יאפשר לך לחזור לחשבונך אחרי התנתקות ולהתחבר באמצעות התקנים אחרים.",
"Keywords": "מילות מפתח",
"Enable notifications for this account": "אפשר התראות לחשבון זה",
"Directory": "ספרייה",
"Invite to this community": "הזמן לקהילה זו",
"Failed to get public room list": "נכשלה קבלת רשימת חדרים ציבוריים",
"Messages containing <span>keywords</span>": "הודעות המכילות <span> מילות מפתח </span>",
"Room not found": "חדר לא נמצא",
"Tuesday": "שלישי",
@ -160,7 +139,6 @@
"Riot uses many advanced browser features, some of which are not available or experimental in your current browser.": "Riot משתמש במספר רב של אפשרויות מתקדמות בדפדפן, חלק מהן לא זמינות או בשלבי נסיון בדפדפן שבשימושך כרגע.",
"Event sent!": "ארוע נשלח!",
"Preparing to send logs": "מתכונן לשלוח יומנים",
"Enable desktop notifications": "אפשר התראות בשולחן העבודה",
"Remember, you can always set an email address in user settings if you change your mind.": "להזכירך: תמיד ניתן לשנות כתובת אימייל בהגדרות משתש. למקרה שתתחרט/י.",
"Explore Account Data": "גלה פרטי משתמש",
"All messages (noisy)": "כל ההודעות (רועש)",
@ -173,17 +151,12 @@
"Monday": "שני",
"Remove from Directory": "הסר מהרשימה",
"Enable them now": "אפשר אותם כעת",
"Messages containing my user name": "הודעות המכילות את שם המשתמש שלי",
"Toolbox": "תיבת כלים",
"Collecting logs": "אוסף יומנים לנפוי שגיאה (דבאג)",
"more": "עוד",
"GitHub issue link:": "קישור לדווח תקלה בGitHub:",
"Search for a room": "חפש חדר",
"Debug logs contain application usage data including your username, the IDs or aliases of the rooms or groups you have visited and the usernames of other users. They do not contain messages.": "יומני ניפוי שגיאה (דבאג) מכילים מידע על שימוש ביישום, כולל שם משתמש, מזהים או כינויים שהתמשת בהם. בחדרי שיחוח, או קבוצות בהם השתתפת. וגם שמות משתמשים אחרים. אך אינם כוללים הודעות.",
"(HTTP status %(httpStatus)s)": "(מצב HTTP %(httpStatus)s )",
"All Rooms": "כל החדרים",
"State Key": "מקש מצב",
"Please install <chromeLink>Chrome</chromeLink> or <firefoxLink>Firefox</firefoxLink> for the best experience.": "אנא התקן <firefoxLink>Firefox</firefoxLink> או <chromeLink>Chrome</chromeLink> לחוויה מיטבית.",
"Wednesday": "רביעי",
"Quote": "ציטוט",
"Send logs": "שלח יומנים",
@ -216,11 +189,9 @@
"Messages in group chats": "הודעות בקבוצות השיחה",
"Yesterday": "אתמול",
"Error encountered (%(errorDetail)s).": "ארעה שגיעה %(errorDetail)s .",
"Login": "התחבר",
"Low Priority": "עדיפות נמוכה",
"Unable to fetch notification target list": "לא ניתן לאחזר רשימת יעדי התראה",
"Set Password": "הגדר סיסמא",
"Enable audible notifications in web client": "אפשר התראות קוליות בדפדפן",
"Off": "סגור",
"Riot does not know how to join a room on this network": "Riot אינו יודע כיצד להצטרף לחדר ברשת זו",
"Mentions only": "מאזכר בלבד",
@ -232,12 +203,10 @@
"Pin Message": "הצמד הודעה",
"Failed to change settings": "נכשל בעת שינוי הגדרות",
"View Community": "הצג קהילה",
"%(count)s Members|one": " םישמתשמ %(count)s",
"Developer Tools": "כלי מפתחים",
"View Source": "הצג מקור",
"Event Content": "תוכן הארוע",
"Thank you!": "רב תודות!",
"Collapse panel": "סגור מסגרת",
"With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "באמצעות הדפדפן הנוכחי שלך המראה של היישום יכול להיות שגוי לחלוטין וחלק מהאפשרויות לא תתפקדנה. אם תרצה לנסות בכל זאת תוכל אבל אז כל האחריות עליך!",
"Checking for an update...": "בודק עדכונים...",
"There are advanced notifications which are not shown here": "ישנן התראות מתקדמות אשר אינן מוצגות כאן"

View file

@ -10,7 +10,6 @@
"Failed to verify email address: make sure you clicked the link in the email": "ईमेल आईडी सत्यापित नही हो पाया: कृपया सुनिश्चित कर लें कि आपने ईमेल में मौजूद लिंक पर क्लिक किया है",
"The platform you're on": "आप जिस प्लेटफार्म पर हैं",
"The version of Riot.im": "रायट.आई एम का जो संस्करण",
"Whether or not you're logged in (we don't record your user name)": "चाहे आप लॉग इन हों या ना हों( हम आपका खाता नाम दर्ज नहीं करते )",
"Your language of choice": "आपकी चयन की भाषा",
"Which officially provided instance you are using, if any": "क्या आप कोई अधिकृत संस्करण इस्तेमाल कर रहे हैं? अगर हां, तो कौन सा",
"Your homeserver's URL": "आपके होमसर्वर का यूआरएल",
@ -43,14 +42,11 @@
"You cannot place VoIP calls in this browser.": "आप इस ब्राउज़र में VoIP कॉल नहीं कर सकते हैं।",
"You cannot place a call with yourself.": "आप अपने साथ कॉल नहीं कर सकते हैं।",
"Could not connect to the integration server": "इंटीग्रेशन सर्वर से संपर्क नहीं हो सका",
"A conference call could not be started because the intgrations server is not available": "कॉन्फ़्रेंस कॉल प्रारंभ नहीं किया जा सका क्योंकि इंटीग्रेशन सर्वर उपलब्ध नहीं है",
"Call in Progress": "कॉल चालू हैं",
"A call is currently being placed!": "वर्तमान में एक कॉल किया जा रहा है!",
"A call is already in progress!": "कॉल पहले ही प्रगति पर है!",
"Permission Required": "अनुमति आवश्यक है",
"You do not have permission to start a conference call in this room": "आपको इस रूम में कॉन्फ़्रेंस कॉल शुरू करने की अनुमति नहीं है",
"The file '%(fileName)s' failed to upload": "फ़ाइल '%(fileName)s' अपलोड करने में विफल रही",
"The file '%(fileName)s' exceeds this home server's size limit for uploads": "फाइल '%(fileName)s' अपलोड के लिए इस होम सर्वर की आकार सीमा से अधिक है",
"Upload Failed": "अपलोड विफल",
"Sun": "रवि",
"Mon": "सोम",
@ -80,7 +76,6 @@
"Who would you like to add to this community?": "आप इस कम्युनिटी में किसे जोड़ना चाहेंगे?",
"Warning: any person you add to a community will be publicly visible to anyone who knows the community ID": "चेतावनी: किसी भी कम्युनिटी में जो भी व्यक्ति आप जोड़ते हैं वह सार्वजनिक रूप से किसी को भी दिखाई देगा जो कम्युनिटी आईडी जानता है",
"Invite new community members": "नए कम्युनिटी के सदस्यों को आमंत्रित करें",
"Name or matrix ID": "नाम या मैट्रिक्स ID",
"Invite to Community": "कम्युनिटी में आमंत्रित करें",
"Which rooms would you like to add to this community?": "आप इस समुदाय में कौन से रूम जोड़ना चाहते हैं?",
"Show these rooms to non-members on the community page and room list?": "क्या आप इन मैट्रिक्स रूम को कम्युनिटी पृष्ठ और रूम लिस्ट के गैर सदस्यों को दिखाना चाहते हैं?",
@ -105,12 +100,9 @@
"Admin": "व्यवस्थापक",
"Start a chat": "एक चैट शुरू करें",
"Who would you like to communicate with?": "आप किसके साथ संवाद करना चाहते हैं?",
"Email, name or matrix ID": "ईमेल, नाम या मैट्रिक्स आईडी",
"Start Chat": "चैट शुरू करें",
"Invite new room members": "नए रूम के सदस्यों को आमंत्रित करें",
"Who would you like to add to this room?": "आप इस रूम में किसे जोड़ना चाहेंगे?",
"Send Invites": "आमंत्रण भेजें",
"Failed to invite user": "उपयोगकर्ता को आमंत्रित करने में विफल",
"Operation failed": "कार्रवाई विफल",
"Failed to invite": "आमंत्रित करने में विफल",
"Failed to invite the following users to the %(roomName)s room:": "निम्नलिखित उपयोगकर्ताओं को %(roomName)s रूम में आमंत्रित करने में विफल:",
@ -132,15 +124,12 @@
"/ddg is not a command": "/ddg एक कमांड नहीं है",
"To use it, just wait for autocomplete results to load and tab through them.": "इसका उपयोग करने के लिए, बस स्वत: पूर्ण परिणामों को लोड करने और उनके माध्यम से टैब के लिए प्रतीक्षा करें।",
"Changes your display nickname": "अपना प्रदर्शन उपनाम बदलता है",
"Changes colour scheme of current room": "वर्तमान कमरे की रंग योजना बदलता है",
"Sets the room topic": "कमरे के विषय सेट करता है",
"Invites user with given id to current room": "दिए गए आईडी के साथ उपयोगकर्ता को वर्तमान रूम में आमंत्रित करता है",
"Joins room with given alias": "दिए गए उपनाम के साथ रूम में शामिल हो जाता है",
"Leave room": "रूम छोड़ें",
"Unrecognised room alias:": "अपरिचित रूम उपनाम:",
"Kicks user with given id": "दिए गए आईडी के साथ उपयोगकर्ता को निर्वासन(किक) करता हैं",
"Bans user with given id": "दिए गए आईडी के साथ उपयोगकर्ता को प्रतिबंध लगाता है",
"Unbans user with given id": "दिए गए आईडी के साथ उपयोगकर्ता को अप्रतिबंधित करता हैं",
"Ignores a user, hiding their messages from you": "उपयोगकर्ता को अनदेखा करें और स्वयं से संदेश छुपाएं",
"Ignored user": "अनदेखा उपयोगकर्ता",
"You are now ignoring %(userId)s": "आप %(userId)s को अनदेखा कर रहे हैं",
@ -198,7 +187,6 @@
"(no answer)": "(कोई जवाब नहीं)",
"(unknown failure: %(reason)s)": "(अज्ञात विफलता: %(reason)s)",
"%(senderName)s ended the call.": "%(senderName)s ने कॉल समाप्त कर दिया।",
"%(senderName)s placed a %(callType)s call.": "%(senderName)s ने %(callType)s कॉल रखा।",
"%(senderName)s sent an invitation to %(targetDisplayName)s to join the room.": "%(senderName)s रूम में शामिल होने के लिए %(targetDisplayName)s को निमंत्रण भेजा।",
"%(senderName)s made future room history visible to all room members, from the point they are invited.": "%(senderName)s ने भविष्य के रूम का इतिहास सभी रूम के सदस्यों के लिए प्रकाशित कर दिया जिस बिंदु से उन्हें आमंत्रित किया गया था।",
"%(senderName)s made future room history visible to all room members, from the point they joined.": "%(senderName)s ने भविष्य के रूम का इतिहास सभी रूम के सदस्यों के लिए दृश्यमान किया, जिस बिंदु में वे शामिल हुए थे।",
@ -212,10 +200,6 @@
"%(widgetName)s widget modified by %(senderName)s": "%(widgetName)s विजेट %(senderName)s द्वारा संशोधित",
"%(widgetName)s widget added by %(senderName)s": "%(widgetName)s विजेट %(senderName)s द्वारा जोड़ा गया",
"%(widgetName)s widget removed by %(senderName)s": "%(widgetName)s विजेट %(senderName)s द्वारा हटा दिया गया",
"%(displayName)s is typing": "%(displayName)s टाइप कर रहा है",
"%(names)s and %(count)s others are typing|other": "%(names)s और %(count)s अन्य टाइप कर रहे हैं",
"%(names)s and %(count)s others are typing|one": "%(names)s और एक दूसरा व्यक्ति टाइप कर रहे हैं",
"%(names)s and %(lastPerson)s are typing": "%(names)s और %(lastPerson)s टाइप कर रहे हैं",
"Failure to create room": "रूम बनाने में विफलता",
"Server may be unavailable, overloaded, or you hit a bug.": "सर्वर अनुपलब्ध, अधिभारित हो सकता है, या अपने एक सॉफ्टवेयर गर्बरी को पाया।",
"Send anyway": "वैसे भी भेजें",
@ -232,27 +216,14 @@
"Please contact your homeserver administrator.": "कृपया अपने होमसर्वर व्यवस्थापक से संपर्क करें।",
"Failed to join room": "रूम में शामिल होने में विफल",
"Message Pinning": "संदेश पिनिंग",
"Increase performance by only loading room members on first view": "पहले दृश्य पर केवल कमरे के सदस्यों को लोड करके प्रदर्शन बढ़ाएं",
"Backup of encryption keys to server": "सर्वर पर एन्क्रिप्शन कुंजी का बैकअप",
"Disable Emoji suggestions while typing": "टाइप करते समय इमोजी सुझाव अक्षम करें",
"Use compact timeline layout": "कॉम्पैक्ट टाइमलाइन लेआउट का प्रयोग करें",
"Hide removed messages": "हटाए गए संदेशों को छुपाएं",
"Hide join/leave messages (invites/kicks/bans unaffected)": "शामिल होने/छोड़ने के सन्देश छुपाएं (आमंत्रित / किक/ प्रतिबंध अप्रभावित)",
"Hide avatar changes": "अवतार परिवर्तन छुपाएं",
"Hide display name changes": "प्रदर्शन नाम परिवर्तन छुपाएं",
"Hide read receipts": "पढ़ी रसीदें छुपाएं",
"Show timestamps in 12 hour format (e.g. 2:30pm)": "१२ घंटे प्रारूप में टाइमस्टैम्प दिखाएं (उदहारण:२:३० अपराह्न बजे)",
"Always show message timestamps": "हमेशा संदेश टाइमस्टैम्प दिखाएं",
"Autoplay GIFs and videos": "जीआईएफ और वीडियो को स्वत: प्ले करें",
"Always show encryption icons": "हमेशा एन्क्रिप्शन आइकन दिखाएं",
"Enable automatic language detection for syntax highlighting": "वाक्यविन्यास हाइलाइटिंग के लिए स्वत: भाषा का पता प्रणाली सक्षम करें",
"Hide avatars in user and room mentions": "उपयोगकर्ता और रूम के उल्लेखों में अवतार छुपाएं",
"Disable big emoji in chat": "बातचीत में बड़ा इमोजी अक्षम करें",
"Don't send typing notifications": "टाइपिंग नोटिफिकेशन न भेजें",
"Automatically replace plain text Emoji": "स्वचालित रूप से सादा पाठ इमोजी को प्रतिस्थापित करें",
"Mirror local video feed": "स्थानीय वीडियो फ़ीड को आईना करें",
"Disable Community Filter Panel": "सामुदायिक फ़िल्टर पैनल अक्षम करें",
"Disable Peer-to-Peer for 1:1 calls": "१:१ कॉल के लिए पीयर-टू-पीयर अक्षम करें",
"Send analytics data": "विश्लेषण डेटा भेजें",
"Never send encrypted messages to unverified devices from this device": "इस डिवाइस से असत्यापित डिवाइस पर एन्क्रिप्टेड संदेश कभी न भेजें",
"Never send encrypted messages to unverified devices in this room from this device": "इस डिवाइस से असत्यापित डिवाइस पर एन्क्रिप्टेड संदेश कभी न भेजें",
@ -260,17 +231,13 @@
"Enable URL previews for this room (only affects you)": "इस रूम के लिए यूआरएल पूर्वावलोकन सक्षम करें (केवल आपको प्रभावित करता है)",
"Enable URL previews by default for participants in this room": "इस रूम में प्रतिभागियों के लिए डिफ़ॉल्ट रूप से यूआरएल पूर्वावलोकन सक्षम करें",
"Room Colour": "रूम का रंग",
"Pin rooms I'm mentioned in to the top of the room list": "रूम की सूची के शीर्ष पर पिन रूम का उल्लेख करें",
"Pin unread rooms to the top of the room list": "रूम की सूची के शीर्ष पर अपठित रूम पिन करें",
"Enable widget screenshots on supported widgets": "समर्थित विजेट्स पर विजेट स्क्रीनशॉट सक्षम करें",
"Show empty room list headings": "खाली रूम सूची शीर्षलेख दिखाएं",
"Show developer tools": "डेवलपर टूल दिखाएं",
"Collecting app version information": "ऐप संस्करण जानकारी एकत्रित कर रहा हैं",
"Collecting logs": "लॉग एकत्रित कर रहा हैं",
"Uploading report": "रिपोर्ट अपलोड हो रहा है",
"Waiting for response from server": "सर्वर से प्रतिक्रिया की प्रतीक्षा कर रहा है",
"Messages containing my display name": "मेरे प्रदर्शन नाम वाले संदेश",
"Messages containing my user name": "मेरे उपयोगकर्ता नाम युक्त संदेश",
"Messages in one-to-one chats": "एक-से-एक चैट में संदेश",
"Messages in group chats": "समूह चैट में संदेश",
"When I'm invited to a room": "जब मुझे एक रूम में आमंत्रित किया जाता है",
@ -284,12 +251,9 @@
"Decline": "पतन",
"Accept": "स्वीकार",
"Error": "त्रुटि",
"A text message has been sent to +%(msisdn)s. Please enter the verification code it contains": "एक टेक्स्ट संदेश %(msisdn)s को भेजा गया है। कृपया इसमें सत्यापन कोड दर्ज करें",
"Incorrect verification code": "गलत सत्यापन कोड",
"Enter Code": "कोड दर्ज करें",
"Submit": "जमा करें",
"Phone": "फ़ोन",
"Add phone number": "फोन नंबर डालें",
"Add": "जोड़े",
"Failed to upload profile picture!": "प्रोफाइल तस्वीर अपलोड करने में विफल!",
"Upload new:": "नया अपलोड करें:",
@ -305,26 +269,18 @@
"New Password": "नया पासवर्ड",
"Confirm password": "पासवर्ड की पुष्टि कीजिये",
"Change Password": "पासवर्ड बदलें",
"Your home server does not support device management.": "आपका होम सर्वर डिवाइस प्रबंधन का समर्थन नहीं करता है।",
"Unable to load device list": "डिवाइस सूची लोड करने में असमर्थ",
"Authentication": "प्रमाणीकरण",
"Delete %(count)s devices|other": "%(count)s यंत्र हटाएं",
"Delete %(count)s devices|one": "यंत्र हटाएं",
"Device ID": "यंत्र आईडी",
"Device Name": "यंत्र का नाम",
"Last seen": "अंतिम बार देखा गया",
"Select devices": "यंत्रो का चयन करें",
"Failed to set display name": "प्रदर्शन नाम सेट करने में विफल",
"Disable Notifications": "नोटीफिकेशन निष्क्रिय करें",
"Enable Notifications": "सूचनाएं सक्षम करें",
"Delete Backup": "बैकअप हटाएं",
"Delete your backed up encryption keys from the server? You will no longer be able to use your recovery key to read encrypted message history": "सर्वर से अपनी बैक अप एन्क्रिप्शन कुंजी हटाएं? एन्क्रिप्टेड संदेश इतिहास पढ़ने के लिए अब आप अपनी रिकवरी कुंजी का उपयोग नहीं कर पाएंगे",
"Delete backup": "बैकअप हटाएं",
"Unable to load key backup status": "कुंजी बैकअप स्थिति लोड होने में असमर्थ",
"This device is uploading keys to this backup": "यह यंत्र इस बैकअप में कुंजी अपलोड कर रहा है",
"This device is <b>not</b> uploading keys to this backup": "यह यंत्र बैकअप में कुंजी अपलोड <b>नहीं</b> कर रहा है",
"Backup has a <validity>valid</validity> signature from this device": "इस डिवाइस से बैकअप में <validity> वैध </ validity> हस्ताक्षर है",
"Backup has a <validity>valid</validity> signature from <verify>verified</verify> device <device>x</device>": "<verify>सत्यापित</ verify> डिवाइस <device>x</ device> से बैकअप में <validity>मान्य</validity> हस्ताक्षर है",
"Backup has a <validity>valid</validity> signature from <verify>unverified</verify> device <device></device>": "<verify>असत्यापित</ verify> डिवाइस <device></ device> से बैकअप में <validity>मान्य</validity> हस्ताक्षर है",
"Backup has an <validity>invalid</validity> signature from <verify>verified</verify> device <device></device>": "<verify>सत्यापित</ verify> डिवाइस <device></ device> से बैकअप में <validity>अमान्य</validity> हस्ताक्षर है",
"Backup has an <validity>invalid</validity> signature from <verify>unverified</verify> device <device></device>": "<verify>असत्यापित</ verify> डिवाइस <device></ device> से बैकअप में <validity>अमान्य</validity> हस्ताक्षर है",
@ -332,9 +288,6 @@
"Backup is not signed by any of your devices": "बैकअप आपके किसी भी डिवाइस द्वारा हस्ताक्षरित नहीं है",
"Backup version: ": "बैकअप संस्करण: ",
"Algorithm: ": "कलन विधि: ",
"Restore backup": "बैकअप बहाल करें",
"No backup is present": "कोई बैकअप प्रस्तुत नहीं है",
"Start a new backup": "एक नया बैकअप शुरू करें",
"Error saving email notification preferences": "ईमेल अधिसूचना प्राथमिकताओं को सहेजने में त्रुटि",
"An error occurred whilst saving your email notification preferences.": "आपकी ईमेल अधिसूचना वरीयताओं को सहेजते समय एक त्रुटि हुई।",
"Keywords": "कीवर्ड",
@ -348,7 +301,6 @@
"Notify me for anything else": "मुझे किसी और चीज़ के लिए सूचित करें",
"Enable notifications for this account": "इस खाते के लिए अधिसूचनाएं सक्षम करें",
"All notifications are currently disabled for all targets.": "सभी सूचनाएं वर्तमान में सभी लक्ष्यों के लिए अक्षम हैं।",
"Add an email address above to configure email notifications": "ईमेल अधिसूचनाओं को कॉन्फ़िगर करने के लिए उपरोक्त एक ईमेल पता जोड़ें",
"Enable email notifications": "ईमेल अधिसूचनाएं सक्षम करें",
"Notifications on the following keywords follow rules which cant be displayed here:": "निम्नलिखित कीवर्ड पर अधिसूचनाएं नियमों का पालन करती हैं जिन्हें यहां प्रदर्शित नहीं किया जा सकता है:",
"Unable to fetch notification target list": "अधिसूचना लक्ष्य सूची लाने में असमर्थ",
@ -391,9 +343,7 @@
"Encrypted messages in group chats": "समूह चैट में एन्क्रिप्टेड संदेश",
"Backup has a <validity>valid</validity> signature from <verify>verified</verify> device <device></device>": "बैकअप के पास <verify>सत्यापित</verify> डिवाइस <device></device> से <validity>वैध</validity> हस्ताक्षर है",
"You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply": "हो सकता है कि आपने उन्हें रायट के अलावा किसी अन्य ग्राहक में कॉन्फ़िगर किया हो। आप उन्हें रायट में ट्यून नहीं कर सकते लेकिन वे अभी भी आवेदन करते हैं",
"Enable desktop notifications": "डेस्कटॉप अधिसूचनाएं सक्षम करें",
"Show message in desktop notification": "डेस्कटॉप अधिसूचना में संदेश दिखाएं",
"Enable audible notifications in web client": "वेब क्लाइंट में श्रव्य अधिसूचनाएं सक्षम करें",
"Off": "बंद",
"On": "चालू",
"Noisy": "शोरगुल",
@ -416,15 +366,10 @@
"Key request sent.": "कुंजी अनुरोध भेजा गया।",
"<requestLink>Re-request encryption keys</requestLink> from your other devices.": "अपने अन्य उपकरणों से <requestLink>एन्क्रिप्शन कुंजी का पुन: अनुरोध</requestLink> करें ।",
"Undecryptable": "डिक्रिप्ट करना संभव नहीं",
"Encrypting": "एन्क्रिप्ट किया जा रहा",
"Encrypted, not sent": "एन्क्रिप्ट हो चूका, भेजा नहीं गया",
"Encrypted by a verified device": "एक सत्यापित डिवाइस द्वारा एन्क्रिप्ट किया गया",
"Encrypted by an unverified device": "एक असत्यापित डिवाइस द्वारा एन्क्रिप्ट किया गया",
"Unencrypted message": "बिना एन्क्रिप्ट वाला संदेश",
"Please select the destination room for this message": "कृपया इस संदेश के लिए गंतव्य रूम का चयन करें",
"Blacklisted": "काली सूची में डाला गया",
"Verified": "सत्यापित",
"Unverified": "असत्यापित",
"device id: ": "डिवाइस आईडी: ",
"Disinvite": "आमंत्रित नहीं करना",
"Kick": "किक",
@ -459,7 +404,6 @@
"Revoke Moderator": "मॉडरेटर को रद्द करें",
"Make Moderator": "मॉडरेटर बनायें",
"Admin Tools": "व्यवस्थापक उपकरण",
"Level:": "स्तर:",
"Close": "बंद",
"and %(count)s others...|other": "और %(count)s अन्य ...",
"and %(count)s others...|one": "और एक अन्य...",
@ -475,12 +419,6 @@
"bulleted-list": "बुलेटेड सूची",
"numbered-list": "गिने-सूची",
"Attachment": "आसक्ति",
"At this time it is not possible to reply with a file so this will be sent without being a reply.": "इस समय फ़ाइल के साथ जवाब देना संभव नहीं है, इसलिए इसे उत्तर दिए बिना भेजा जाएगा।",
"Are you sure you want to upload the following files?": "क्या आप वाकई निम्नलिखित फाइलें अपलोड करना चाहते हैं?",
"The following files cannot be uploaded:": "निम्नलिखित फाइलें अपलोड नहीं की जा सकती हैं:",
"Upload Files": "फाइल अपलोड करें",
"Encrypted room": "एन्क्रिप्टेड रूम",
"Unencrypted room": "अनएन्क्रिप्टेड रूम",
"Hangup": "फोन रख देना",
"Voice call": "आवाज कॉल",
"Video call": "वीडियो कॉल",
@ -493,8 +431,6 @@
"This room has been replaced and is no longer active.": "इस रूम को बदल दिया गया है और अब सक्रिय नहीं है।",
"The conversation continues here.": "वार्तालाप यहां जारी है।",
"You do not have permission to post to this room": "आपको इस रूम में पोस्ट करने की अनुमति नहीं है",
"Turn Markdown on": "मार्कडाउन चालू करें",
"Turn Markdown off": "मार्कडाउन बंद करें",
"Hide Text Formatting Toolbar": "टेक्स्ट स्वरूपण टूलबार छुपाएं",
"Server error": "सर्वर त्रुटि",
"Server unavailable, overloaded, or something else went wrong.": "सर्वर अनुपलब्ध, अधिभारित, या कुछ और गलत हो गया।",
@ -521,7 +457,6 @@
"Offline": "ऑफलाइन",
"Unknown": "अज्ञात",
"Chat with Riot Bot": "रायट बॉट के साथ चैट करें",
"You can also set a custom identity server, but you won't be able to invite users by email address, or be invited by email address yourself.": "आप एक कस्टम पहचान सर्वर भी सेट कर सकते हैं, लेकिन आप उपयोगकर्ताओं को ईमेल पते से आमंत्रित नहीं कर पाएंगे, या स्वयं ईमेल पते से आमंत्रित नहीं किया जाएगा।",
"Whether or not you're logged in (we don't record your username)": "आप लॉग इन हैं या नहीं (हम आपका उपयोगकर्ता नाम रिकॉर्ड नहीं करते हैं)",
"The file '%(fileName)s' exceeds this homeserver's size limit for uploads": "फ़ाइल '%(fileName)s' अपलोड के लिए इस होमस्वर के आकार की सीमा से अधिक है",
"Upgrades a room to a new version": "एक रूम को एक नए संस्करण में अपग्रेड करता है",
@ -544,7 +479,6 @@
"Straight rows of keys are easy to guess": "कुंजी की सीधी पंक्तियों का अनुमान लगाना आसान है",
"Short keyboard patterns are easy to guess": "लघु कीबोर्ड पैटर्न का अनुमान लगाना आसान है",
"Custom user status messages": "कस्टम उपयोगकर्ता स्थिति संदेश",
"Show recent room avatars above the room list (refresh to apply changes)": "कमरे की सूची के ऊपर हाल के अवतारों को दिखाएं (परिवर्तनों को लागू करने के लिए ताज़ा करें)",
"Group & filter rooms by custom tags (refresh to apply changes)": "कस्टम टैग द्वारा समूह और फ़िल्टर कमरे (परिवर्तन लागू करने के लिए ताज़ा करें)",
"Render simple counters in room header": "कमरे के हेडर में साधारण काउंटर रेंडर करें",
"Enable Emoji suggestions while typing": "टाइप करते समय इमोजी सुझावों को सक्षम करें",
@ -552,7 +486,6 @@
"Show join/leave messages (invites/kicks/bans unaffected)": "जोड़े / छोड़ें संदेशों को दिखाए (आमंत्रित / किक / प्रतिबंध अप्रभावित)",
"Show avatar changes": "अवतार परिवर्तन दिखाएं",
"Show display name changes": "प्रदर्शन नाम परिवर्तन दिखाएं",
"Show read receipts": "पढ़ी गई रसीदें दिखाएं",
"Show avatars in user and room mentions": "उपयोगकर्ता और कक्ष उल्लेख में अवतार दिखाएँ",
"Enable big emoji in chat": "चैट में बड़े इमोजी सक्षम करें",
"Send typing notifications": "टाइपिंग सूचनाएं भेजें",
@ -615,7 +548,6 @@
"Book": "पुस्तक",
"Pencil": "पेंसिल",
"Paperclip": "पेपर क्लिप",
"Scisors": "कैंची",
"Padlock": "ताला",
"Key": "चाबी",
"Hammer": "हथौड़ा",
@ -649,9 +581,7 @@
"Encrypted messages are secured with end-to-end encryption. Only you and the recipient(s) have the keys to read these messages.": "एन्क्रिप्ट किए गए संदेश एंड-टू-एंड एन्क्रिप्शन के साथ सुरक्षित हैं। केवल आपके और प्राप्तकर्ता के पास ही इन संदेशों को पढ़ने की कुंजी है।",
"Restore from Backup": "बैकअप से बहाल करना",
"This device is backing up your keys. ": "यह उपकरण आपकी कुंजी का बैकअप ले रहा है। ",
"This device is <b>not backing up your keys</b>.": "यह उपकरण <b> आपकी कुंजी का बैकअप नहीं कर रहा है </ b>।",
"Back up your keys before signing out to avoid losing them.": "उन्हें खोने से बचने के लिए साइन आउट करने से पहले अपनी कुंजियों का बैकअप लें।",
"Use key backup": "कुंजी बैकअप का उपयोग करें",
"Backing up %(sessionsRemaining)s keys...": "%(sessionsRemaining)s कुंजी का बैकअप कर रहा है ...",
"All keys backed up": "सभी कुंजियाँ वापस आ गईं",
"Backup has a signature from <verify>unknown</verify> device with ID %(deviceId)s.": "बैकअप में आईडी %(deviceId)s के साथ <verify>अज्ञात</verify> डिवाइस से एक हस्ताक्षर है।",
@ -668,7 +598,6 @@
"Display Name": "प्रदर्शित होने वाला नाम",
"Save": "अमुकनाम्ना",
"This room is not accessible by remote Matrix servers": "यह रूम रिमोट मैट्रिक्स सर्वर द्वारा सुलभ नहीं है",
"Upgrade room to version %(ver)s": "रूम को संस्करण %(ver)s में अपग्रेड किया गया",
"Room information": "रूम जानकारी",
"Internal room ID:": "आंतरिक कक्ष आईडी:",
"Room version": "रूम का संस्करण",
@ -690,7 +619,6 @@
"Phone numbers": "फोन नंबर",
"Language and region": "भाषा और क्षेत्र",
"Theme": "थीम",
"Default theme": "पूर्व निर्धारित थीम",
"Dark theme": "डार्क थीम",
"Account management": "खाता प्रबंधन",
"Deactivating your account is a permanent action - be careful!": "अपने खाते को निष्क्रिय करना एक स्थायी कार्रवाई है - सावधान रहें!",
@ -704,7 +632,6 @@
"Bug reporting": "बग रिपोर्टिंग",
"If you've submitted a bug via GitHub, debug logs can help us track down the problem. Debug logs contain application usage data including your username, the IDs or aliases of the rooms or groups you have visited and the usernames of other users. They do not contain messages.": "यदि आपने GitHub के माध्यम से बग सबमिट किया है, तो डिबग लॉग हमें समस्या को ट्रैक करने में मदद कर सकते हैं। डीबग लॉग में आपके उपयोगकर्ता नाम, आपके द्वारा देखे गए कमरों या समूहों के आईडी या उपनाम और अन्य उपयोगकर्ताओं के उपयोगकर्ता नाम सहित एप्लिकेशन उपयोग डेटा होता है। उसमे व्यक्तिगत सन्देश नहीं रहते हैं।",
"Submit debug logs": "डिबग लॉग जमा करें",
"Clear Cache and Reload": "कैश साफ़ और रीलोड करें",
"FAQ": "सामान्य प्रश्न",
"Versions": "संस्करण",
"matrix-react-sdk version:": "मैट्रिक्स-प्रतिक्रिया-एसडीके संस्करण:",
@ -726,7 +653,6 @@
"Order rooms in the room list by most important first instead of most recent": "कक्ष सूचि में सभी कक्षों को हाल के कक्षों के बजाय सबसे महत्वपूर्ण वाले कक्ष पहले रखे",
"Scissors": "कैंची",
"Light theme": "लाइट थीम",
"Close button should minimize window to tray": "क्लोज बटन को विंडो को ट्रे में मिनीमाइज करना चाहिए",
"Timeline": "समयसीमा",
"Room list": "कक्ष सूचि",
"Autocomplete delay (ms)": "स्वत: पूर्ण विलंब (ms)",
@ -755,23 +681,8 @@
"Microphone": "माइक्रोफ़ोन",
"Camera": "कैमरा",
"Voice & Video": "ध्वनि और वीडियो",
"To change the room's avatar, you must be a": "कमरे के अवतार को बदलने के लिए, आपको होना चाहिए",
"To change the room's name, you must be a": "कमरे का नाम बदलने के लिए, आपको होना चाहिए",
"To change the room's main address, you must be a": "कमरे के मुख्य पते को बदलने के लिए, आपको होना चाहिए",
"To change the room's history visibility, you must be a": "कमरे के इतिहास की दृश्यता को बदलने के लिए, आपको होना चाहिए",
"To change the permissions in the room, you must be a": "कमरे में अनुमतियों को बदलने के लिए, आपको होना चाहिए",
"To change the topic, you must be a": "विषय को बदलने के लिए, आपको होना चाहिए",
"To modify widgets in the room, you must be a": "कमरे में विगेट्स को संशोधित करने के लिए, आपको होना चाहिए",
"Failed to unban": "अप्रतिबंधित करने में विफल",
"Banned by %(displayName)s": "%(displayName)s द्वारा प्रतिबंधित",
"The default role for new room members is": "नए कमरे के सदस्यों के लिए डिफ़ॉल्ट भूमिका है",
"To send messages, you must be a": "संदेश भेजने के लिए, आपको होना चाहिए",
"To invite users into the room, you must be a": "उपयोगकर्ताओं को कमरे में आमंत्रित करने के लिए, आपको होना चाहिए",
"To configure the room, you must be a": "कमरे को कॉन्फ़िगर करने के लिए, आपको होना चाहिए",
"To kick users, you must be a": "उपयोगकर्ताओं को किक करने के लिए, आपको होना चाहिए",
"To ban users, you must be a": "उपयोगकर्ताओं को प्रतिबंधित करने के लिए, आपको होना चाहिए",
"To remove other users' messages, you must be a": "अन्य उपयोगकर्ताओं के संदेशों को हटाने के लिए, आपको होना चाहिए",
"To notify everyone in the room, you must be a": "कमरे में सभी को सूचित करने के लिए, आपको होना चाहिए",
"No users have specific privileges in this room": "इस कमरे में किसी भी उपयोगकर्ता के विशेष विशेषाधिकार नहीं हैं",
"Whether or not you're using the 'breadcrumbs' feature (avatars above the room list)": "आप 'ब्रेडक्रंब' सुविधा का उपयोग कर रहे हैं या नहीं (कमरे की सूची के ऊपर अवतार)",
"Replying With Files": "फाइलों के साथ उत्तर",
@ -783,14 +694,12 @@
"Room upgrades are usually recommended when a room version is considered <i>unstable</i>. Unstable room versions might have bugs, missing features, or security vulnerabilities.": "एक कमरे के संस्करण को <i>अस्थिर</i> माना जाता है, तो आमतौर पर कमरे के उन्नयन की सिफारिश की जाती है। अस्थिर कमरे के संस्करणों में बग, लापता विशेषताएं या सुरक्षा कमजोरियां हो सकती हैं।",
"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 />.": "रूम का उन्नयन आमतौर पर केवल रूम के <i>सर्वर-साइड</i> को प्रभावित करता है। यदि आपको अपने रायट क्लाइंट के साथ समस्या हो रही है, तो कृपया <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>चेतावनी</b>: किसी कमरे को अपग्रेड करना <i>कमरे के सदस्यों को कमरे के नए संस्करण में स्वचालित रूप से माइग्रेट नहीं करना है।</i> हम कमरे के पुराने संस्करण में नए कमरे के लिए एक लिंक पोस्ट करेंगे। नए कमरे में शामिल होने के लिए कमरे के सदस्यों को इस लिंक पर क्लिक करना होगा।",
"Upgrade": "अपग्रेड",
"Adds a custom widget by URL to the room": "रूम में URL द्वारा एक कस्टम विजेट जोड़ता है",
"Please supply a https:// or http:// widget URL": "कृपया एक https:// या http:// विजेट URL की आपूर्ति करें",
"You cannot modify widgets in this room.": "आप इस रूम में विजेट्स को संशोधित नहीं कर सकते।",
"%(senderName)s revoked the invitation for %(targetDisplayName)s to join the room.": "%(senderName)s ने कमरे में शामिल होने के लिए %(targetDisplayName)s के निमंत्रण को रद्द कर दिया।",
"User %(userId)s is already in the room": "उपयोगकर्ता %(userId)s पहले से ही रूम में है",
"The user must be unbanned before they can be invited.": "उपयोगकर्ता को आमंत्रित करने से पहले उन्हें प्रतिबंधित किया जाना चाहिए।",
"Show recent room avatars above the room list": "रूम की सूची के ऊपर हाल के अवतारों को दिखाएं",
"Enable desktop notifications for this device": "इस उपकरण के लिए डेस्कटॉप सूचनाएं सक्षम करें",
"Enable audible notifications for this device": "इस उपकरण के लिए श्रव्य सूचनाएँ सक्षम करें"
}

View file

@ -4,6 +4,5 @@
"Failed to verify email address: make sure you clicked the link in the email": "Nismo u mogućnosti verificirati Vašu email adresu. Provjerite dali ste kliknuli link u mailu",
"The platform you're on": "Platforma na kojoj se nalazite",
"The version of Riot.im": "Verzija Riot.im",
"Whether or not you're logged in (we don't record your user name)": "Dali ste prijavljeni ili ne (mi ne spremamo Vaše korisničko ime)",
"Your language of choice": "Izabrani jezik"
}

File diff suppressed because it is too large Load diff

View file

@ -3,8 +3,6 @@
"Account": "Akun",
"Add": "Tambah",
"Add a topic": "Tambah topik",
"Add email address": "Tambah alamat email",
"Add phone number": "Tambah nomor telpon",
"No Microphones detected": "Tidak ada mikrofon terdeteksi",
"No media permissions": "Tidak ada izin media",
"Microphone": "Mikrofon",
@ -13,39 +11,28 @@
"Are you sure?": "Anda yakin?",
"An error has occurred.": "Telah terjadi kesalahan.",
"Are you sure you want to reject the invitation?": "Anda yakin menolak undangannya?",
"Can't load user settings": "Tidak dapat memuat pengaturan pengguna",
"Change Password": "Ubah Password",
"Click here to fix": "Klik di sini untuk perbaiki",
"Close": "Tutup",
"Commands": "Perintah",
"Confirm password": "Konfirmasi password",
"Confirm your new password": "Konfirmasi password baru",
"Continue": "Lanjut",
"Create an account": "Buat akun",
"Create Room": "Buat Ruang",
"Current password": "Password sekarang",
"Deactivate Account": "Nonaktifkan Akun",
"Delete": "Hapus",
"Device ID": "ID Perangkat",
"Devices": "Perangkat",
"Don't send typing notifications": "Jangan kirim notifikasi pengetikan",
"Email": "Email",
"Email address": "Alamat email",
"Email address (optional)": "Alamat email (pilihan)",
"Enable encryption": "Aktifkan enkripsi",
"Enable Notifications": "Aktifkan Notifikasi",
"Algorithm": "Algoritma",
"Attachment": "Lampiran",
"Command error": "Perintah gagal",
"Conference call failed.": "Panggilan konferensi gagal.",
"Decline": "Tolak",
"Default": "Bawaan",
"Device ID:": "ID Perangkat:",
"Direct chats": "Obrolan langsung",
"Display name": "Nama yang ditampilkan",
"Download %(text)s": "Unduh %(text)s",
"Encrypted room": "Ruang terenkripsi",
"Enter Code": "Masukkan Kode",
"Event information": "Informasi Event",
"Export": "Ekspor",
"Failed to join room": "Gagal gabung ruang",
@ -54,24 +41,19 @@
"Failed to send email": "Gagal mengirim email",
"Favourite": "Favorit",
"Favourites": "Favorit",
"Forgot your password?": "Lupa password?",
"Import": "Impor",
"Incorrect verification code": "Kode verifikasi tidak benar",
"Invalid Email Address": "Alamat email tidak benar",
"Invited": "Diundang",
"Sign in with": "Masuk dengan",
"Leave room": "Meninggalkan ruang",
"Level:": "Tingkat:",
"Logout": "Keluar",
"Low priority": "Prioritas rendah",
"Markdown is disabled": "Markdown dinonaktifkan",
"Markdown is enabled": "Markdown diaktifkan",
"Mobile phone number": "Nomor telpon seluler",
"Mute": "Bisu",
"Name": "Nama",
"New password": "Password Baru",
"New passwords don't match": "Password baru tidak cocok",
"not set": "tidak diisi",
"<not supported>": "<tidak didukung>",
"NOT verified": "TIDAK terverifikasi",
"No results": "Tidak ada hasil",
@ -88,7 +70,6 @@
"riot-web version:": "riot-web versi:",
"Return to login screen": "Kembali ke halaman masuk",
"Room Colour": "Warna Ruang",
"Room name (optional)": "Nama ruang (pilihan)",
"Rooms": "Ruang",
"Save": "Simpan",
"Search": "Cari",
@ -98,7 +79,6 @@
"Server error": "Server bermasalah",
"Session ID": "ID Sesi",
"Settings": "Pengaturan",
"Show panel": "Tampilkan panel",
"Sign in": "Masuk",
"Sign out": "Keluar",
"Someone": "Seseorang",
@ -107,7 +87,6 @@
"Success": "Sukses",
"This email address was not found": "Alamat email ini tidak ada",
"This room": "Ruang ini",
"Turn Markdown off": "Matikan Markdown",
"Unable to add email address": "Tidak dapat menambahkan alamat email",
"Unable to verify email address.": "Tidak dapat memverifikasi alamat email.",
"Unable to load device list": "Tidak dapat memuat daftar perangkat",
@ -115,7 +94,6 @@
"unknown error code": "kode kesalahan tidak diketahui",
"unknown device": "perangkat tidak diketahui",
"User ID": "ID Pengguna",
"User name": "Nama pengguna",
"Verification": "Verifikasi",
"verified": "terverifikasi",
"Verification Pending": "Verifikasi Tertunda",
@ -125,7 +103,6 @@
"Warning!": "Peringatan!",
"You are already in a call.": "Anda telah berada di panggilan.",
"You cannot place a call with yourself.": "Anda tidak dapat melakukan panggilan dengan diri sendiri.",
"Your password has been reset": "Password Anda telah diatur ulang",
"Sun": "Min",
"Mon": "Sen",
"Tue": "Sel",
@ -145,34 +122,27 @@
"Oct": "Okt",
"Nov": "Nov",
"Dec": "Des",
"A text message has been sent to +%(msisdn)s. Please enter the verification code it contains": "Sebuah pesan sudah dikirim ke +%(msisdn)s. Mohon masukkan kode verifikasi pada pesan tersebut",
"%(targetName)s accepted an invitation.": "%(targetName)s telah menerima undangan.",
"%(targetName)s accepted the invitation for %(displayName)s.": "%(targetName)s menerima undangan untuk %(displayName)s.",
"Access Token:": "Token Akses:",
"Active call (%(roomName)s)": "Panggilan aktif (%(roomName)s)",
"Admin": "Admin",
"Admin Tools": "Peralatan Admin",
"VoIP": "VoIP",
"Missing Media Permissions, click here to request.": "Tidak ada Izin Media, klik disini untuk meminta.",
"No Webcams detected": "Tidak ada Webcam terdeteksi",
"You may need to manually permit Riot to access your microphone/webcam": "Anda mungkin perlu secara manual mengizinkan Riot untuk mengakses mikrofon/webcam",
"Default Device": "Perangkat Bawaan",
"Advanced": "Tingkat Lanjut",
"Hide removed messages": "Sembunyikan pesan yang dihapus",
"Always show message timestamps": "Selalu tampilkan cap waktu dari pesan",
"Authentication": "Autentikasi",
"Are you sure you want to leave the room '%(roomName)s'?": "Anda yakin ingin meninggalkan ruang '%(roomName)s'?",
"A new password must be entered.": "Password baru harus diisi.",
"%(items)s and %(lastItem)s": "%(items)s dan %(lastItem)s",
"%(names)s and %(lastPerson)s are typing": "%(names)s dan %(lastPerson)s sedang mengetik",
"%(senderName)s answered the call.": "%(senderName)s telah menjawab panggilan.",
"Anyone who knows the room's link, including guests": "Siapa pun yang tahu tautan ruang, termasuk tamu",
"Anyone who knows the room's link, apart from guests": "Siapa pun yang tahu tautan ruang, selain tamu",
"Are you sure you want to upload the following files?": "Anda yakin akan mengunggah berkas-berkas berikut?",
"Blacklisted": "Didaftarhitamkan",
"%(senderName)s banned %(targetName)s.": "%(senderName)s telah memblokir %(targetName)s.",
"Banned users": "Pengguna yang diblokir",
"Bulk Options": "Opsi Massal",
"Can't connect to homeserver - please check your connectivity, ensure your <a>homeserver's SSL certificate</a> is trusted, and that a browser extension is not blocking requests.": "Tidak dapat terhubung ke server Home - harap cek koneksi anda, pastikan <a>sertifikat SSL server Home</a> Anda terpercaya, dan ekstensi dari browser tidak memblokir permintaan.",
"Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. Either use HTTPS or <a>enable unsafe scripts</a>.": "Tidak dapat terhubung ke server Home melalui HTTP ketika URL di browser berupa HTTPS. Pilih gunakan HTTPS atau <a>aktifkan skrip yang tidak aman</a>.",
"%(senderName)s changed their profile picture.": "%(senderName)s telah mengubah foto profilnya.",
@ -181,26 +151,19 @@
"%(senderDisplayName)s removed the room name.": "%(senderDisplayName)s telah menghapus nama ruang.",
"%(senderDisplayName)s changed the room name to %(roomName)s.": "%(senderDisplayName)s telah mengubah nama ruang menjadi %(roomName)s.",
"%(senderDisplayName)s changed the topic to \"%(topic)s\".": "%(senderDisplayName)s telah mengubah topik menjadi \"%(topic)s\".",
"Changes to who can read history will only apply to future messages in this room": "Pengubahan siapa yang dapat membaca sejarah akan berlaku untuk pesan selanjutnya di ruang ini",
"Changing password will currently reset any end-to-end encryption keys on all devices, making encrypted chat history unreadable, unless you first export your room keys and re-import them afterwards. In future this will be improved.": "Mengubah password saat ini akan mengatur ulang semua kunci enkripsi end-to-end di semua perangkat, menyebabkan sejarah obrolan yang terenkripsi menjadi tidak dapat dibaca, kecuali sebelumnya Anda ekspor dahulu kunci ruang lalu kemudian impor ulang setelahnya. Ke depan hal ini akan diperbaiki.",
"<a>Click here</a> to join the discussion!": "<a>Klik di sini</a> untuk gabung diskusi!",
"click to reveal": "Klik untuk menampilkan",
"Conference calls are not supported in this client": "Panggilan konferensi tidak didukung oleh klien ini",
"Could not connect to the integration server": "Tidak dapat terhubung ke server integrasi",
"Create a new chat or reuse an existing one": "Buat obrolan baru atau gunakan yang sudah ada",
"Cryptography": "Kriptografi",
"Deactivate my account": "Nonaktifkan akun saya",
"Decrypt %(text)s": "Dekrip %(text)s",
"Decryption error": "Dekripsi gagal",
"Device already verified!": "Perangkat telah terverifikasi!",
"device id: ": "id perangkat: ",
"Device key:": "Kunci Perangkat:",
"Devices will not yet be able to decrypt history from before they joined the room": "Perangkat tidak akan dapat mendekripsi sejarah sebelum gabung ke ruang",
"Ban": "Blokir",
"Bans user with given id": "Blokir pengguna dengan id",
"Fetching third party location failed": "Gagal mengambil lokasi pihak ketiga",
"A new version of Riot is available.": "Riot versi baru telah tersedia.",
"Couldn't load home page": "Tidak dapat memuat halaman utama",
"All notifications are currently disabled for all targets.": "Semua notifikasi saat ini dinonaktifkan untuk semua target.",
"Uploading report": "Unggah laporan",
"Sunday": "Minggu",
@ -209,16 +172,12 @@
"Notification targets": "Target notifikasi",
"Failed to set direct chat tag": "Gagal mengatur tag obrolan langsung",
"Today": "Hari Ini",
"Failed to get protocol list from Home Server": "Gagal mendapatkan daftar protokol dari Server Home",
"You are not receiving desktop notifications": "Anda tidak menerima notifikasi desktop",
"Dismiss": "Abaikan",
"Update": "Perbarui",
"Notifications": "Notifikasi",
"What's New": "Apa Yang Baru",
"Add an email address above to configure email notifications": "Tambahkan alamat email di atas untuk konfigurasi notifikasi email",
"Expand panel": "Luaskan panel",
"On": "Nyala",
"Filter room names": "Saring nama ruang",
"Changelog": "Daftar perubahan",
"Waiting for response from server": "Menunggu respon dari server",
"Leave": "Tinggalkan",
@ -227,13 +186,10 @@
"To return to your account in future you need to <u>set a password</u>": "Untuk kembali ke akun di lain waktu, Anda perlu <u>mengisi password</u>",
"Forget": "Lupakan",
"World readable": "Terpublikasi Umum",
"#example": "#contoh",
"Hide panel": "Sembunyikan panel",
"You cannot delete this image. (%(code)s)": "Anda tidak dapat menghapus gambar ini. (%(code)s)",
"Cancel Sending": "Batalkan pengiriman",
"Warning": "Peringatan",
"This Room": "Ruang ini",
"The Home Server may be too old to support third party networks": "Server Home mungkin terlalu kuno untuk mendukung jaringan pihak ketiga",
"Noisy": "Berisik",
"Error saving email notification preferences": "Terjadi kesalahan saat menyimpan pilihan notifikasi email",
"Messages containing my display name": "Pesan mengandung nama tampilan saya",
@ -258,8 +214,6 @@
"Delete the room alias %(alias)s and remove %(name)s from the directory?": "Hapus alias ruang %(alias)s dan hapus %(name)s dari direktori?",
"This will allow you to return to your account after signing out, and sign in on other devices.": "Hal ini akan memperbolehkan anda kembali ke akun setelah keluar dan masuk kembali di perangkat lain.",
"Enable notifications for this account": "Aktifkan notifikasi untuk akun ini",
"Directory": "Direktori",
"Failed to get public room list": "Gagal mendapatkan daftar ruang publik",
"Messages containing <span>keywords</span>": "Pesan mengandung <span>kata kunci</span>",
"Room not found": "Ruang tidak ditemukan",
"Tuesday": "Selasa",
@ -267,7 +221,6 @@
"Search…": "Cari…",
"Remove %(name)s from the directory?": "Hapus %(name)s dari direktori?",
"Riot uses many advanced browser features, some of which are not available or experimental in your current browser.": "Riot menggunakan banyak fitur terdepan dari browser, dimana tidak tersedia atau dalam fase eksperimen di browser Anda.",
"Enable desktop notifications": "Aktifkan notifikasi desktop",
"Unnamed room": "Ruang tanpa nama",
"Friday": "Jumat",
"Remember, you can always set an email address in user settings if you change your mind.": "Ingat, Anda selalu dapat mengubah alamat email di pengaturan pengguna jika anda berubah pikiran.",
@ -281,9 +234,7 @@
"Monday": "Senin",
"Remove from Directory": "Hapus dari DIrektori",
"Enable them now": "Aktifkan sekarang",
"Messages containing my user name": "Pesan mengandung nama pengguna saya",
"Collecting logs": "Mengumpulkan catatan",
"more": "lagi",
"(HTTP status %(httpStatus)s)": "(status HTTP %(httpStatus)s)",
"Failed to forget room %(errCode)s": "Gagal melupakan ruang %(errCode)s",
"Wednesday": "Rabu",
@ -305,7 +256,6 @@
"Unable to look up room ID from server": "Tidak dapat mencari ID ruang dari server",
"Couldn't find a matching Matrix room": "Tidak dapat menemukan ruang Matrix yang sesuai",
"Invite to this room": "Undang ke ruang ini",
"Search for a room": "Cari ruang obrolan",
"Thursday": "Kamis",
"Forward Message": "Teruskan Pesan",
"Back": "Kembali",
@ -322,7 +272,6 @@
"Low Priority": "Prioritas Rendah",
"Unable to fetch notification target list": "Tidak dapat mengambil daftar notifikasi target",
"Set Password": "Ubah Password",
"Enable audible notifications in web client": "Aktifkan notifikasi suara di klien web",
"Off": "Mati",
"Riot does not know how to join a room on this network": "Riot tidak tau bagaimana gabung ruang di jaringan ini",
"Mentions only": "Hanya jika disinggung",
@ -330,7 +279,6 @@
"Remove": "Hapus",
"You can now return to your account after signing out, and sign in on other devices.": "Anda dapat kembali ke akun setelah keluar dan masuk kembali di perangkat lain.",
"Enable email notifications": "Aktifkan notifikasi email",
"Login": "Masuk",
"No rooms to show": "Tidak ada ruang ditunjukkan",
"Download this file": "Unduh file ini",
"Failed to change settings": "Gagal mengubah pengaturan",
@ -338,7 +286,6 @@
"View Source": "Tampilkan Sumber",
"Custom Server Options": "Pilihan Server Khusus",
"Thank you!": "Terima kasih!",
"Collapse panel": "Lipat panel",
"With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "Dengan browser ini, tampilan dari aplikasi mungkin tidak sesuai, dan beberapa atau bahkan semua fitur mungkin tidak berjalan. Jika Anda ingin tetap mencobanya, Anda bisa melanjutkan, tapi Anda tanggung sendiri jika muncul masalah yang terjadi!",
"Checking for an update...": "Cek pembaruan...",
"There are advanced notifications which are not shown here": "Ada notifikasi lanjutan yang tidak ditampilkan di sini",
@ -370,7 +317,6 @@
"Existing Call": "Panggilan Berlangsung",
"VoIP is unsupported": "VoIP tidak didukung",
"You cannot place VoIP calls in this browser.": "Anda tidak dapat melakukan panggilan VoIP di browser ini.",
"A conference call could not be started because the intgrations server is not available": "Panggilan massal tidak dapat dimulai karena server integrasi tidak tersedia",
"Call in Progress": "Panggilan Berlangsung",
"A call is currently being placed!": "Sedang melakukan panggilan sekarang!",
"A call is already in progress!": "Masih ada panggilan berlangsung!",

View file

@ -13,9 +13,7 @@
"Answer": "Svara",
"The remote side failed to pick up": "Ekki var svarað á fjartengda endanum",
"VoIP is unsupported": "Enginn stuðningur við VoIP",
"Conference calls are not supported in encrypted rooms": "Símafundir eru ekki studdir í dulrituðum spjallrásum",
"Warning!": "Aðvörun!",
"Conference calling is in development and may not be reliable.": "Símafundir eru í þróun og gætu verið óáreiðanlegir.",
"Upload Failed": "Upphleðsla mistókst",
"Sun": "sun",
"Mon": "mán",
@ -48,7 +46,6 @@
"Moderator": "Umsjónarmaður",
"Admin": "Stjórnandi",
"Start a chat": "Hefja spjall",
"Email, name or matrix ID": "Tölvupóstfang, nafn eða Matrix-auðkenni",
"Start Chat": "Hefja spjall",
"Operation failed": "Aðgerð tókst ekki",
"You need to be logged in.": "Þú þarft að vera skráð/ur inn.",
@ -70,8 +67,6 @@
"Send anyway": "Senda samt",
"Send": "Senda",
"Unnamed Room": "Nafnlaus spjallrás",
"Hide join/leave messages (invites/kicks/bans unaffected)": "Fela taka-þátt/hætta skilaboð (hefur ekki áhrif á boð/spörk/bönn)",
"Hide read receipts": "Fela leskvittanir",
"Show timestamps in 12 hour format (e.g. 2:30pm)": "Birta tímamerki á 12 stunda sniði (t.d. 2:30 fh)",
"Always show message timestamps": "Alltaf birta tímamerki skilaboða",
"Send analytics data": "Senda greiningargögn",
@ -84,7 +79,6 @@
"Uploading report": "Sendi inn skýrslu",
"Waiting for response from server": "Bíð eftir svari frá vefþjóni",
"Messages containing my display name": "Skilaboð sem innihalda birtingarnafn mitt",
"Messages containing my user name": "Skilaboð sem innihalda notandanafn mitt",
"Messages in one-to-one chats": "Skilaboð í maður-á-mann spjalli",
"Messages in group chats": "Skilaboð í hópaspjalli",
"When I'm invited to a room": "Þegar mér er boðið á spjallrás",
@ -96,10 +90,8 @@
"Decline": "Hafna",
"Accept": "Samþykkja",
"Error": "Villa",
"Enter Code": "Settu inn kóða",
"Submit": "Senda inn",
"Phone": "Sími",
"Add phone number": "Bæta við símanúmeri",
"Add": "Bæta við",
"Continue": "Halda áfram",
"Export E2E room keys": "Flytja út E2E dulritunarlykla spjallrásar",
@ -112,7 +104,6 @@
"Delete %(count)s devices|other": "Eyða %(count)s tækjum",
"Delete %(count)s devices|one": "Eyða tæki",
"Device ID": "Auðkenni tækis",
"Device Name": "Heiti tækis",
"Last seen": "Sást síðast",
"Enable Notifications": "Virkja tilkynningar",
"Error saving email notification preferences": "Villa við að vista valkosti pósttilkynninga",
@ -127,13 +118,10 @@
"Notify for all other messages/rooms": "Senda tilkynningar fyrir öll önnur skilaboð/spjallrásir",
"Notify me for anything else": "Senda mér tilkynningar fyrir allt annað",
"Enable notifications for this account": "Virkja tilkynningar fyrir þennan notandaaðgang",
"Add an email address above to configure email notifications": "Settu inn tölvupóstfang hér fyrir ofan til að stilla tilkynningar með tölvupósti",
"Enable email notifications": "Virkja tilkynningar í tölvupósti",
"Notification targets": "Markmið tilkynninga",
"Advanced notification settings": "Ítarlegar stillingar á tilkynningum",
"Enable desktop notifications": "Virkja tilkynningar á skjáborði",
"Show message in desktop notification": "Birta tilkynningu í innbyggðu kerfistilkynningakerfi",
"Enable audible notifications in web client": "Virkja hljóðtilkynningar í vefviðmóti",
"Off": "Slökkt",
"On": "Kveikt",
"Noisy": "Hávært",
@ -147,8 +135,6 @@
"Options": "Valkostir",
"Unencrypted message": "Ódulrituð skilaboð",
"Blacklisted": "Á bannlista",
"Verified": "Sannreynt",
"Unverified": "Óstaðfest",
"device id: ": "Auðkenni tækis: ",
"Kick": "Sparka",
"Unban": "Afbanna",
@ -167,11 +153,9 @@
"Mute": "Þagga hljóð",
"Make Moderator": "Gera að umsjónarmanni",
"Admin Tools": "Kerfisstjóratól",
"Level:": "Stig:",
"Invited": "Boðið",
"Filter room members": "Sía meðlimi spjallrásar",
"Attachment": "Viðhengi",
"Upload Files": "Senda inn skrár",
"Hangup": "Leggja á",
"Voice call": "Raddsamtal",
"Video call": "_Myndsímtal",
@ -183,11 +167,6 @@
"Command error": "Skipanavilla",
"bold": "feitletrað",
"italic": "skáletrað",
"strike": "yfirstrikað",
"underline": "undirstrikað",
"code": "kóði",
"quote": "tilvitnun",
"bullet": "áherslumerki",
"Loading...": "Hleð inn...",
"Online": "Nettengt",
"Idle": "Iðjulaust",
@ -208,19 +187,12 @@
"Rooms": "Spjallrásir",
"Low priority": "Lítill forgangur",
"Historical": "Ferilskráning",
"Rejoin": "Taka þátt aftur",
"This room": "Þessi spjallrás",
"This is a preview of this room. Room interactions have been disabled": "Þetta er forskoðun á spjallrásinni. Samskipti spjallrásarinnar hafa verið gerð óvirk",
"Privacy warning": "Aðvörun vegna gagnaleyndar",
"unknown error code": "óþekktur villukóði",
"Failed to forget room %(errCode)s": "Mistókst að gleyma spjallrásinni %(errCode)s",
"Encryption is enabled in this room": "Dulritun er virk í þessari spjallrás",
"Encryption is not enabled in this room": "Dulritun er ekki virk í þessari spjallrás",
"Banned users": "Bannaðir notendur",
"Leave room": "Fara af spjallrás",
"Favourite": "Eftirlæti",
"Tagged as: ": "Merkt sem: ",
"To link to a room it must have <a>an address</a>.": "Til að tengja við spjallrás verður hún að vera með <a>vistfang</a>.",
"Who can access this room?": "Hver hefur aðgang að þessari spjallrás?",
"Only people who have been invited": "Aðeins fólk sem hefur verið boðið",
"Anyone who knows the room's link, apart from guests": "Hver sá sem þekkir slóðina á spjallrásina, fyrir utan gesti",
@ -240,8 +212,6 @@
"Close": "Loka",
"Invalid alias format": "Ógilt snið samnefnis",
"not specified": "ekki tilgreint",
"not set": "ekki stillt",
"Addresses": "Vistföng",
"Invalid community ID": "Ógilt auðkenni samfélags",
"Flair": "Hlutverksmerki",
"This room is not showing flair for any communities": "Þessi spjallrás sýnir ekki hlutverksmerki fyrir nein samfélög",
@ -256,23 +226,15 @@
"Yesterday": "Í gær",
"Error decrypting attachment": "Villa við afkóðun viðhengis",
"Copied!": "Afritað",
"This Home Server would like to make sure you are not a robot": "Þessi heimavefþjónn vill ganga úr skugga um að þú sért ekki vélmenni",
"Custom Server Options": "Sérsniðnir valkostir vefþjóns",
"Dismiss": "Hunsa",
"To continue, please enter your password.": "Til að halda áfram, settu inn lykilorðið þitt.",
"Password:": "Lykilorð:",
"Please check your email to continue registration.": "Skoðaðu tölvupóstinn þinn til að geta haldið áfram með skráningu.",
"Code": "Kóði",
"powered by Matrix": "keyrt með Matrix",
"User name": "Notandanafn",
"Forgot your password?": "Gleymdirðu lykilorðinu?",
"Email address": "Tölvupóstfang",
"Sign in": "Skrá inn",
"Email address (optional)": "Tölvupóstfang (valfrjálst)",
"Register": "Nýskrá",
"Home server URL": "Slóð á heimaþjón",
"Identity server URL": "Slóð á auðkennisþjón",
"What does this mean?": "Hvað þýðir þetta?",
"Filter community members": "Sía meðlimi samfélags",
"Remove": "Fjarlægja",
"Something went wrong!": "Eitthvað fór úrskeiðis!",
@ -291,14 +253,12 @@
"Downloading update...": "Sæki uppfærslu...",
"Warning": "Aðvörun",
"Allow": "Leyfa",
"Picture": "Mynd",
"Edit": "Breyta",
"Unblacklist": "Taka af bannlista",
"Blacklist": "Bannlisti",
"Unverify": "Afturkalla sannvottun",
"Verify...": "Sannreyna...",
"No results": "Engar niðurstöður",
"Delete": "Eyða",
"Communities": "Samfélög",
"Home": "Heim",
"You cannot delete this image. (%(code)s)": "Þú getur ekki eytt þessari mynd. (%(code)s)",
@ -316,13 +276,9 @@
"Thank you!": "Takk fyrir!",
"Failed to send logs: ": "Mistókst að senda atvikaskrár: ",
"Submit debug logs": "Senda inn aflúsunarannála",
"GitHub issue link:": "Slóð villutilkynningar á GitHub:",
"Notes:": "Athugasemdir:",
"Send logs": "Senda atvikaskrá",
"Unavailable": "Ekki tiltækt",
"Changelog": "Breytingaskrá",
"Start new chat": "Hefja nýtt spjall",
"Start Chatting": "Hefja spjall",
"Confirm Removal": "Staðfesta fjarlægingu",
"Create Community": "Búa til samfélag",
"Community Name": "Heiti samfélags",
@ -331,13 +287,10 @@
"example": "dæmi",
"Create": "Búa til",
"Create Room": "Búa til spjallrás",
"Room name (optional)": "Heiti spjallrásar (valkvætt)",
"Advanced options": "Ítarlegir valkostir",
"Unknown error": "Óþekkt villa",
"Incorrect password": "Rangt lykilorð",
"Deactivate Account": "Gera notandaaðgang óvirkann",
"To continue, please enter your password:": "Til að halda áfram, settu inn lykilorðið þitt:",
"password": "lykilorð",
"Device name": "Heiti tækis",
"Device key": "Dulritunarlykill tækis",
"Verify device": "Sannreyna tæki",
@ -359,7 +312,6 @@
"Verification Pending": "Sannvottun í bið",
"Please check your email and click on the link it contains. Once this is done, click continue.": "Skoðaðu tölvupóstinn þinn og smelltu á tengilinn sem hann inniheldur. Þegar því er lokið skaltu smella á að halda áfram.",
"Skip": "Sleppa",
"User names may only contain letters, numbers, dots, hyphens and underscores.": "Notendanöfn mega einungis innihalda bókstafi, tölustafi, punkta, bandstrik eða undirstrik.",
"Username not available": "Notandanafnið er ekki tiltækt",
"Username available": "Notandanafnið er tiltækt",
"You have successfully set a password!": "Þér tókst að setja lykilorð!",
@ -391,70 +343,45 @@
"Low Priority": "Lítill forgangur",
"Direct Chat": "Beint spjall",
"View Community": "Skoða samfélag",
"Please install <chromeLink>Chrome</chromeLink> or <firefoxLink>Firefox</firefoxLink> for the best experience.": "Endilega settu upp <chromeLink>Chrome</chromeLink> eða <firefoxLink>Firefox</firefoxLink> til að þetta gangi sem best.",
"<safariLink>Safari</safariLink> and <operaLink>Opera</operaLink> work too.": "<safariLink>Safari</safariLink> og <operaLink>Opera</operaLink> virka líka ágætlega.",
"I understand the risks and wish to continue": "Ég skil áhættuna og vil halda áfram",
"Name": "Nafn",
"Topic": "Umfjöllunarefni",
"Failed to upload image": "Gat ekki sent inn mynd",
"Add rooms to this community": "Bæta spjallrásum í þetta samfélag",
"Featured Users:": "Notendur í sviðsljósinu:",
"Everyone": "Allir",
"Description": "Lýsing",
"Login": "Innskráning",
"Signed Out": "Skráð/ur út",
"Terms and Conditions": "Skilmálar og kvaðir",
"Logout": "Útskráning",
"Members": "Meðlimir",
"%(count)s Members|other": "%(count)s þátttakendur",
"%(count)s Members|one": "%(count)s þátttakandi",
"Invite to this room": "Bjóða inn á þessa spjallrás",
"Files": "Skrár",
"Notifications": "Tilkynningar",
"Hide panel": "Fela spjald",
"Invite to this community": "Bjóða í þetta samfélag",
"The server may be unavailable or overloaded": "Netþjónninn gæti verið undir miklu álagi eða ekki til taks",
"Room not found": "Spjallrás fannst ekki",
"Directory": "Efnisskrá",
"Search for a room": "Leita að spjallrás",
"#example": "#dæmi",
"Connectivity to the server has been lost.": "Tenging við vefþjón hefur rofnað.",
"Active call": "Virkt samtal",
"more": "meira",
"Failed to upload file": "Gat ekki sent inn skrá",
"Search failed": "Leit mistókst",
"Room": "Spjallrás",
"Fill screen": "Fylla skjáinn",
"Expand panel": "Fletta út spjaldi",
"Collapse panel": "Fella saman spjald",
"Filter room names": "Sía heiti spjallrása",
"Clear filter": "Hreinsa síu",
"Light theme": "Ljóst þema",
"Dark theme": "Dökkt þema",
"Success": "Tókst",
"Interface Language": "Tungumál notandaviðmóts",
"User Interface": "Notandaviðmót",
"Import E2E room keys": "Flytja inn E2E dulritunarlykla spjallrásar",
"Cryptography": "Dulritun",
"Device ID:": "Auðkenni tækis:",
"Device key:": "Dulritunarlykill tækis:",
"Ignored Users": "Hunsaðir notendur",
"Riot collects anonymous analytics to allow us to improve the application.": "Riot safnar nafnlausum greiningargögnum til að gera okkur kleift að bæta forritið.",
"Labs": "Tilraunir",
"Deactivate my account": "Gera notandaaðganginn minn óvirkann",
"Clear Cache": "Hreinsa skyndiminni",
"Updates": "Uppfærslur",
"Check for update": "Athuga með uppfærslu",
"Default Device": "Sjálfgefið tæki",
"Microphone": "Hljóðnemi",
"Camera": "Myndavél",
"VoIP": "VoIP",
"Email": "Tölvupóstfang",
"Add email address": "Bæta við tölvupóstfangi",
"Profile": "Notandasnið",
"Display name": "Birtingarnafn",
"Account": "Notandaaðgangur",
"Logged in as:": "Skráð inn sem:",
"Access Token:": "Aðgangsteikn:",
"click to reveal": "smelltu til að birta",
"Identity Server is": "Auðkennisþjónn er",
@ -467,18 +394,9 @@
"New passwords must match each other.": "Nýju lykilorðin verða að vera þau sömu.",
"I have verified my email address": "Ég hef staðfest tölvupóstfangið mitt",
"Return to login screen": "Fara aftur í innskráningargluggann",
"To reset your password, enter the email address linked to your account": "Til að endursetja lykilorðið þitt, settu þá inn tölvupóstfangið sem tengt er notandaaðgangnum þínum",
"New password": "Nýtt lykilorð",
"Confirm your new password": "Staðfestu nýtt lykilorð",
"Send Reset Email": "Senda endurstillingarpóst",
"Create an account": "Stofna notandaaðgang",
"Incorrect username and/or password.": "Rangt notandanafn og/eða lykilorð.",
"Upload an avatar:": "Hlaða inn auðkennismynd:",
"Missing password.": "Lykilorð vantar.",
"Passwords don't match.": "Lykilorðin samsvara ekki.",
"This doesn't look like a valid email address.": "Þetta lítur ekki út eins og gilt tölvupóstfang.",
"This doesn't look like a valid phone number.": "Þetta lítur ekki út eins og gilt símanúmer.",
"An unknown error occurred.": "Óþekkt villa kom upp.",
"Commands": "Skipanir",
"Users": "Notendur",
"unknown device": "óþekkt tæki",
@ -512,7 +430,6 @@
"Review Devices": "Yfirfara tæki",
"Call Timeout": "Tímamörk hringingar",
"Unable to capture screen": "Get ekki tekið skjámynd",
"Name or matrix ID": "Nafn eða Matrix-auðkenni",
"Invite to Community": "Bjóða í samfélag",
"Add rooms to the community": "Bæta spjallrásum í þetta samfélag",
"Add to community": "Bæta í samfélag",
@ -520,15 +437,11 @@
"This email address was not found": "Tölvupóstfangið fannst ekki",
"Existing Call": "Fyrirliggjandi samtal",
"You are already in a call.": "Þú ert nú þegar í samtali.",
"Failed to set up conference call": "Mistókst að setja upp símafund",
"Invite new community members": "Bjóða nýjum meðlimum í samfélag",
"Which rooms would you like to add to this community?": "Hvaða spjallrásum myndir þú vilja bæta í þetta samfélag?",
"Invite new room members": "Bjóða nýjum meðlimum á spjallrás",
"Who would you like to add to this room?": "Hverjum myndir þú vilja bæta á þessa spjallrás?",
"Send Invites": "Senda boðskort",
"Failed to invite user": "Mistókst að bjóða notanda",
"Failed to invite": "Mistókst að bjóða",
"Reload widget": "Endurlesa viðmótshluta",
"Missing roomId.": "Vantar spjallrásarauðkenni.",
"/ddg is not a command": "/ddg er ekki skipun",
"Ignored user": "Hunsaður notandi",
@ -551,8 +464,6 @@
"ex. @bob:example.com": "t.d. @jon:netfang.is",
"Matrix ID": "Matrix-auðkenni",
"Matrix Room ID": "Matrix-auðkenni spjallrásar",
"Start chatting": "Hefja spjall",
"This setting cannot be changed later!": "Ekki er hægt að breyta þessari stillingu síðar!",
"Send Custom Event": "Senda sérsniðið atvik",
"Event sent!": "Atvik sent!",
"State Key": "Stöðulykill",
@ -561,7 +472,6 @@
"You added a new device '%(displayName)s', which is requesting encryption keys.": "Þú bættir við nýju tæki '%(displayName)s', sem er að krefjast dulritunarlykla.",
"Your unverified device '%(displayName)s' is requesting encryption keys.": "ósannvottaða tækið þitt '%(displayName)s' er að krefjast dulritunarlykla.",
"Loading device info...": "Hleð inn upplýsingum um tæki...",
"Log out and remove encryption keys?": "Skrá út og fjarlægja dulritunarlykla?",
"Clear Storage and Sign Out": "Hreinsa gagnageymslu og skrá út",
"Unable to restore session": "Tókst ekki að endurheimta setu",
"This doesn't appear to be a valid email address": "Þetta lítur ekki út eins og gilt tölvupóstfang",
@ -575,8 +485,6 @@
"Public Chat": "Opinbert spjall",
"Collapse Reply Thread": "Fella saman svarþráð",
"Sorry, your browser is <b>not</b> able to run Riot.": "Því miður, vafrinn þinn getur <b>ekki</b> keyrt Riot.",
"Make this room private": "Gera þessa spjallrás einka",
"Encrypt room": "Dulrita spjallrás",
"Add a Room": "Bæta við spjallrás",
"Add a User": "Bæta við notanda",
"Unable to accept invite": "Mistókst að þiggja boð",
@ -595,14 +503,12 @@
"Who can join this community?": "Hverjir geta tekið þátt í þessu samfélagi?",
"Long Description (HTML)": "Tæmandi lýsing (HTML)",
"Failed to load %(groupId)s": "Mistókst að hlaða inn %(groupId)s",
"Couldn't load home page": "Gat ekki hlaðið inn heimasíðu",
"Reject invitation": "Hafna boði",
"Are you sure you want to reject the invitation?": "Ertu viss um að þú viljir hafna þessu boði?",
"Failed to reject invitation": "Mistókst að hafna boði",
"Scroll to bottom of page": "Skruna neðst á síðu",
"No more results": "Ekki fleiri niðurstöður",
"Unknown room %(roomId)s": "Óþekkt spjallrás %(roomId)s",
"Failed to save settings": "Mistókst að vista stillingar",
"Failed to reject invite": "Mistókst að hafna boði",
"Click to unmute video": "Smelltu til að virkja hljóð í myndskeiði",
"Click to mute video": "Smelltu til að þagga niður í myndskeiði",
@ -612,27 +518,13 @@
"Uploading %(filename)s and %(count)s others|other": "Sendi inn %(filename)s og %(count)s til viðbótar",
"Uploading %(filename)s and %(count)s others|zero": "Sendi inn %(filename)s",
"Uploading %(filename)s and %(count)s others|one": "Sendi inn %(filename)s og %(count)s til viðbótar",
"Status.im theme": "Status.im þema",
"Can't load user settings": "Gat ekki hlaði inn notandastillingum",
"Server may be unavailable or overloaded": "Netþjónninn gæti verið undir miklu álagi eða ekki til taks",
"Remove Contact Information?": "Fjarlægja upplýsingar um tengilið?",
"Remove %(threePid)s?": "Fjarlægja %(threePid)s?",
"Unable to remove contact information": "Ekki tókst að fjarlægja upplýsingar um tengilið",
"Refer a friend to Riot:": "Mæla með Riot við vin:",
"Autocomplete Delay (ms):": "Töf við sjálfvirka klárun (msek):",
"<not supported>": "<ekki stutt>",
"These are experimental features that may break in unexpected ways": "Þetta eru eiginleikar á tilraunastigi sem gætu bilað á óvæntan hátt",
"Use with caution": "Notist með varúð",
"Clear Cache and Reload": "Hreinsa skyndiminni og endurhlaða",
"No Microphones detected": "Engir hljóðnemar fundust",
"No Webcams detected": "Engar vefmyndavélar fundust",
"Homeserver is": "Heimanetþjónn er",
"Sign in to get started": "Skráðu þig inn til að komast í gang",
"Failed to fetch avatar URL": "Ekki tókst að sækja slóð á auðkennismynd",
"Set a display name:": "Stilltu birtingarnafn:",
"Password too short (min %(MIN_PASSWORD_LENGTH)s).": "Lykilorð er of stutt (lágmark %(MIN_PASSWORD_LENGTH)s).",
"You need to enter a user name.": "Þú þarft að setja inn notandanafn.",
"I already have an account": "Ég er nú þegar með notandaaðgang",
"Displays action": "Birtir aðgerð",
"Changes your display nickname": "Breytir birtu gælunafni þínu",
"Searches DuckDuckGo for results": "Leitar í DuckDuckGo að niðurstöðum",

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more