Merge branch 'develop' of https://github.com/matrix-org/matrix-react-sdk into t3chguy/display-capture

This commit is contained in:
Michael Telatynski 2020-08-28 17:26:10 +01:00
commit 2823156ef6
100 changed files with 4228 additions and 1844 deletions

View file

@ -9,7 +9,7 @@ of dealing with the different levels and exposes easy to use getters and setters
## Levels ## Levels
Granular Settings rely on a series of known levels in order to use the correct value for the scenario. These levels, in Granular Settings rely on a series of known levels in order to use the correct value for the scenario. These levels, in
order of prioirty, are: order of priority, are:
* `device` - The current user's device * `device` - The current user's device
* `room-device` - The current user's device, but only when in a specific room * `room-device` - The current user's device, but only when in a specific room
* `room-account` - The current user's account, but only when in a specific room * `room-account` - The current user's account, but only when in a specific room
@ -25,33 +25,10 @@ that room administrators cannot force account-only settings upon participants.
## Settings ## Settings
Settings are the different options a user may set or experience in the application. These are pre-defined in Settings are the different options a user may set or experience in the application. These are pre-defined in
`src/settings/Settings.js` under the `SETTINGS` constant and have the following minimum requirements: `src/settings/Settings.ts` under the `SETTINGS` constant, and match the `ISetting` interface as defined there.
```
// The ID is used to reference the setting throughout the application. This must be unique.
"theSettingId": {
// The levels this setting supports is required. In `src/settings/Settings.js` there are various pre-set arrays
// for this option - they should be used where possible to avoid copy/pasting arrays across settings.
supportedLevels: [...],
// The default for this setting serves two purposes: It provides a value if the setting is not defined at other Settings that support the config level can be set in the config file under the `settingDefaults` key (note that some
// levels, and it serves to demonstrate the expected type to other developers. The value isn't enforced, but it settings, like the "theme" setting, are special cased in the config file):
// should be respected throughout the code. The default may be any data type.
default: false,
// The display name has two notations: string and object. The object notation allows for different translatable
// strings to be used for different levels, while the string notation represents the string for all levels.
displayName: _td("Change something"), // effectively `displayName: { "default": _td("Change something") }`
displayName: {
"room": _td("Change something for participants of this room"),
// Note: the default will be used if the level requested (such as `device`) does not have a string defined here.
"default": _td("Change something"),
}
}
```
Settings that support the config level can be set in the config file under the `settingDefaults` key (note that some settings, like the "theme" setting, are special cased in the config file):
```json ```json
{ {
... ...
@ -119,38 +96,29 @@ for you. If a display name cannot be found, it will return `null`.
## Features ## Features
Occasionally some parts of the application may be undergoing testing and are not quite production ready. These are Feature flags are just like regular settings with some underlying semantics for how they are meant to be used. Usually
commonly known to be behind a "labs flag". Features behind lab flags must go through the granular settings system, and a feature flag is used when a portion of the application is under development or not ready for full release yet, such
look and act very much normal settings. The exception is that they must supply `isFeature: true` as part of the setting as new functionality or experimental ideas. In these cases, the feature name *should* be named with the `feature_*`
definition and should go through the helper functions on `SettingsStore`. convention and must be tagged with `isFeature: true` in the setting definition. By doing so, the feature will automatically
appear in the "labs" section of the user's settings.
Although features have levels and a default value, the calculation of those options is blocked by the feature's state. Features can be controlled at the config level using the following structure:
A feature's state is determined from the `SdkConfig` and is a little complex. If `enableLabs` (a legacy flag) is `true`
then the feature's state is `labs`, if it is `false`, the state is `disable`. If `enableLabs` is not set then the state
is determined from the `features` config, such as in the following:
```json ```json
"features": { "features": {
"feature_lazyloading": "labs" "feature_lazyloading": true
} }
``` ```
In this example, `feature_lazyloading` is in the `labs` state. It may also be in the `enable` or `disable` state with a
similar approach. If the state is invalid, the feature is in the `disable` state. A feature's levels are only calculated
if it is in the `labs` state, therefore the default only applies in that scenario. If the state is `enable`, the feature
is always-on.
Once a feature flag has served its purpose, it is generally recommended to remove it and the associated feature flag When `true`, the user will see the feature as enabled. Similarly, when `false` the user will see the feature as disabled.
checks. This would enable the feature implicitly as it is part of the application now. The user will only be able to change/see these states if `showLabsSettings: true` is in the config.
### Determining if a feature is enabled ### Determining if a feature is enabled
A simple call to `SettingsStore.isFeatureEnabled` will tell you if the feature is enabled. This will perform all the Call `SettingsStore.getValue()` as you would for any other setting.
required calculations to determine if the feature is enabled based upon the configuration and user selection.
### Enabling a feature ### Enabling a feature
Features can only be enabled if the feature is in the `labs` state, otherwise this is a no-op. To find the current set Call `SettingsStore.setValue("feature_name", null, SettingLevel.DEVICE, true)`.
of features in the `labs` state, call `SettingsStore.getLabsFeatures`. To set the value, call
`SettingsStore.setFeatureEnabled`.
## Setting controllers ## Setting controllers
@ -162,7 +130,7 @@ kept up to date with the setting where it is otherwise not possible. An example
they can only be considered enabled if the platform supports notifications, and enabling notifications requires they can only be considered enabled if the platform supports notifications, and enabling notifications requires
additional steps to actually enable notifications. additional steps to actually enable notifications.
For more information, see `src/settings/controllers/SettingController.js`. For more information, see `src/settings/controllers/SettingController.ts`.
## Local echo ## Local echo
@ -222,7 +190,7 @@ The `SettingsStore` uses the hardcoded `LEVEL_ORDER` constant to ensure that it
The array is checked from left to right, simulating the behaviour of overriding values from the higher levels. Each The array is checked from left to right, simulating the behaviour of overriding values from the higher levels. Each
level should be defined in this array, including `default`. level should be defined in this array, including `default`.
Handlers (`src/settings/handlers/SettingsHandler.js`) represent a single level and are responsible for getting and Handlers (`src/settings/handlers/SettingsHandler.ts`) represent a single level and are responsible for getting and
setting values at that level. Handlers also provide additional information to the `SettingsStore` such as if the level setting values at that level. Handlers also provide additional information to the `SettingsStore` such as if the level
is supported or if the current user may set values at the level. The `SettingsStore` will use the handler to enforce is supported or if the current user may set values at the level. The `SettingsStore` will use the handler to enforce
checks and manipulate settings. Handlers are also responsible for dealing with migration patterns or legacy settings for checks and manipulate settings. Handlers are also responsible for dealing with migration patterns or legacy settings for
@ -230,7 +198,7 @@ their level (for example, a setting being renamed or using a different key from
Handlers are provided to the `SettingsStore` via the `LEVEL_HANDLERS` constant. `SettingsStore` will optimize lookups by Handlers are provided to the `SettingsStore` via the `LEVEL_HANDLERS` constant. `SettingsStore` will optimize lookups by
only considering handlers that are supported on the platform. only considering handlers that are supported on the platform.
Local echo is achieved through `src/settings/handlers/LocalEchoWrapper.js` which acts as a wrapper around a given Local echo is achieved through `src/settings/handlers/LocalEchoWrapper.ts` which acts as a wrapper around a given
handler. This is automatically applied to all defined `LEVEL_HANDLERS` and proxies the calls to the wrapped handler handler. This is automatically applied to all defined `LEVEL_HANDLERS` and proxies the calls to the wrapped handler
where possible. The echo is achieved by a simple object cache stored within the class itself. The cache is invalidated where possible. The echo is achieved by a simple object cache stored within the class itself. The cache is invalidated
immediately upon the proxied save call succeeding or failing. immediately upon the proxied save call succeeding or failing.
@ -240,20 +208,7 @@ Controllers are notified of changes by the `SettingsStore`, and are given the op
### Features ### Features
Features automatically get considered as `disabled` if they are not listed in the `SdkConfig` or `enableLabs` is See above for feature reference.
false/not set. Features are always checked against the configuration before going through the level order as they have
the option of being forced-on or forced-off for the application. This is done by the `features` section and looks
something like this:
```
"features": {
"feature_groups": "enable",
"feature_pinning": "disable", // the default
"feature_presence": "labs"
}
```
If `enableLabs` is true in the configuration, the default for features becomes `"labs"`.
### Watchers ### Watchers

View file

@ -53,17 +53,17 @@
@import "./views/avatars/_PulsedAvatar.scss"; @import "./views/avatars/_PulsedAvatar.scss";
@import "./views/context_menus/_IconizedContextMenu.scss"; @import "./views/context_menus/_IconizedContextMenu.scss";
@import "./views/context_menus/_MessageContextMenu.scss"; @import "./views/context_menus/_MessageContextMenu.scss";
@import "./views/context_menus/_RoomTileContextMenu.scss";
@import "./views/context_menus/_StatusMessageContextMenu.scss"; @import "./views/context_menus/_StatusMessageContextMenu.scss";
@import "./views/context_menus/_TagTileContextMenu.scss"; @import "./views/context_menus/_TagTileContextMenu.scss";
@import "./views/context_menus/_TopLeftMenu.scss";
@import "./views/context_menus/_WidgetContextMenu.scss"; @import "./views/context_menus/_WidgetContextMenu.scss";
@import "./views/dialogs/_AddressPickerDialog.scss"; @import "./views/dialogs/_AddressPickerDialog.scss";
@import "./views/dialogs/_Analytics.scss"; @import "./views/dialogs/_Analytics.scss";
@import "./views/dialogs/_BugReportDialog.scss"; @import "./views/dialogs/_BugReportDialog.scss";
@import "./views/dialogs/_ChangelogDialog.scss"; @import "./views/dialogs/_ChangelogDialog.scss";
@import "./views/dialogs/_ChatCreateOrReuseChatDialog.scss"; @import "./views/dialogs/_ChatCreateOrReuseChatDialog.scss";
@import "./views/dialogs/_CommunityPrototypeInviteDialog.scss";
@import "./views/dialogs/_ConfirmUserActionDialog.scss"; @import "./views/dialogs/_ConfirmUserActionDialog.scss";
@import "./views/dialogs/_CreateCommunityPrototypeDialog.scss";
@import "./views/dialogs/_CreateGroupDialog.scss"; @import "./views/dialogs/_CreateGroupDialog.scss";
@import "./views/dialogs/_CreateRoomDialog.scss"; @import "./views/dialogs/_CreateRoomDialog.scss";
@import "./views/dialogs/_DeactivateAccountDialog.scss"; @import "./views/dialogs/_DeactivateAccountDialog.scss";
@ -108,6 +108,7 @@
@import "./views/elements/_FormButton.scss"; @import "./views/elements/_FormButton.scss";
@import "./views/elements/_IconButton.scss"; @import "./views/elements/_IconButton.scss";
@import "./views/elements/_ImageView.scss"; @import "./views/elements/_ImageView.scss";
@import "./views/elements/_InfoTooltip.scss";
@import "./views/elements/_InlineSpinner.scss"; @import "./views/elements/_InlineSpinner.scss";
@import "./views/elements/_ManageIntegsButton.scss"; @import "./views/elements/_ManageIntegsButton.scss";
@import "./views/elements/_PowerSelector.scss"; @import "./views/elements/_PowerSelector.scss";
@ -157,7 +158,6 @@
@import "./views/right_panel/_UserInfo.scss"; @import "./views/right_panel/_UserInfo.scss";
@import "./views/right_panel/_VerificationPanel.scss"; @import "./views/right_panel/_VerificationPanel.scss";
@import "./views/room_settings/_AliasSettings.scss"; @import "./views/room_settings/_AliasSettings.scss";
@import "./views/room_settings/_ColorSettings.scss";
@import "./views/rooms/_AppsDrawer.scss"; @import "./views/rooms/_AppsDrawer.scss";
@import "./views/rooms/_Autocomplete.scss"; @import "./views/rooms/_Autocomplete.scss";
@import "./views/rooms/_AuxPanel.scss"; @import "./views/rooms/_AuxPanel.scss";

View file

@ -30,30 +30,11 @@ limitations under the License.
cursor: pointer; cursor: pointer;
} }
.mx_TagPanel .mx_TagPanel_clearButton_container {
/* Constant height within flex mx_TagPanel */
height: 70px;
width: 56px;
flex: none;
justify-content: center;
align-items: flex-start;
display: none;
}
.mx_TagPanel .mx_TagPanel_clearButton object {
/* Same as .mx_SearchBox padding-top */
margin-top: 24px;
pointer-events: none;
}
.mx_TagPanel .mx_TagPanel_divider { .mx_TagPanel .mx_TagPanel_divider {
height: 0px; height: 0px;
width: 34px; width: 90%;
border-bottom: 1px solid $panel-divider-color; border: none;
display: none; border-bottom: 1px solid $tagpanel-divider-color;
} }
.mx_TagPanel .mx_TagPanel_scroller { .mx_TagPanel .mx_TagPanel_scroller {
@ -76,12 +57,57 @@ limitations under the License.
// opacity: 0.5; // opacity: 0.5;
position: relative; position: relative;
} }
.mx_TagPanel .mx_TagTile.mx_TagTile_prototype {
padding: 3px;
}
.mx_TagPanel .mx_TagTile:focus, .mx_TagPanel .mx_TagTile:focus,
.mx_TagPanel .mx_TagTile:hover, .mx_TagPanel .mx_TagTile:hover,
.mx_TagPanel .mx_TagTile.mx_TagTile_selected { .mx_TagPanel .mx_TagTile.mx_TagTile_selected {
// opacity: 1; // opacity: 1;
} }
.mx_TagPanel .mx_TagTile.mx_TagTile_selected_prototype {
background-color: $primary-bg-color;
border-radius: 6px;
}
.mx_TagTile_selected_prototype {
.mx_TagTile_homeIcon::before {
background-color: $primary-fg-color; // dark-on-light
}
}
.mx_TagTile:not(.mx_TagTile_selected_prototype) .mx_TagTile_homeIcon {
background-color: $roomheader-addroom-bg-color;
border-radius: 48px;
&::before {
background-color: $roomheader-addroom-fg-color;
}
}
.mx_TagTile_homeIcon {
width: 32px;
height: 32px;
position: relative;
&::before {
mask-image: url('$(res)/img/element-icons/home.svg');
mask-position: center;
mask-repeat: no-repeat;
mask-size: 21px;
content: '';
display: inline-block;
width: 32px;
height: 32px;
position: absolute;
top: calc(50% - 16px);
left: calc(50% - 16px);
}
}
.mx_TagPanel .mx_TagTile_plus { .mx_TagPanel .mx_TagTile_plus {
margin-bottom: 12px; margin-bottom: 12px;
height: 32px; height: 32px;

View file

@ -1,114 +0,0 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_RoomTileContextMenu {
padding: 6px;
}
.mx_RoomTileContextMenu_tag_icon {
padding-right: 8px;
padding-left: 4px;
display: inline-block;
}
.mx_RoomTileContextMenu_tag_icon_set {
padding-right: 8px;
padding-left: 4px;
display: none;
}
.mx_RoomTileContextMenu_tag_field, .mx_RoomTileContextMenu_leave {
padding-top: 8px;
padding-right: 20px;
padding-bottom: 8px;
cursor: pointer;
white-space: nowrap;
display: flex;
align-items: center;
line-height: $font-16px;
}
.mx_RoomTileContextMenu_tag_field.mx_RoomTileContextMenu_tag_fieldSet {
font-weight: bold;
}
.mx_RoomTileContextMenu_tag_field.mx_RoomTileContextMenu_tag_fieldSet .mx_RoomTileContextMenu_tag_icon {
display: none;
}
.mx_RoomTileContextMenu_tag_field.mx_RoomTileContextMenu_tag_fieldSet .mx_RoomTileContextMenu_tag_icon_set {
display: inline-block;
}
.mx_RoomTileContextMenu_tag_field.mx_RoomTileContextMenu_tag_fieldDisabled {
color: rgba(0, 0, 0, 0.2);
}
.mx_RoomTileContextMenu_separator {
margin-top: 0;
margin-bottom: 0;
border-bottom-style: none;
border-left-style: none;
border-right-style: none;
border-top-style: solid;
border-top-width: 1px;
border-color: $menu-border-color;
}
.mx_RoomTileContextMenu_leave {
color: $warning-color;
}
.mx_RoomTileContextMenu_notif_picker {
position: absolute;
top: 16px;
left: 5px;
}
.mx_RoomTileContextMenu_notif_field {
padding-top: 4px;
padding-right: 6px;
padding-bottom: 10px;
padding-left: 8px; /* 20px */
cursor: pointer;
white-space: nowrap;
display: flex;
align-items: center;
}
.mx_RoomTileContextMenu_notif_field.mx_RoomTileContextMenu_notif_fieldSet {
font-weight: bold;
}
.mx_RoomTileContextMenu_notif_field.mx_RoomTileContextMenu_notif_fieldDisabled {
color: rgba(0, 0, 0, 0.2);
}
.mx_RoomTileContextMenu_notif_icon {
padding-right: 4px;
padding-left: 4px;
}
.mx_RoomTileContextMenu_notif_activeIcon {
display: inline-block;
opacity: 0;
position: relative;
left: -5px;
}
.mx_RoomTileContextMenu_notif_fieldSet .mx_RoomTileContextMenu_notif_activeIcon {
opacity: 1;
}

View file

@ -1,96 +0,0 @@
/*
Copyright 2018 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_TopLeftMenu {
min-width: 210px;
border-radius: 4px;
.mx_TopLeftMenu_greyedText {
font-size: $font-12px;
opacity: 0.5;
}
.mx_TopLeftMenu_upgradeLink {
font-size: $font-12px;
img {
margin-left: 5px;
}
}
.mx_TopLeftMenu_section:not(:last-child) {
border-bottom: 1px solid $menu-border-color;
}
.mx_TopLeftMenu_section_noIcon {
margin: 5px 0;
padding: 5px 20px 5px 15px;
div:not(:first-child) {
margin-top: 5px;
}
}
.mx_TopLeftMenu_section_withIcon {
margin: 5px 0;
padding: 0;
list-style: none;
.mx_TopLeftMenu_icon_home::after {
mask-image: url('$(res)/img/feather-customised/home.svg');
}
.mx_TopLeftMenu_icon_help::after {
mask-image: url('$(res)/img/feather-customised/life-buoy.svg');
}
.mx_TopLeftMenu_icon_settings::after {
mask-image: url('$(res)/img/feather-customised/settings.svg');
}
.mx_TopLeftMenu_icon_signin::after {
mask-image: url('$(res)/img/feather-customised/sign-in.svg');
}
.mx_TopLeftMenu_icon_signout::after {
mask-image: url('$(res)/img/feather-customised/sign-out.svg');
}
.mx_AccessibleButton::after {
mask-repeat: no-repeat;
mask-position: 0 center;
mask-size: $font-16px;
position: absolute;
width: $font-16px;
height: $font-16px;
content: "";
top: 5px;
left: 14px;
background-color: $primary-fg-color;
}
.mx_AccessibleButton {
position: relative;
cursor: pointer;
white-space: nowrap;
padding: 5px 20px 5px 43px;
}
.mx_AccessibleButton:hover {
background-color: $menu-selected-color;
}
}
}

View file

@ -0,0 +1,88 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_CommunityPrototypeInviteDialog {
&.mx_Dialog_fixedWidth {
width: 360px;
}
.mx_Dialog_content {
margin-bottom: 0;
.mx_CommunityPrototypeInviteDialog_people {
position: relative;
margin-bottom: 4px;
.mx_AccessibleButton {
display: inline-block;
background-color: $focus-bg-color; // XXX: Abuse of variables
border-radius: 4px;
padding: 3px 5px;
font-size: $font-12px;
float: right;
}
}
.mx_CommunityPrototypeInviteDialog_morePeople {
margin-top: 8px;
}
.mx_CommunityPrototypeInviteDialog_person {
position: relative;
margin-top: 4px;
& > * {
vertical-align: middle;
}
.mx_Checkbox {
position: absolute;
right: 0;
top: calc(50% - 8px); // checkbox is 16px high
width: 16px; // to force a square
}
.mx_CommunityPrototypeInviteDialog_personIdentifiers {
display: inline-block;
& > * {
display: block;
}
.mx_CommunityPrototypeInviteDialog_personName {
font-weight: 600;
font-size: $font-14px;
color: $primary-fg-color;
margin-left: 7px;
}
.mx_CommunityPrototypeInviteDialog_personId {
font-size: $font-12px;
color: $muted-fg-color;
margin-left: 7px;
}
}
}
.mx_CommunityPrototypeInviteDialog_primaryButton {
display: block;
font-size: $font-13px;
line-height: 20px;
height: 20px;
margin-top: 24px;
}
}
}

View file

@ -0,0 +1,102 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_CreateCommunityPrototypeDialog {
.mx_Dialog_content {
display: flex;
flex-direction: row;
margin-bottom: 12px;
.mx_CreateCommunityPrototypeDialog_colName {
flex-basis: 66.66%;
padding-right: 100px;
.mx_Field input {
font-size: $font-16px;
line-height: $font-20px;
}
.mx_CreateCommunityPrototypeDialog_subtext {
display: block;
color: $muted-fg-color;
margin-bottom: 16px;
&:last-child {
margin-top: 16px;
}
&.mx_CreateCommunityPrototypeDialog_subtext_error {
color: $warning-color;
}
}
.mx_CreateCommunityPrototypeDialog_communityId {
position: relative;
.mx_InfoTooltip {
float: right;
}
}
.mx_AccessibleButton {
display: block;
height: 32px;
font-size: $font-16px;
line-height: 32px;
}
}
.mx_CreateCommunityPrototypeDialog_colAvatar {
flex-basis: 33.33%;
.mx_CreateCommunityPrototypeDialog_avatarContainer {
margin-top: 12px;
margin-bottom: 20px;
.mx_CreateCommunityPrototypeDialog_avatar,
.mx_CreateCommunityPrototypeDialog_placeholderAvatar {
width: 96px;
height: 96px;
border-radius: 96px;
}
.mx_CreateCommunityPrototypeDialog_placeholderAvatar {
background-color: #368bd6; // hardcoded for both themes
&::before {
display: inline-block;
background-color: #fff; // hardcoded because the background is
mask-repeat: no-repeat;
mask-size: 96px;
width: 96px;
height: 96px;
mask-position: center;
content: '';
vertical-align: middle;
mask-image: url('$(res)/img/element-icons/add-photo.svg');
}
}
}
.mx_CreateCommunityPrototypeDialog_tip {
& > b, & > span {
display: block;
color: $muted-fg-color;
}
}
}
}
}

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2019 New Vector Ltd. Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -14,26 +14,21 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
.mx_ColorSettings_roomColor { .mx_InfoTooltip_icon {
width: 16px;
height: 16px;
display: inline-block; display: inline-block;
position: relative;
width: 37px;
height: 37px;
border: 1px solid #979797;
margin-right: 13px;
cursor: pointer;
} }
.mx_ColorSettings_roomColor_selected { .mx_InfoTooltip_icon::before {
position: absolute; display: inline-block;
left: 10px; background-color: $muted-fg-color;
top: 4px; mask-repeat: no-repeat;
cursor: default !important; mask-size: 16px;
} width: 16px;
height: 16px;
.mx_ColorSettings_roomColorPrimary { mask-position: center;
height: 10px; content: '';
position: absolute; vertical-align: middle;
bottom: 0px; mask-image: url('$(res)/img/element-icons/info.svg');
width: 100%;
} }

View file

@ -0,0 +1,5 @@
<svg width="84" height="84" viewBox="0 0 84 84" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M36.7988 34.9062C37.077 33.5217 38.2978 32.5 39.7396 32.5H44.2604C45.7022 32.5 46.923 33.5217 47.2012 34.9062C47.2429 35.1137 47.3232 35.3141 47.4627 35.4731L48.0649 36.1595C48.2548 36.3759 48.5287 36.5 48.8166 36.5H52C53.1046 36.5 54 37.3954 54 38.5V49.5C54 50.6046 53.1046 51.5 52 51.5H32C30.8954 51.5 30 50.6046 30 49.5V38.5C30 37.3954 30.8954 36.5 32 36.5H35.1834C35.4713 36.5 35.7452 36.3759 35.9351 36.1595L36.5373 35.4731C36.6768 35.3141 36.7571 35.1137 36.7988 34.9062ZM42 47.5C44.2091 47.5 46 45.7091 46 43.5C46 41.2909 44.2091 39.5 42 39.5C39.7909 39.5 38 41.2909 38 43.5C38 45.7091 39.7909 47.5 42 47.5Z" fill="white"/>
<rect x="32" y="35" width="3" height="1" rx="0.5" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M59.75 27C59.75 26.5858 59.4142 26.25 59 26.25C58.5858 26.25 58.25 26.5858 58.25 27V31.25L54 31.25C53.5858 31.25 53.25 31.5858 53.25 32C53.25 32.4142 53.5858 32.75 54 32.75L58.25 32.75V37C58.25 37.4142 58.5858 37.75 59 37.75C59.4142 37.75 59.75 37.4142 59.75 37V32.75L64 32.75C64.4142 32.75 64.75 32.4142 64.75 32C64.75 31.5858 64.4142 31.25 64 31.25L59.75 31.25V27Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -0,0 +1,3 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.33301 7.28322V14.9493C2.33301 16.0735 3.25744 16.9776 4.38152 16.9659C4.90089 16.9605 5.44431 16.9567 6 16.9543V11.5C6 10.6716 6.67157 10 7.5 10H10.5C11.3284 10 12 10.6716 12 11.5V16.9662C12.6022 16.9703 13.1579 16.9748 13.6449 16.9791C14.7592 16.989 15.6663 16.0899 15.6663 14.9756V7.28178C15.6663 6.89062 15.4946 6.52064 15.1965 6.2673L9.97115 1.82572C9.411 1.3496 8.58834 1.3496 8.0282 1.82572L2.80281 6.2673C2.50477 6.52064 2.33301 6.89206 2.33301 7.28322Z" fill="#737D8C"/>
</svg>

After

Width:  |  Height:  |  Size: 634 B

View file

@ -0,0 +1,4 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="10" cy="10" r="9.5" stroke="#787878"/>
<path d="M9.79248 14H11.2065V8H9.79248V14ZM10.5034 7.14844C10.9526 7.14844 11.3198 6.80469 11.3198 6.38281C11.3198 5.95703 10.9526 5.61328 10.5034 5.61328C10.0503 5.61328 9.68311 5.95703 9.68311 6.38281C9.68311 6.80469 10.0503 7.14844 10.5034 7.14844Z" fill="#787878"/>
</svg>

After

Width:  |  Height:  |  Size: 424 B

View file

@ -119,6 +119,8 @@ $roomlist-bg-color: rgba(33, 38, 44, 0.90);
$roomlist-header-color: $tertiary-fg-color; $roomlist-header-color: $tertiary-fg-color;
$roomsublist-divider-color: $primary-fg-color; $roomsublist-divider-color: $primary-fg-color;
$tagpanel-divider-color: $roomlist-header-color;
$roomtile-preview-color: $secondary-fg-color; $roomtile-preview-color: $secondary-fg-color;
$roomtile-default-badge-bg-color: #61708b; $roomtile-default-badge-bg-color: #61708b;
$roomtile-selected-bg-color: rgba(141, 151, 165, 0.2); $roomtile-selected-bg-color: rgba(141, 151, 165, 0.2);

View file

@ -116,6 +116,8 @@ $roomlist-bg-color: $header-panel-bg-color;
$roomsublist-divider-color: $primary-fg-color; $roomsublist-divider-color: $primary-fg-color;
$tagpanel-divider-color: $roomlist-header-color;
$roomtile-preview-color: #9e9e9e; $roomtile-preview-color: #9e9e9e;
$roomtile-default-badge-bg-color: #61708b; $roomtile-default-badge-bg-color: #61708b;
$roomtile-selected-bg-color: #1A1D23; $roomtile-selected-bg-color: #1A1D23;

View file

@ -183,6 +183,8 @@ $roomlist-bg-color: $header-panel-bg-color;
$roomlist-header-color: $primary-fg-color; $roomlist-header-color: $primary-fg-color;
$roomsublist-divider-color: $primary-fg-color; $roomsublist-divider-color: $primary-fg-color;
$tagpanel-divider-color: $roomlist-header-color;
$roomtile-preview-color: #9e9e9e; $roomtile-preview-color: #9e9e9e;
$roomtile-default-badge-bg-color: #61708b; $roomtile-default-badge-bg-color: #61708b;
$roomtile-selected-bg-color: #fff; $roomtile-selected-bg-color: #fff;

View file

@ -177,6 +177,8 @@ $roomlist-bg-color: rgba(245, 245, 245, 0.90);
$roomlist-header-color: $tertiary-fg-color; $roomlist-header-color: $tertiary-fg-color;
$roomsublist-divider-color: $primary-fg-color; $roomsublist-divider-color: $primary-fg-color;
$tagpanel-divider-color: $roomlist-header-color;
$roomtile-preview-color: $secondary-fg-color; $roomtile-preview-color: $secondary-fg-color;
$roomtile-default-badge-bg-color: #61708b; $roomtile-default-badge-bg-color: #61708b;
$roomtile-selected-bg-color: #FFF; $roomtile-selected-bg-color: #FFF;

View file

@ -27,10 +27,12 @@ import {ModalManager} from "../Modal";
import SettingsStore from "../settings/SettingsStore"; import SettingsStore from "../settings/SettingsStore";
import {ActiveRoomObserver} from "../ActiveRoomObserver"; import {ActiveRoomObserver} from "../ActiveRoomObserver";
import {Notifier} from "../Notifier"; import {Notifier} from "../Notifier";
import type {Renderer} from "react-dom";
declare global { declare global {
interface Window { interface Window {
Modernizr: ModernizrStatic; Modernizr: ModernizrStatic;
matrixChat: ReturnType<Renderer>;
mxMatrixClientPeg: IMatrixClientPeg; mxMatrixClientPeg: IMatrixClientPeg;
Olm: { Olm: {
init: () => Promise<void>; init: () => Promise<void>;

View file

@ -21,6 +21,7 @@ import { deriveKey } from 'matrix-js-sdk/src/crypto/key_passphrase';
import { decodeRecoveryKey } from 'matrix-js-sdk/src/crypto/recoverykey'; import { decodeRecoveryKey } from 'matrix-js-sdk/src/crypto/recoverykey';
import { _t } from './languageHandler'; import { _t } from './languageHandler';
import {encodeBase64} from "matrix-js-sdk/src/crypto/olmlib"; import {encodeBase64} from "matrix-js-sdk/src/crypto/olmlib";
import { isSecureBackupRequired } from './utils/WellKnownUtils';
// This stores the secret storage private keys in memory for the JS SDK. This is // This stores the secret storage private keys in memory for the JS SDK. This is
// only meant to act as a cache to avoid prompting the user multiple times // only meant to act as a cache to avoid prompting the user multiple times
@ -34,6 +35,17 @@ function isCachingAllowed() {
return secretStorageBeingAccessed; return secretStorageBeingAccessed;
} }
/**
* This can be used by other components to check if secret storage access is in
* progress, so that we can e.g. avoid intermittently showing toasts during
* secret storage setup.
*
* @returns {bool}
*/
export function isSecretStorageBeingAccessed() {
return secretStorageBeingAccessed;
}
export class AccessCancelledError extends Error { export class AccessCancelledError extends Error {
constructor() { constructor() {
super("Secret storage access canceled"); super("Secret storage access canceled");
@ -57,19 +69,19 @@ async function getSecretStorageKey({ keys: keyInfos }, ssssItemName) {
if (keyInfoEntries.length > 1) { if (keyInfoEntries.length > 1) {
throw new Error("Multiple storage key requests not implemented"); throw new Error("Multiple storage key requests not implemented");
} }
const [name, info] = keyInfoEntries[0]; const [keyId, keyInfo] = keyInfoEntries[0];
// Check the in-memory cache // Check the in-memory cache
if (isCachingAllowed() && secretStorageKeys[name]) { if (isCachingAllowed() && secretStorageKeys[keyId]) {
return [name, secretStorageKeys[name]]; return [keyId, secretStorageKeys[keyId]];
} }
const inputToKey = async ({ passphrase, recoveryKey }) => { const inputToKey = async ({ passphrase, recoveryKey }) => {
if (passphrase) { if (passphrase) {
return deriveKey( return deriveKey(
passphrase, passphrase,
info.passphrase.salt, keyInfo.passphrase.salt,
info.passphrase.iterations, keyInfo.passphrase.iterations,
); );
} else { } else {
return decodeRecoveryKey(recoveryKey); return decodeRecoveryKey(recoveryKey);
@ -81,10 +93,10 @@ async function getSecretStorageKey({ keys: keyInfos }, ssssItemName) {
AccessSecretStorageDialog, AccessSecretStorageDialog,
/* props= */ /* props= */
{ {
keyInfo: info, keyInfo,
checkPrivateKey: async (input) => { checkPrivateKey: async (input) => {
const key = await inputToKey(input); const key = await inputToKey(input);
return await MatrixClientPeg.get().checkSecretStorageKey(key, info); return await MatrixClientPeg.get().checkSecretStorageKey(key, keyInfo);
}, },
}, },
/* className= */ null, /* className= */ null,
@ -106,11 +118,15 @@ async function getSecretStorageKey({ keys: keyInfos }, ssssItemName) {
const key = await inputToKey(input); const key = await inputToKey(input);
// Save to cache to avoid future prompts in the current session // Save to cache to avoid future prompts in the current session
if (isCachingAllowed()) { cacheSecretStorageKey(keyId, key);
secretStorageKeys[name] = key;
}
return [name, key]; return [keyId, key];
}
function cacheSecretStorageKey(keyId, key) {
if (isCachingAllowed()) {
secretStorageKeys[keyId] = key;
}
} }
const onSecretRequested = async function({ const onSecretRequested = async function({
@ -158,6 +174,7 @@ const onSecretRequested = async function({
export const crossSigningCallbacks = { export const crossSigningCallbacks = {
getSecretStorageKey, getSecretStorageKey,
cacheSecretStorageKey,
onSecretRequested, onSecretRequested,
}; };
@ -206,9 +223,20 @@ export async function accessSecretStorage(func = async () => { }, forceReset = f
const { finished } = Modal.createTrackedDialogAsync('Create Secret Storage dialog', '', const { finished } = Modal.createTrackedDialogAsync('Create Secret Storage dialog', '',
import("./async-components/views/dialogs/secretstorage/CreateSecretStorageDialog"), import("./async-components/views/dialogs/secretstorage/CreateSecretStorageDialog"),
{ {
force: forceReset, forceReset,
},
null,
/* priority = */ false,
/* static = */ true,
/* options = */ {
onBeforeClose(reason) {
// If Secure Backup is required, you cannot leave the modal.
if (reason === "backgroundClick") {
return !isSecureBackupRequired();
}
return true;
},
}, },
null, /* priority = */ false, /* static = */ true,
); );
const [confirmed] = await finished; const [confirmed] = await finished;
if (!confirmed) { if (!confirmed) {
@ -216,7 +244,7 @@ export async function accessSecretStorage(func = async () => { }, forceReset = f
} }
} else { } else {
const InteractiveAuthDialog = sdk.getComponent("dialogs.InteractiveAuthDialog"); const InteractiveAuthDialog = sdk.getComponent("dialogs.InteractiveAuthDialog");
await cli.bootstrapSecretStorage({ await cli.bootstrapCrossSigning({
authUploadDeviceSigningKeys: async (makeRequest) => { authUploadDeviceSigningKeys: async (makeRequest) => {
const { finished } = Modal.createTrackedDialog( const { finished } = Modal.createTrackedDialog(
'Cross-signing keys dialog', '', InteractiveAuthDialog, 'Cross-signing keys dialog', '', InteractiveAuthDialog,
@ -231,7 +259,9 @@ export async function accessSecretStorage(func = async () => { }, forceReset = f
throw new Error("Cross-signing key upload auth canceled"); throw new Error("Cross-signing key upload auth canceled");
} }
}, },
getBackupPassphrase: promptForBackupPassphrase, });
await cli.bootstrapSecretStorage({
getKeyBackupPassphrase: promptForBackupPassphrase,
}); });
} }

View file

@ -15,6 +15,7 @@ limitations under the License.
*/ */
import {MatrixClientPeg} from './MatrixClientPeg'; import {MatrixClientPeg} from './MatrixClientPeg';
import dis from "./dispatcher/dispatcher";
import { import {
hideToast as hideBulkUnverifiedSessionsToast, hideToast as hideBulkUnverifiedSessionsToast,
showToast as showBulkUnverifiedSessionsToast, showToast as showBulkUnverifiedSessionsToast,
@ -28,11 +29,16 @@ import {
hideToast as hideUnverifiedSessionsToast, hideToast as hideUnverifiedSessionsToast,
showToast as showUnverifiedSessionsToast, showToast as showUnverifiedSessionsToast,
} from "./toasts/UnverifiedSessionToast"; } from "./toasts/UnverifiedSessionToast";
import {privateShouldBeEncrypted} from "./createRoom"; import { privateShouldBeEncrypted } from "./createRoom";
import { isSecretStorageBeingAccessed, accessSecretStorage } from "./CrossSigningManager";
import { isSecureBackupRequired } from './utils/WellKnownUtils';
import { isLoggedIn } from './components/structures/MatrixChat';
const KEY_BACKUP_POLL_INTERVAL = 5 * 60 * 1000; const KEY_BACKUP_POLL_INTERVAL = 5 * 60 * 1000;
export default class DeviceListener { export default class DeviceListener {
private dispatcherRef: string;
// device IDs for which the user has dismissed the verify toast ('Later') // device IDs for which the user has dismissed the verify toast ('Later')
private dismissed = new Set<string>(); private dismissed = new Set<string>();
// has the user dismissed any of the various nag toasts to setup encryption on this device? // has the user dismissed any of the various nag toasts to setup encryption on this device?
@ -60,6 +66,7 @@ export default class DeviceListener {
MatrixClientPeg.get().on('crossSigning.keysChanged', this._onCrossSingingKeysChanged); MatrixClientPeg.get().on('crossSigning.keysChanged', this._onCrossSingingKeysChanged);
MatrixClientPeg.get().on('accountData', this._onAccountData); MatrixClientPeg.get().on('accountData', this._onAccountData);
MatrixClientPeg.get().on('sync', this._onSync); MatrixClientPeg.get().on('sync', this._onSync);
this.dispatcherRef = dis.register(this._onAction);
this._recheck(); this._recheck();
} }
@ -73,6 +80,10 @@ export default class DeviceListener {
MatrixClientPeg.get().removeListener('accountData', this._onAccountData); MatrixClientPeg.get().removeListener('accountData', this._onAccountData);
MatrixClientPeg.get().removeListener('sync', this._onSync); MatrixClientPeg.get().removeListener('sync', this._onSync);
} }
if (this.dispatcherRef) {
dis.unregister(this.dispatcherRef);
this.dispatcherRef = null;
}
this.dismissed.clear(); this.dismissed.clear();
this.dismissedThisDeviceToast = false; this.dismissedThisDeviceToast = false;
this.keyBackupInfo = null; this.keyBackupInfo = null;
@ -158,6 +169,11 @@ export default class DeviceListener {
if (state === 'PREPARED' && prevState === null) this._recheck(); if (state === 'PREPARED' && prevState === null) this._recheck();
}; };
_onAction = ({ action }) => {
if (action !== "on_logged_in") return;
this._recheck();
};
// The server doesn't tell us when key backup is set up, so we poll // The server doesn't tell us when key backup is set up, so we poll
// & cache the result // & cache the result
async _getKeyBackupInfo() { async _getKeyBackupInfo() {
@ -170,6 +186,9 @@ export default class DeviceListener {
} }
private shouldShowSetupEncryptionToast() { private shouldShowSetupEncryptionToast() {
// If we're in the middle of a secret storage operation, we're likely
// modifying the state involved here, so don't add new toasts to setup.
if (isSecretStorageBeingAccessed()) return false;
// In a default configuration, show the toasts. If the well-known config causes e2ee default to be false // In a default configuration, show the toasts. If the well-known config causes e2ee default to be false
// then do not show the toasts until user is in at least one encrypted room. // then do not show the toasts until user is in at least one encrypted room.
if (privateShouldBeEncrypted()) return true; if (privateShouldBeEncrypted()) return true;
@ -188,9 +207,13 @@ export default class DeviceListener {
// (we add a listener on sync to do once check after the initial sync is done) // (we add a listener on sync to do once check after the initial sync is done)
if (!cli.isInitialSyncComplete()) return; if (!cli.isInitialSyncComplete()) return;
// JRS: This will change again in the next PR which moves secret storage
// later in the process.
const crossSigningReady = await cli.isCrossSigningReady(); const crossSigningReady = await cli.isCrossSigningReady();
const secretStorageReady = await cli.isSecretStorageReady();
const allSystemsReady = crossSigningReady && secretStorageReady;
if (this.dismissedThisDeviceToast || crossSigningReady) { if (this.dismissedThisDeviceToast || allSystemsReady) {
hideSetupEncryptionToast(); hideSetupEncryptionToast();
} else if (this.shouldShowSetupEncryptionToast()) { } else if (this.shouldShowSetupEncryptionToast()) {
// make sure our keys are finished downloading // make sure our keys are finished downloading
@ -207,10 +230,18 @@ export default class DeviceListener {
showSetupEncryptionToast(SetupKind.UPGRADE_ENCRYPTION); showSetupEncryptionToast(SetupKind.UPGRADE_ENCRYPTION);
} else { } else {
// No cross-signing or key backup on account (set up encryption) // No cross-signing or key backup on account (set up encryption)
await cli.waitForClientWellKnown();
if (isSecureBackupRequired() && isLoggedIn()) {
// If we're meant to set up, and Secure Backup is required,
// trigger the flow directly without a toast once logged in.
hideSetupEncryptionToast();
accessSecretStorage();
} else {
showSetupEncryptionToast(SetupKind.SET_UP_ENCRYPTION); showSetupEncryptionToast(SetupKind.SET_UP_ENCRYPTION);
} }
} }
} }
}
// This needs to be done after awaiting on downloadKeys() above, so // This needs to be done after awaiting on downloadKeys() above, so
// we make sure we get the devices after the fetch is done. // we make sure we get the devices after the fetch is done.

View file

@ -197,7 +197,7 @@ export default class FromWidgetPostMessageApi {
const integId = (data && data.integId) ? data.integId : null; const integId = (data && data.integId) ? data.integId : null;
// TODO: Open the right integration manager for the widget // TODO: Open the right integration manager for the widget
if (SettingsStore.isFeatureEnabled("feature_many_integration_managers")) { if (SettingsStore.getValue("feature_many_integration_managers")) {
IntegrationManagers.sharedInstance().openAll( IntegrationManagers.sharedInstance().openAll(
MatrixClientPeg.get().getRoom(RoomViewStore.getRoomId()), MatrixClientPeg.get().getRoom(RoomViewStore.getRoomId()),
`type_${integType}`, `type_${integType}`,

View file

@ -23,6 +23,7 @@ import Modal from './Modal';
import * as sdk from './'; import * as sdk from './';
import { _t } from './languageHandler'; import { _t } from './languageHandler';
import {KIND_DM, KIND_INVITE} from "./components/views/dialogs/InviteDialog"; import {KIND_DM, KIND_INVITE} from "./components/views/dialogs/InviteDialog";
import CommunityPrototypeInviteDialog from "./components/views/dialogs/CommunityPrototypeInviteDialog";
/** /**
* Invites multiple addresses to a room * Invites multiple addresses to a room
@ -56,6 +57,13 @@ export function showRoomInviteDialog(roomId) {
); );
} }
export function showCommunityRoomInviteDialog(roomId, communityName) {
Modal.createTrackedDialog(
'Invite Users to Community', '', CommunityPrototypeInviteDialog, {communityName, roomId},
/*className=*/null, /*isPriority=*/false, /*isStatic=*/true,
);
}
/** /**
* Checks if the given MatrixEvent is a valid 3rd party user invite. * Checks if the given MatrixEvent is a valid 3rd party user invite.
* @param {MatrixEvent} event The event to check * @param {MatrixEvent} event The event to check
@ -77,7 +85,7 @@ export function isValid3pidInvite(event) {
export function inviteUsersToRoom(roomId, userIds) { export function inviteUsersToRoom(roomId, userIds) {
return inviteMultipleToRoom(roomId, userIds).then((result) => { return inviteMultipleToRoom(roomId, userIds).then((result) => {
const room = MatrixClientPeg.get().getRoom(roomId); const room = MatrixClientPeg.get().getRoom(roomId);
return _showAnyInviteErrors(result.states, room, result.inviter); showAnyInviteErrors(result.states, room, result.inviter);
}).catch((err) => { }).catch((err) => {
console.error(err.stack); console.error(err.stack);
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
@ -88,7 +96,7 @@ export function inviteUsersToRoom(roomId, userIds) {
}); });
} }
function _showAnyInviteErrors(addrs, room, inviter) { export function showAnyInviteErrors(addrs, room, inviter) {
// Show user any errors // Show user any errors
const failedUsers = Object.keys(addrs).filter(a => addrs[a] === 'error'); const failedUsers = Object.keys(addrs).filter(a => addrs[a] === 'error');
if (failedUsers.length === 1 && inviter.fatal) { if (failedUsers.length === 1 && inviter.fatal) {
@ -100,6 +108,7 @@ function _showAnyInviteErrors(addrs, room, inviter) {
title: _t("Failed to invite users to the room:", {roomName: room.name}), title: _t("Failed to invite users to the room:", {roomName: room.name}),
description: inviter.getErrorText(failedUsers[0]), description: inviter.getErrorText(failedUsers[0]),
}); });
return false;
} else { } else {
const errorList = []; const errorList = [];
for (const addr of failedUsers) { for (const addr of failedUsers) {
@ -118,8 +127,9 @@ function _showAnyInviteErrors(addrs, room, inviter) {
title: _t("Failed to invite the following users to the %(roomName)s room:", {roomName: room.name}), title: _t("Failed to invite the following users to the %(roomName)s room:", {roomName: room.name}),
description, description,
}); });
return false;
} }
} }
return addrs; return true;
} }

View file

@ -43,7 +43,7 @@ import SdkConfig from "./SdkConfig";
import { ensureDMExists } from "./createRoom"; import { ensureDMExists } from "./createRoom";
import { ViewUserPayload } from "./dispatcher/payloads/ViewUserPayload"; import { ViewUserPayload } from "./dispatcher/payloads/ViewUserPayload";
import { Action } from "./dispatcher/actions"; import { Action } from "./dispatcher/actions";
import { EffectiveMembership, getEffectiveMembership } from "./utils/membership"; import { EffectiveMembership, getEffectiveMembership, leaveRoomBehaviour } from "./utils/membership";
// XXX: workaround for https://github.com/microsoft/TypeScript/issues/31816 // XXX: workaround for https://github.com/microsoft/TypeScript/issues/31816
interface HTMLInputEvent extends Event { interface HTMLInputEvent extends Event {
@ -601,11 +601,7 @@ export const Commands = [
} }
if (!targetRoomId) targetRoomId = roomId; if (!targetRoomId) targetRoomId = roomId;
return success( return success(leaveRoomBehaviour(targetRoomId));
cli.leaveRoomChain(targetRoomId).then(function() {
dis.dispatch({action: 'view_next_room'});
}),
);
}, },
category: CommandCategories.actions, category: CommandCategories.actions,
}), }),

View file

@ -30,6 +30,7 @@ import StyledRadioButton from '../../../../components/views/elements/StyledRadio
import AccessibleButton from "../../../../components/views/elements/AccessibleButton"; import AccessibleButton from "../../../../components/views/elements/AccessibleButton";
import DialogButtons from "../../../../components/views/elements/DialogButtons"; import DialogButtons from "../../../../components/views/elements/DialogButtons";
import InlineSpinner from "../../../../components/views/elements/InlineSpinner"; import InlineSpinner from "../../../../components/views/elements/InlineSpinner";
import { isSecureBackupRequired } from '../../../../utils/WellKnownUtils';
const PHASE_LOADING = 0; const PHASE_LOADING = 0;
const PHASE_LOADERROR = 1; const PHASE_LOADERROR = 1;
@ -55,12 +56,12 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
static propTypes = { static propTypes = {
hasCancel: PropTypes.bool, hasCancel: PropTypes.bool,
accountPassword: PropTypes.string, accountPassword: PropTypes.string,
force: PropTypes.bool, forceReset: PropTypes.bool,
}; };
static defaultProps = { static defaultProps = {
hasCancel: true, hasCancel: true,
force: false, forceReset: false,
}; };
constructor(props) { constructor(props) {
@ -85,8 +86,8 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
canUploadKeysWithPasswordOnly: null, canUploadKeysWithPasswordOnly: null,
accountPassword: props.accountPassword || "", accountPassword: props.accountPassword || "",
accountPasswordCorrect: null, accountPasswordCorrect: null,
passPhraseKeySelected: CREATE_STORAGE_OPTION_KEY, passPhraseKeySelected: CREATE_STORAGE_OPTION_KEY,
canSkip: !isSecureBackupRequired(),
}; };
this._passphraseField = createRef(); this._passphraseField = createRef();
@ -117,8 +118,8 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
MatrixClientPeg.get().isCryptoEnabled() && await MatrixClientPeg.get().isKeyBackupTrusted(backupInfo) MatrixClientPeg.get().isCryptoEnabled() && await MatrixClientPeg.get().isKeyBackupTrusted(backupInfo)
); );
const { force } = this.props; const { forceReset } = this.props;
const phase = (backupInfo && !force) ? PHASE_MIGRATE : PHASE_CHOOSE_KEY_PASSPHRASE; const phase = (backupInfo && !forceReset) ? PHASE_MIGRATE : PHASE_CHOOSE_KEY_PASSPHRASE;
this.setState({ this.setState({
phase, phase,
@ -276,20 +277,25 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.get();
const { force } = this.props; const { forceReset } = this.props;
try { try {
if (force) { if (forceReset) {
console.log("Forcing secret storage reset"); // log something so we can debug this later console.log("Forcing cross-signing and secret storage reset");
await cli.bootstrapSecretStorage({ await cli.bootstrapSecretStorage({
authUploadDeviceSigningKeys: this._doBootstrapUIAuth,
createSecretStorageKey: async () => this._recoveryKey, createSecretStorageKey: async () => this._recoveryKey,
setupNewKeyBackup: true, setupNewKeyBackup: true,
setupNewSecretStorage: true, setupNewSecretStorage: true,
}); });
} else { await cli.bootstrapCrossSigning({
await cli.bootstrapSecretStorage({
authUploadDeviceSigningKeys: this._doBootstrapUIAuth, authUploadDeviceSigningKeys: this._doBootstrapUIAuth,
setupNewCrossSigning: true,
});
} else {
await cli.bootstrapCrossSigning({
authUploadDeviceSigningKeys: this._doBootstrapUIAuth,
});
await cli.bootstrapSecretStorage({
createSecretStorageKey: async () => this._recoveryKey, createSecretStorageKey: async () => this._recoveryKey,
keyBackupInfo: this.state.backupInfo, keyBackupInfo: this.state.backupInfo,
setupNewKeyBackup: !this.state.backupInfo, setupNewKeyBackup: !this.state.backupInfo,
@ -470,7 +476,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
primaryButton={_t("Continue")} primaryButton={_t("Continue")}
onPrimaryButtonClick={this._onChooseKeyPassphraseFormSubmit} onPrimaryButtonClick={this._onChooseKeyPassphraseFormSubmit}
onCancel={this._onCancelClick} onCancel={this._onCancelClick}
hasCancel={true} hasCancel={this.state.canSkip}
/> />
</form>; </form>;
} }
@ -687,7 +693,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
<div className="mx_Dialog_buttons"> <div className="mx_Dialog_buttons">
<DialogButtons primaryButton={_t('Retry')} <DialogButtons primaryButton={_t('Retry')}
onPrimaryButtonClick={this._onLoadRetryClick} onPrimaryButtonClick={this._onLoadRetryClick}
hasCancel={true} hasCancel={this.state.canSkip}
onCancel={this._onCancel} onCancel={this._onCancel}
/> />
</div> </div>
@ -714,7 +720,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
_titleForPhase(phase) { _titleForPhase(phase) {
switch (phase) { switch (phase) {
case PHASE_CHOOSE_KEY_PASSPHRASE: case PHASE_CHOOSE_KEY_PASSPHRASE:
return _t('Set up Secure backup'); return _t('Set up Secure Backup');
case PHASE_MIGRATE: case PHASE_MIGRATE:
return _t('Upgrade your encryption'); return _t('Upgrade your encryption');
case PHASE_PASSPHRASE: case PHASE_PASSPHRASE:
@ -742,7 +748,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
<div className="mx_Dialog_buttons"> <div className="mx_Dialog_buttons">
<DialogButtons primaryButton={_t('Retry')} <DialogButtons primaryButton={_t('Retry')}
onPrimaryButtonClick={this._bootstrapSecretStorage} onPrimaryButtonClick={this._bootstrapSecretStorage}
hasCancel={true} hasCancel={this.state.canSkip}
onCancel={this._onCancel} onCancel={this._onCancel}
/> />
</div> </div>

View file

@ -378,7 +378,7 @@ export default class LeftPanel extends React.Component<IProps, IState> {
const tagPanel = !this.state.showTagPanel ? null : ( const tagPanel = !this.state.showTagPanel ? null : (
<div className="mx_LeftPanel_tagPanelContainer"> <div className="mx_LeftPanel_tagPanelContainer">
<TagPanel/> <TagPanel/>
{SettingsStore.isFeatureEnabled("feature_custom_tags") ? <CustomRoomTagPanel /> : null} {SettingsStore.getValue("feature_custom_tags") ? <CustomRoomTagPanel /> : null}
</div> </div>
); );

View file

@ -76,6 +76,8 @@ import { OpenToTabPayload } from "../../dispatcher/payloads/OpenToTabPayload";
import ErrorDialog from "../views/dialogs/ErrorDialog"; import ErrorDialog from "../views/dialogs/ErrorDialog";
import { RoomNotificationStateStore } from "../../stores/notifications/RoomNotificationStateStore"; import { RoomNotificationStateStore } from "../../stores/notifications/RoomNotificationStateStore";
import { SettingLevel } from "../../settings/SettingLevel"; import { SettingLevel } from "../../settings/SettingLevel";
import { leaveRoomBehaviour } from "../../utils/membership";
import CreateCommunityPrototypeDialog from "../views/dialogs/CreateCommunityPrototypeDialog";
/** constants for MatrixChat.state.view */ /** constants for MatrixChat.state.view */
export enum Views { export enum Views {
@ -619,7 +621,10 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
this.createRoom(payload.public); this.createRoom(payload.public);
break; break;
case 'view_create_group': { case 'view_create_group': {
const CreateGroupDialog = sdk.getComponent("dialogs.CreateGroupDialog"); let CreateGroupDialog = sdk.getComponent("dialogs.CreateGroupDialog")
if (SettingsStore.getValue("feature_communities_v2_prototypes")) {
CreateGroupDialog = CreateCommunityPrototypeDialog;
}
Modal.createTrackedDialog('Create Community', '', CreateGroupDialog); Modal.createTrackedDialog('Create Community', '', CreateGroupDialog);
break; break;
} }
@ -1082,50 +1087,13 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
button: _t("Leave"), button: _t("Leave"),
onFinished: (shouldLeave) => { onFinished: (shouldLeave) => {
if (shouldLeave) { if (shouldLeave) {
const d = MatrixClientPeg.get().leaveRoomChain(roomId); const d = leaveRoomBehaviour(roomId);
// FIXME: controller shouldn't be loading a view :( // FIXME: controller shouldn't be loading a view :(
const Loader = sdk.getComponent("elements.Spinner"); const Loader = sdk.getComponent("elements.Spinner");
const modal = Modal.createDialog(Loader, null, 'mx_Dialog_spinner'); const modal = Modal.createDialog(Loader, null, 'mx_Dialog_spinner');
d.then((errors) => { d.finally(() => modal.close());
modal.close();
for (const leftRoomId of Object.keys(errors)) {
const err = errors[leftRoomId];
if (!err) continue;
console.error("Failed to leave room " + leftRoomId + " " + err);
let title = _t("Failed to leave room");
let message = _t("Server may be unavailable, overloaded, or you hit a bug.");
if (err.errcode === 'M_CANNOT_LEAVE_SERVER_NOTICE_ROOM') {
title = _t("Can't leave Server Notices room");
message = _t(
"This room is used for important messages from the Homeserver, " +
"so you cannot leave it.",
);
} else if (err && err.message) {
message = err.message;
}
Modal.createTrackedDialog('Failed to leave room', '', ErrorDialog, {
title: title,
description: message,
});
return;
}
if (this.state.currentRoomId === roomId) {
dis.dispatch({action: 'view_next_room'});
}
}, (err) => {
// This should only happen if something went seriously wrong with leaving the chain.
modal.close();
console.error("Failed to leave room " + roomId + " " + err);
Modal.createTrackedDialog('Failed to leave room', '', ErrorDialog, {
title: _t("Failed to leave room"),
description: _t("Unknown error"),
});
});
} }
}, },
}); });
@ -2085,3 +2053,12 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
</ErrorBoundary>; </ErrorBoundary>;
} }
} }
export function isLoggedIn(): boolean {
// JRS: Maybe we should move the step that writes this to the window out of
// `element-web` and into this file? Better yet, we should probably create a
// store to hold this state.
// See also https://github.com/vector-im/element-web/issues/15034.
const app = window.matrixChat;
return app && (app as MatrixChat).state.view === Views.LOGGED_IN;
}

View file

@ -30,6 +30,10 @@ import { instanceForInstanceId, protocolNameForInstanceId } from '../../utils/Di
import Analytics from '../../Analytics'; import Analytics from '../../Analytics';
import {getHttpUriForMxc} from "matrix-js-sdk/src/content-repo"; import {getHttpUriForMxc} from "matrix-js-sdk/src/content-repo";
import {ALL_ROOMS} from "../views/directory/NetworkDropdown"; import {ALL_ROOMS} from "../views/directory/NetworkDropdown";
import SettingsStore from "../../settings/SettingsStore";
import TagOrderStore from "../../stores/TagOrderStore";
import GroupStore from "../../stores/GroupStore";
import FlairStore from "../../stores/FlairStore";
const MAX_NAME_LENGTH = 80; const MAX_NAME_LENGTH = 80;
const MAX_TOPIC_LENGTH = 160; const MAX_TOPIC_LENGTH = 160;
@ -46,6 +50,7 @@ export default createReactClass({
}, },
getInitialState: function() { getInitialState: function() {
const selectedCommunityId = TagOrderStore.getSelectedTags()[0];
return { return {
publicRooms: [], publicRooms: [],
loading: true, loading: true,
@ -54,6 +59,10 @@ export default createReactClass({
instanceId: undefined, instanceId: undefined,
roomServer: MatrixClientPeg.getHomeserverName(), roomServer: MatrixClientPeg.getHomeserverName(),
filterString: null, filterString: null,
selectedCommunityId: SettingsStore.getValue("feature_communities_v2_prototypes")
? selectedCommunityId
: null,
communityName: null,
}; };
}, },
@ -71,6 +80,8 @@ export default createReactClass({
this.setState({protocolsLoading: false}); this.setState({protocolsLoading: false});
return; return;
} }
if (!this.state.selectedCommunityId) {
MatrixClientPeg.get().getThirdpartyProtocols().then((response) => { MatrixClientPeg.get().getThirdpartyProtocols().then((response) => {
this.protocols = response; this.protocols = response;
this.setState({protocolsLoading: false}); this.setState({protocolsLoading: false});
@ -89,10 +100,19 @@ export default createReactClass({
error: _t( error: _t(
'%(brand)s failed to get the protocol list from the homeserver. ' + '%(brand)s failed to get the protocol list from the homeserver. ' +
'The homeserver may be too old to support third party networks.', 'The homeserver may be too old to support third party networks.',
{ brand }, {brand},
), ),
}); });
}); });
} else {
// We don't use the protocols in the communities v2 prototype experience
this.setState({protocolsLoading: false});
// Grab the profile info async
FlairStore.getGroupProfileCached(MatrixClientPeg.get(), this.state.selectedCommunityId).then(profile => {
this.setState({communityName: profile.name});
});
}
this.refreshRoomList(); this.refreshRoomList();
}, },
@ -105,6 +125,33 @@ export default createReactClass({
}, },
refreshRoomList: function() { refreshRoomList: function() {
if (this.state.selectedCommunityId) {
this.setState({
publicRooms: GroupStore.getGroupRooms(this.state.selectedCommunityId).map(r => {
return {
// Translate all the group properties to the directory format
room_id: r.roomId,
name: r.name,
topic: r.topic,
canonical_alias: r.canonicalAlias,
num_joined_members: r.numJoinedMembers,
avatarUrl: r.avatarUrl,
world_readable: r.worldReadable,
guest_can_join: r.guestsCanJoin,
};
}).filter(r => {
const filterString = this.state.filterString;
if (filterString) {
const containedIn = (s: string) => (s || "").toLowerCase().includes(filterString.toLowerCase());
return containedIn(r.name) || containedIn(r.topic) || containedIn(r.canonical_alias);
}
return true;
}),
loading: false,
});
return;
}
this.nextBatch = null; this.nextBatch = null;
this.setState({ this.setState({
publicRooms: [], publicRooms: [],
@ -114,6 +161,7 @@ export default createReactClass({
}, },
getMoreRooms: function() { getMoreRooms: function() {
if (this.state.selectedCommunityId) return Promise.resolve(); // no more rooms
if (!MatrixClientPeg.get()) return Promise.resolve(); if (!MatrixClientPeg.get()) return Promise.resolve();
this.setState({ this.setState({
@ -239,7 +287,7 @@ export default createReactClass({
}, },
onRoomClicked: function(room, ev) { onRoomClicked: function(room, ev) {
if (ev.shiftKey) { if (ev.shiftKey && !this.state.selectedCommunityId) {
ev.preventDefault(); ev.preventDefault();
this.removeFromDirectory(room); this.removeFromDirectory(room);
} else { } else {
@ -610,6 +658,18 @@ export default createReactClass({
} }
} }
let dropdown = (
<NetworkDropdown
protocols={this.protocols}
onOptionChange={this.onOptionChange}
selectedServerName={this.state.roomServer}
selectedInstanceId={this.state.instanceId}
/>
);
if (this.state.selectedCommunityId) {
dropdown = null;
}
listHeader = <div className="mx_RoomDirectory_listheader"> listHeader = <div className="mx_RoomDirectory_listheader">
<DirectorySearchBox <DirectorySearchBox
className="mx_RoomDirectory_searchbox" className="mx_RoomDirectory_searchbox"
@ -619,12 +679,7 @@ export default createReactClass({
placeholder={placeholder} placeholder={placeholder}
showJoinButton={showJoinButton} showJoinButton={showJoinButton}
/> />
<NetworkDropdown {dropdown}
protocols={this.protocols}
onOptionChange={this.onOptionChange}
selectedServerName={this.state.roomServer}
selectedInstanceId={this.state.instanceId}
/>
</div>; </div>;
} }
const explanation = const explanation =
@ -637,12 +692,16 @@ export default createReactClass({
}}, }},
); );
const title = this.state.selectedCommunityId
? _t("Explore rooms in %(communityName)s", {
communityName: this.state.communityName || this.state.selectedCommunityId,
}) : _t("Explore rooms");
return ( return (
<BaseDialog <BaseDialog
className={'mx_RoomDirectory_dialog'} className={'mx_RoomDirectory_dialog'}
hasCancel={true} hasCancel={true}
onFinished={this.props.onFinished} onFinished={this.props.onFinished}
title={_t("Explore rooms")} title={title}
> >
<div className="mx_RoomDirectory"> <div className="mx_RoomDirectory">
{explanation} {explanation}

View file

@ -29,6 +29,8 @@ import { Droppable } from 'react-beautiful-dnd';
import classNames from 'classnames'; import classNames from 'classnames';
import MatrixClientContext from "../../contexts/MatrixClientContext"; import MatrixClientContext from "../../contexts/MatrixClientContext";
import AutoHideScrollbar from "./AutoHideScrollbar"; import AutoHideScrollbar from "./AutoHideScrollbar";
import SettingsStore from "../../settings/SettingsStore";
import UserTagTile from "../views/elements/UserTagTile";
const TagPanel = createReactClass({ const TagPanel = createReactClass({
displayName: 'TagPanel', displayName: 'TagPanel',
@ -93,20 +95,24 @@ const TagPanel = createReactClass({
} }
}, },
onCreateGroupClick(ev) {
ev.stopPropagation();
dis.dispatch({action: 'view_create_group'});
},
onClearFilterClick(ev) { onClearFilterClick(ev) {
dis.dispatch({action: 'deselect_tags'}); dis.dispatch({action: 'deselect_tags'});
}, },
renderGlobalIcon() {
if (!SettingsStore.getValue("feature_communities_v2_prototypes")) return null;
return (
<div>
<UserTagTile />
<hr className="mx_TagPanel_divider" />
</div>
);
},
render() { render() {
const DNDTagTile = sdk.getComponent('elements.DNDTagTile'); const DNDTagTile = sdk.getComponent('elements.DNDTagTile');
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
const ActionButton = sdk.getComponent('elements.ActionButton'); const ActionButton = sdk.getComponent('elements.ActionButton');
const TintableSvg = sdk.getComponent('elements.TintableSvg');
const tags = this.state.orderedTags.map((tag, index) => { const tags = this.state.orderedTags.map((tag, index) => {
return <DNDTagTile return <DNDTagTile
@ -118,26 +124,29 @@ const TagPanel = createReactClass({
}); });
const itemsSelected = this.state.selectedTags.length > 0; const itemsSelected = this.state.selectedTags.length > 0;
let clearButton;
if (itemsSelected) {
clearButton = <AccessibleButton className="mx_TagPanel_clearButton" onClick={this.onClearFilterClick}>
<TintableSvg src={require("../../../res/img/icons-close.svg")} width="24" height="24"
alt={_t("Clear filter")}
title={_t("Clear filter")}
/>
</AccessibleButton>;
}
const classes = classNames('mx_TagPanel', { const classes = classNames('mx_TagPanel', {
mx_TagPanel_items_selected: itemsSelected, mx_TagPanel_items_selected: itemsSelected,
}); });
return <div className={classes}> let createButton = (
<div className="mx_TagPanel_clearButton_container"> <ActionButton
{ clearButton } tooltip
</div> label={_t("Communities")}
<div className="mx_TagPanel_divider" /> action="toggle_my_groups"
className="mx_TagTile mx_TagTile_plus" />
);
if (SettingsStore.getValue("feature_communities_v2_prototypes")) {
createButton = (
<ActionButton
tooltip
label={_t("Create community")}
action="view_create_group"
className="mx_TagTile mx_TagTile_plus" />
);
}
return <div className={classes} onClick={this.onClearFilterClick}>
<AutoHideScrollbar <AutoHideScrollbar
className="mx_TagPanel_scroller" className="mx_TagPanel_scroller"
// XXX: Use onMouseDown as a workaround for https://github.com/atlassian/react-beautiful-dnd/issues/273 // XXX: Use onMouseDown as a workaround for https://github.com/atlassian/react-beautiful-dnd/issues/273
@ -153,13 +162,10 @@ const TagPanel = createReactClass({
className="mx_TagPanel_tagTileContainer" className="mx_TagPanel_tagTileContainer"
ref={provided.innerRef} ref={provided.innerRef}
> >
{ this.renderGlobalIcon() }
{ tags } { tags }
<div> <div>
<ActionButton {createButton}
tooltip
label={_t("Communities")}
action="toggle_my_groups"
className="mx_TagTile mx_TagTile_plus" />
</div> </div>
{ provided.placeholder } { provided.placeholder }
</div> </div>

View file

@ -295,7 +295,10 @@ export default class UserMenu extends React.Component<IProps, IState> {
public render() { public render() {
const avatarSize = 32; // should match border-radius of the avatar const avatarSize = 32; // should match border-radius of the avatar
let name = <span className="mx_UserMenu_userName">{OwnProfileStore.instance.displayName}</span>; const displayName = OwnProfileStore.instance.displayName || MatrixClientPeg.get().getUserId();
const avatarUrl = OwnProfileStore.instance.getHttpAvatarUrl(avatarSize);
let name = <span className="mx_UserMenu_userName">{displayName}</span>;
let buttons = ( let buttons = (
<span className="mx_UserMenu_headerButtons"> <span className="mx_UserMenu_headerButtons">
{/* masked image in CSS */} {/* masked image in CSS */}
@ -324,9 +327,9 @@ export default class UserMenu extends React.Component<IProps, IState> {
<div className="mx_UserMenu_row"> <div className="mx_UserMenu_row">
<span className="mx_UserMenu_userAvatarContainer"> <span className="mx_UserMenu_userAvatarContainer">
<BaseAvatar <BaseAvatar
idName={MatrixClientPeg.get().getUserId()} idName={displayName}
name={OwnProfileStore.instance.displayName || MatrixClientPeg.get().getUserId()} name={displayName}
url={OwnProfileStore.instance.getHttpAvatarUrl(avatarSize)} url={avatarUrl}
width={avatarSize} width={avatarSize}
height={avatarSize} height={avatarSize}
resizeMethod="crop" resizeMethod="crop"

View file

@ -42,22 +42,13 @@ interface IProps {
className?: string; className?: string;
} }
const useImageUrl = ({url, urls}): [string, () => void] => { const calculateUrls = (url, urls) => {
const [imageUrls, setUrls] = useState<string[]>([]);
const [urlsIndex, setIndex] = useState<number>();
const onError = useCallback(() => {
setIndex(i => i + 1); // try the next one
}, []);
const memoizedUrls = useMemo(() => urls, [JSON.stringify(urls)]); // eslint-disable-line react-hooks/exhaustive-deps
useEffect(() => {
// work out the full set of urls to try to load. This is formed like so: // work out the full set of urls to try to load. This is formed like so:
// imageUrls: [ props.url, ...props.urls ] // imageUrls: [ props.url, ...props.urls ]
let _urls = []; let _urls = [];
if (!SettingsStore.getValue("lowBandwidth")) { if (!SettingsStore.getValue("lowBandwidth")) {
_urls = memoizedUrls || []; _urls = urls || [];
if (url) { if (url) {
_urls.unshift(url); // put in urls[0] _urls.unshift(url); // put in urls[0]
@ -65,11 +56,21 @@ const useImageUrl = ({url, urls}): [string, () => void] => {
} }
// deduplicate URLs // deduplicate URLs
_urls = Array.from(new Set(_urls)); return Array.from(new Set(_urls));
};
const useImageUrl = ({url, urls}): [string, () => void] => {
const [imageUrls, setUrls] = useState<string[]>(calculateUrls(url, urls));
const [urlsIndex, setIndex] = useState<number>(0);
const onError = useCallback(() => {
setIndex(i => i + 1); // try the next one
}, []);
useEffect(() => {
setUrls(calculateUrls(url, urls));
setIndex(0); setIndex(0);
setUrls(_urls); }, [url, JSON.stringify(urls)]); // eslint-disable-line react-hooks/exhaustive-deps
}, [url, memoizedUrls]); // eslint-disable-line react-hooks/exhaustive-deps
const cli = useContext(MatrixClientContext); const cli = useContext(MatrixClientContext);
const onClientSync = useCallback((syncState, prevState) => { const onClientSync = useCallback((syncState, prevState) => {

View file

@ -53,7 +53,7 @@ export default class MemberStatusMessageAvatar extends React.Component {
if (this.props.member.userId !== MatrixClientPeg.get().getUserId()) { if (this.props.member.userId !== MatrixClientPeg.get().getUserId()) {
throw new Error("Cannot use MemberStatusMessageAvatar on anyone but the logged in user"); throw new Error("Cannot use MemberStatusMessageAvatar on anyone but the logged in user");
} }
if (!SettingsStore.isFeatureEnabled("feature_custom_status")) { if (!SettingsStore.getValue("feature_custom_status")) {
return; return;
} }
const { user } = this.props.member; const { user } = this.props.member;
@ -105,7 +105,7 @@ export default class MemberStatusMessageAvatar extends React.Component {
resizeMethod={this.props.resizeMethod} resizeMethod={this.props.resizeMethod}
/>; />;
if (!SettingsStore.isFeatureEnabled("feature_custom_status")) { if (!SettingsStore.getValue("feature_custom_status")) {
return avatar; return avatar;
} }

View file

@ -114,9 +114,12 @@ export default class RoomAvatar extends React.Component<IProps, IState> {
} }
private onRoomAvatarClick = () => { private onRoomAvatarClick = () => {
const avatarUrl = this.props.room.getAvatarUrl( const avatarUrl = Avatar.avatarUrlForRoom(
MatrixClientPeg.get().getHomeserverUrl(), this.props.room,
null, null, null, false); null,
null,
null,
);
const params = { const params = {
src: avatarUrl, src: avatarUrl,
name: this.props.room.name, name: this.props.room.name,

View file

@ -81,7 +81,7 @@ export default createReactClass({
let canPin = room.currentState.mayClientSendStateEvent('m.room.pinned_events', cli); let canPin = room.currentState.mayClientSendStateEvent('m.room.pinned_events', cli);
// HACK: Intentionally say we can't pin if the user doesn't want to use the functionality // HACK: Intentionally say we can't pin if the user doesn't want to use the functionality
if (!SettingsStore.isFeatureEnabled("feature_pinning")) canPin = false; if (!SettingsStore.getValue("feature_pinning")) canPin = false;
this.setState({canRedact, canPin}); this.setState({canRedact, canPin});
}, },

View file

@ -1,404 +0,0 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
Copyright 2017 Vector Creations Ltd
Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
Copyright 2019 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
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 createReactClass from 'create-react-class';
import classNames from 'classnames';
import * as sdk from '../../../index';
import { _t, _td } from '../../../languageHandler';
import {MatrixClientPeg} from '../../../MatrixClientPeg';
import dis from '../../../dispatcher/dispatcher';
import DMRoomMap from '../../../utils/DMRoomMap';
import * as Rooms from '../../../Rooms';
import * as RoomNotifs from '../../../RoomNotifs';
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>
);
};
export default createReactClass({
displayName: 'RoomTileContextMenu',
propTypes: {
room: PropTypes.object.isRequired,
/* callback called when the menu is dismissed */
onFinished: PropTypes.func,
},
getInitialState() {
const dmRoomMap = new DMRoomMap(MatrixClientPeg.get());
return {
roomNotifState: RoomNotifs.getRoomNotifsState(this.props.room.roomId),
isFavourite: this.props.room.tags.hasOwnProperty("m.favourite"),
isLowPriority: this.props.room.tags.hasOwnProperty("m.lowpriority"),
isDirectMessage: Boolean(dmRoomMap.getUserIdForRoomId(this.props.room.roomId)),
};
},
componentDidMount: function() {
this._unmounted = false;
},
componentWillUnmount: function() {
this._unmounted = true;
},
_toggleTag: function(tagNameOn, tagNameOff) {
if (!MatrixClientPeg.get().isGuest()) {
sleep(500).then(() => {
dis.dispatch(RoomListActions.tagRoom(
MatrixClientPeg.get(),
this.props.room,
tagNameOff, tagNameOn,
undefined, 0,
), true);
this.props.onFinished();
});
}
},
_onClickFavourite: function() {
// Tag room as 'Favourite'
if (!this.state.isFavourite && this.state.isLowPriority) {
this.setState({
isFavourite: true,
isLowPriority: false,
});
this._toggleTag("m.favourite", "m.lowpriority");
} else if (this.state.isFavourite) {
this.setState({isFavourite: false});
this._toggleTag(null, "m.favourite");
} else if (!this.state.isFavourite) {
this.setState({isFavourite: true});
this._toggleTag("m.favourite");
}
},
_onClickLowPriority: function() {
// Tag room as 'Low Priority'
if (!this.state.isLowPriority && this.state.isFavourite) {
this.setState({
isFavourite: false,
isLowPriority: true,
});
this._toggleTag("m.lowpriority", "m.favourite");
} else if (this.state.isLowPriority) {
this.setState({isLowPriority: false});
this._toggleTag(null, "m.lowpriority");
} else if (!this.state.isLowPriority) {
this.setState({isLowPriority: true});
this._toggleTag("m.lowpriority");
}
},
_onClickDM: function() {
if (MatrixClientPeg.get().isGuest()) return;
const newIsDirectMessage = !this.state.isDirectMessage;
this.setState({
isDirectMessage: newIsDirectMessage,
});
Rooms.guessAndSetDMRoom(
this.props.room, newIsDirectMessage,
).then(sleep(500)).finally(() => {
// Close the context menu
if (this.props.onFinished) {
this.props.onFinished();
}
}, (err) => {
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Failed to set Direct Message status of room', '', ErrorDialog, {
title: _t('Failed to set Direct Message status of room'),
description: ((err && err.message) ? err.message : _t('Operation failed')),
});
});
},
_onClickLeave: function() {
// Leave room
dis.dispatch({
action: 'leave_room',
room_id: this.props.room.roomId,
});
// Close the context menu
if (this.props.onFinished) {
this.props.onFinished();
}
},
_onClickReject: function() {
dis.dispatch({
action: 'reject_invite',
room_id: this.props.room.roomId,
});
// Close the context menu
if (this.props.onFinished) {
this.props.onFinished();
}
},
_onClickForget: function() {
// FIXME: duplicated with RoomSettings (and dead code in RoomView)
MatrixClientPeg.get().forget(this.props.room.roomId).then(() => {
// Switch to another room view if we're currently viewing the
// historical room
if (RoomViewStore.getRoomId() === this.props.room.roomId) {
dis.dispatch({ action: 'view_next_room' });
}
}, function(err) {
const errCode = err.errcode || _td("unknown error code");
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Failed to forget room', '', ErrorDialog, {
title: _t('Failed to forget room %(errCode)s', {errCode: errCode}),
description: ((err && err.message) ? err.message : _t('Operation failed')),
});
});
// Close the context menu
if (this.props.onFinished) {
this.props.onFinished();
}
},
_saveNotifState: function(newState) {
if (MatrixClientPeg.get().isGuest()) return;
const oldState = this.state.roomNotifState;
const roomId = this.props.room.roomId;
this.setState({
roomNotifState: newState,
});
RoomNotifs.setRoomNotifsState(roomId, newState).then(() => {
// delay slightly so that the user can see their state change
// before closing the menu
return sleep(500).then(() => {
if (this._unmounted) return;
// Close the context menu
if (this.props.onFinished) {
this.props.onFinished();
}
});
}, (error) => {
// TODO: some form of error notification to the user
// to inform them that their state change failed.
// For now we at least set the state back
if (this._unmounted) return;
this.setState({
roomNotifState: oldState,
});
});
},
_onClickAlertMe: function() {
this._saveNotifState(RoomNotifs.ALL_MESSAGES_LOUD);
},
_onClickAllNotifs: function() {
this._saveNotifState(RoomNotifs.ALL_MESSAGES);
},
_onClickMentions: function() {
this._saveNotifState(RoomNotifs.MENTIONS_ONLY);
},
_onClickMute: function() {
this._saveNotifState(RoomNotifs.MUTE);
},
_renderNotifMenu: function() {
return (
<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>
<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>
);
},
_onClickSettings: function() {
dis.dispatch({
action: 'open_room_settings',
room_id: this.props.room.roomId,
});
if (this.props.onFinished) {
this.props.onFinished();
}
},
_renderSettingsMenu: function() {
return (
<div>
<MenuItem className="mx_RoomTileContextMenu_tag_field" onClick={this._onClickSettings}>
<img className="mx_RoomTileContextMenu_tag_icon" src={require("../../../../res/img/feather-customised/settings.svg")} width="15" height="15" alt="" />
{ _t('Settings') }
</MenuItem>
</div>
);
},
_renderLeaveMenu: function(membership) {
if (!membership) {
return null;
}
let leaveClickHandler = null;
let leaveText = null;
switch (membership) {
case "join":
leaveClickHandler = this._onClickLeave;
leaveText = _t('Leave');
break;
case "leave":
case "ban":
leaveClickHandler = this._onClickForget;
leaveText = _t('Forget');
break;
case "invite":
leaveClickHandler = this._onClickReject;
leaveText = _t('Reject');
break;
}
return (
<div>
<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 }
</MenuItem>
</div>
);
},
_renderRoomTagMenu: function() {
return (
<div>
<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>
);
},
render: function() {
const myMembership = this.props.room.getMyMembership();
switch (myMembership) {
case 'join':
return <div>
{ this._renderNotifMenu() }
<hr className="mx_RoomTileContextMenu_separator" role="separator" />
{ this._renderLeaveMenu(myMembership) }
<hr className="mx_RoomTileContextMenu_separator" role="separator" />
{ this._renderRoomTagMenu() }
<hr className="mx_RoomTileContextMenu_separator" role="separator" />
{ this._renderSettingsMenu() }
</div>;
case 'invite':
return <div>
{ this._renderLeaveMenu(myMembership) }
</div>;
default:
return <div>
{ this._renderLeaveMenu(myMembership) }
<hr className="mx_RoomTileContextMenu_separator" role="separator" />
{ this._renderSettingsMenu() }
</div>;
}
},
});

View file

@ -1,155 +0,0 @@
/*
Copyright 2018, 2019 New Vector Ltd
Copyright 2019 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
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 dis from '../../../dispatcher/dispatcher';
import { _t } from '../../../languageHandler';
import LogoutDialog from "../dialogs/LogoutDialog";
import Modal from "../../../Modal";
import SdkConfig from '../../../SdkConfig';
import { getHostingLink } from '../../../utils/HostingLink';
import {MatrixClientPeg} from '../../../MatrixClientPeg';
import {MenuItem} from "../../structures/ContextMenu";
import * as sdk from "../../../index";
import {getHomePageUrl} from "../../../utils/pages";
import {Action} from "../../../dispatcher/actions";
export default class TopLeftMenu extends React.Component {
static propTypes = {
displayName: PropTypes.string.isRequired,
userId: PropTypes.string.isRequired,
onFinished: PropTypes.func,
// Optional function to collect a reference to the container
// of this component directly.
containerRef: PropTypes.func,
};
constructor() {
super();
this.viewHomePage = this.viewHomePage.bind(this);
this.openSettings = this.openSettings.bind(this);
this.signIn = this.signIn.bind(this);
this.signOut = this.signOut.bind(this);
}
hasHomePage() {
return !!getHomePageUrl(SdkConfig.get());
}
render() {
const isGuest = MatrixClientPeg.get().isGuest();
const hostingSignupLink = getHostingLink('user-context-menu');
let hostingSignup = null;
if (hostingSignupLink) {
hostingSignup = <div className="mx_TopLeftMenu_upgradeLink">
{_t(
"<a>Upgrade</a> to your own domain", {},
{
a: sub =>
<a href={hostingSignupLink} target="_blank" rel="noreferrer noopener" tabIndex={-1}>{sub}</a>,
},
)}
<a href={hostingSignupLink} target="_blank" rel="noreferrer noopener" role="presentation" aria-hidden={true} tabIndex={-1}>
<img src={require("../../../../res/img/external-link.svg")} width="11" height="10" alt='' />
</a>
</div>;
}
let homePageItem = null;
if (this.hasHomePage()) {
homePageItem = (
<MenuItem className="mx_TopLeftMenu_icon_home" onClick={this.viewHomePage}>
{_t("Home")}
</MenuItem>
);
}
let signInOutItem;
if (isGuest) {
signInOutItem = (
<MenuItem className="mx_TopLeftMenu_icon_signin" onClick={this.signIn}>
{_t("Sign in")}
</MenuItem>
);
} else {
signInOutItem = (
<MenuItem className="mx_TopLeftMenu_icon_signout" onClick={this.signOut}>
{_t("Sign out")}
</MenuItem>
);
}
const helpItem = (
<MenuItem className="mx_TopLeftMenu_icon_help" onClick={this.openHelp}>
{_t("Help")}
</MenuItem>
);
const settingsItem = (
<MenuItem className="mx_TopLeftMenu_icon_settings" onClick={this.openSettings}>
{_t("Settings")}
</MenuItem>
);
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" role="none">
{homePageItem}
{settingsItem}
{helpItem}
{signInOutItem}
</ul>
</div>;
}
openHelp = () => {
this.closeMenu();
const RedesignFeedbackDialog = sdk.getComponent("views.dialogs.RedesignFeedbackDialog");
Modal.createTrackedDialog('Report bugs & give feedback', '', RedesignFeedbackDialog);
};
viewHomePage() {
dis.dispatch({action: 'view_home_page'});
this.closeMenu();
}
openSettings() {
dis.fire(Action.ViewUserSettings);
this.closeMenu();
}
signIn() {
dis.dispatch({action: 'start_login'});
this.closeMenu();
}
signOut() {
Modal.createTrackedDialog('Logout E2E Export', '', LogoutDialog);
this.closeMenu();
}
closeMenu() {
if (this.props.onFinished) this.props.onFinished();
}
}

View file

@ -0,0 +1,252 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { ChangeEvent, FormEvent } from 'react';
import BaseDialog from "./BaseDialog";
import { _t } from "../../../languageHandler";
import { IDialogProps } from "./IDialogProps";
import Field from "../elements/Field";
import AccessibleButton from "../elements/AccessibleButton";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
import InfoTooltip from "../elements/InfoTooltip";
import dis from "../../../dispatcher/dispatcher";
import {showCommunityRoomInviteDialog} from "../../../RoomInvite";
import { arrayFastClone } from "../../../utils/arrays";
import SdkConfig from "../../../SdkConfig";
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
import InviteDialog from "./InviteDialog";
import BaseAvatar from "../avatars/BaseAvatar";
import {getHttpUriForMxc} from "matrix-js-sdk/src/content-repo";
import {inviteMultipleToRoom, showAnyInviteErrors} from "../../../RoomInvite";
import {humanizeTime} from "../../../utils/humanize";
import StyledCheckbox from "../elements/StyledCheckbox";
import Modal from "../../../Modal";
import ErrorDialog from "./ErrorDialog";
interface IProps extends IDialogProps {
roomId: string;
communityName: string;
}
interface IPerson {
userId: string;
user: RoomMember;
lastActive: number;
}
interface IState {
emailTargets: string[];
userTargets: string[];
showPeople: boolean;
people: IPerson[];
numPeople: number;
busy: boolean;
}
export default class CommunityPrototypeInviteDialog extends React.PureComponent<IProps, IState> {
constructor(props: IProps) {
super(props);
this.state = {
emailTargets: [],
userTargets: [],
showPeople: false,
people: this.buildSuggestions(),
numPeople: 5, // arbitrary default
busy: false,
};
}
private buildSuggestions(): IPerson[] {
const alreadyInvited = new Set([MatrixClientPeg.get().getUserId(), SdkConfig.get()['welcomeUserId']]);
if (this.props.roomId) {
const room = MatrixClientPeg.get().getRoom(this.props.roomId);
if (!room) throw new Error("Room ID given to InviteDialog does not look like a room");
room.getMembersWithMembership('invite').forEach(m => alreadyInvited.add(m.userId));
room.getMembersWithMembership('join').forEach(m => alreadyInvited.add(m.userId));
// add banned users, so we don't try to invite them
room.getMembersWithMembership('ban').forEach(m => alreadyInvited.add(m.userId));
}
return InviteDialog.buildRecents(alreadyInvited);
}
private onSubmit = async (ev: FormEvent) => {
ev.preventDefault();
ev.stopPropagation();
this.setState({busy: true});
try {
const targets = [...this.state.emailTargets, ...this.state.userTargets];
const result = await inviteMultipleToRoom(this.props.roomId, targets);
const room = MatrixClientPeg.get().getRoom(this.props.roomId);
const success = showAnyInviteErrors(result.states, room, result.inviter);
if (success) {
this.props.onFinished(true);
} else {
this.setState({busy: false});
}
} catch (e) {
this.setState({busy: false});
console.error(e);
Modal.createTrackedDialog('Failed to invite', '', ErrorDialog, {
title: _t("Failed to invite"),
description: ((e && e.message) ? e.message : _t("Operation failed")),
});
}
};
private onAddressChange = (ev: ChangeEvent<HTMLInputElement>, index: number) => {
const targets = arrayFastClone(this.state.emailTargets);
if (index >= targets.length) {
targets.push(ev.target.value);
} else {
targets[index] = ev.target.value;
}
this.setState({emailTargets: targets});
};
private onAddressBlur = (index: number) => {
const targets = arrayFastClone(this.state.emailTargets);
if (index >= targets.length) return; // not important
if (targets[index].trim() === "") {
targets.splice(index, 1);
this.setState({emailTargets: targets});
}
};
private onShowPeopleClick = () => {
this.setState({showPeople: !this.state.showPeople});
};
private setPersonToggle = (person: IPerson, selected: boolean) => {
const targets = arrayFastClone(this.state.userTargets);
if (selected && !targets.includes(person.userId)) {
targets.push(person.userId);
} else if (!selected && targets.includes(person.userId)) {
targets.splice(targets.indexOf(person.userId), 1);
}
this.setState({userTargets: targets});
};
private renderPerson(person: IPerson, key: any) {
const avatarSize = 36;
return (
<div className="mx_CommunityPrototypeInviteDialog_person" key={key}>
<BaseAvatar
url={getHttpUriForMxc(
MatrixClientPeg.get().getHomeserverUrl(), person.user.getMxcAvatarUrl(),
avatarSize, avatarSize, "crop")}
name={person.user.name}
idName={person.user.userId}
width={avatarSize}
height={avatarSize}
/>
<div className="mx_CommunityPrototypeInviteDialog_personIdentifiers">
<span className="mx_CommunityPrototypeInviteDialog_personName">{person.user.name}</span>
<span className="mx_CommunityPrototypeInviteDialog_personId">{person.userId}</span>
</div>
<StyledCheckbox onChange={(e) => this.setPersonToggle(person, e.target.checked)} />
</div>
);
}
private onShowMorePeople = () => {
this.setState({numPeople: this.state.numPeople + 5}); // arbitrary increase
};
public render() {
const emailAddresses = [];
this.state.emailTargets.forEach((address, i) => {
emailAddresses.push(
<Field
key={i}
value={address}
onChange={(e) => this.onAddressChange(e, i)}
label={_t("Email address")}
placeholder={_t("Email address")}
onBlur={() => this.onAddressBlur(i)}
/>
);
});
// Push a clean input
emailAddresses.push(
<Field
key={emailAddresses.length}
value={""}
onChange={(e) => this.onAddressChange(e, emailAddresses.length)}
label={emailAddresses.length > 0 ? _t("Add another email") : _t("Email address")}
placeholder={emailAddresses.length > 0 ? _t("Add another email") : _t("Email address")}
/>
);
let peopleIntro = null;
let people = [];
if (this.state.showPeople) {
const humansToPresent = this.state.people.slice(0, this.state.numPeople);
humansToPresent.forEach((person, i) => {
people.push(this.renderPerson(person, i));
});
if (humansToPresent.length < this.state.people.length) {
people.push(
<AccessibleButton
onClick={this.onShowMorePeople}
kind="link" key="more"
className="mx_CommunityPrototypeInviteDialog_morePeople"
>{_t("Show more")}</AccessibleButton>
);
}
}
if (this.state.people.length > 0) {
peopleIntro = (
<div className="mx_CommunityPrototypeInviteDialog_people">
<span>{_t("People you know on %(brand)s", {brand: SdkConfig.get().brand})}</span>
<AccessibleButton onClick={this.onShowPeopleClick}>
{this.state.showPeople ? _t("Hide") : _t("Show")}
</AccessibleButton>
</div>
);
}
let buttonText = _t("Skip");
const targetCount = this.state.userTargets.length + this.state.emailTargets.length;
if (targetCount > 0) {
buttonText = _t("Send %(count)s invites", {count: targetCount});
}
return (
<BaseDialog
className="mx_CommunityPrototypeInviteDialog"
onFinished={this.props.onFinished}
title={_t("Invite people to join %(communityName)s", {communityName: this.props.communityName})}
>
<form onSubmit={this.onSubmit}>
<div className="mx_Dialog_content">
{emailAddresses}
{peopleIntro}
{people}
<AccessibleButton
kind="primary" onClick={this.onSubmit}
disabled={this.state.busy}
className="mx_CommunityPrototypeInviteDialog_primaryButton"
>{buttonText}</AccessibleButton>
</div>
</form>
</BaseDialog>
);
}
}

View file

@ -0,0 +1,223 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { ChangeEvent } from 'react';
import BaseDialog from "./BaseDialog";
import { _t } from "../../../languageHandler";
import { IDialogProps } from "./IDialogProps";
import Field from "../elements/Field";
import AccessibleButton from "../elements/AccessibleButton";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
import InfoTooltip from "../elements/InfoTooltip";
import dis from "../../../dispatcher/dispatcher";
import {showCommunityRoomInviteDialog} from "../../../RoomInvite";
import GroupStore from "../../../stores/GroupStore";
interface IProps extends IDialogProps {
}
interface IState {
name: string;
localpart: string;
error: string;
busy: boolean;
avatarFile: File;
avatarPreview: string;
}
export default class CreateCommunityPrototypeDialog extends React.PureComponent<IProps, IState> {
private avatarUploadRef: React.RefObject<HTMLInputElement> = React.createRef();
constructor(props: IProps) {
super(props);
this.state = {
name: "",
localpart: "",
error: null,
busy: false,
avatarFile: null,
avatarPreview: null,
};
}
private onNameChange = (ev: ChangeEvent<HTMLInputElement>) => {
const localpart = (ev.target.value || "").toLowerCase().replace(/[^a-z0-9.\-_]/g, '-');
this.setState({name: ev.target.value, localpart});
};
private onSubmit = async (ev) => {
ev.preventDefault();
ev.stopPropagation();
if (this.state.busy) return;
// We'll create the community now to see if it's taken, leaving it active in
// the background for the user to look at while they invite people.
this.setState({busy: true});
try {
let avatarUrl = ''; // must be a string for synapse to accept it
if (this.state.avatarFile) {
avatarUrl = await MatrixClientPeg.get().uploadContent(this.state.avatarFile);
}
const result = await MatrixClientPeg.get().createGroup({
localpart: this.state.localpart,
profile: {
name: this.state.name,
avatar_url: avatarUrl,
},
});
// Ensure the tag gets selected now that we've created it
dis.dispatch({action: 'deselect_tags'}, true);
dis.dispatch({
action: 'select_tag',
tag: result.group_id,
});
// Close our own dialog before moving much further
this.props.onFinished(true);
if (result.room_id) {
// Force the group store to update as it might have missed the general chat
await GroupStore.refreshGroupRooms(result.group_id);
dis.dispatch({
action: 'view_room',
room_id: result.room_id,
});
showCommunityRoomInviteDialog(result.room_id, this.state.name);
} else {
dis.dispatch({
action: 'view_group',
group_id: result.group_id,
group_is_new: true,
});
}
} catch (e) {
console.error(e);
this.setState({
busy: false,
error: _t(
"There was an error creating your community. The name may be taken or the " +
"server is unable to process your request.",
),
});
}
};
private onAvatarChanged = (e: ChangeEvent<HTMLInputElement>) => {
if (!e.target.files || !e.target.files.length) {
this.setState({avatarFile: null});
} else {
this.setState({busy: true});
const file = e.target.files[0];
const reader = new FileReader();
reader.onload = (ev: ProgressEvent<FileReader>) => {
this.setState({avatarFile: file, busy: false, avatarPreview: ev.target.result as string});
};
reader.readAsDataURL(file);
}
};
private onChangeAvatar = () => {
if (this.avatarUploadRef.current) this.avatarUploadRef.current.click();
};
public render() {
let communityId = null;
if (this.state.localpart) {
communityId = (
<span className="mx_CreateCommunityPrototypeDialog_communityId">
{_t("Community ID: +<localpart />:%(domain)s", {
domain: MatrixClientPeg.getHomeserverName(),
}, {
localpart: () => <u>{this.state.localpart}</u>,
})}
<InfoTooltip
tooltip={_t(
"Use this when referencing your community to others. The community ID " +
"cannot be changed.",
)}
/>
</span>
);
}
let helpText = (
<span className="mx_CreateCommunityPrototypeDialog_subtext">
{_t("You can change this later if needed.")}
</span>
);
if (this.state.error) {
helpText = (
<span className="mx_CreateCommunityPrototypeDialog_subtext mx_CreateCommunityPrototypeDialog_subtext_error">
{this.state.error}
</span>
);
}
let preview = <img src={this.state.avatarPreview} className="mx_CreateCommunityPrototypeDialog_avatar" />;
if (!this.state.avatarPreview) {
preview = <div className="mx_CreateCommunityPrototypeDialog_placeholderAvatar" />
}
return (
<BaseDialog
className="mx_CreateCommunityPrototypeDialog"
onFinished={this.props.onFinished}
title={_t("What's the name of your community or team?")}
>
<form onSubmit={this.onSubmit}>
<div className="mx_Dialog_content">
<div className="mx_CreateCommunityPrototypeDialog_colName">
<Field
value={this.state.name}
onChange={this.onNameChange}
placeholder={_t("Enter name")}
label={_t("Enter name")}
/>
{helpText}
<span className="mx_CreateCommunityPrototypeDialog_subtext">
{/*nbsp is to reserve the height of this element when there's nothing*/}
&nbsp;{communityId}
</span>
<AccessibleButton kind="primary" onClick={this.onSubmit} disabled={this.state.busy}>
{_t("Create")}
</AccessibleButton>
</div>
<div className="mx_CreateCommunityPrototypeDialog_colAvatar">
<input
type="file" style={{display: "none"}}
ref={this.avatarUploadRef} accept="image/*"
onChange={this.onAvatarChanged}
/>
<AccessibleButton onClick={this.onChangeAvatar} className="mx_CreateCommunityPrototypeDialog_avatarContainer">
{preview}
</AccessibleButton>
<div className="mx_CreateCommunityPrototypeDialog_tip">
<b>{_t("Add image (optional)")}</b>
<span>
{_t("An image will help people identify your community.")}
</span>
</div>
</div>
</div>
</form>
</BaseDialog>
);
}
}

View file

@ -25,6 +25,8 @@ import { _t } from '../../../languageHandler';
import {MatrixClientPeg} from '../../../MatrixClientPeg'; import {MatrixClientPeg} from '../../../MatrixClientPeg';
import {Key} from "../../../Keyboard"; import {Key} from "../../../Keyboard";
import {privateShouldBeEncrypted} from "../../../createRoom"; import {privateShouldBeEncrypted} from "../../../createRoom";
import TagOrderStore from "../../../stores/TagOrderStore";
import GroupStore from "../../../stores/GroupStore";
export default createReactClass({ export default createReactClass({
displayName: 'CreateRoomDialog', displayName: 'CreateRoomDialog',
@ -70,6 +72,10 @@ export default createReactClass({
opts.encryption = this.state.isEncrypted; opts.encryption = this.state.isEncrypted;
} }
if (TagOrderStore.getSelectedPrototypeTag()) {
opts.associatedWithCommunity = TagOrderStore.getSelectedPrototypeTag();
}
return opts; return opts;
}, },
@ -178,18 +184,25 @@ export default createReactClass({
const LabelledToggleSwitch = sdk.getComponent('views.elements.LabelledToggleSwitch'); const LabelledToggleSwitch = sdk.getComponent('views.elements.LabelledToggleSwitch');
const RoomAliasField = sdk.getComponent('views.elements.RoomAliasField'); const RoomAliasField = sdk.getComponent('views.elements.RoomAliasField');
let publicPrivateLabel;
let aliasField; let aliasField;
if (this.state.isPublic) { if (this.state.isPublic) {
publicPrivateLabel = (<p>{_t("Set a room address to easily share your room with other people.")}</p>);
const domain = MatrixClientPeg.get().getDomain(); const domain = MatrixClientPeg.get().getDomain();
aliasField = ( aliasField = (
<div className="mx_CreateRoomDialog_aliasContainer"> <div className="mx_CreateRoomDialog_aliasContainer">
<RoomAliasField ref={ref => this._aliasFieldRef = ref} onChange={this.onAliasChange} domain={domain} value={this.state.alias} /> <RoomAliasField ref={ref => this._aliasFieldRef = ref} onChange={this.onAliasChange} domain={domain} value={this.state.alias} />
</div> </div>
); );
} else { }
publicPrivateLabel = (<p>{_t("This room is private, and can only be joined by invitation.")}</p>);
let publicPrivateLabel = <p>{_t(
"Private rooms can be found and joined by invitation only. Public rooms can be " +
"found and joined by anyone.",
)}</p>;
if (TagOrderStore.getSelectedPrototypeTag()) {
publicPrivateLabel = <p>{_t(
"Private rooms can be found and joined by invitation only. Public rooms can be " +
"found and joined by anyone in this community.",
)}</p>;
} }
let e2eeSection; let e2eeSection;
@ -212,7 +225,25 @@ export default createReactClass({
</React.Fragment>; </React.Fragment>;
} }
const title = this.state.isPublic ? _t('Create a public room') : _t('Create a private room'); let federateLabel = _t(
"You might enable this if the room will only be used for collaborating with internal " +
"teams on your homeserver. This cannot be changed later.",
);
if (SdkConfig.get().default_federate === false) {
// We only change the label if the default setting is different to avoid jarring text changes to the
// user. They will have read the implications of turning this off/on, so no need to rephrase for them.
federateLabel = _t(
"You might disable this if the room will be used for collaborating with external " +
"teams who have their own homeserver. This cannot be changed later.",
);
}
let title = this.state.isPublic ? _t('Create a public room') : _t('Create a private room');
if (TagOrderStore.getSelectedPrototypeTag()) {
const summary = GroupStore.getSummary(TagOrderStore.getSelectedPrototypeTag());
const name = summary?.profile?.name || TagOrderStore.getSelectedPrototypeTag();
title = _t("Create a room in %(communityName)s", {communityName: name});
}
return ( return (
<BaseDialog className="mx_CreateRoomDialog" onFinished={this.props.onFinished} <BaseDialog className="mx_CreateRoomDialog" onFinished={this.props.onFinished}
title={title} title={title}
@ -227,7 +258,15 @@ export default createReactClass({
{ aliasField } { aliasField }
<details ref={this.collectDetailsRef} className="mx_CreateRoomDialog_details"> <details ref={this.collectDetailsRef} className="mx_CreateRoomDialog_details">
<summary className="mx_CreateRoomDialog_details_summary">{ this.state.detailsOpen ? _t('Hide advanced') : _t('Show advanced') }</summary> <summary className="mx_CreateRoomDialog_details_summary">{ this.state.detailsOpen ? _t('Hide advanced') : _t('Show advanced') }</summary>
<LabelledToggleSwitch label={ _t('Block users on other matrix homeservers from joining this room (This setting cannot be changed later!)')} onChange={this.onNoFederateChange} value={this.state.noFederate} /> <LabelledToggleSwitch
label={_t(
"Block anyone not part of %(serverName)s from ever joining this room.",
{serverName: MatrixClientPeg.getHomeserverName()},
)}
onChange={this.onNoFederateChange}
value={this.state.noFederate}
/>
<p>{federateLabel}</p>
</details> </details>
</div> </div>
</form> </form>

View file

@ -0,0 +1,19 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
export interface IDialogProps {
onFinished: (bool) => void;
}

View file

@ -327,7 +327,7 @@ export default class InviteDialog extends React.PureComponent {
this.state = { this.state = {
targets: [], // array of Member objects (see interface above) targets: [], // array of Member objects (see interface above)
filterText: "", filterText: "",
recents: this._buildRecents(alreadyInvited), recents: InviteDialog.buildRecents(alreadyInvited),
numRecentsShown: INITIAL_ROOMS_SHOWN, numRecentsShown: INITIAL_ROOMS_SHOWN,
suggestions: this._buildSuggestions(alreadyInvited), suggestions: this._buildSuggestions(alreadyInvited),
numSuggestionsShown: INITIAL_ROOMS_SHOWN, numSuggestionsShown: INITIAL_ROOMS_SHOWN,
@ -344,7 +344,7 @@ export default class InviteDialog extends React.PureComponent {
this._editorRef = createRef(); this._editorRef = createRef();
} }
_buildRecents(excludedTargetIds: Set<string>): {userId: string, user: RoomMember, lastActive: number} { static buildRecents(excludedTargetIds: Set<string>): {userId: string, user: RoomMember, lastActive: number} {
const rooms = DMRoomMap.shared().getUniqueRoomsWithIndividuals(); // map of userId => js-sdk Room const rooms = DMRoomMap.shared().getUniqueRoomsWithIndividuals(); // map of userId => js-sdk Room
// Also pull in all the rooms tagged as DefaultTagID.DM so we don't miss anything. Sometimes the // Also pull in all the rooms tagged as DefaultTagID.DM so we don't miss anything. Sometimes the

View file

@ -87,7 +87,7 @@ export default class RoomSettingsDialog extends React.Component {
<NotificationSettingsTab roomId={this.props.roomId} />, <NotificationSettingsTab roomId={this.props.roomId} />,
)); ));
if (SettingsStore.isFeatureEnabled("feature_bridge_state")) { if (SettingsStore.getValue("feature_bridge_state")) {
tabs.push(new Tab( tabs.push(new Tab(
ROOM_BRIDGES_TAB, ROOM_BRIDGES_TAB,
_td("Bridges"), _td("Bridges"),

View file

@ -27,9 +27,9 @@ import Spinner from "../elements/Spinner";
import AccessibleButton from "../elements/AccessibleButton"; import AccessibleButton from "../elements/AccessibleButton";
import { UPDATE_EVENT } from "../../../stores/AsyncStore"; import { UPDATE_EVENT } from "../../../stores/AsyncStore";
import { MatrixClientPeg } from "../../../MatrixClientPeg"; import { MatrixClientPeg } from "../../../MatrixClientPeg";
import { IDialogProps } from "./IDialogProps";
interface IProps { interface IProps extends IDialogProps {
onFinished: (bool) => void;
} }
export default class ServerOfflineDialog extends React.PureComponent<IProps> { export default class ServerOfflineDialog extends React.PureComponent<IProps> {

View file

@ -31,6 +31,7 @@ import {toRightOf} from "../../structures/ContextMenu";
import {copyPlaintext, selectText} from "../../../utils/strings"; import {copyPlaintext, selectText} from "../../../utils/strings";
import StyledCheckbox from '../elements/StyledCheckbox'; import StyledCheckbox from '../elements/StyledCheckbox';
import AccessibleTooltipButton from '../elements/AccessibleTooltipButton'; import AccessibleTooltipButton from '../elements/AccessibleTooltipButton';
import { IDialogProps } from "./IDialogProps";
const socials = [ const socials = [
{ {
@ -60,8 +61,7 @@ const socials = [
}, },
]; ];
interface IProps { interface IProps extends IDialogProps {
onFinished: () => void;
target: Room | User | Group | RoomMember | MatrixEvent; target: Room | User | Group | RoomMember | MatrixEvent;
permalinkCreator: RoomPermalinkCreator; permalinkCreator: RoomPermalinkCreator;
} }

View file

@ -54,7 +54,7 @@ export default class UserSettingsDialog extends React.Component {
super(); super();
this.state = { this.state = {
mjolnirEnabled: SettingsStore.isFeatureEnabled("feature_mjolnir"), mjolnirEnabled: SettingsStore.getValue("feature_mjolnir"),
}; };
} }
@ -116,7 +116,7 @@ export default class UserSettingsDialog extends React.Component {
"mx_UserSettingsDialog_securityIcon", "mx_UserSettingsDialog_securityIcon",
<SecurityUserSettingsTab closeSettingsFn={this.props.onFinished} />, <SecurityUserSettingsTab closeSettingsFn={this.props.onFinished} />,
)); ));
if (SdkConfig.get()['showLabsSettings'] || SettingsStore.getLabsFeatures().length > 0) { if (SdkConfig.get()['showLabsSettings']) {
tabs.push(new Tab( tabs.push(new Tab(
USER_LABS_TAB, USER_LABS_TAB,
_td("Labs"), _td("Labs"),

View file

@ -311,7 +311,7 @@ export default class AppTile extends React.Component {
this.props.onEditClick(); this.props.onEditClick();
} else { } else {
// TODO: Open the right manager for the widget // TODO: Open the right manager for the widget
if (SettingsStore.isFeatureEnabled("feature_many_integration_managers")) { if (SettingsStore.getValue("feature_many_integration_managers")) {
IntegrationManagers.sharedInstance().openAll( IntegrationManagers.sharedInstance().openAll(
this.props.room, this.props.room,
'type_' + this.props.app.type, 'type_' + this.props.app.type,

View file

@ -0,0 +1,73 @@
/*
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.
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 classNames from 'classnames';
import AccessibleButton from "./AccessibleButton";
import Tooltip from './Tooltip';
import { _t } from "../../../languageHandler";
interface ITooltipProps {
tooltip?: React.ReactNode;
tooltipClassName?: string;
}
interface IState {
hover: boolean;
}
export default class InfoTooltip extends React.PureComponent<ITooltipProps, IState> {
constructor(props: ITooltipProps) {
super(props);
this.state = {
hover: false,
};
}
onMouseOver = () => {
this.setState({
hover: true,
});
};
onMouseLeave = () => {
this.setState({
hover: false,
});
};
render() {
const {tooltip, children, tooltipClassName} = this.props;
const title = _t("Information");
// Tooltip are forced on the right for a more natural feel to them on info icons
const tip = this.state.hover ? <Tooltip
className="mx_InfoTooltip_container"
tooltipClassName={classNames("mx_InfoTooltip_tooltip", tooltipClassName)}
label={tooltip || title}
forceOnRight={true}
/> : <div />;
return (
<div onMouseOver={this.onMouseOver} onMouseLeave={this.onMouseLeave} className="mx_InfoTooltip">
<span className="mx_InfoTooltip_icon" aria-label={title} />
{children}
{tip}
</div>
);
}
}

View file

@ -28,7 +28,7 @@ export default createReactClass({
const imgClass = this.props.imgClassName || ""; const imgClass = this.props.imgClassName || "";
let imageSource; let imageSource;
if (SettingsStore.isFeatureEnabled('feature_new_spinner')) { if (SettingsStore.getValue('feature_new_spinner')) {
imageSource = require("../../../../res/img/spinner.svg"); imageSource = require("../../../../res/img/spinner.svg");
} else { } else {
imageSource = require("../../../../res/img/spinner.gif"); imageSource = require("../../../../res/img/spinner.gif");

View file

@ -34,7 +34,7 @@ export default class ManageIntegsButton extends React.Component {
if (!managers.hasManager()) { if (!managers.hasManager()) {
managers.openNoManagerDialog(); managers.openNoManagerDialog();
} else { } else {
if (SettingsStore.isFeatureEnabled("feature_many_integration_managers")) { if (SettingsStore.getValue("feature_many_integration_managers")) {
managers.openAll(this.props.room); managers.openAll(this.props.room);
} else { } else {
managers.getPrimaryManager().open(this.props.room); managers.getPrimaryManager().open(this.props.room);

View file

@ -22,7 +22,7 @@ import SettingsStore from "../../../settings/SettingsStore";
const Spinner = ({w = 32, h = 32, imgClassName, message}) => { const Spinner = ({w = 32, h = 32, imgClassName, message}) => {
let imageSource; let imageSource;
if (SettingsStore.isFeatureEnabled('feature_new_spinner')) { if (SettingsStore.getValue('feature_new_spinner')) {
imageSource = require("../../../../res/img/spinner.svg"); imageSource = require("../../../../res/img/spinner.svg");
} else { } else {
imageSource = require("../../../../res/img/spinner.gif"); imageSource = require("../../../../res/img/spinner.gif");

View file

@ -30,6 +30,7 @@ import GroupStore from '../../../stores/GroupStore';
import TagOrderStore from '../../../stores/TagOrderStore'; import TagOrderStore from '../../../stores/TagOrderStore';
import MatrixClientContext from "../../../contexts/MatrixClientContext"; import MatrixClientContext from "../../../contexts/MatrixClientContext";
import AccessibleButton from "./AccessibleButton"; import AccessibleButton from "./AccessibleButton";
import SettingsStore from "../../../settings/SettingsStore";
// A class for a child of TagPanel (possibly wrapped in a DNDTagTile) that represents // 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: // a thing to click on for the user to filter the visible rooms in the RoomList to:
@ -46,6 +47,7 @@ export default createReactClass({
contextMenuButtonRef: PropTypes.object, contextMenuButtonRef: PropTypes.object,
openMenu: PropTypes.func, openMenu: PropTypes.func,
menuDisplayed: PropTypes.bool, menuDisplayed: PropTypes.bool,
selected: PropTypes.bool,
}, },
statics: { statics: {
@ -112,6 +114,7 @@ export default createReactClass({
}, },
onMouseOver: function() { onMouseOver: function() {
if (SettingsStore.getValue("feature_communities_v2_prototypes")) return;
this.setState({ hover: true }); this.setState({ hover: true });
}, },
@ -123,6 +126,7 @@ export default createReactClass({
// Prevent the TagTile onClick event firing as well // Prevent the TagTile onClick event firing as well
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
if (SettingsStore.getValue("feature_communities_v2_prototypes")) return;
this.setState({ hover: false }); this.setState({ hover: false });
this.props.openMenu(); this.props.openMenu();
}, },
@ -137,9 +141,12 @@ export default createReactClass({
profile.avatarUrl, avatarHeight, avatarHeight, "crop", profile.avatarUrl, avatarHeight, avatarHeight, "crop",
) : null; ) : null;
const isPrototype = SettingsStore.getValue("feature_communities_v2_prototypes");
const className = classNames({ const className = classNames({
mx_TagTile: true, mx_TagTile: true,
mx_TagTile_selected: this.props.selected, mx_TagTile_prototype: isPrototype,
mx_TagTile_selected: this.props.selected && !isPrototype,
mx_TagTile_selected_prototype: this.props.selected && isPrototype,
}); });
const badge = TagOrderStore.getGroupBadge(this.props.tag); const badge = TagOrderStore.getGroupBadge(this.props.tag);

View file

@ -0,0 +1,85 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import React from "react";
import defaultDispatcher from "../../../dispatcher/dispatcher";
import * as fbEmitter from "fbemitter";
import TagOrderStore from "../../../stores/TagOrderStore";
import AccessibleTooltipButton from "./AccessibleTooltipButton";
import classNames from "classnames";
import { _t } from "../../../languageHandler";
interface IProps {
}
interface IState {
selected: boolean;
}
export default class UserTagTile extends React.PureComponent<IProps, IState> {
private tagStoreRef: fbEmitter.EventSubscription;
constructor(props: IProps) {
super(props);
this.state = {
selected: TagOrderStore.getSelectedTags().length === 0,
};
}
public componentDidMount() {
this.tagStoreRef = TagOrderStore.addListener(this.onTagStoreUpdate);
}
public componentWillUnmount() {
this.tagStoreRef.remove();
}
private onTagStoreUpdate = () => {
const selected = TagOrderStore.getSelectedTags().length === 0;
this.setState({selected});
};
private onTileClick = (ev) => {
ev.preventDefault();
ev.stopPropagation();
// Deselect all tags
defaultDispatcher.dispatch({action: "deselect_tags"});
};
public render() {
// XXX: We reuse TagTile classes for ease of demonstration - we should probably generify
// TagTile instead if we continue to use this component.
const className = classNames({
mx_TagTile: true,
mx_TagTile_prototype: true,
mx_TagTile_selected_prototype: this.state.selected,
mx_TagTile_home: true,
});
return (
<AccessibleTooltipButton
className={className}
onClick={this.onTileClick}
title={_t("Home")}
>
<div className="mx_TagTile_avatar">
<div className="mx_TagTile_homeIcon" />
</div>
</AccessibleTooltipButton>
);
}
}

View file

@ -95,7 +95,7 @@ export default createReactClass({
} }
} }
if (SettingsStore.isFeatureEnabled("feature_mjolnir")) { if (SettingsStore.getValue("feature_mjolnir")) {
const key = `mx_mjolnir_render_${this.props.mxEvent.getRoomId()}__${this.props.mxEvent.getId()}`; const key = `mx_mjolnir_render_${this.props.mxEvent.getRoomId()}__${this.props.mxEvent.getId()}`;
const allowRender = localStorage.getItem(key) === "true"; const allowRender = localStorage.getItem(key) === "true";

View file

@ -1428,7 +1428,7 @@ const UserInfoHeader = ({onClose, member, e2eStatus}) => {
presenceLastActiveAgo = member.user.lastActiveAgo; presenceLastActiveAgo = member.user.lastActiveAgo;
presenceCurrentlyActive = member.user.currentlyActive; presenceCurrentlyActive = member.user.currentlyActive;
if (SettingsStore.isFeatureEnabled("feature_custom_status")) { if (SettingsStore.getValue("feature_custom_status")) {
statusMessage = member.user._unstable_statusMessage; statusMessage = member.user._unstable_statusMessage;
} }
} }

View file

@ -1,154 +0,0 @@
/*
Copyright 2016 OpenMarket Ltd
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 createReactClass from 'create-react-class';
import Tinter from '../../../Tinter';
import dis from '../../../dispatcher/dispatcher';
import SettingsStore from "../../../settings/SettingsStore";
import {SettingLevel} from "../../../settings/SettingLevel";
const ROOM_COLORS = [
// magic room default values courtesy of Ribot
[Tinter.getKeyRgb()[0], Tinter.getKeyRgb()[1]],
["#81bddb", "#eaf1f4"],
["#bd79cb", "#f3eaf5"],
["#c65d94", "#f5eaef"],
["#e55e5e", "#f5eaea"],
["#eca46f", "#f5eeea"],
["#dad658", "#f5f4ea"],
["#80c553", "#eef5ea"],
["#bb814e", "#eee8e3"],
//["#595959", "#ececec"], // Grey makes everything appear disabled, so remove it for now
];
// Dev note: this component is not attached anywhere, but is left here as it
// has a high possibility of being used in the nearish future.
// Ref: https://github.com/vector-im/element-web/issues/8421
export default createReactClass({
displayName: 'ColorSettings',
propTypes: {
room: PropTypes.object.isRequired,
},
getInitialState: function() {
const data = {
index: 0,
primary_color: ROOM_COLORS[0][0],
secondary_color: ROOM_COLORS[0][1],
hasChanged: false,
};
const scheme = SettingsStore.getValueAt(SettingLevel.ROOM_ACCOUNT, "roomColor", this.props.room.roomId);
if (scheme.primary_color && scheme.secondary_color) {
// We only use the user's scheme if the scheme is valid.
data.primary_color = scheme.primary_color;
data.secondary_color = scheme.secondary_color;
}
data.index = this._getColorIndex(data);
if (data.index === -1) {
// append the unrecognised colours to our palette
data.index = ROOM_COLORS.length;
ROOM_COLORS.push([
scheme.primary_color, scheme.secondary_color,
]);
}
return data;
},
saveSettings: function() { // : Promise
if (!this.state.hasChanged) {
return Promise.resolve(); // They didn't explicitly give a color to save.
}
const originalState = this.getInitialState();
if (originalState.primary_color !== this.state.primary_color ||
originalState.secondary_color !== this.state.secondary_color) {
console.log("ColorSettings: Saving new color");
// We would like guests to be able to set room colour but currently
// they can't, so we still send the request but display a sensible
// error if it fails.
// TODO: Support guests for room color. Technically this is possible via granular settings
// Granular settings would mean the guest is forced to use the DEVICE level though.
SettingsStore.setValue("roomColor", this.props.room.roomId, SettingLevel.ROOM_ACCOUNT, {
primary_color: this.state.primary_color,
secondary_color: this.state.secondary_color,
}).catch(function(err) {
if (err.errcode === 'M_GUEST_ACCESS_FORBIDDEN') {
dis.dispatch({action: 'require_registration'});
}
});
}
return Promise.resolve(); // no color diff
},
_getColorIndex: function(scheme) {
if (!scheme || !scheme.primary_color || !scheme.secondary_color) {
return -1;
}
// XXX: we should validate these values
for (let i = 0; i < ROOM_COLORS.length; i++) {
const room_color = ROOM_COLORS[i];
if (room_color[0] === String(scheme.primary_color).toLowerCase() &&
room_color[1] === String(scheme.secondary_color).toLowerCase()) {
return i;
}
}
return -1;
},
_onColorSchemeChanged: function(index) {
// preview what the user just changed the scheme to.
Tinter.tint(ROOM_COLORS[index][0], ROOM_COLORS[index][1]);
this.setState({
index: index,
primary_color: ROOM_COLORS[index][0],
secondary_color: ROOM_COLORS[index][1],
hasChanged: true,
});
},
render: function() {
return (
<div className="mx_ColorSettings_roomColors">
{ ROOM_COLORS.map((room_color, i) => {
let selected;
if (i === this.state.index) {
selected = (
<div className="mx_ColorSettings_roomColor_selected">
<img src={require("../../../../res/img/tick.svg")} width="17" height="14" alt="./" />
</div>
);
}
const boundClick = this._onColorSchemeChanged.bind(this, i);
return (
<div className="mx_ColorSettings_roomColor"
key={"room_color_" + i}
style={{ backgroundColor: room_color[1] }}
onClick={boundClick}>
{ selected }
<div className="mx_ColorSettings_roomColorPrimary" style={{ backgroundColor: room_color[0] }}></div>
</div>
);
}) }
</div>
);
},
});

View file

@ -130,7 +130,7 @@ export default createReactClass({
}, },
_launchManageIntegrations: function() { _launchManageIntegrations: function() {
if (SettingsStore.isFeatureEnabled("feature_many_integration_managers")) { if (SettingsStore.getValue("feature_many_integration_managers")) {
IntegrationManagers.sharedInstance().openAll(); IntegrationManagers.sharedInstance().openAll();
} else { } else {
IntegrationManagers.sharedInstance().getPrimaryManager().open(this.props.room, 'add_integ'); IntegrationManagers.sharedInstance().getPrimaryManager().open(this.props.room, 'add_integ');

View file

@ -104,7 +104,7 @@ export default createReactClass({
}, },
_rateLimitedUpdate: new RateLimitedFunc(function() { _rateLimitedUpdate: new RateLimitedFunc(function() {
if (SettingsStore.isFeatureEnabled("feature_state_counters")) { if (SettingsStore.getValue("feature_state_counters")) {
this.setState({counters: this._computeCounters()}); this.setState({counters: this._computeCounters()});
} }
}, 500), }, 500),
@ -112,7 +112,7 @@ export default createReactClass({
_computeCounters: function() { _computeCounters: function() {
let counters = []; let counters = [];
if (this.props.room && SettingsStore.isFeatureEnabled("feature_state_counters")) { if (this.props.room && SettingsStore.getValue("feature_state_counters")) {
const stateEvs = this.props.room.currentState.getStateEvents('re.jki.counter'); const stateEvs = this.props.room.currentState.getStateEvents('re.jki.counter');
stateEvs.sort((a, b) => { stateEvs.sort((a, b) => {
return a.getStateKey() < b.getStateKey(); return a.getStateKey() < b.getStateKey();
@ -206,7 +206,7 @@ export default createReactClass({
/>; />;
let stateViews = null; let stateViews = null;
if (this.state.counters && SettingsStore.isFeatureEnabled("feature_state_counters")) { if (this.state.counters && SettingsStore.getValue("feature_state_counters")) {
let counters = []; let counters = [];
this.state.counters.forEach((counter, idx) => { this.state.counters.forEach((counter, idx) => {

View file

@ -50,7 +50,7 @@ export default createReactClass({
componentDidMount() { componentDidMount() {
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.get();
if (SettingsStore.isFeatureEnabled("feature_custom_status")) { if (SettingsStore.getValue("feature_custom_status")) {
const { user } = this.props.member; const { user } = this.props.member;
if (user) { if (user) {
user.on("User._unstable_statusMessage", this._onStatusMessageCommitted); user.on("User._unstable_statusMessage", this._onStatusMessageCommitted);
@ -209,7 +209,7 @@ export default createReactClass({
const presenceState = member.user ? member.user.presence : null; const presenceState = member.user ? member.user.presence : null;
let statusMessage = null; let statusMessage = null;
if (member.user && SettingsStore.isFeatureEnabled("feature_custom_status")) { if (member.user && SettingsStore.getValue("feature_custom_status")) {
statusMessage = this.state.statusMessage; statusMessage = this.state.statusMessage;
} }

View file

@ -226,7 +226,7 @@ export default createReactClass({
title={_t("Settings")} />; title={_t("Settings")} />;
} }
if (this.props.onPinnedClick && SettingsStore.isFeatureEnabled('feature_pinning')) { if (this.props.onPinnedClick && SettingsStore.getValue('feature_pinning')) {
let pinsIndicator = null; let pinsIndicator = null;
if (this._hasUnreadPins()) { if (this._hasUnreadPins()) {
pinsIndicator = (<div className="mx_RoomHeader_pinsIndicator mx_RoomHeader_pinsIndicatorUnread" />); pinsIndicator = (<div className="mx_RoomHeader_pinsIndicator mx_RoomHeader_pinsIndicatorUnread" />);

View file

@ -45,6 +45,7 @@ import { arrayFastClone, arrayHasDiff } from "../../../utils/arrays";
import { objectShallowClone, objectWithOnly } from "../../../utils/objects"; import { objectShallowClone, objectWithOnly } from "../../../utils/objects";
import { IconizedContextMenuOption, IconizedContextMenuOptionList } from "../context_menus/IconizedContextMenu"; import { IconizedContextMenuOption, IconizedContextMenuOptionList } from "../context_menus/IconizedContextMenu";
import AccessibleButton from "../elements/AccessibleButton"; import AccessibleButton from "../elements/AccessibleButton";
import TagOrderStore from "../../../stores/TagOrderStore";
interface IProps { interface IProps {
onKeyDown: (ev: React.KeyboardEvent) => void; onKeyDown: (ev: React.KeyboardEvent) => void;
@ -129,7 +130,9 @@ const TAG_AESTHETICS: {
}} }}
/> />
<IconizedContextMenuOption <IconizedContextMenuOption
label={_t("Explore public rooms")} label={TagOrderStore.getSelectedPrototypeTag()
? _t("Explore community rooms")
: _t("Explore public rooms")}
iconClassName="mx_RoomList_iconExplore" iconClassName="mx_RoomList_iconExplore"
onClick={(e) => { onClick={(e) => {
e.preventDefault(); e.preventDefault();

View file

@ -26,6 +26,8 @@ import classNames from 'classnames';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import SdkConfig from "../../../SdkConfig"; import SdkConfig from "../../../SdkConfig";
import IdentityAuthClient from '../../../IdentityAuthClient'; import IdentityAuthClient from '../../../IdentityAuthClient';
import {CommunityPrototypeStore} from "../../../stores/CommunityPrototypeStore";
import {UPDATE_EVENT} from "../../../stores/AsyncStore";
const MessageCase = Object.freeze({ const MessageCase = Object.freeze({
NotLoggedIn: "NotLoggedIn", NotLoggedIn: "NotLoggedIn",
@ -100,6 +102,7 @@ export default createReactClass({
componentDidMount: function() { componentDidMount: function() {
this._checkInvitedEmail(); this._checkInvitedEmail();
CommunityPrototypeStore.instance.on(UPDATE_EVENT, this._onCommunityUpdate);
}, },
componentDidUpdate: function(prevProps, prevState) { componentDidUpdate: function(prevProps, prevState) {
@ -108,6 +111,10 @@ export default createReactClass({
} }
}, },
componentWillUnmount: function() {
CommunityPrototypeStore.instance.off(UPDATE_EVENT, this._onCommunityUpdate);
},
_checkInvitedEmail: async function() { _checkInvitedEmail: async function() {
// If this is an invite and we've been told what email address was // If this is an invite and we've been told what email address was
// invited, fetch the user's account emails and discovery bindings so we // invited, fetch the user's account emails and discovery bindings so we
@ -143,6 +150,13 @@ export default createReactClass({
} }
}, },
_onCommunityUpdate: function (roomId) {
if (this.props.room && this.props.room.roomId !== roomId) {
return;
}
this.forceUpdate(); // we have nothing to update
},
_getMessageCase() { _getMessageCase() {
const isGuest = MatrixClientPeg.get().isGuest(); const isGuest = MatrixClientPeg.get().isGuest();
@ -219,8 +233,15 @@ export default createReactClass({
} }
}, },
_communityProfile: function() {
if (this.props.room) return CommunityPrototypeStore.instance.getInviteProfile(this.props.room.roomId);
return {displayName: null, avatarMxc: null};
},
_roomName: function(atStart = false) { _roomName: function(atStart = false) {
const name = this.props.room ? this.props.room.name : this.props.roomAlias; let name = this.props.room ? this.props.room.name : this.props.roomAlias;
const profile = this._communityProfile();
if (profile.displayName) name = profile.displayName;
if (name) { if (name) {
return name; return name;
} else if (atStart) { } else if (atStart) {
@ -439,7 +460,10 @@ export default createReactClass({
} }
case MessageCase.Invite: { case MessageCase.Invite: {
const RoomAvatar = sdk.getComponent("views.avatars.RoomAvatar"); const RoomAvatar = sdk.getComponent("views.avatars.RoomAvatar");
const avatar = <RoomAvatar room={this.props.room} oobData={this.props.oobData} />; const oobData = Object.assign({}, this.props.oobData, {
avatarUrl: this._communityProfile().avatarMxc,
});
const avatar = <RoomAvatar room={this.props.room} oobData={oobData} />;
const inviteMember = this._getInviteMember(); const inviteMember = this._getInviteMember();
let inviterElement; let inviterElement;

View file

@ -27,7 +27,7 @@ import defaultDispatcher from '../../../dispatcher/dispatcher';
import { Key } from "../../../Keyboard"; import { Key } from "../../../Keyboard";
import ActiveRoomObserver from "../../../ActiveRoomObserver"; import ActiveRoomObserver from "../../../ActiveRoomObserver";
import { _t } from "../../../languageHandler"; import { _t } from "../../../languageHandler";
import { ChevronFace, ContextMenuTooltipButton, MenuItemRadio } from "../../structures/ContextMenu"; import { ChevronFace, ContextMenuTooltipButton } from "../../structures/ContextMenu";
import { DefaultTagID, TagID } from "../../../stores/room-list/models"; import { DefaultTagID, TagID } from "../../../stores/room-list/models";
import { MessagePreviewStore, ROOM_PREVIEW_CHANGED } from "../../../stores/room-list/MessagePreviewStore"; import { MessagePreviewStore, ROOM_PREVIEW_CHANGED } from "../../../stores/room-list/MessagePreviewStore";
import DecoratedRoomAvatar from "../avatars/DecoratedRoomAvatar"; import DecoratedRoomAvatar from "../avatars/DecoratedRoomAvatar";
@ -47,8 +47,11 @@ import { PROPERTY_UPDATED } from "../../../stores/local-echo/GenericEchoChamber"
import IconizedContextMenu, { import IconizedContextMenu, {
IconizedContextMenuCheckbox, IconizedContextMenuCheckbox,
IconizedContextMenuOption, IconizedContextMenuOption,
IconizedContextMenuOptionList, IconizedContextMenuRadio IconizedContextMenuOptionList,
IconizedContextMenuRadio
} from "../context_menus/IconizedContextMenu"; } from "../context_menus/IconizedContextMenu";
import { CommunityPrototypeStore, IRoomProfile } from "../../../stores/CommunityPrototypeStore";
import { UPDATE_EVENT } from "../../../stores/AsyncStore";
interface IProps { interface IProps {
room: Room; room: Room;
@ -101,6 +104,7 @@ export default class RoomTile extends React.PureComponent<IProps, IState> {
this.notificationState.on(NOTIFICATION_STATE_UPDATE, this.onNotificationUpdate); this.notificationState.on(NOTIFICATION_STATE_UPDATE, this.onNotificationUpdate);
this.roomProps = EchoChamber.forRoom(this.props.room); this.roomProps = EchoChamber.forRoom(this.props.room);
this.roomProps.on(PROPERTY_UPDATED, this.onRoomPropertyUpdate); this.roomProps.on(PROPERTY_UPDATED, this.onRoomPropertyUpdate);
CommunityPrototypeStore.instance.on(UPDATE_EVENT, this.onCommunityUpdate);
} }
private onNotificationUpdate = () => { private onNotificationUpdate = () => {
@ -140,6 +144,7 @@ export default class RoomTile extends React.PureComponent<IProps, IState> {
defaultDispatcher.unregister(this.dispatcherRef); defaultDispatcher.unregister(this.dispatcherRef);
MessagePreviewStore.instance.off(ROOM_PREVIEW_CHANGED, this.onRoomPreviewChanged); MessagePreviewStore.instance.off(ROOM_PREVIEW_CHANGED, this.onRoomPreviewChanged);
this.notificationState.off(NOTIFICATION_STATE_UPDATE, this.onNotificationUpdate); this.notificationState.off(NOTIFICATION_STATE_UPDATE, this.onNotificationUpdate);
CommunityPrototypeStore.instance.off(UPDATE_EVENT, this.onCommunityUpdate);
} }
private onAction = (payload: ActionPayload) => { private onAction = (payload: ActionPayload) => {
@ -150,6 +155,11 @@ export default class RoomTile extends React.PureComponent<IProps, IState> {
} }
}; };
private onCommunityUpdate = (roomId: string) => {
if (roomId !== this.props.room.roomId) return;
this.forceUpdate(); // we don't have anything to actually update
};
private onRoomPreviewChanged = (room: Room) => { private onRoomPreviewChanged = (room: Room) => {
if (this.props.room && room.roomId === this.props.room.roomId) { if (this.props.room && room.roomId === this.props.room.roomId) {
// generatePreview() will return nothing if the user has previews disabled // generatePreview() will return nothing if the user has previews disabled
@ -461,11 +471,21 @@ export default class RoomTile extends React.PureComponent<IProps, IState> {
'mx_RoomTile_minimized': this.props.isMinimized, 'mx_RoomTile_minimized': this.props.isMinimized,
}); });
let roomProfile: IRoomProfile = {displayName: null, avatarMxc: null};
if (this.props.tag === DefaultTagID.Invite) {
roomProfile = CommunityPrototypeStore.instance.getInviteProfile(this.props.room.roomId);
}
let name = roomProfile.displayName || this.props.room.name;
if (typeof name !== 'string') name = '';
name = name.replace(":", ":\u200b"); // add a zero-width space to allow linewrapping after the colon
const roomAvatar = <DecoratedRoomAvatar const roomAvatar = <DecoratedRoomAvatar
room={this.props.room} room={this.props.room}
avatarSize={32} avatarSize={32}
tag={this.props.tag} tag={this.props.tag}
displayBadge={this.props.isMinimized} displayBadge={this.props.isMinimized}
oobData={({avatarUrl: roomProfile.avatarMxc})}
/>; />;
let badge: React.ReactNode; let badge: React.ReactNode;
@ -482,10 +502,6 @@ export default class RoomTile extends React.PureComponent<IProps, IState> {
); );
} }
let name = this.props.room.name;
if (typeof name !== 'string') name = '';
name = name.replace(":", ":\u200b"); // add a zero-width space to allow linewrapping after the colon
let messagePreview = null; let messagePreview = null;
if (this.showMessagePreview && this.state.messagePreview) { if (this.showMessagePreview && this.state.messagePreview) {
messagePreview = ( messagePreview = (

View file

@ -363,7 +363,7 @@ export default class Stickerpicker extends React.Component {
*/ */
_launchManageIntegrations() { _launchManageIntegrations() {
// TODO: Open the right integration manager for the widget // TODO: Open the right integration manager for the widget
if (SettingsStore.isFeatureEnabled("feature_many_integration_managers")) { if (SettingsStore.getValue("feature_many_integration_managers")) {
IntegrationManagers.sharedInstance().openAll( IntegrationManagers.sharedInstance().openAll(
this.props.room, this.props.room,
`type_${WidgetType.STICKERPICKER.preferred}`, `type_${WidgetType.STICKERPICKER.preferred}`,

View file

@ -89,6 +89,7 @@ export default class CrossSigningPanel extends React.PureComponent {
const homeserverSupportsCrossSigning = const homeserverSupportsCrossSigning =
await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing"); await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing");
const crossSigningReady = await cli.isCrossSigningReady(); const crossSigningReady = await cli.isCrossSigningReady();
const secretStorageReady = await cli.isSecretStorageReady();
this.setState({ this.setState({
crossSigningPublicKeysOnDevice, crossSigningPublicKeysOnDevice,
@ -101,6 +102,7 @@ export default class CrossSigningPanel extends React.PureComponent {
secretStorageKeyInAccount, secretStorageKeyInAccount,
homeserverSupportsCrossSigning, homeserverSupportsCrossSigning,
crossSigningReady, crossSigningReady,
secretStorageReady,
}); });
} }
@ -151,6 +153,7 @@ export default class CrossSigningPanel extends React.PureComponent {
secretStorageKeyInAccount, secretStorageKeyInAccount,
homeserverSupportsCrossSigning, homeserverSupportsCrossSigning,
crossSigningReady, crossSigningReady,
secretStorageReady,
} = this.state; } = this.state;
let errorSection; let errorSection;
@ -166,14 +169,19 @@ export default class CrossSigningPanel extends React.PureComponent {
summarisedStatus = <p>{_t( summarisedStatus = <p>{_t(
"Your homeserver does not support cross-signing.", "Your homeserver does not support cross-signing.",
)}</p>; )}</p>;
} else if (crossSigningReady) { } else if (crossSigningReady && secretStorageReady) {
summarisedStatus = <p> {_t( summarisedStatus = <p> {_t(
"Cross-signing and secret storage are enabled.", "Cross-signing and secret storage are ready for use.",
)}</p>;
} else if (crossSigningReady && !secretStorageReady) {
summarisedStatus = <p> {_t(
"Cross-signing is ready for use, but secret storage is " +
"currently not being used to backup your keys.",
)}</p>; )}</p>;
} else if (crossSigningPrivateKeysInStorage) { } else if (crossSigningPrivateKeysInStorage) {
summarisedStatus = <p>{_t( summarisedStatus = <p>{_t(
"Your account has a cross-signing identity in secret storage, but it " + "Your account has a cross-signing identity in secret storage, " +
"is not yet trusted by this session.", "but it is not yet trusted by this session.",
)}</p>; )}</p>;
} else { } else {
summarisedStatus = <p>{_t( summarisedStatus = <p>{_t(

View file

@ -21,6 +21,7 @@ import * as sdk from '../../../index';
import {MatrixClientPeg} from '../../../MatrixClientPeg'; import {MatrixClientPeg} from '../../../MatrixClientPeg';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import Modal from '../../../Modal'; import Modal from '../../../Modal';
import { isSecureBackupRequired } from '../../../utils/WellKnownUtils';
export default class KeyBackupPanel extends React.PureComponent { export default class KeyBackupPanel extends React.PureComponent {
constructor(props) { constructor(props) {
@ -315,14 +316,19 @@ export default class KeyBackupPanel extends React.PureComponent {
trustedLocally = _t("This backup is trusted because it has been restored on this session"); trustedLocally = _t("This backup is trusted because it has been restored on this session");
} }
let deleteBackupButton;
if (!isSecureBackupRequired()) {
deleteBackupButton = <AccessibleButton kind="danger" onClick={this._deleteBackup}>
{_t("Delete Backup")}
</AccessibleButton>;
}
const buttonRow = ( const buttonRow = (
<div className="mx_KeyBackupPanel_buttonRow"> <div className="mx_KeyBackupPanel_buttonRow">
<AccessibleButton kind="primary" onClick={this._restoreBackup}> <AccessibleButton kind="primary" onClick={this._restoreBackup}>
{restoreButtonCaption} {restoreButtonCaption}
</AccessibleButton>&nbsp;&nbsp;&nbsp; </AccessibleButton>&nbsp;&nbsp;&nbsp;
<AccessibleButton kind="danger" onClick={this._deleteBackup}> {deleteBackupButton}
{_t("Delete Backup")}
</AccessibleButton>
</div> </div>
); );

View file

@ -237,7 +237,7 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
} }
let customThemeForm: JSX.Element; let customThemeForm: JSX.Element;
if (SettingsStore.isFeatureEnabled("feature_custom_themes")) { if (SettingsStore.getValue("feature_custom_themes")) {
let messageElement = null; let messageElement = null;
if (this.state.customThemeMessage.text) { if (this.state.customThemeMessage.text) {
if (this.state.customThemeMessage.isError) { if (this.state.customThemeMessage.isError) {

View file

@ -28,14 +28,15 @@ export class LabsSettingToggle extends React.Component {
}; };
_onChange = async (checked) => { _onChange = async (checked) => {
await SettingsStore.setFeatureEnabled(this.props.featureId, checked); await SettingsStore.setValue(this.props.featureId, null, SettingLevel.DEVICE, checked);
this.forceUpdate(); this.forceUpdate();
}; };
render() { render() {
const label = SettingsStore.getDisplayName(this.props.featureId); const label = SettingsStore.getDisplayName(this.props.featureId);
const value = SettingsStore.isFeatureEnabled(this.props.featureId); const value = SettingsStore.getValue(this.props.featureId);
return <LabelledToggleSwitch value={value} label={label} onChange={this._onChange} />; const canChange = SettingsStore.canSetValue(this.props.featureId, null, SettingLevel.DEVICE);
return <LabelledToggleSwitch value={value} label={label} onChange={this._onChange} disabled={!canChange} />;
} }
} }
@ -46,7 +47,7 @@ export default class LabsUserSettingsTab extends React.Component {
render() { render() {
const SettingsFlag = sdk.getComponent("views.elements.SettingsFlag"); const SettingsFlag = sdk.getComponent("views.elements.SettingsFlag");
const flags = SettingsStore.getLabsFeatures().map(f => <LabsSettingToggle featureId={f} key={f} />); const flags = SettingsStore.getFeatureSettingNames().map(f => <LabsSettingToggle featureId={f} key={f} />);
return ( return (
<div className="mx_SettingsTab"> <div className="mx_SettingsTab">
<div className="mx_SettingsTab_heading">{_t("Labs")}</div> <div className="mx_SettingsTab_heading">{_t("Labs")}</div>

View file

@ -157,6 +157,9 @@ export default class VoiceUserSettingsTab extends React.Component {
label: _t('Default Device'), label: _t('Default Device'),
}; };
const getDefaultDevice = (devices) => { const getDefaultDevice = (devices) => {
// Note we're looking for a device with deviceId 'default' but adding a device
// with deviceId == the empty string: this is because Chrome gives us a device
// with deviceId 'default', so we're looking for this, not the one we are adding.
if (!devices.some((i) => i.deviceId === 'default')) { if (!devices.some((i) => i.deviceId === 'default')) {
devices.unshift(defaultOption); devices.unshift(defaultOption);
return ''; return '';

View file

@ -26,8 +26,8 @@ import dis from "./dispatcher/dispatcher";
import * as Rooms from "./Rooms"; import * as Rooms from "./Rooms";
import DMRoomMap from "./utils/DMRoomMap"; import DMRoomMap from "./utils/DMRoomMap";
import {getAddressType} from "./UserAddress"; import {getAddressType} from "./UserAddress";
import { getE2EEWellKnown } from "./utils/WellKnownUtils";
const E2EE_WK_KEY = "im.vector.riot.e2ee"; import GroupStore from "./stores/GroupStore";
// we define a number of interfaces which take their names from the js-sdk // we define a number of interfaces which take their names from the js-sdk
/* eslint-disable camelcase */ /* eslint-disable camelcase */
@ -80,6 +80,7 @@ interface IOpts {
encryption?: boolean; encryption?: boolean;
inlineErrors?: boolean; inlineErrors?: boolean;
andView?: boolean; andView?: boolean;
associatedWithCommunity?: string;
} }
/** /**
@ -182,6 +183,10 @@ export default function createRoom(opts: IOpts): Promise<string | null> {
} else { } else {
return Promise.resolve(); return Promise.resolve();
} }
}).then(() => {
if (opts.associatedWithCommunity) {
return GroupStore.addRoomToGroup(opts.associatedWithCommunity, roomId, false);
}
}).then(function() { }).then(function() {
// NB createRoom doesn't block on the client seeing the echo that the // NB createRoom doesn't block on the client seeing the echo that the
// room has been created, so we race here with the client knowing that // room has been created, so we race here with the client knowing that
@ -294,12 +299,11 @@ export async function ensureDMExists(client: MatrixClient, userId: string): Prom
return roomId; return roomId;
} }
export function privateShouldBeEncrypted() { export function privateShouldBeEncrypted(): boolean {
const clientWellKnown = MatrixClientPeg.get().getClientWellKnown(); const e2eeWellKnown = getE2EEWellKnown();
if (clientWellKnown && clientWellKnown[E2EE_WK_KEY]) { if (e2eeWellKnown) {
const defaultDisabled = clientWellKnown[E2EE_WK_KEY]["default"] === false; const defaultDisabled = e2eeWellKnown["default"] === false;
return !defaultDisabled; return !defaultDisabled;
} }
return true; return true;
} }

View file

@ -36,11 +36,11 @@ export const useSettingValue = (settingName: string, roomId: string = null, excl
// Hook to fetch whether a feature is enabled and dynamically update when that changes // Hook to fetch whether a feature is enabled and dynamically update when that changes
export const useFeatureEnabled = (featureName: string, roomId: string = null) => { export const useFeatureEnabled = (featureName: string, roomId: string = null) => {
const [enabled, setEnabled] = useState(SettingsStore.isFeatureEnabled(featureName, roomId)); const [enabled, setEnabled] = useState(SettingsStore.getValue(featureName, roomId));
useEffect(() => { useEffect(() => {
const ref = SettingsStore.watchSetting(featureName, roomId, () => { const ref = SettingsStore.watchSetting(featureName, roomId, () => {
setEnabled(SettingsStore.isFeatureEnabled(featureName, roomId)); setEnabled(SettingsStore.getValue(featureName, roomId));
}); });
// clean-up // clean-up
return () => { return () => {

View file

@ -2164,5 +2164,54 @@
"Add users and servers you want to ignore here. Use asterisks to have %(brand)s match any characters. For example, <code>@bot:*</code> would ignore all users that have the name 'bot' on any server.": "Sem přídejte servery a uživatele, které chcete ignorovat. Hvězdička pro %(brand)s zastupuje libovolný počet kterýchkoliv znaků. Např. <code>@bot:*</code> bude ignorovat všechny uživatele se jménem „bot“ na kterémkoliv serveru.", "Add users and servers you want to ignore here. Use asterisks to have %(brand)s match any characters. For example, <code>@bot:*</code> would ignore all users that have the name 'bot' on any server.": "Sem přídejte servery a uživatele, které chcete ignorovat. Hvězdička pro %(brand)s zastupuje libovolný počet kterýchkoliv znaků. Např. <code>@bot:*</code> bude ignorovat všechny uživatele se jménem „bot“ na kterémkoliv serveru.",
"Signature upload success": "Podpis úspěšně nahrán", "Signature upload success": "Podpis úspěšně nahrán",
"Signature upload failed": "Podpis se nepodařilo nahrát", "Signature upload failed": "Podpis se nepodařilo nahrát",
"If the other version of %(brand)s is still open in another tab, please close it as using %(brand)s on the same host with both lazy loading enabled and disabled simultaneously will cause issues.": "Je-li jiná verze programu %(brand)s stále otevřená na jiné kartě, tak ji prosím zavřete, neboť užívání programu %(brand)s stejným hostitelem se zpožděným nahráváním současně povoleným i zakázaným bude působit problémy." "If the other version of %(brand)s is still open in another tab, please close it as using %(brand)s on the same host with both lazy loading enabled and disabled simultaneously will cause issues.": "Je-li jiná verze programu %(brand)s stále otevřená na jiné kartě, tak ji prosím zavřete, neboť užívání programu %(brand)s stejným hostitelem se zpožděným nahráváním současně povoleným i zakázaným bude působit problémy.",
"Unexpected server error trying to leave the room": "Neočekávaná chyba serveru při odcházení z místnosti",
"The person who invited you already left the room.": "Uživatel který vás pozval už místnosti není.",
"The person who invited you already left the room, or their server is offline.": "Uživatel který vás pozvat už odešel z místnosti a nebo je jeho server offline.",
"You left the call": "Odešli jste z hovoru",
"%(senderName)s left the call": "%(senderName)s opustil/a hovor",
"Call ended": "Hovor skončil",
"You started a call": "Začali jste hovor",
"%(senderName)s started a call": "%(senderName)s začal/a hovor",
"Waiting for answer": "Čekání na odpověď",
"%(senderName)s is calling": "%(senderName)s volá",
"* %(senderName)s %(emote)s": "* %(senderName)s %(emote)s",
"%(senderName)s: %(message)s": "%(senderName)s: %(message)s",
"%(senderName)s: %(reaction)s": "%(senderName)s: %(reaction)s",
"%(senderName)s: %(stickerName)s": "%(senderName)s: %(stickerName)s",
"Change notification settings": "Upravit nastavení oznámení",
"Communities v2 prototypes. Requires compatible homeserver. Highly experimental - use with caution.": "Prototyp komunit verze 2. Vyžaduje kompatibilní domovský server. Experimentální - používejte opatrně.",
"Use custom size": "Použít vlastní velikost",
"Use a more compact Modern layout": "Používat kompaktní Moderní vzhled",
"Use a system font": "Používat systémové nastavení písma",
"System font name": "Jméno systémového písma",
"Uploading logs": "Nahrávání záznamů",
"Downloading logs": "Stahování záznamů",
"Unknown caller": "Neznámý volající",
"Incoming voice call": "Příchozí hovor",
"Incoming video call": "Příchozí videohovor",
"Incoming call": "Příchozí hovor",
"Your server isn't responding to some <a>requests</a>.": "Váš server neodpovídá na některé <a>požadavky</a>.",
"Master private key:": "Hlavní soukromý klíč:",
"%(brand)s can't securely cache encrypted messages locally while running in a web browser. Use <desktopLink>%(brand)s Desktop</desktopLink> for encrypted messages to appear in search results.": "%(brand)s nemůže v prohlížeči lokálně bezpečně uložit zprávy. Použijte <desktopLink>%(brand)s Desktop</desktopLink> aby fungovalo vyhledávání v šifrovaných zprávách.",
"Your server admin has disabled end-to-end encryption by default in private rooms & Direct Messages.": "Váš administrátor vypnul šifrování ve výchozím nastavení soukromých místností a přímých chatů.",
"To link to this room, please add an address.": "Přidejte prosím místnosti adresu aby na ní šlo odkazovat.",
"The authenticity of this encrypted message can't be guaranteed on this device.": "Pravost této šifrované zprávy nelze na tomto zařízení ověřit.",
"Emoji picker": "Výběr emoji",
"No recently visited rooms": "Žádné nedávno navštívené místnosti",
"People": "Lidé",
"Explore public rooms": "Prozkoumat veřejné místnosti",
"Custom Tag": "Vlastní štítek",
"Can't see what youre looking for?": "Nikde nevidíte co hledáte?",
"Explore all public rooms": "Prozkoumat všechny veřejné místnosti",
"%(count)s results|other": "%(count)s výsledků",
"Preparing to download logs": "Příprava na stažení záznamů",
"Download logs": "Stáhnout záznamy",
"a new cross-signing key signature": "nový podpis klíče pro cross-signing",
"a key signature": "podpis klíče",
"%(brand)s encountered an error during upload of:": "%(brand)s narazil na chybu při nahrávání:",
"Upload completed": "Nahrávání dokončeno",
"Cancelled signature upload": "Nahrávání podpisu zrušeno",
"Unable to upload": "Nelze nahrát",
"Server isn't responding": "Server neodpovídá"
} }

View file

@ -572,7 +572,7 @@
"was unbanned %(count)s times|one": "wurde entbannt", "was unbanned %(count)s times|one": "wurde entbannt",
"%(oneUser)schanged their name %(count)s times|one": "%(oneUser)shat den Namen geändert", "%(oneUser)schanged their name %(count)s times|one": "%(oneUser)shat den Namen geändert",
"%(items)s and %(count)s others|other": "%(items)s und %(count)s andere", "%(items)s and %(count)s others|other": "%(items)s und %(count)s andere",
"%(items)s and %(count)s others|one": "%(items)s und noch jemand", "%(items)s and %(count)s others|one": "%(items)s und ein weiteres Raummitglied",
"An email has been sent to %(emailAddress)s. Once you've followed the link it contains, click below.": "Eine E-Mail wurde an %(emailAddress)s gesendet. Folge dem in der E-Mail enthaltenen Link und klicke dann unten.", "An email has been sent to %(emailAddress)s. Once you've followed the link it contains, click below.": "Eine E-Mail wurde an %(emailAddress)s gesendet. Folge dem in der E-Mail enthaltenen Link und klicke dann unten.",
"The visibility of '%(roomName)s' in %(groupId)s could not be updated.": "Die Sichtbarkeit von '%(roomName)s' in %(groupId)s konnte nicht aktualisiert werden.", "The visibility of '%(roomName)s' in %(groupId)s could not be updated.": "Die Sichtbarkeit von '%(roomName)s' in %(groupId)s konnte nicht aktualisiert werden.",
"Visibility in Room List": "Sichtbarkeit in Raum-Liste", "Visibility in Room List": "Sichtbarkeit in Raum-Liste",
@ -784,7 +784,7 @@
"Checking for an update...": "Nach Updates suchen...", "Checking for an update...": "Nach Updates suchen...",
"Missing roomId.": "Fehlende Raum-ID.", "Missing roomId.": "Fehlende Raum-ID.",
"Every page you use in the app": "Jede Seite, die du in der App benutzt", "Every page you use in the app": "Jede Seite, die du in der App benutzt",
"e.g. <CurrentPageURL>": "z.B. <CurrentPageURL>", "e.g. <CurrentPageURL>": "z. B. <CurrentPageURL>",
"Your device resolution": "Deine Bildschirmauflösung", "Your device resolution": "Deine Bildschirmauflösung",
"Popout widget": "Widget ausklinken", "Popout widget": "Widget ausklinken",
"Always show encryption icons": "Immer Verschlüsselungssymbole zeigen", "Always show encryption icons": "Immer Verschlüsselungssymbole zeigen",
@ -1034,7 +1034,7 @@
"%(senderDisplayName)s made the room invite only.": "%(senderDisplayName)s hat den Raum auf eingeladene User beschränkt.", "%(senderDisplayName)s made the room invite only.": "%(senderDisplayName)s hat den Raum auf eingeladene User beschränkt.",
"%(senderDisplayName)s changed the join rule to %(rule)s": "%(senderDisplayName)s änderte die Zutrittsregel auf '%(rule)s'", "%(senderDisplayName)s changed the join rule to %(rule)s": "%(senderDisplayName)s änderte die Zutrittsregel auf '%(rule)s'",
"%(senderDisplayName)s has allowed guests to join the room.": "%(senderDisplayName)s erlaubte Gäste diesem Raum beizutreten.", "%(senderDisplayName)s has allowed guests to join the room.": "%(senderDisplayName)s erlaubte Gäste diesem Raum beizutreten.",
"%(senderDisplayName)s has prevented guests from joining the room.": "%(senderDisplayName)s hat verboten, dass Gäste diesem Raum beitreten.", "%(senderDisplayName)s has prevented guests from joining the room.": "%(senderDisplayName)s hat Gästen verboten diesem Raum beizutreten.",
"%(senderDisplayName)s changed guest access to %(rule)s": "%(senderDisplayName)s änderte den Gastzugriff auf '%(rule)s'", "%(senderDisplayName)s changed guest access to %(rule)s": "%(senderDisplayName)s änderte den Gastzugriff auf '%(rule)s'",
"Group & filter rooms by custom tags (refresh to apply changes)": "Gruppiere & filtere Räume nach eigenen Tags (neu laden um Änderungen zu übernehmen)", "Group & filter rooms by custom tags (refresh to apply changes)": "Gruppiere & filtere Räume nach eigenen Tags (neu laden um Änderungen zu übernehmen)",
"Unable to find a supported verification method.": "Konnte kein unterstützte Verifikationsmethode finden.", "Unable to find a supported verification method.": "Konnte kein unterstützte Verifikationsmethode finden.",
@ -1328,7 +1328,7 @@
"Find a room…": "Suche einen Raum…", "Find a room…": "Suche einen Raum…",
"Find a room… (e.g. %(exampleRoom)s)": "Suche einen Raum… (z.B. %(exampleRoom)s)", "Find a room… (e.g. %(exampleRoom)s)": "Suche einen Raum… (z.B. %(exampleRoom)s)",
"If you can't find the room you're looking for, ask for an invite or <a>Create a new room</a>.": "Wenn du den gesuchten Raum nicht finden kannst, frage nach einer Einladung für den Raum oder <a>Erstelle einen neuen Raum</a>.", "If you can't find the room you're looking for, ask for an invite or <a>Create a new room</a>.": "Wenn du den gesuchten Raum nicht finden kannst, frage nach einer Einladung für den Raum oder <a>Erstelle einen neuen Raum</a>.",
"Alternatively, you can try to use the public server at <code>turn.matrix.org</code>, but this will not be as reliable, and it will share your IP address with that server. You can also manage this in Settings.": "Alternativ kannst du versuchen, den öffentlichen Server unter <code>turn.matrix.org</code> zu verwenden. Allerdings wird dieser nicht so zuverlässig sein, und deine IP-Adresse mit diesem teilen. Du kannst dies auch in den Einstellungen konfigurieren.", "Alternatively, you can try to use the public server at <code>turn.matrix.org</code>, but this will not be as reliable, and it will share your IP address with that server. You can also manage this in Settings.": "Alternativ kannst du versuchen, den öffentlichen Server unter <code>turn.matrix.org</code> zu verwenden. Allerdings wird dieser nicht so zuverlässig sein, und deine IP-Adresse mit diesem Server teilen. Du kannst dies auch in den Einstellungen konfigurieren.",
"This action requires accessing the default identity server <server /> to validate an email address or phone number, but the server does not have any terms of service.": "Diese Handlung erfordert es, auf den Standard-Identitätsserver <server /> zuzugreifen, um eine E-Mail Adresse oder Telefonnummer zu validieren, aber der Server hat keine Nutzungsbedingungen.", "This action requires accessing the default identity server <server /> to validate an email address or phone number, but the server does not have any terms of service.": "Diese Handlung erfordert es, auf den Standard-Identitätsserver <server /> zuzugreifen, um eine E-Mail Adresse oder Telefonnummer zu validieren, aber der Server hat keine Nutzungsbedingungen.",
"Only continue if you trust the owner of the server.": "Fahre nur fort, wenn du den Inhaber*innen des Servers vertraust.", "Only continue if you trust the owner of the server.": "Fahre nur fort, wenn du den Inhaber*innen des Servers vertraust.",
"Trust": "Vertrauen", "Trust": "Vertrauen",
@ -1337,7 +1337,7 @@
"Use an identity server to invite by email. Manage in Settings.": "Nutze einen Identitätsserver, um über E-Mail Einladungen zu verschicken. Verwalte es in den Einstellungen.", "Use an identity server to invite by email. Manage in Settings.": "Nutze einen Identitätsserver, um über E-Mail Einladungen zu verschicken. Verwalte es in den Einstellungen.",
"%(name)s (%(userId)s)": "%(name)s (%(userId)s)", "%(name)s (%(userId)s)": "%(name)s (%(userId)s)",
"Try out new ways to ignore people (experimental)": "Versuche neue Möglichkeiten, um Menschen zu ignorieren (experimentell)", "Try out new ways to ignore people (experimental)": "Versuche neue Möglichkeiten, um Menschen zu ignorieren (experimentell)",
"Send read receipts for messages (requires compatible homeserver to disable)": "Schicke Lesebestätigungen für Nachrichten (erfordert kompatiblen Heimserver zum Deaktivieren)", "Send read receipts for messages (requires compatible homeserver to disable)": "Lesebestätigungen für Nachrichten senden (Deaktivieren erfordert einen kompatiblen Heimserver)",
"My Ban List": "Meine Bannliste", "My Ban List": "Meine Bannliste",
"This is your list of users/servers you have blocked - don't leave the room!": "Dies ist die Liste von Benutzer*innen/Servern, die du blockiert hast - verlasse den Raum nicht!", "This is your list of users/servers you have blocked - don't leave the room!": "Dies ist die Liste von Benutzer*innen/Servern, die du blockiert hast - verlasse den Raum nicht!",
"Accept <policyLink /> to continue:": "Akzeptiere <policyLink />, um fortzufahren:", "Accept <policyLink /> to continue:": "Akzeptiere <policyLink />, um fortzufahren:",
@ -1587,8 +1587,8 @@
"Reject & Ignore user": "Ablehnen & Nutzer ignorieren", "Reject & Ignore user": "Ablehnen & Nutzer ignorieren",
"%(senderName)s changed a rule that was banning users matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s ändert eine Ausschluss-Regel von %(oldGlob)s nach %(newGlob)s, wegen %(reason)s", "%(senderName)s changed a rule that was banning users matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s ändert eine Ausschluss-Regel von %(oldGlob)s nach %(newGlob)s, wegen %(reason)s",
"%(senderName)s changed a rule that was banning rooms matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s ändert eine Ausschluss-Regel für Räume von %(oldGlob)s nach %(newGlob)s, wegen %(reason)s", "%(senderName)s changed a rule that was banning rooms matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s ändert eine Ausschluss-Regel für Räume von %(oldGlob)s nach %(newGlob)s, wegen %(reason)s",
"Allow fallback call assist server turn.matrix.org when your homeserver does not offer one (your IP address would be shared during a call)": "Erlaube den Standard-Server zur Anrufunterstützung (turn.matrix.org) zu verwenden wenn dein Heimserver keinen eigenen anbietet (deine IP Adresse wird bei dem Anruf übermittelt)", "Allow fallback call assist server turn.matrix.org when your homeserver does not offer one (your IP address would be shared during a call)": "Auf den Server turn.matrix.org zurückgreifen, falls deine Heimserver keine Anruf-Assistenz anbietet (deine IP-Adresse wird während eines Anrufs geteilt)",
"Show more": "mehr", "Show more": "Mehr zeigen",
"This session is <b>not backing up your keys</b>, but you do have an existing backup you can restore from and add to going forward.": "Diese Sitzung <b>speichert deine Schlüssel nicht</b>, du kannst sie aber an die Schlüsselsicherung anschließen.", "This session is <b>not backing up your keys</b>, but you do have an existing backup you can restore from and add to going forward.": "Diese Sitzung <b>speichert deine Schlüssel nicht</b>, du kannst sie aber an die Schlüsselsicherung anschließen.",
"Connect this session to key backup before signing out to avoid losing any keys that may only be on this session.": "Verbinde diese Sitzung mit deiner Schlüsselsicherung bevor du dich abmeldest, um den Verlust von Schlüsseln zu vermeiden.", "Connect this session to key backup before signing out to avoid losing any keys that may only be on this session.": "Verbinde diese Sitzung mit deiner Schlüsselsicherung bevor du dich abmeldest, um den Verlust von Schlüsseln zu vermeiden.",
"This backup is trusted because it has been restored on this session": "Dieser Sicherung wird vertraut, da sie während dieser Sitzung wiederhergestellt wurde", "This backup is trusted because it has been restored on this session": "Dieser Sicherung wird vertraut, da sie während dieser Sitzung wiederhergestellt wurde",
@ -1632,12 +1632,12 @@
"Make a copy of your recovery key": "Speichere deinen Wiederherstellungsschlüssel", "Make a copy of your recovery key": "Speichere deinen Wiederherstellungsschlüssel",
"Sends a message as html, without interpreting it as markdown": "Verschickt eine Nachricht im html-Format, ohne sie in Markdown zu formatieren", "Sends a message as html, without interpreting it as markdown": "Verschickt eine Nachricht im html-Format, ohne sie in Markdown zu formatieren",
"Show rooms with unread notifications first": "Räume mit nicht gelesenen Benachrichtungen zuerst zeigen", "Show rooms with unread notifications first": "Räume mit nicht gelesenen Benachrichtungen zuerst zeigen",
"Show shortcuts to recently viewed rooms above the room list": "Kurzbefehlezu den kürzlich gesichteteten Räumen über der Raumliste anzeigen", "Show shortcuts to recently viewed rooms above the room list": "Kurzbefehle zu den kürzlich gesichteteten Räumen über der Raumliste anzeigen",
"Use Single Sign On to continue": "Nutze „Single Sign-On“ (Einmal-Anmeldung) um fortzufahren", "Use Single Sign On to continue": "Verwende Single Sign on um fortzufahren",
"Confirm adding this email address by using Single Sign On to prove your identity.": "Bestätige das Hinzufügen dieser E-Mail-Adresse mit „Single Sign-On“, um deine Identität nachzuweisen.", "Confirm adding this email address by using Single Sign On to prove your identity.": "Bestätige die hinzugefügte E-Mail-Adresse mit Single Sign-On, um deine Identität nachzuweisen.",
"Single Sign On": "Single Sign-On", "Single Sign On": "Single Sign-On",
"Confirm adding email": "Hinzufügen der E-Mail-Adresse bestätigen", "Confirm adding email": "Bestätige hinzugefügte E-Mail-Addresse",
"Confirm adding this phone number by using Single Sign On to prove your identity.": "Bestätige das Hinzufügen dieser Telefonnummer, indem du deine Identität mittels Single Sign-On nachweist.", "Confirm adding this phone number by using Single Sign On to prove your identity.": "Bestätige die hinzugefügte Telefonnummer, indem du deine Identität mittels Single Sign-On nachweist.",
"Click the button below to confirm adding this phone number.": "Klicke unten die Schaltfläche, um die hinzugefügte Telefonnummer zu bestätigen.", "Click the button below to confirm adding this phone number.": "Klicke unten die Schaltfläche, um die hinzugefügte Telefonnummer zu bestätigen.",
"If you cancel now, you won't complete your operation.": "Wenn du jetzt abbrichst, wirst du deinen Vorgang nicht fertigstellen.", "If you cancel now, you won't complete your operation.": "Wenn du jetzt abbrichst, wirst du deinen Vorgang nicht fertigstellen.",
"%(name)s is requesting verification": "%(name)s fordert eine Verifizierung an", "%(name)s is requesting verification": "%(name)s fordert eine Verifizierung an",
@ -1645,14 +1645,14 @@
"Command failed": "Befehl fehlgeschlagen", "Command failed": "Befehl fehlgeschlagen",
"Could not find user in room": "Der Benutzer konnte im Raum nicht gefunden werden", "Could not find user in room": "Der Benutzer konnte im Raum nicht gefunden werden",
"Click the button below to confirm adding this email address.": "Klicke unten auf die Schaltfläche, um die hinzugefügte E-Mail-Adresse zu bestätigen.", "Click the button below to confirm adding this email address.": "Klicke unten auf die Schaltfläche, um die hinzugefügte E-Mail-Adresse zu bestätigen.",
"Confirm adding phone number": "Hinzufügen der Telefonnummer bestätigen", "Confirm adding phone number": "Bestätige hinzugefügte Telefonnummer",
"%(senderName)s changed a rule that was banning servers matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s ändert eine Ausschluss-Regel für Server von %(oldGlob)s nach %(newGlob)s wegen %(reason)s", "%(senderName)s changed a rule that was banning servers matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s ändert eine Ausschluss-Regel für Server von %(oldGlob)s nach %(newGlob)s wegen %(reason)s",
"%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s erneuert eine Ausschluss-Regel von %(oldGlob)s nach %(newGlob)s wegen %(reason)s", "%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s erneuert eine Ausschluss-Regel von %(oldGlob)s nach %(newGlob)s wegen %(reason)s",
"Not Trusted": "Nicht vertraut", "Not Trusted": "Nicht vertraut",
"Manually Verify by Text": "Verifiziere manuell mit einem Text", "Manually Verify by Text": "Verifiziere manuell mit einem Text",
"Interactively verify by Emoji": "Verifiziere interaktiv mit Emojis", "Interactively verify by Emoji": "Verifiziere interaktiv mit Emojis",
"Support adding custom themes": "Unterstütze das Hinzufügen von benutzerdefinierten Designs", "Support adding custom themes": "Unterstütze das Hinzufügen von benutzerdefinierten Designs",
"Ask this user to verify their session, or manually verify it below.": "Bitte diese/n Nutzer!n, seine/ihre Sitzung zu verifizieren, oder verifiziere diese unten manuell.", "Ask this user to verify their session, or manually verify it below.": "Bitte diesen Nutzer, seine Sitzung zu verifizieren, oder verifiziere diesen unten manuell.",
"a few seconds from now": "in ein paar Sekunden", "a few seconds from now": "in ein paar Sekunden",
"Manually verify all remote sessions": "Verifiziere alle Remotesitzungen", "Manually verify all remote sessions": "Verifiziere alle Remotesitzungen",
"Confirm the emoji below are displayed on both sessions, in the same order:": "Bestätige, dass die unten angezeigten Emojis auf beiden Sitzungen in der selben Reihenfolge angezeigt werden:", "Confirm the emoji below are displayed on both sessions, in the same order:": "Bestätige, dass die unten angezeigten Emojis auf beiden Sitzungen in der selben Reihenfolge angezeigt werden:",
@ -1724,7 +1724,7 @@
"Upgrade this room to the recommended room version": "Aktualisiere diesen Raum auf die empfohlene Raumversion", "Upgrade this room to the recommended room version": "Aktualisiere diesen Raum auf die empfohlene Raumversion",
"this room": "Dieser Raum", "this room": "Dieser Raum",
"View older messages in %(roomName)s.": "Zeige alte Nachrichten in %(roomName)s.", "View older messages in %(roomName)s.": "Zeige alte Nachrichten in %(roomName)s.",
"Send a bug report with logs": "Sende Fehlermeldung mit Protokoll", "Send a bug report with logs": "Sende einen Fehlerbericht mit Logs",
"Verify all your sessions to ensure your account & messages are safe": "Verifiziere alle deine Sitzungen, um dein Konto und deine Nachrichten zu schützen", "Verify all your sessions to ensure your account & messages are safe": "Verifiziere alle deine Sitzungen, um dein Konto und deine Nachrichten zu schützen",
"Verify your other session using one of the options below.": "Verifiziere deine andere Sitzung mit einer der folgenden Optionen.", "Verify your other session using one of the options below.": "Verifiziere deine andere Sitzung mit einer der folgenden Optionen.",
"You signed in to a new session without verifying it:": "Du hast dich in einer neuen Sitzung angemeldet ohne sie zu verifizieren:", "You signed in to a new session without verifying it:": "Du hast dich in einer neuen Sitzung angemeldet ohne sie zu verifizieren:",
@ -1732,16 +1732,16 @@
"Upgrade": "Hochstufen", "Upgrade": "Hochstufen",
"Verify the new login accessing your account: %(name)s": "Verifiziere die neue Anmeldung an deinem Konto: %(name)s", "Verify the new login accessing your account: %(name)s": "Verifiziere die neue Anmeldung an deinem Konto: %(name)s",
"From %(deviceName)s (%(deviceId)s)": "Von %(deviceName)s (%(deviceId)s)", "From %(deviceName)s (%(deviceId)s)": "Von %(deviceName)s (%(deviceId)s)",
"Your homeserver does not support cross-signing.": "Dein Heimserver unterstützt cross-signing nicht.", "Your homeserver does not support cross-signing.": "Dein Heimserver unterstützt Cross-Signing nicht.",
"Cross-signing and secret storage are enabled.": "Cross-signing und der sichere Speicher wurden eingerichtet.", "Cross-signing and secret storage are enabled.": "Cross-signing und der sichere Speicher wurden eingerichtet.",
"Your account has a cross-signing identity in secret storage, but it is not yet trusted by this session.": "Dein Konto hat eine cross-signing Identität im sicheren Speicher aber diese Sitzung wird noch nicht vertraut.", "Your account has a cross-signing identity in secret storage, but it is not yet trusted by this session.": "Dein Konto hat eine Cross-Signing Identität im sicheren Speicher, aber dieser wird von dieser Sitzung noch nicht vertraut.",
"Cross-signing and secret storage are not yet set up.": "Cross-signing und der sichere Speicher wurden noch nicht eingerichtet.", "Cross-signing and secret storage are not yet set up.": "Cross-Signing und der sichere Speicher sind noch nicht eingerichtet.",
"Reset cross-signing and secret storage": "Setze cross-signing und den sicheren Speicher zurück", "Reset cross-signing and secret storage": "Setze Cross-Signing und den sicheren Speicher zurück",
"Bootstrap cross-signing and secret storage": "Richte cross-signing und den sicheren Speicher ein", "Bootstrap cross-signing and secret storage": "Richte cross-signing und den sicheren Speicher ein",
"unexpected type": "unbekannter Typ", "unexpected type": "unbekannter Typ",
"Cross-signing public keys:": "Öffentliche Cross-signing Schlüssel:", "Cross-signing public keys:": "Öffentliche Cross-Signing-Schlüssel:",
"in memory": "im Speicher", "in memory": "im Speicher",
"Cross-signing private keys:": "Private Cross-signing Schlüssel:", "Cross-signing private keys:": "Private Cross-Signing-Schlüssel:",
"in secret storage": "im sicheren Speicher", "in secret storage": "im sicheren Speicher",
"Self signing private key:": "Selbst signierter privater Schlüssel:", "Self signing private key:": "Selbst signierter privater Schlüssel:",
"cached locally": "lokal zwischengespeichert", "cached locally": "lokal zwischengespeichert",
@ -1754,7 +1754,7 @@
"exists": "existiert", "exists": "existiert",
"Delete sessions|other": "Lösche Sitzungen", "Delete sessions|other": "Lösche Sitzungen",
"Delete sessions|one": "Lösche Sitzung", "Delete sessions|one": "Lösche Sitzung",
"Individually verify each session used by a user to mark it as trusted, not trusting cross-signed devices.": "Sitzungen eines Benutzers einzeln verifizieren. Geräten, die ein Benutzer als vertrauenswürdig markiert hat, wird nicht automatisch vertraut (cross-signing).", "Individually verify each session used by a user to mark it as trusted, not trusting cross-signed devices.": "Alle Sitzungen einzeln verifizieren, anstatt auch Sitzungen zu vertrauen, die durch Cross-Signing verifiziert sind.",
"Securely cache encrypted messages locally for them to appear in search results, using ": "Der Zwischenspeicher für die lokale Suche in verschlüsselten Nachrichten benötigt ", "Securely cache encrypted messages locally for them to appear in search results, using ": "Der Zwischenspeicher für die lokale Suche in verschlüsselten Nachrichten benötigt ",
" to store messages from ": " um Nachrichten aus ", " to store messages from ": " um Nachrichten aus ",
"%(brand)s is missing some components required for securely caching encrypted messages locally. If you'd like to experiment with this feature, build a custom %(brand)s Desktop with <nativeLink>search components added</nativeLink>.": "%(brand)s benötigt weitere Komponenten um verschlüsselte Nachrichten lokal zu durchsuchen. Wenn du diese Funktion testen möchtest kannst du dir deine eigene Version von %(brand)s Desktop mit der <nativeLink>integrierten Suchfunktion bauen</nativeLink>.", "%(brand)s is missing some components required for securely caching encrypted messages locally. If you'd like to experiment with this feature, build a custom %(brand)s Desktop with <nativeLink>search components added</nativeLink>.": "%(brand)s benötigt weitere Komponenten um verschlüsselte Nachrichten lokal zu durchsuchen. Wenn du diese Funktion testen möchtest kannst du dir deine eigene Version von %(brand)s Desktop mit der <nativeLink>integrierten Suchfunktion bauen</nativeLink>.",
@ -2408,5 +2408,20 @@
"Store your Security Key somewhere safe, like a password manager or a safe, as its used to safeguard your encrypted data.": "Bewahre deinen Sicherheitsschlüssel an einem sicheren Ort wie z. B. in einem Passwort-Manager oder einem Safe auf. Er wird zum Schutz deiner verschlüsselten Daten verwendet.", "Store your Security Key somewhere safe, like a password manager or a safe, as its used to safeguard your encrypted data.": "Bewahre deinen Sicherheitsschlüssel an einem sicheren Ort wie z. B. in einem Passwort-Manager oder einem Safe auf. Er wird zum Schutz deiner verschlüsselten Daten verwendet.",
"If you cancel now, you may lose encrypted messages & data if you lose access to your logins.": "Wenn du jetzt abbrichst, kannst du verschlüsselte Nachrichten und Daten verlieren, wenn du den Zugriff auf deine Logins verlierst.", "If you cancel now, you may lose encrypted messages & data if you lose access to your logins.": "Wenn du jetzt abbrichst, kannst du verschlüsselte Nachrichten und Daten verlieren, wenn du den Zugriff auf deine Logins verlierst.",
"You can also set up Secure Backup & manage your keys in Settings.": "Du kannst auch in den Einstellungen eine Sicherung erstellen & deine Schlüssel verwalten.", "You can also set up Secure Backup & manage your keys in Settings.": "Du kannst auch in den Einstellungen eine Sicherung erstellen & deine Schlüssel verwalten.",
"Set up Secure backup": "Sicheres Backup einrichten" "Set up Secure backup": "Sicheres Backup einrichten",
"Show message previews for reactions in DMs": "Anzeigen einer Nachrichtenvorschau für Reaktionen in DMs",
"Show message previews for reactions in all rooms": "Zeigen Sie eine Nachrichtenvorschau für Reaktionen in allen Räumen an",
"Uploading logs": "Protokolle werden hochgeladen",
"Downloading logs": "Protokolle werden heruntergeladen",
"Explore public rooms": "Erkunde öffentliche Räume",
"Can't see what youre looking for?": "Kannst du nicht finden wonach du suchst?",
"Explore all public rooms": "Erkunde alle öffentlichen Räume",
"%(count)s results|other": "%(count)s Ergebnisse",
"Preparing to download logs": "Bereite das Herunterladen der Protokolle vor",
"Download logs": "Protokolle herunterladen",
"Unexpected server error trying to leave the room": "Unerwarteter Server-Fehler beim Versuch den Raum zu verlassen",
"Error leaving room": "Fehler beim Verlassen des Raums",
"Communities v2 prototypes. Requires compatible homeserver. Highly experimental - use with caution.": "Communities v2 Prototyp. Benötigt einen kompatiblen Heimserver. Höchst experimentell - mit Vorsicht verwenden.",
"Explore rooms in %(communityName)s": "Erkunde Räume in %(communityName)s",
"Set up Secure Backup": "Sicherung einrichten"
} }

View file

@ -347,6 +347,10 @@
"Your browser does not support the required cryptography extensions": "Your browser does not support the required cryptography extensions", "Your browser does not support the required cryptography extensions": "Your browser does not support the required cryptography extensions",
"Not a valid %(brand)s keyfile": "Not a valid %(brand)s keyfile", "Not a valid %(brand)s keyfile": "Not a valid %(brand)s keyfile",
"Authentication check failed: incorrect password?": "Authentication check failed: incorrect password?", "Authentication check failed: incorrect password?": "Authentication check failed: incorrect password?",
"Unexpected server error trying to leave the room": "Unexpected server error trying to leave the room",
"Can't leave Server Notices room": "Can't leave Server Notices room",
"This room is used for important messages from the Homeserver, so you cannot leave it.": "This room is used for important messages from the Homeserver, so you cannot leave it.",
"Error leaving room": "Error leaving room",
"Unrecognised address": "Unrecognised address", "Unrecognised address": "Unrecognised address",
"You do not have permission to invite people to this room.": "You do not have permission to invite people to this room.", "You do not have permission to invite people to this room.": "You do not have permission to invite people to this room.",
"User %(userId)s is already in the room": "User %(userId)s is already in the room", "User %(userId)s is already in the room": "User %(userId)s is already in the room",
@ -440,6 +444,7 @@
"%(senderName)s: %(reaction)s": "%(senderName)s: %(reaction)s", "%(senderName)s: %(reaction)s": "%(senderName)s: %(reaction)s",
"%(senderName)s: %(stickerName)s": "%(senderName)s: %(stickerName)s", "%(senderName)s: %(stickerName)s": "%(senderName)s: %(stickerName)s",
"Change notification settings": "Change notification settings", "Change notification settings": "Change notification settings",
"Communities v2 prototypes. Requires compatible homeserver. Highly experimental - use with caution.": "Communities v2 prototypes. Requires compatible homeserver. Highly experimental - use with caution.",
"New spinner design": "New spinner design", "New spinner design": "New spinner design",
"Message Pinning": "Message Pinning", "Message Pinning": "Message Pinning",
"Custom user status messages": "Custom user status messages", "Custom user status messages": "Custom user status messages",
@ -640,7 +645,8 @@
"Confirm password": "Confirm password", "Confirm password": "Confirm password",
"Change Password": "Change Password", "Change Password": "Change Password",
"Your homeserver does not support cross-signing.": "Your homeserver does not support cross-signing.", "Your homeserver does not support cross-signing.": "Your homeserver does not support cross-signing.",
"Cross-signing and secret storage are enabled.": "Cross-signing and secret storage are enabled.", "Cross-signing and secret storage are ready for use.": "Cross-signing and secret storage are ready for use.",
"Cross-signing is ready for use, but secret storage is currently not being used to backup your keys.": "Cross-signing is ready for use, but secret storage is currently not being used to backup your keys.",
"Your account has a cross-signing identity in secret storage, but it is not yet trusted by this session.": "Your account has a cross-signing identity in secret storage, but it is not yet trusted by this session.", "Your account has a cross-signing identity in secret storage, but it is not yet trusted by this session.": "Your account has a cross-signing identity in secret storage, but it is not yet trusted by this session.",
"Cross-signing and secret storage are not yet set up.": "Cross-signing and secret storage are not yet set up.", "Cross-signing and secret storage are not yet set up.": "Cross-signing and secret storage are not yet set up.",
"Reset cross-signing and secret storage": "Reset cross-signing and secret storage", "Reset cross-signing and secret storage": "Reset cross-signing and secret storage",
@ -1116,6 +1122,7 @@
"Rooms": "Rooms", "Rooms": "Rooms",
"Add room": "Add room", "Add room": "Add room",
"Create new room": "Create new room", "Create new room": "Create new room",
"Explore community rooms": "Explore community rooms",
"Explore public rooms": "Explore public rooms", "Explore public rooms": "Explore public rooms",
"Low priority": "Low priority", "Low priority": "Low priority",
"System Alerts": "System Alerts", "System Alerts": "System Alerts",
@ -1479,6 +1486,7 @@
"Rotate Right": "Rotate Right", "Rotate Right": "Rotate Right",
"Rotate clockwise": "Rotate clockwise", "Rotate clockwise": "Rotate clockwise",
"Download this file": "Download this file", "Download this file": "Download this file",
"Information": "Information",
"Language Dropdown": "Language Dropdown", "Language Dropdown": "Language Dropdown",
"Manage Integrations": "Manage Integrations", "Manage Integrations": "Manage Integrations",
"%(nameList)s %(transitionList)s": "%(nameList)s %(transitionList)s", "%(nameList)s %(transitionList)s": "%(nameList)s %(transitionList)s",
@ -1550,6 +1558,7 @@
"And %(count)s more...|other": "And %(count)s more...", "And %(count)s more...|other": "And %(count)s more...",
"ex. @bob:example.com": "ex. @bob:example.com", "ex. @bob:example.com": "ex. @bob:example.com",
"Add User": "Add User", "Add User": "Add User",
"Home": "Home",
"Enter a server name": "Enter a server name", "Enter a server name": "Enter a server name",
"Looks good": "Looks good", "Looks good": "Looks good",
"Can't find this server or its room list": "Can't find this server or its room list", "Can't find this server or its room list": "Can't find this server or its room list",
@ -1592,6 +1601,15 @@
"Unable to load commit detail: %(msg)s": "Unable to load commit detail: %(msg)s", "Unable to load commit detail: %(msg)s": "Unable to load commit detail: %(msg)s",
"Unavailable": "Unavailable", "Unavailable": "Unavailable",
"Changelog": "Changelog", "Changelog": "Changelog",
"Email address": "Email address",
"Add another email": "Add another email",
"People you know on %(brand)s": "People you know on %(brand)s",
"Hide": "Hide",
"Show": "Show",
"Skip": "Skip",
"Send %(count)s invites|other": "Send %(count)s invites",
"Send %(count)s invites|one": "Send %(count)s invite",
"Invite people to join %(communityName)s": "Invite people to join %(communityName)s",
"You cannot delete this message. (%(code)s)": "You cannot delete this message. (%(code)s)", "You cannot delete this message. (%(code)s)": "You cannot delete this message. (%(code)s)",
"Removing…": "Removing…", "Removing…": "Removing…",
"Destroy cross-signing keys?": "Destroy cross-signing keys?", "Destroy cross-signing keys?": "Destroy cross-signing keys?",
@ -1602,6 +1620,15 @@
"Clear all data in this session?": "Clear all data in this session?", "Clear all data in this session?": "Clear all data in this session?",
"Clearing all data from this session is permanent. Encrypted messages will be lost unless their keys have been backed up.": "Clearing all data from this session is permanent. Encrypted messages will be lost unless their keys have been backed up.", "Clearing all data from this session is permanent. Encrypted messages will be lost unless their keys have been backed up.": "Clearing all data from this session is permanent. Encrypted messages will be lost unless their keys have been backed up.",
"Clear all data": "Clear all data", "Clear all data": "Clear all data",
"There was an error creating your community. The name may be taken or the server is unable to process your request.": "There was an error creating your community. The name may be taken or the server is unable to process your request.",
"Community ID: +<localpart />:%(domain)s": "Community ID: +<localpart />:%(domain)s",
"Use this when referencing your community to others. The community ID cannot be changed.": "Use this when referencing your community to others. The community ID cannot be changed.",
"You can change this later if needed.": "You can change this later if needed.",
"What's the name of your community or team?": "What's the name of your community or team?",
"Enter name": "Enter name",
"Create": "Create",
"Add image (optional)": "Add image (optional)",
"An image will help people identify your community.": "An image will help people identify your community.",
"Community IDs cannot be empty.": "Community IDs cannot be empty.", "Community IDs cannot be empty.": "Community IDs cannot be empty.",
"Community IDs may only contain characters a-z, 0-9, or '=_-./'": "Community IDs may only contain characters a-z, 0-9, or '=_-./'", "Community IDs may only contain characters a-z, 0-9, or '=_-./'": "Community IDs may only contain characters a-z, 0-9, or '=_-./'",
"Something went wrong whilst creating your community": "Something went wrong whilst creating your community", "Something went wrong whilst creating your community": "Something went wrong whilst creating your community",
@ -1610,20 +1637,22 @@
"Example": "Example", "Example": "Example",
"Community ID": "Community ID", "Community ID": "Community ID",
"example": "example", "example": "example",
"Create": "Create",
"Please enter a name for the room": "Please enter a name for the room", "Please enter a name for the room": "Please enter a name for the room",
"Set a room address to easily share your room with other people.": "Set a room address to easily share your room with other people.", "Private rooms can be found and joined by invitation only. Public rooms can be found and joined by anyone.": "Private rooms can be found and joined by invitation only. Public rooms can be found and joined by anyone.",
"This room is private, and can only be joined by invitation.": "This room is private, and can only be joined by invitation.", "Private rooms can be found and joined by invitation only. Public rooms can be found and joined by anyone in this community.": "Private rooms can be found and joined by invitation only. Public rooms can be found and joined by anyone in this community.",
"You cant disable this later. Bridges & most bots wont work yet.": "You cant disable this later. Bridges & most bots wont work yet.", "You cant disable this later. Bridges & most bots wont work yet.": "You cant disable this later. Bridges & most bots wont work yet.",
"Enable end-to-end encryption": "Enable end-to-end encryption", "Enable end-to-end encryption": "Enable end-to-end encryption",
"You might enable this if the room will only be used for collaborating with internal teams on your homeserver. This cannot be changed later.": "You might enable this if the room will only be used for collaborating with internal teams on your homeserver. This cannot be changed later.",
"You might disable this if the room will be used for collaborating with external teams who have their own homeserver. This cannot be changed later.": "You might disable this if the room will be used for collaborating with external teams who have their own homeserver. This cannot be changed later.",
"Create a public room": "Create a public room", "Create a public room": "Create a public room",
"Create a private room": "Create a private room", "Create a private room": "Create a private room",
"Create a room in %(communityName)s": "Create a room in %(communityName)s",
"Name": "Name", "Name": "Name",
"Topic (optional)": "Topic (optional)", "Topic (optional)": "Topic (optional)",
"Make this room public": "Make this room public", "Make this room public": "Make this room public",
"Hide advanced": "Hide advanced", "Hide advanced": "Hide advanced",
"Show advanced": "Show advanced", "Show advanced": "Show advanced",
"Block users on other matrix homeservers from joining this room (This setting cannot be changed later!)": "Block users on other matrix homeservers from joining this room (This setting cannot be changed later!)", "Block anyone not part of %(serverName)s from ever joining this room.": "Block anyone not part of %(serverName)s from ever joining this room.",
"Create Room": "Create Room", "Create Room": "Create Room",
"Sign out": "Sign out", "Sign out": "Sign out",
"To avoid losing your chat history, you must export your room keys before logging out. You will need to go back to the newer version of %(brand)s to do this": "To avoid losing your chat history, you must export your room keys before logging out. You will need to go back to the newer version of %(brand)s to do this", "To avoid losing your chat history, you must export your room keys before logging out. You will need to go back to the newer version of %(brand)s to do this": "To avoid losing your chat history, you must export your room keys before logging out. You will need to go back to the newer version of %(brand)s to do this",
@ -1769,9 +1798,7 @@
"Clearing your browser's storage may fix the problem, but will sign you out and cause any encrypted chat history to become unreadable.": "Clearing your browser's storage may fix the problem, but will sign you out and cause any encrypted chat history to become unreadable.", "Clearing your browser's storage may fix the problem, but will sign you out and cause any encrypted chat history to become unreadable.": "Clearing your browser's storage may fix the problem, but will sign you out and cause any encrypted chat history to become unreadable.",
"Verification Pending": "Verification Pending", "Verification Pending": "Verification Pending",
"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.", "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.",
"Email address": "Email address",
"This will allow you to reset your password and receive notifications.": "This will allow you to reset your password and receive notifications.", "This will allow you to reset your password and receive notifications.": "This will allow you to reset your password and receive notifications.",
"Skip": "Skip",
"A username can only contain lower case letters, numbers and '=_-./'": "A username can only contain lower case letters, numbers and '=_-./'", "A username can only contain lower case letters, numbers and '=_-./'": "A username can only contain lower case letters, numbers and '=_-./'",
"Username not available": "Username not available", "Username not available": "Username not available",
"Username invalid: %(errMessage)s": "Username invalid: %(errMessage)s", "Username invalid: %(errMessage)s": "Username invalid: %(errMessage)s",
@ -1879,23 +1906,11 @@
"Source URL": "Source URL", "Source URL": "Source URL",
"Collapse Reply Thread": "Collapse Reply Thread", "Collapse Reply Thread": "Collapse Reply Thread",
"Report Content": "Report Content", "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)",
"Mentions only": "Mentions only",
"Leave": "Leave",
"Forget": "Forget",
"Direct Chat": "Direct Chat",
"Clear status": "Clear status", "Clear status": "Clear status",
"Update status": "Update status", "Update status": "Update status",
"Set status": "Set status", "Set status": "Set status",
"Set a new status...": "Set a new status...", "Set a new status...": "Set a new status...",
"View Community": "View Community", "View Community": "View Community",
"Hide": "Hide",
"Home": "Home",
"Sign in": "Sign in",
"Help": "Help",
"Reload": "Reload", "Reload": "Reload",
"Take picture": "Take picture", "Take picture": "Take picture",
"Remove for everyone": "Remove for everyone", "Remove for everyone": "Remove for everyone",
@ -1936,6 +1951,7 @@
"Phone": "Phone", "Phone": "Phone",
"Not sure of your password? <a>Set a new one</a>": "Not sure of your password? <a>Set a new one</a>", "Not sure of your password? <a>Set a new one</a>": "Not sure of your password? <a>Set a new one</a>",
"Sign in with": "Sign in with", "Sign in with": "Sign in with",
"Sign in": "Sign in",
"No identity server is configured so you cannot add an email address in order to reset your password in the future.": "No identity server is configured so you cannot add an email address in order to reset your password in the future.", "No identity server is configured so you cannot add an email address in order to reset your password in the future.": "No identity server is configured so you cannot add an email address in order to reset your password in the future.",
"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?", "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?",
"Use an email address to recover your account": "Use an email address to recover your account", "Use an email address to recover your account": "Use an email address to recover your account",
@ -1998,6 +2014,7 @@
"You are an administrator of this community. You will not be able to rejoin without an invite from another administrator.": "You are an administrator of this community. You will not be able to rejoin without an invite from another administrator.", "You are an administrator of this community. You will not be able to rejoin without an invite from another administrator.": "You are an administrator of this community. You will not be able to rejoin without an invite from another administrator.",
"Leave Community": "Leave Community", "Leave Community": "Leave Community",
"Leave %(groupName)s?": "Leave %(groupName)s?", "Leave %(groupName)s?": "Leave %(groupName)s?",
"Leave": "Leave",
"Unable to leave community": "Unable to leave community", "Unable to leave community": "Unable to leave community",
"Community Settings": "Community Settings", "Community Settings": "Community Settings",
"Want more than a community? <a>Get your own server</a>": "Want more than a community? <a>Get your own server</a>", "Want more than a community? <a>Get your own server</a>": "Want more than a community? <a>Get your own server</a>",
@ -2028,10 +2045,7 @@
"Failed to reject invitation": "Failed to reject invitation", "Failed to reject invitation": "Failed to reject invitation",
"This room is not public. You will not be able to rejoin without an invite.": "This room is not public. You will not be able to rejoin without an invite.", "This room is not public. You will not be able to rejoin without an invite.": "This room is not public. You will not be able to rejoin without an invite.",
"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 leave the room '%(roomName)s'?": "Are you sure you want to leave the room '%(roomName)s'?",
"Failed to leave room": "Failed to leave room", "Failed to forget room %(errCode)s": "Failed to forget room %(errCode)s",
"Can't leave Server Notices room": "Can't leave Server Notices room",
"This room is used for important messages from the Homeserver, so you cannot leave it.": "This room is used for important messages from the Homeserver, so you cannot leave it.",
"Unknown error": "Unknown error",
"Signed Out": "Signed Out", "Signed Out": "Signed Out",
"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, this session has been signed out. Please sign in again.": "For security, this session has been signed out. Please sign in again.",
"Terms and Conditions": "Terms and Conditions", "Terms and Conditions": "Terms and Conditions",
@ -2071,6 +2085,7 @@
"Find a room…": "Find a room…", "Find a room…": "Find a room…",
"Find a room… (e.g. %(exampleRoom)s)": "Find a room… (e.g. %(exampleRoom)s)", "Find a room… (e.g. %(exampleRoom)s)": "Find a room… (e.g. %(exampleRoom)s)",
"If you can't find the room you're looking for, ask for an invite or <a>Create a new room</a>.": "If you can't find the room you're looking for, ask for an invite or <a>Create a new room</a>.", "If you can't find the room you're looking for, ask for an invite or <a>Create a new room</a>.": "If you can't find the room you're looking for, ask for an invite or <a>Create a new room</a>.",
"Explore rooms in %(communityName)s": "Explore rooms in %(communityName)s",
"Clear filter": "Clear filter", "Clear filter": "Clear filter",
"Search rooms": "Search rooms", "Search rooms": "Search rooms",
"You can't send any messages until you review and agree to <consentLink>our terms and conditions</consentLink>.": "You can't send any messages until you review and agree to <consentLink>our terms and conditions</consentLink>.", "You can't send any messages until you review and agree to <consentLink>our terms and conditions</consentLink>.": "You can't send any messages until you review and agree to <consentLink>our terms and conditions</consentLink>.",
@ -2097,6 +2112,7 @@
"Click to mute video": "Click to mute video", "Click to mute video": "Click to mute video",
"Click to unmute audio": "Click to unmute audio", "Click to unmute audio": "Click to unmute audio",
"Click to mute audio": "Click to mute audio", "Click to mute audio": "Click to mute audio",
"Create community": "Create community",
"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 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.", "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.",
"Failed to load timeline position": "Failed to load timeline position", "Failed to load timeline position": "Failed to load timeline position",
@ -2106,6 +2122,7 @@
"Switch to light mode": "Switch to light mode", "Switch to light mode": "Switch to light mode",
"Switch to dark mode": "Switch to dark mode", "Switch to dark mode": "Switch to dark mode",
"Switch theme": "Switch theme", "Switch theme": "Switch theme",
"Notification settings": "Notification settings",
"Security & privacy": "Security & privacy", "Security & privacy": "Security & privacy",
"All settings": "All settings", "All settings": "All settings",
"Feedback": "Feedback", "Feedback": "Feedback",
@ -2203,6 +2220,7 @@
"User Autocomplete": "User Autocomplete", "User Autocomplete": "User Autocomplete",
"Passphrases must match": "Passphrases must match", "Passphrases must match": "Passphrases must match",
"Passphrase must not be empty": "Passphrase must not be empty", "Passphrase must not be empty": "Passphrase must not be empty",
"Unknown error": "Unknown error",
"Export room keys": "Export room keys", "Export room keys": "Export room keys",
"This process allows you to export the keys for messages you have received in encrypted rooms to a local file. You will then be able to import the file into another Matrix client in the future, so that client will also be able to decrypt these messages.": "This process allows you to export the keys for messages you have received in encrypted rooms to a local file. You will then be able to import the file into another Matrix client in the future, so that client will also be able to decrypt these messages.", "This process allows you to export the keys for messages you have received in encrypted rooms to a local file. You will then be able to import the file into another Matrix client in the future, so that client will also be able to decrypt these messages.": "This process allows you to export the keys for messages you have received in encrypted rooms to a local file. You will then be able to import the file into another Matrix client in the future, so that client will also be able to decrypt these messages.",
"The exported file will allow anyone who can read it to decrypt any encrypted messages that you can see, so you should be careful to keep it secure. To help with this, you should enter a passphrase below, which will be used to encrypt the exported data. It will only be possible to import the data by using the same passphrase.": "The exported file will allow anyone who can read it to decrypt any encrypted messages that you can see, so you should be careful to keep it secure. To help with this, you should enter a passphrase below, which will be used to encrypt the exported data. It will only be possible to import the data by using the same passphrase.", "The exported file will allow anyone who can read it to decrypt any encrypted messages that you can see, so you should be careful to keep it secure. To help with this, you should enter a passphrase below, which will be used to encrypt the exported data. It will only be possible to import the data by using the same passphrase.": "The exported file will allow anyone who can read it to decrypt any encrypted messages that you can see, so you should be careful to keep it secure. To help with this, you should enter a passphrase below, which will be used to encrypt the exported data. It will only be possible to import the data by using the same passphrase.",
@ -2241,7 +2259,7 @@
"Retry": "Retry", "Retry": "Retry",
"If you cancel now, you may lose encrypted messages & data if you lose access to your logins.": "If you cancel now, you may lose encrypted messages & data if you lose access to your logins.", "If you cancel now, you may lose encrypted messages & data if you lose access to your logins.": "If you cancel now, you may lose encrypted messages & data if you lose access to your logins.",
"You can also set up Secure Backup & manage your keys in Settings.": "You can also set up Secure Backup & manage your keys in Settings.", "You can also set up Secure Backup & manage your keys in Settings.": "You can also set up Secure Backup & manage your keys in Settings.",
"Set up Secure backup": "Set up Secure backup", "Set up Secure Backup": "Set up Secure Backup",
"Upgrade your encryption": "Upgrade your encryption", "Upgrade your encryption": "Upgrade your encryption",
"Set a Security Phrase": "Set a Security Phrase", "Set a Security Phrase": "Set a Security Phrase",
"Confirm Security Phrase": "Confirm Security Phrase", "Confirm Security Phrase": "Confirm Security Phrase",

View file

@ -858,7 +858,7 @@
"Gift": "Donaco", "Gift": "Donaco",
"Light bulb": "Lampo", "Light bulb": "Lampo",
"Book": "Libro", "Book": "Libro",
"Pencil": "Grifelo", "Pencil": "Krajono",
"Scissors": "Tondilo", "Scissors": "Tondilo",
"Key": "Ŝlosilo", "Key": "Ŝlosilo",
"Hammer": "Martelo", "Hammer": "Martelo",
@ -2387,5 +2387,25 @@
"Enable advanced debugging for the room list": "Ŝalti altnivelan erarserĉadon por la ĉambrobreto", "Enable advanced debugging for the room list": "Ŝalti altnivelan erarserĉadon por la ĉambrobreto",
"* %(senderName)s %(emote)s": "* %(senderName)s %(emote)s", "* %(senderName)s %(emote)s": "* %(senderName)s %(emote)s",
"Custom Tag": "Propra etikedo", "Custom Tag": "Propra etikedo",
"Feedback": "Prikomenti" "Feedback": "Prikomenti",
"The person who invited you already left the room.": "La persono, kiu vin invitis, jam foriris de la ĉambro.",
"The person who invited you already left the room, or their server is offline.": "Aŭ la persono, kiu vin invitis, jam foriris de la ĉambro, aŭ ĝia servilo estas eksterreta.",
"Change notification settings": "Ŝanĝi agordojn pri sciigoj",
"Show message previews for reactions in DMs": "Montri antaŭrigardojn al mesaĝoj ĉe reagoj en rektaj ĉambroj",
"Show message previews for reactions in all rooms": "Montri antaŭrigardojn al mesaĝoj ĉe reagoj en ĉiuj ĉambroj",
"Your server isn't responding to some <a>requests</a>.": "Via servilo ne respondas al iuj <a>petoj</a>.",
"Server isn't responding": "Servilo ne respondas",
"Your server isn't responding to some of your requests. Below are some of the most likely reasons.": "Via servilo ne respondas al iuj el viaj petoj. Vidu sube kelkon de la plej probablaj kialoj.",
"The server (%(serverName)s) took too long to respond.": "La servilo (%(serverName)s) tro longe ne respondis.",
"Your firewall or anti-virus is blocking the request.": "Via fajroŝirmilo aŭ kontraŭvirusilo blokas la peton.",
"A browser extension is preventing the request.": "Kromprogramo de la foliumilo malhelpas la peton.",
"The server is offline.": "La servilo estas eksterreta.",
"The server has denied your request.": "La servilo rifuzis vian peton.",
"Your area is experiencing difficulties connecting to the internet.": "Via loko nun havas problemojn pri interreta konekto.",
"A connection error occurred while trying to contact the server.": "Eraris konekto dum provo kontakti la servilon.",
"The server is not configured to indicate what the problem is (CORS).": "La servilo ne estas agordita por indiki la problemon (CORS).",
"Recent changes that have not yet been received": "Freŝaj ŝanĝoj ankoraŭ ne ricevitaj",
"No files visible in this room": "Neniuj dosieroj videblas en ĉi tiu ĉambro",
"You have no visible notifications in this room.": "Vi havas neniujn videblajn sciigojn en ĉi tiu ĉambro.",
"%(brand)s Android": "%(brand)s por Android"
} }

View file

@ -170,7 +170,7 @@
"Are you sure you want to remove <b>%(serverName)s</b>": "Kas sa oled kindel et soovid eemadlada <b>%(serverName)s</b>", "Are you sure you want to remove <b>%(serverName)s</b>": "Kas sa oled kindel et soovid eemadlada <b>%(serverName)s</b>",
"Remove server": "Eemalda server", "Remove server": "Eemalda server",
"%(networkName)s rooms": "%(networkName)s jututoad", "%(networkName)s rooms": "%(networkName)s jututoad",
"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.": "Kas sa oled kindel et soovid eemaldada (kustutada) seda sündmust? Pane tähele, et see muutus võib tagasi pöörduda, kui muudad hiljem jututoa nime või teemanime.", "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.": "Kas sa oled kindel et soovid eemaldada (kustutada) seda sündmust? Pane tähele, et see muutus võib tagasi pöörduda, kui muudad hiljem jututoa nime või teema nime.",
"Sign out and remove encryption keys?": "Logi välja ja eemalda krüptimisvõtmed?", "Sign out and remove encryption keys?": "Logi välja ja eemalda krüptimisvõtmed?",
"Upload files (%(current)s of %(total)s)": "Lae failid üles (%(current)s / %(total)s)", "Upload files (%(current)s of %(total)s)": "Lae failid üles (%(current)s / %(total)s)",
"Upload files": "Lae failid üles", "Upload files": "Lae failid üles",
@ -650,7 +650,7 @@
"Where youre logged in": "Kus sa oled võrku loginud", "Where youre logged in": "Kus sa oled võrku loginud",
"Manage the names of and sign out of your sessions below or <a>verify them in your User Profile</a>.": "Halda alljärgnevas oma sessioonide nimesid, logi neist välja või <a>verifitseeri neid oma kasutajaprofiilis</a>.", "Manage the names of and sign out of your sessions below or <a>verify them in your User Profile</a>.": "Halda alljärgnevas oma sessioonide nimesid, logi neist välja või <a>verifitseeri neid oma kasutajaprofiilis</a>.",
"A session's public name is visible to people you communicate with": "Sessiooni avalik nimi on nähtav neile, kellega sa suhtled", "A session's public name is visible to people you communicate with": "Sessiooni avalik nimi on nähtav neile, kellega sa suhtled",
"%(brand)s collects anonymous analytics to allow us to improve the application.": "Võimaldamaks meil rakendust parandada kogub %(brand)s anonüümset analüütikat.", "%(brand)s collects anonymous analytics to allow us to improve the application.": "Võimaldamaks meil rakendust parandada kogub %(brand)s anonüümset teavet rakenduse kasutuse kohta.",
"Privacy is important to us, so we don't collect any personal or identifiable data for our analytics.": "Privaatsus on meile oluline ning seega me ei kogu ei isiklikke ega isikustatavaid andmeid.", "Privacy is important to us, so we don't collect any personal or identifiable data for our analytics.": "Privaatsus on meile oluline ning seega me ei kogu ei isiklikke ega isikustatavaid andmeid.",
"Learn more about how we use analytics.": "Loe lisaks kuidas me kasutama analüütikat.", "Learn more about how we use analytics.": "Loe lisaks kuidas me kasutama analüütikat.",
"No media permissions": "Meediaõigused puuduvad", "No media permissions": "Meediaõigused puuduvad",
@ -839,7 +839,7 @@
"Heart": "Süda", "Heart": "Süda",
"Smiley": "Smaili", "Smiley": "Smaili",
"Robot": "Robot", "Robot": "Robot",
"Hat": "Müts", "Hat": "Kübar",
"Glasses": "Prillid", "Glasses": "Prillid",
"Spanner": "Mutrivõti", "Spanner": "Mutrivõti",
"Santa": "Jõuluvana", "Santa": "Jõuluvana",
@ -870,7 +870,7 @@
"Anchor": "Ankur", "Anchor": "Ankur",
"Headphones": "Kõrvaklapid", "Headphones": "Kõrvaklapid",
"Folder": "Kaust", "Folder": "Kaust",
"Pin": "Knopka", "Pin": "Nööpnõel",
"Verify all your sessions to ensure your account & messages are safe": "Selleks et sinu konto ja sõnumid oleks turvatud, verifitseeri kõik oma sessioonid", "Verify all your sessions to ensure your account & messages are safe": "Selleks et sinu konto ja sõnumid oleks turvatud, verifitseeri kõik oma sessioonid",
"Later": "Hiljem", "Later": "Hiljem",
"Review": "Vaata üle", "Review": "Vaata üle",
@ -1025,7 +1025,7 @@
"Permissions": "Õigused", "Permissions": "Õigused",
"Select the roles required to change various parts of the room": "Vali rollid, mis on vajalikud jututoa eri osade muutmiseks", "Select the roles required to change various parts of the room": "Vali rollid, mis on vajalikud jututoa eri osade muutmiseks",
"Enable encryption?": "Kas võtame krüptimise kasutusele?", "Enable encryption?": "Kas võtame krüptimise kasutusele?",
"Once enabled, encryption for a room cannot be disabled. Messages sent in an encrypted room cannot be seen by the server, only by the participants of the room. Enabling encryption may prevent many bots and bridges from working correctly. <a>Learn more about encryption.</a>": "Kui kord juba kasutusele võetud, siis krüptimist enam hiljem ära lõpetada ei saa. Krüptitud sõnumeid ei saa lugeda ei vaheapealses veebiliikluses ega serveris ja vaid jututoa liikmed saavad neid lugeda. Krüptimise kasutusele võtmine takistada nii robotite kui sõnumisildade tööd. <a>Lisateave krüptimise kohta.</a>", "Once enabled, encryption for a room cannot be disabled. Messages sent in an encrypted room cannot be seen by the server, only by the participants of the room. Enabling encryption may prevent many bots and bridges from working correctly. <a>Learn more about encryption.</a>": "Kui kord juba kasutusele võetud, siis krüptimist enam hiljem ära lõpetada ei saa. Krüptitud sõnumeid ei saa lugeda ei vaheapealses veebiliikluses ega serveris ja vaid jututoa liikmed saavad neid lugeda. Krüptimise kasutusele võtmine võib takistada nii robotite kui sõnumisildade tööd. <a>Lisateave krüptimise kohta.</a>",
"Guests cannot join this room even if explicitly invited.": "Külalised ei saa selle jututoaga liituda ka siis, kui neid on otseselt kutsutud.", "Guests cannot join this room even if explicitly invited.": "Külalised ei saa selle jututoaga liituda ka siis, kui neid on otseselt kutsutud.",
"Click here to fix": "Parandamiseks klõpsi siia", "Click here to fix": "Parandamiseks klõpsi siia",
"Server error": "Serveri viga", "Server error": "Serveri viga",
@ -1334,7 +1334,7 @@
"If you cancel now, you won't complete your operation.": "Kui sa katkestad nüüd, siis sul jääb pooleliolev tegevus lõpetamata.", "If you cancel now, you won't complete your operation.": "Kui sa katkestad nüüd, siis sul jääb pooleliolev tegevus lõpetamata.",
"Cancel entering passphrase?": "Kas katkestame paroolifraasi sisestamise?", "Cancel entering passphrase?": "Kas katkestame paroolifraasi sisestamise?",
"Enter passphrase": "Sisesta paroolifraas", "Enter passphrase": "Sisesta paroolifraas",
"Setting up keys": "Võtamevõtmed kasutusele", "Setting up keys": "Võtame krüptovõtmed kasutusele",
"Room name or address": "Jututoa nimi või aadress", "Room name or address": "Jututoa nimi või aadress",
"Unable to enable Notifications": "Teavituste kasutusele võtmine ei õnnestunud", "Unable to enable Notifications": "Teavituste kasutusele võtmine ei õnnestunud",
"This email address was not found": "Seda e-posti aadressi ei leidunud", "This email address was not found": "Seda e-posti aadressi ei leidunud",
@ -2289,8 +2289,8 @@
"All keys backed up": "Kõik krüptovõtmed on varundatud", "All keys backed up": "Kõik krüptovõtmed on varundatud",
"Backup has a <validity>valid</validity> signature from this user": "Varukoopial on selle kasutaja <validity>kehtiv</validity> allkiri", "Backup has a <validity>valid</validity> signature from this user": "Varukoopial on selle kasutaja <validity>kehtiv</validity> allkiri",
"Backup has a <validity>invalid</validity> signature from this user": "Varukoopial on selle kasutaja <validity>vigane</validity> allkiri", "Backup has a <validity>invalid</validity> signature from this user": "Varukoopial on selle kasutaja <validity>vigane</validity> allkiri",
"Backup has a signature from <verify>unknown</verify> user with ID %(deviceId)s": "Varukoopial <verify>tundmatu</verify> kasutaja allkiri seadme tunnusega %(deviceId)s", "Backup has a signature from <verify>unknown</verify> user with ID %(deviceId)s": "Varukoopial on <verify>tundmatu</verify> kasutaja allkiri seadme tunnusega %(deviceId)s",
"Backup has a signature from <verify>unknown</verify> session with ID %(deviceId)s": "Varukoopial <verify>tundmatu</verify> sessiooni allkiri seadme tunnusega %(deviceId)s", "Backup has a signature from <verify>unknown</verify> session with ID %(deviceId)s": "Varukoopial on <verify>tundmatu</verify> sessiooni allkiri seadme tunnusega %(deviceId)s",
"Backup has a <validity>valid</validity> signature from this session": "Varukoopial on selle sessiooni <validity>kehtiv</validity> allkiri", "Backup has a <validity>valid</validity> signature from this session": "Varukoopial on selle sessiooni <validity>kehtiv</validity> allkiri",
"Backup has an <validity>invalid</validity> signature from this session": "Varukoopial on selle sessiooni <validity>vigane</validity> allkiri", "Backup has an <validity>invalid</validity> signature from this session": "Varukoopial on selle sessiooni <validity>vigane</validity> allkiri",
"Backup is not signed by any of your sessions": "Varunduse andmetel pole mitte ühegi sinu sessiooni allkirja", "Backup is not signed by any of your sessions": "Varunduse andmetel pole mitte ühegi sinu sessiooni allkirja",
@ -2403,5 +2403,27 @@
"You have no visible notifications in this room.": "Jututoas pole nähtavaid teavitusi.", "You have no visible notifications in this room.": "Jututoas pole nähtavaid teavitusi.",
"You're all caught up.": "Ei tea... kõik vist on nüüd tehtud.", "You're all caught up.": "Ei tea... kõik vist on nüüd tehtud.",
"Youre all caught up": "Ei tea... kõik vist on nüüd tehtud", "Youre all caught up": "Ei tea... kõik vist on nüüd tehtud",
"%(brand)s Android": "%(brand)s Android" "%(brand)s Android": "%(brand)s Android",
"Show message previews for reactions in DMs": "Näita eelvaates otsesõnumitele regeerimisi",
"Show message previews for reactions in all rooms": "Näita kõikides jututubades eelvaadetes sõnumitele regeerimisi",
"Master private key:": "Üldine privaatvõti:",
"Recent changes that have not yet been received": "Hiljutised muudatused, mis pole veel alla laetud või saabunud",
"Explore public rooms": "Sirvi avalikke jututubasid",
"Forces the current outbound group session in an encrypted room to be discarded": "Sunnib loobuma praeguse krüptitud jututoa rühmavestluse seansist",
"You've previously used %(brand)s on %(host)s with lazy loading of members enabled. In this version lazy loading is disabled. As the local cache is not compatible between these two settings, %(brand)s needs to resync your account.": "Oled varem kasutanud %(brand)s serveriga %(host)s ja lubanud andmete laisa laadimise. Selles versioonis on laisk laadimine keelatud. Kuna kohalik vahemälu nende kahe seadistuse vahel ei ühildu, peab %(brand)s sinu konto uuesti sünkroonima.",
"If the other version of %(brand)s is still open in another tab, please close it as using %(brand)s on the same host with both lazy loading enabled and disabled simultaneously will cause issues.": "Kui %(brand)s teine versioon on mõnel teisel vahekaardil endiselt avatud, palun sulge see. %(brand)s kasutamine samal serveril põhjustab vigu olukorras, kus laisk laadimine on samal ajal lubatud ja keelatud.",
"Data from an older version of %(brand)s 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.": "%(brand)s vanema versiooni andmed on tuvastatud. See kindlasti põhjustab läbiva krüptimise tõrke vanemas versioonis. Läbivalt krüptitud sõnumid, mida on vanema versiooni kasutamise ajal hiljuti vahetatud, ei pruugi selles versioonis olla dekrüptitavad. See võib põhjustada vigu ka selle versiooniga saadetud sõnumite lugemisel. Kui teil tekib probleeme, logige välja ja uuesti sisse. Sõnumite ajaloo säilitamiseks eksportige ja uuesti importige oma krüptovõtmed.",
"Navigation": "Navigeerimine",
"Uploading logs": "Laen üles logisid",
"Downloading logs": "Laen alla logisid",
"Can't see what youre looking for?": "Kas sa ei leia seda, mida otsisid?",
"Explore all public rooms": "Sirvi kõiki avalikke jututubasid",
"%(count)s results|other": "%(count)s tulemust",
"Preparing to download logs": "Valmistun logikirjete allalaadimiseks",
"Download logs": "Lae logikirjed alla",
"Unexpected server error trying to leave the room": "Jututoast lahkumisel tekkis serveris ootamatu viga",
"Error leaving room": "Viga jututoast lahkumisel",
"Communities v2 prototypes. Requires compatible homeserver. Highly experimental - use with caution.": "Kogukondade v2 prototüüp. Eeldab, et koduserver toetab sellist funktsionaalsust. Lahendus on esialgne ja katseline - kui kasutad, siis väga ettevaatlikult.",
"Explore rooms in %(communityName)s": "Uuri jututubasid %(communityName)s kogukonnas",
"Set up Secure Backup": "Võta kasutusele turvaline varundus"
} }

View file

@ -2233,7 +2233,7 @@
"Alt": "Alt", "Alt": "Alt",
"Alt Gr": "Alt Gr", "Alt Gr": "Alt Gr",
"Shift": "Maiús", "Shift": "Maiús",
"Super": "Super", "Super": "Súper",
"Ctrl": "Ctrl", "Ctrl": "Ctrl",
"Toggle Bold": "Activa Resaltar", "Toggle Bold": "Activa Resaltar",
"Toggle Italics": "Activa Cursiva", "Toggle Italics": "Activa Cursiva",
@ -2410,5 +2410,20 @@
"Youre all caught up": "Xa estás ó día", "Youre all caught up": "Xa estás ó día",
"You have no visible notifications in this room.": "Non tes notificacións visibles nesta sala.", "You have no visible notifications in this room.": "Non tes notificacións visibles nesta sala.",
"%(brand)s Android": "%(brand)s Android", "%(brand)s Android": "%(brand)s Android",
"Master private key:": "Chave mestra principal:" "Master private key:": "Chave mestra principal:",
"Show message previews for reactions in DMs": "Mostrar vista previa das mensaxes para reaccións en MDs",
"Show message previews for reactions in all rooms": "Mostrar vista previa das mensaxes para reaccións en todas as salas",
"Explore public rooms": "Explorar salas públicas",
"Uploading logs": "Subindo o rexistro",
"Downloading logs": "Descargando o rexistro",
"Can't see what youre looking for?": "¿Non atopas o que buscas?",
"Explore all public rooms": "Explora todas as salas públicas",
"%(count)s results|other": "%(count)s resultados",
"Preparing to download logs": "Preparándose para descargar rexistro",
"Download logs": "Descargar rexistro",
"Unexpected server error trying to leave the room": "Fallo non agardado no servidor ó intentar saír da sala",
"Error leaving room": "Erro ó saír da sala",
"Communities v2 prototypes. Requires compatible homeserver. Highly experimental - use with caution.": "Prototipos de Comunidades v2. Require un servidor compatible. Característica experimental - usa con tino.",
"Explore rooms in %(communityName)s": "Explorar salas en %(communityName)s",
"Set up Secure Backup": "Configurar Copia de apoio Segura"
} }

View file

@ -811,7 +811,7 @@
"This room is used for important messages from the Homeserver, so you cannot leave it.": "Ez a szoba fontos szerverüzenetek közlésére jött létre, nem tudsz kilépni belőle.", "This room is used for important messages from the Homeserver, so you cannot leave it.": "Ez a szoba fontos szerverüzenetek közlésére jött létre, nem tudsz kilépni belőle.",
"No Audio Outputs detected": "Nem található hang kimenet", "No Audio Outputs detected": "Nem található hang kimenet",
"Audio Output": "Hang kimenet", "Audio Output": "Hang kimenet",
"Share Link to User": "Hivatkozás megosztása felhasználóval", "Share Link to User": "A felhasználóra mutató hivatkozás",
"Share room": "Szoba megosztása", "Share room": "Szoba megosztása",
"Share Room": "Szoba megosztása", "Share Room": "Szoba megosztása",
"Link to most recent message": "A legfrissebb üzenetre hivatkozás", "Link to most recent message": "A legfrissebb üzenetre hivatkozás",
@ -987,7 +987,7 @@
"Send typing notifications": "Gépelés visszajelzés küldése", "Send typing notifications": "Gépelés visszajelzés küldése",
"Enable Community Filter Panel": "Közösségi szűrő panel bekapcsolása", "Enable Community Filter Panel": "Közösségi szűrő panel bekapcsolása",
"Messages containing my username": "Üzenetek amik a nevemet tartalmazzák", "Messages containing my username": "Üzenetek amik a nevemet tartalmazzák",
"The other party cancelled the verification.": "A másik fél törölte az ellenőrzést.", "The other party cancelled the verification.": "A másik fél megszakította az ellenőrzést.",
"Verified!": "Ellenőrizve!", "Verified!": "Ellenőrizve!",
"You've successfully verified this user.": "Sikeresen ellenőrizted ezt a felhasználót.", "You've successfully verified this user.": "Sikeresen ellenőrizted ezt a felhasználót.",
"Secure messages with this user are end-to-end encrypted and not able to be read by third parties.": "Az üzenetek a felhasználóval végponttól végpontig titkosítva vannak és azt más nem tudja elolvasni.", "Secure messages with this user are end-to-end encrypted and not able to be read by third parties.": "Az üzenetek a felhasználóval végponttól végpontig titkosítva vannak és azt más nem tudja elolvasni.",
@ -1630,7 +1630,7 @@
"<strong>%(role)s</strong> in %(roomName)s": "<strong>%(role)s</strong> a szobában: %(roomName)s", "<strong>%(role)s</strong> in %(roomName)s": "<strong>%(role)s</strong> a szobában: %(roomName)s",
"Messages in this room are end-to-end encrypted.": "Az üzenetek a szobában végponttól végpontig titkosítottak.", "Messages in this room are end-to-end encrypted.": "Az üzenetek a szobában végponttól végpontig titkosítottak.",
"Security": "Biztonság", "Security": "Biztonság",
"Verify": "Ellenőriz", "Verify": "Ellenőrzés",
"Any of the following data may be shared:": "Az alábbi adatok közül bármelyik megosztásra kerülhet:", "Any of the following data may be shared:": "Az alábbi adatok közül bármelyik megosztásra kerülhet:",
"Your display name": "Megjelenítési neved", "Your display name": "Megjelenítési neved",
"Your avatar URL": "Profilképed URL-je", "Your avatar URL": "Profilképed URL-je",
@ -1888,7 +1888,7 @@
"You've successfully verified %(displayName)s!": "Sikeresen ellenőrizted a felhasználót: %(displayName)s!", "You've successfully verified %(displayName)s!": "Sikeresen ellenőrizted a felhasználót: %(displayName)s!",
"Got it": "Értem", "Got it": "Értem",
"Encryption enabled": "Titkosítás bekapcsolva", "Encryption enabled": "Titkosítás bekapcsolva",
"Messages in this room are end-to-end encrypted. Learn more & verify this user in their user profile.": "Ebben a szobában az üzenetek végpontok között titkosítottak. További információkért és ellenőrzéshez nyisd meg a felhasználó profilját.", "Messages in this room are end-to-end encrypted. Learn more & verify this user in their user profile.": "Ebben a szobában az üzenetek végpontok között titkosítottak. További információkért és az ellenőrzéshez nyisd meg a felhasználók profiljait!",
"Encryption not enabled": "Titkosítás nincs engedélyezve", "Encryption not enabled": "Titkosítás nincs engedélyezve",
"The encryption used by this room isn't supported.": "A szobában használt titkosítás nem támogatott.", "The encryption used by this room isn't supported.": "A szobában használt titkosítás nem támogatott.",
"Clear all data in this session?": "Minden adat törlése ebben a munkamenetben?", "Clear all data in this session?": "Minden adat törlése ebben a munkamenetben?",
@ -2109,7 +2109,7 @@
"Server did not return valid authentication information.": "A szerver semmilyen érvényes azonosítási információt sem küldött vissza.", "Server did not return valid authentication information.": "A szerver semmilyen érvényes azonosítási információt sem küldött vissza.",
"There was a problem communicating with the server. Please try again.": "A szerverrel való kommunikációval probléma történt. Kérlek próbáld újra.", "There was a problem communicating with the server. Please try again.": "A szerverrel való kommunikációval probléma történt. Kérlek próbáld újra.",
"Sign in with SSO": "Belépés SSO-val", "Sign in with SSO": "Belépés SSO-val",
"Welcome to %(appName)s": "Üdv itt: %(appName)s", "Welcome to %(appName)s": "Üdvözöl az %(appName)s",
"Liberate your communication": "Szabadítsd fel a kommunikációdat", "Liberate your communication": "Szabadítsd fel a kommunikációdat",
"Send a Direct Message": "Közvetlen üzenet küldése", "Send a Direct Message": "Közvetlen üzenet küldése",
"Explore Public Rooms": "Nyilvános szobák felderítése", "Explore Public Rooms": "Nyilvános szobák felderítése",
@ -2177,7 +2177,7 @@
"Waiting for your other session to verify…": "A másik munkameneted ellenőrzésére várunk…", "Waiting for your other session to verify…": "A másik munkameneted ellenőrzésére várunk…",
"You've successfully verified your device!": "Sikeresen ellenőrizted az eszközödet!", "You've successfully verified your device!": "Sikeresen ellenőrizted az eszközödet!",
"Message deleted": "Üzenet törölve", "Message deleted": "Üzenet törölve",
"Message deleted by %(name)s": "%(name)s törölte az üzenetet", "Message deleted by %(name)s": "%(name)s törölte ezt az üzenetet",
"QR Code": "QR kód", "QR Code": "QR kód",
"To continue, use Single Sign On to prove your identity.": "A folytatáshoz a személyazonosságod megerősítéséhez használd az egyszeri bejelentkezést.", "To continue, use Single Sign On to prove your identity.": "A folytatáshoz a személyazonosságod megerősítéséhez használd az egyszeri bejelentkezést.",
"Confirm to continue": "Erősítsd meg a továbblépéshez", "Confirm to continue": "Erősítsd meg a továbblépéshez",
@ -2234,12 +2234,12 @@
"Emoji picker": "Emodzsi választó", "Emoji picker": "Emodzsi választó",
"No recently visited rooms": "Nincsenek nemrégiben meglátogatott szobák", "No recently visited rooms": "Nincsenek nemrégiben meglátogatott szobák",
"People": "Emberek", "People": "Emberek",
"Sort by": "Rendezve:", "Sort by": "Rendezés",
"Unread rooms": "Olvasatlan szobák", "Unread rooms": "Olvasatlan szobák",
"Always show first": "Mindig az elsőt mutatja", "Always show first": "Mindig az elsőt mutatja",
"Show": "Mutat", "Show": "Mutat",
"Message preview": "Üzenet előnézet", "Message preview": "Üzenet előnézet",
"List options": "Lista beállítások", "List options": "Lista beállításai",
"Show %(count)s more|other": "Még %(count)s megjelenítése", "Show %(count)s more|other": "Még %(count)s megjelenítése",
"Show %(count)s more|one": "Még %(count)s megjelenítése", "Show %(count)s more|one": "Még %(count)s megjelenítése",
"Leave Room": "Szoba elhagyása", "Leave Room": "Szoba elhagyása",
@ -2404,5 +2404,14 @@
"Your area is experiencing difficulties connecting to the internet.": "Probléma az Internet elérésben.", "Your area is experiencing difficulties connecting to the internet.": "Probléma az Internet elérésben.",
"A connection error occurred while trying to contact the server.": "Kapcsolati hiba lépett fel miközben a szervert próbáltad elérni.", "A connection error occurred while trying to contact the server.": "Kapcsolati hiba lépett fel miközben a szervert próbáltad elérni.",
"The server is not configured to indicate what the problem is (CORS).": "A szerver nincs beállítva, hogy megmutassa mi okozhatta a hibát (CORS).", "The server is not configured to indicate what the problem is (CORS).": "A szerver nincs beállítva, hogy megmutassa mi okozhatta a hibát (CORS).",
"Recent changes that have not yet been received": "Legutóbbi változások amik még nem érkeztek meg" "Recent changes that have not yet been received": "Legutóbbi változások amik még nem érkeztek meg",
"Show message previews for reactions in DMs": "Üzenet előnézet mutatása a reakcióhoz a közvetlen beszélgetéseknél",
"Show message previews for reactions in all rooms": "Üzenet előnézet mutatása a reakciókhoz minden szobában",
"Master private key:": "Privát elsődleges kulcs:",
"No files visible in this room": "Ebben a szobában nincsenek fájlok",
"Attach files from chat or just drag and drop them anywhere in a room.": "Csatolj fájlt a csevegésből vagy húzd és ejtsd bárhova a szobában.",
"Youre all caught up": "Mindent elolvastál",
"You have no visible notifications in this room.": "Nincsenek látható értesítéseid ebben a szobában.",
"%(brand)s Android": "%(brand)s Android",
"Explore public rooms": "Nyilvános szobák felderítése"
} }

View file

@ -2413,5 +2413,15 @@
"Attach files from chat or just drag and drop them anywhere in a room.": "Allega file dalla chat o trascinali in qualsiasi punto in una stanza.", "Attach files from chat or just drag and drop them anywhere in a room.": "Allega file dalla chat o trascinali in qualsiasi punto in una stanza.",
"Youre all caught up": "Non hai nulla di nuovo da vedere", "Youre all caught up": "Non hai nulla di nuovo da vedere",
"You have no visible notifications in this room.": "Non hai alcuna notifica visibile in questa stanza.", "You have no visible notifications in this room.": "Non hai alcuna notifica visibile in questa stanza.",
"%(brand)s Android": "%(brand)s Android" "%(brand)s Android": "%(brand)s Android",
"Show message previews for reactions in DMs": "Mostra anteprime messaggi per le reazioni nei messaggi diretti",
"Show message previews for reactions in all rooms": "Mostra anteprime messaggi per le reazioni in tutte le stanze",
"Explore public rooms": "Esplora stanze pubbliche",
"Uploading logs": "Invio dei log",
"Downloading logs": "Scaricamento dei log",
"Can't see what youre looking for?": "Non vedi quello che cerchi?",
"Explore all public rooms": "Esplora tutte le stanze pubbliche",
"%(count)s results|other": "%(count)s risultati",
"Preparing to download logs": "Preparazione al download dei log",
"Download logs": "Scarica i log"
} }

View file

@ -579,7 +579,7 @@
"%(severalUsers)sleft %(count)s times|one": "%(severalUsers)s は退出しました", "%(severalUsers)sleft %(count)s times|one": "%(severalUsers)s は退出しました",
"%(oneUser)sleft %(count)s times|other": "%(oneUser)s は %(count)s 回退出しました", "%(oneUser)sleft %(count)s times|other": "%(oneUser)s は %(count)s 回退出しました",
"%(oneUser)sleft %(count)s times|one": "%(oneUser)s は退出しました", "%(oneUser)sleft %(count)s times|one": "%(oneUser)s は退出しました",
"%(severalUsers)sjoined and left %(count)s times|other": "%(severalUsers)s が%(count)s 回参加し、退出した", "%(severalUsers)sjoined and left %(count)s times|other": "%(severalUsers)s が %(count)s 回参加し、退出しました",
"%(severalUsers)sjoined and left %(count)s times|one": "%(severalUsers)s は参加して退出しました", "%(severalUsers)sjoined and left %(count)s times|one": "%(severalUsers)s は参加して退出しました",
"%(oneUser)sjoined and left %(count)s times|other": "%(oneUser)s が %(count)s 回参加し退出しました", "%(oneUser)sjoined and left %(count)s times|other": "%(oneUser)s が %(count)s 回参加し退出しました",
"%(oneUser)sjoined and left %(count)s times|one": "%(oneUser)s が参加し退出しました", "%(oneUser)sjoined and left %(count)s times|one": "%(oneUser)s が参加し退出しました",
@ -668,7 +668,7 @@
"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": "古いバージョンの部屋でのユーザーの発言を停止し、新しい部屋に移動するようユーザーに通知するメッセージを投稿する",
"Mention": "記載", "Mention": "記載",
"%(severalUsers)shad their invitations withdrawn %(count)s times|other": "%(severalUsers)s が %(count)s 回招待を撤回した", "%(severalUsers)shad their invitations withdrawn %(count)s times|other": "%(severalUsers)s が %(count)s 回招待を取り消しました",
"was unbanned %(count)s times|one": "ブロック解除されました", "was unbanned %(count)s times|one": "ブロック解除されました",
"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": "新しい部屋の始めに古い部屋にリンクを張って、人々が古いメッセージを見ることができるようにする",
"Sign out": "サインアウト", "Sign out": "サインアウト",
@ -1373,5 +1373,19 @@
"Show %(count)s more|one": "さらに %(count)s 件を表示", "Show %(count)s more|one": "さらに %(count)s 件を表示",
"%(num)s minutes ago": "%(num)s 分前", "%(num)s minutes ago": "%(num)s 分前",
"%(num)s hours ago": "%(num)s 時間前", "%(num)s hours ago": "%(num)s 時間前",
"%(num)s days ago": "%(num)s 日前" "%(num)s days ago": "%(num)s 日前",
"Favourited": "お気に入り登録中",
"Room options": "部屋の設定",
"Ignored users": "無視しているユーザー",
"Show tray icon and minimize window to it on close": "トレイアイコンを表示しウィンドウを閉じても最小化して待機する",
"This message cannot be decrypted": "メッセージが復号できません",
"Unencrypted": "暗号化されていません",
"Encrypted by a deleted session": "削除済みのセッションによる暗号化",
"Scroll to most recent messages": "最新のメッセージを表示",
"Emoji picker": "絵文字を選択",
"All rooms": "全ての部屋",
"Your server": "あなたのサーバー",
"Matrix": "Matrix",
"Add a new server": "新しいサーバーを追加",
"Server name": "サーバー名"
} }

File diff suppressed because it is too large Load diff

View file

@ -1407,5 +1407,14 @@
"Sign in to your Matrix account on %(serverName)s": "Logg inn på Matrix-kontoen din på %(serverName)s", "Sign in to your Matrix account on %(serverName)s": "Logg inn på Matrix-kontoen din på %(serverName)s",
"Sign in to your Matrix account on <underlinedServerName />": "Logg inn på Matrix-kontoen din på <underlinedServerName />", "Sign in to your Matrix account on <underlinedServerName />": "Logg inn på Matrix-kontoen din på <underlinedServerName />",
"If you've joined lots of rooms, this might take a while": "Hvis du har blitt med i mange rom, kan dette ta en stund", "If you've joined lots of rooms, this might take a while": "Hvis du har blitt med i mange rom, kan dette ta en stund",
"Your new session is now verified. It has access to your encrypted messages, and other users will see it as trusted.": "Den nye økten din er nå verifisert. Den har tilgang til dine krypterte meldinger, og andre brukere vil se at den blir stolt på." "Your new session is now verified. It has access to your encrypted messages, and other users will see it as trusted.": "Den nye økten din er nå verifisert. Den har tilgang til dine krypterte meldinger, og andre brukere vil se at den blir stolt på.",
"%(senderName)s made future room history visible to all room members, from the point they are invited.": "%(senderName)s gjorde fremtidig romhistorikk synlig for alle rommedlemmer, fra det tidspunktet de ble/blir invitert.",
"%(senderName)s made future room history visible to all room members, from the point they joined.": "%(senderName)s gjorde fremtidig romhistorikk synlig for alle rommedlemmer, fra det tidspunktet de ble med.",
"%(senderName)s made future room history visible to all room members.": "%(senderName)s gjorde fremtidig romhistorikk synlig for alle rommedlemmer.",
"%(senderName)s made future room history visible to anyone.": "%(senderName)s gjorde fremtidig romhistorikk synlig for alle.",
"%(senderName)s made future room history visible to unknown (%(visibility)s).": "%(senderName)s gjorde fremtidig romhistorikk synlig for alle rommedlemmer (%(visibility)s).",
"To return to your account in future you need to set a password": "For å komme tilbake til kontoen din senere, må du velge et passord",
"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)": "Vennligst glem alle meldingene jeg har sendt når kontoen min er deaktivert (<b>Advarsel:</b> Dette vil føre til at fremtidige brukere ser en ufullstendig visning av samtaler)",
"To help us prevent this in future, please <a>send us logs</a>.": "For å hjelpe oss med å forhindre dette i fremtiden, vennligst <a>send oss loggfiler</a>.",
"No identity server is configured so you cannot add an email address in order to reset your password in the future.": "Ingen identitetstjener er satt opp, så du kan ikke bruke en E-postadresse til å tilbakestille passordet ditt senere."
} }

View file

@ -59,5 +59,284 @@
"This Room": "Aquesta sala", "This Room": "Aquesta sala",
"All Rooms": "Totas les salas", "All Rooms": "Totas les salas",
"Search…": "Cercar…", "Search…": "Cercar…",
"Server error": "Error servidor" "Server error": "Error servidor",
"Single Sign On": "Autentificacion unica",
"Confirm": "Confirmar",
"Dismiss": "Far desaparéisser",
"OK": "Dacòrdi",
"Continue": "Contunhar",
"Go Back": "En arrièr",
"Cancel": "Anullar",
"Sun": "Dg",
"Mon": "Dl",
"Tue": "Dm",
"Wed": "Dc",
"Thu": "Dj",
"Fri": "Dv",
"Sat": "Ds",
"Jan": "Gen",
"Feb": "Febr",
"Mar": "Març",
"Apr": "Abr",
"May": "mai",
"Jun": "Junh",
"Jul": "Julh",
"Aug": "Ago",
"Sep": "Set",
"Oct": "Oct",
"Nov": "Nov",
"Dec": "Dec",
"PM": "PM",
"AM": "AM",
"Trust": "Aprovacion",
"Sign In": "Se connectar",
"Default": "Predefinit",
"Moderator": "Moderator",
"Admin": "Admin",
"Operation failed": "L'operacion a fracassat",
"Messages": "Messatges",
"Actions": "Accions",
"Advanced": "Avançat",
"Other": "Autre",
"Usage": "Usatge",
"Command failed": "La comanda a fracassat",
"Thank you!": "Mercés !",
"Reason": "Rason",
"Light": "Clar",
"Dark": "Escur",
"Review": "Reveire",
"Notifications": "Notificacions",
"Close": "Tampar",
"Ok": "Validar",
"Set up": "Parametrar",
"Upgrade": "Metre a jorn",
"Verify": "Verificar",
"Update": "Mesa a jorn",
"Restart": "Reaviar",
"Font size": "Talha de poliça",
"Incoming video call": "Sonada vidèo entranta",
"Incoming call": "Sonada entranta",
"Accept": "Acceptar",
"Start": "Començament",
"Cancelling…": "Anullacion...",
"Fish": "Pes",
"Butterfly": "Parpalhòl",
"Tree": "Arborescéncia",
"Cloud": "Nívol",
"Apple": "Apple",
"Heart": "Còr",
"Clock": "Relòtge",
"Pencil": "Gredon",
"Scissors": "Cisèus intelligents",
"Lock": "Verrolhar",
"Key": "Clau",
"Telephone": "Telefòn",
"Trophy": "Trophy",
"Ball": "Balas",
"Anchor": "Ancorar",
"Headphones": "Escotadors",
"Folder": "Dorsièr",
"Pin": "Penjar",
"Upload": "Enviar",
"Show less": "Ne veire mens",
"Show more": "Ne veire mai",
"Current password": "Senhal actual",
"New Password": "Senhal novèl",
"Confirm password": "Confirmar lo senhal",
"Change Password": "Modificar senhal",
"not found": "pas trobat",
"exists": "existís",
"Authentication": "Autentificacion",
"ID": "ID",
"Manage": "Manage",
"Enable": "Activar",
"Restore from Backup": "Restablir a partir de l'archiu",
"Keywords": "Mots clau",
"Clear notifications": "Escafar",
"Off": "Atudat",
"Display Name": "Nom d'afichatge",
"Save": "Salvagardar",
"Disconnect": "Se desconnectar",
"Go back": "Precedent",
"Change": "Cambiar",
"Theme": "Tèma",
"Compact": "Ordenador",
"Success": "Succès",
"Profile": "Perfil",
"Account": "Compte",
"General": "General",
"Legal": "Legal",
"Credits": "Crèdits",
"FAQ": "FAQ",
"Keyboard Shortcuts": "Acorchis de clavièr",
"Versions": "Versions",
"Unsubscribe": "Se desabonar",
"Ignore": "Ignorar",
"Subscribe": "S'inscriure",
"Preferences": "Preferéncias",
"Composer": "Compositor",
"Timeline": "Axe temporal",
"Unignore": "Ignorar pas",
"Security & Privacy": "Seguretat e vida privada",
"Audio Output": "Sortida àudio",
"Microphone": "Microfòn",
"Camera": "Aparelh de fotografiar",
"Bridges": "Bridges",
"Sounds": "Sons",
"Reset": "Recomençar",
"Browse": "Percórrer",
"Unban": "Reabilitar",
"Permissions": "Permissions",
"Encryption": "Chiframent",
"Encrypted": "Chifrat",
"Complete": "Acabat",
"Revoke": "Revocar",
"Share": "Partiment",
"Add": "Ajustar",
"Phone Number": "Numèro de telefòn",
"Mod": "Moderador",
"Unencrypted": "Pas chifrat",
"Hangup": "Penjar",
"Italics": "Italicas",
"Strikethrough": "Raiat",
"Invites": "Convits",
"People": "Gent",
"Historical": "Istoric",
"Sign Up": "Sinscriure",
"Appearance": "Aparéncia",
"Sort by": "Triar per",
"Activity": "Activitat",
"A-Z": "A-Z",
"List options": "Opcions de lista",
"Favourite": "Favorit",
"Low Priority": "Prioritat bassa",
"Mark all as read": "Tot marcar coma legit",
"Members": "Participants",
"Trusted": "Fisable",
"Not trusted": "Pas securizat",
"Invite": "Convidar",
"Demote": "Retrogradar",
"Kick": "Forabandir",
"Ban": "Bandir",
"Are you sure?": "O volètz vertadièrament?",
"Security": "Seguretat",
"Yes": "Òc",
"Got it": "Ai comprés",
"Sunday": "Dimenge",
"Monday": "Diluns",
"Tuesday": "Dimars",
"Wednesday": "Dimècres",
"Thursday": "Dijòus",
"Friday": "Divendres",
"Saturday": "Dissabte",
"Today": "Uèi",
"Yesterday": "Ièr",
"View Source": "Veire la font",
"Reply": "Respondre",
"Edit": "Editar",
"Attachment": "Pèça junta",
"Show image": "Afichar l'imatge",
"Show all": "O mostrar tot",
"Failed to copy": "Impossible de copiar",
"Smileys & People": "Emoticònas e personatges",
"Animals & Nature": "Animals e natura",
"Food & Drink": "Noiridura e bevenda",
"Activities": "Activitats",
"Travel & Places": "Viatges e luòcs",
"Objects": "Objèctes",
"Symbols": "Simbòls",
"Flags": "Marcadors",
"Categories": "Categorias",
"Cancel search": "Anullar la recèrca",
"More options": "Autras opcions",
"Join": "Jónher",
"No results": "Pas cap de resultat",
"Rotate Left": "Pivotar cap a èrra",
"Rotate Right": "Pivotar cap a drecha",
"Rotate clockwise": "Pivotar dins lo sens de las agulhas d'un relòtge",
"Add User": "Apondre un utilizaire",
"Matrix": "Matritz",
"Server name": "Títol del servidor",
"email address": "adreça de messatjariá",
"Notes": "Nòtas",
"Unavailable": "Pas disponible",
"Changelog": "Istoric dels cambiaments (Changelog)",
"Removing…": "Supression en cors…",
"Example": "Exemple",
"example": "exemple",
"Create": "Crear",
"Name": "Escais",
"Sign out": "Se desconnectar",
"Back": "Precedenta",
"Send": "Mandar",
"Toolbox": "Bóstia d'aisinas",
"Developer Tools": "Aisinas de desvolopament",
"An error has occurred.": "Una error s'es producha.",
"Suggestions": "Prepausicions",
"Go": "Validar",
"Session name": "Nom de session",
"Your password": "Vòstre senhal",
"Refresh": "Actualizada",
"Email address": "Adreça de corrièl",
"Skip": "Ignorar",
"Checking...": "Verificacion en cors...",
"Copy": "Copiar",
"Terms of Service": "Terms of Service",
"Service": "Servici",
"Summary": "Resumit",
"Document": "Document",
"Next": "Seguent",
"Upload files": "Mandar de fichièrs",
"Allow": "Autorizar",
"Deny": "Refusar",
"Custom": "Personalizada",
"Address (optional)": "Adreça (opcionala)",
"Leave": "Quitar",
"Forget": "Doblidar",
"Hide": "Amagar",
"Home": "Dorsièr personal",
"Sign in": "Connexion",
"Reload": "Tornar cargar",
"Away": "Absent",
"Submit": "Mandar",
"Enter password": "Sasissètz lo senhal",
"Email": "Corrièl",
"Username": "Nom d'_utilizaire",
"Phone": "Telefòn",
"Passwords don't match": "Los senhals correspondon pas",
"Register": "S'enregistrar",
"Free": "Liure",
"Premium": "De la melhora qualitat",
"Everyone": "Tot lo monde",
"Description": "descripcion",
"Unknown error": "Error desconeguda",
"Logout": "Desconnexion",
"Preview": "Apercebut",
"View": "Visualizacion",
"Search failed": "La recèrca a fracassat",
"Room": "Sala",
"Feedback": "Comentaris",
"Incorrect password": "Senhal incorrècte",
"Commands": "Comandas",
"Emoji": "Emoji",
"Users": "Utilizaires",
"Export": "Exportar",
"Import": "Importar",
"Restore": "Restablir",
"Download": "Telecargament",
"Retry": "Tornar ensajar",
"Success!": "Capitada!",
"Navigation": "Navigacion",
"Alt": "Alt",
"Alt Gr": "Alt Gr",
"Shift": "Descalatge",
"Super": "Super",
"Ctrl": "Ctrl",
"Upload a file": "Actualizar un fichièr",
"Page Up": "Pagina precedenta",
"Page Down": "Pagina seguenta",
"Esc": "Escap",
"Enter": "Entrada",
"Space": "Espaci",
"End": "Fin"
} }

View file

@ -20,7 +20,7 @@
"Current password": "Senha atual", "Current password": "Senha atual",
"Deactivate Account": "Desativar minha conta", "Deactivate Account": "Desativar minha conta",
"Default": "Padrão", "Default": "Padrão",
"Deops user with given id": "Retirar função de moderador do usuário com o identificador informado", "Deops user with given id": "Retirar nível de moderador do usuário com o identificador informado",
"Displays action": "Visualizar atividades", "Displays action": "Visualizar atividades",
"Emoji": "Emoji", "Emoji": "Emoji",
"Error": "Erro", "Error": "Erro",
@ -39,7 +39,7 @@
"Historical": "Histórico", "Historical": "Histórico",
"Homeserver is": "Servidor padrão é", "Homeserver is": "Servidor padrão é",
"Identity Server is": "O servidor de identificação é", "Identity Server is": "O servidor de identificação é",
"I have verified my email address": "Eu verifiquei o meu endereço de e-mail", "I have verified my email address": "Eu confirmei o meu endereço de e-mail",
"Import E2E room keys": "Importar chave de criptografia ponta-a-ponta (E2E) da sala", "Import E2E room keys": "Importar chave de criptografia ponta-a-ponta (E2E) da sala",
"Invalid Email Address": "Endereço de e-mail inválido", "Invalid Email Address": "Endereço de e-mail inválido",
"Invites": "Convidar", "Invites": "Convidar",
@ -62,7 +62,7 @@
"Passwords can't be empty": "As senhas não podem estar em branco", "Passwords can't be empty": "As senhas não podem estar em branco",
"Permissions": "Permissões", "Permissions": "Permissões",
"Phone": "Telefone", "Phone": "Telefone",
"Please check your email and click on the link it contains. Once this is done, click continue.": "Por favor, verifique o seu e-mail e clique no link enviado. Feito isso, clique em continuar.", "Please check your email and click on the link it contains. Once this is done, click continue.": "Por favor, confirme o seu e-mail e clique no link enviado. Feito isso, clique em continuar.",
"Privileged Users": "Usuárias/os privilegiadas/os", "Privileged Users": "Usuárias/os privilegiadas/os",
"Profile": "Perfil", "Profile": "Perfil",
"Reject invitation": "Recusar o convite", "Reject invitation": "Recusar o convite",
@ -85,20 +85,20 @@
"This room is not accessible by remote Matrix servers": "Esta sala não é acessível para servidores Matrix remotos", "This room is not accessible by remote Matrix servers": "Esta sala não é acessível para servidores Matrix remotos",
"Unable to add email address": "Não foi possível adicionar um endereço de e-mail", "Unable to add email address": "Não foi possível adicionar um endereço de e-mail",
"Unable to remove contact information": "Não foi possível remover informação de contato", "Unable to remove contact information": "Não foi possível remover informação de contato",
"Unable to verify email address.": "Não foi possível verificar o endereço de e-mail.", "Unable to verify email address.": "Não foi possível confirmar o endereço de e-mail.",
"Unban": "Remover banimento", "Unban": "Remover banimento",
"unknown error code": "código de erro desconhecido", "unknown error code": "código de erro desconhecido",
"Upload avatar": "Enviar uma foto de perfil", "Upload avatar": "Enviar uma foto de perfil",
"Upload file": "Enviar arquivo", "Upload file": "Enviar arquivo",
"Users": "Usuários", "Users": "Usuários",
"Verification Pending": "Verificação pendente", "Verification Pending": "Confirmação pendente",
"Video call": "Chamada de vídeo", "Video call": "Chamada de vídeo",
"Voice call": "Chamada de voz", "Voice call": "Chamada de voz",
"VoIP conference finished.": "Chamada em grupo encerrada.", "VoIP conference finished.": "Chamada em grupo encerrada.",
"VoIP conference started.": "Chamada em grupo iniciada.", "VoIP conference started.": "Chamada em grupo iniciada.",
"Who can access this room?": "Quem pode acessar esta sala?", "Who can access this room?": "Quem pode acessar esta sala?",
"Who can read history?": "Quem pode ler o histórico da sala?", "Who can read history?": "Quem pode ler o histórico da sala?",
"You do not have permission to post to this room": "Você não tem permissão de postar nesta sala", "You do not have permission to post to this room": "Você não tem permissão para digitar nesta sala",
"You have no visible notifications": "Voce não possui notificações visíveis", "You have no visible notifications": "Voce não possui notificações visíveis",
"Sun": "Dom", "Sun": "Dom",
"Mon": "Seg", "Mon": "Seg",
@ -135,7 +135,7 @@
"Existing Call": "Chamada em andamento", "Existing Call": "Chamada em andamento",
"Failed to send email": "Não foi possível enviar e-mail", "Failed to send email": "Não foi possível enviar e-mail",
"Failed to send request.": "Não foi possível mandar requisição.", "Failed to send request.": "Não foi possível mandar requisição.",
"Failed to verify email address: make sure you clicked the link in the email": "Falha ao verificar o endereço de e-mail: certifique-se de clicar no link do e-mail", "Failed to verify email address: make sure you clicked the link in the email": "Falha ao confirmar o endereço de e-mail: certifique-se de clicar no link do e-mail",
"Failure to create room": "Não foi possível criar a sala", "Failure to create room": "Não foi possível criar a sala",
"%(userId)s from %(fromPowerLevel)s to %(toPowerLevel)s": "%(userId)s de %(fromPowerLevel)s para %(toPowerLevel)s", "%(userId)s from %(fromPowerLevel)s to %(toPowerLevel)s": "%(userId)s de %(fromPowerLevel)s para %(toPowerLevel)s",
"%(senderName)s invited %(targetName)s.": "%(senderName)s convidou %(targetName)s.", "%(senderName)s invited %(targetName)s.": "%(senderName)s convidou %(targetName)s.",
@ -156,7 +156,7 @@
"%(senderName)s removed their display name (%(oldDisplayName)s).": "%(senderName)s removeu o nome e sobrenome (%(oldDisplayName)s).", "%(senderName)s removed their display name (%(oldDisplayName)s).": "%(senderName)s removeu o nome e sobrenome (%(oldDisplayName)s).",
"%(senderName)s removed their profile picture.": "%(senderName)s removeu a foto de perfil.", "%(senderName)s removed their profile picture.": "%(senderName)s removeu a foto de perfil.",
"%(senderName)s requested a VoIP conference.": "%(senderName)s deseja iniciar uma chamada em grupo.", "%(senderName)s requested a VoIP conference.": "%(senderName)s deseja iniciar uma chamada em grupo.",
"%(brand)s does not have permission to send you notifications - please check your browser settings": "%(brand)s não tem permissão para lhe enviar notificações - verifique as configurações do seu navegador", "%(brand)s does not have permission to send you notifications - please check your browser settings": "%(brand)s não tem permissão para lhe enviar notificações - confirme as configurações do seu navegador",
"%(brand)s was not given permission to send notifications - please try again": "%(brand)s não tem permissão para lhe enviar notificações - tente novamente", "%(brand)s was not given permission to send notifications - please try again": "%(brand)s não tem permissão para lhe enviar notificações - tente novamente",
"Room %(roomId)s not visible": "A sala %(roomId)s não está visível", "Room %(roomId)s not visible": "A sala %(roomId)s não está visível",
"%(senderDisplayName)s sent an image.": "%(senderDisplayName)s enviou uma imagem.", "%(senderDisplayName)s sent an image.": "%(senderDisplayName)s enviou uma imagem.",
@ -168,7 +168,7 @@
"The remote side failed to pick up": "A pessoa não atendeu a chamada", "The remote side failed to pick up": "A pessoa não atendeu a chamada",
"This room is not recognised.": "Esta sala não é reconhecida.", "This room is not recognised.": "Esta sala não é reconhecida.",
"This phone number is already in use": "Este número de telefone já está sendo usado", "This phone number is already in use": "Este número de telefone já está sendo usado",
"To use it, just wait for autocomplete results to load and tab through them.": "Para usar esta funcionalidade, aguarde o carregamento dos resultados de autocompletar e então escolha entre as opções.", "To use it, just wait for autocomplete results to load and tab through them.": "Para usar este recurso, aguarde o carregamento dos resultados de autocompletar e então escolha entre as opções.",
"%(senderName)s unbanned %(targetName)s.": "%(senderName)s removeu o banimento de %(targetName)s.", "%(senderName)s unbanned %(targetName)s.": "%(senderName)s removeu o banimento de %(targetName)s.",
"Unable to capture screen": "Não foi possível capturar a imagem da tela", "Unable to capture screen": "Não foi possível capturar a imagem da tela",
"Unable to enable Notifications": "Não foi possível ativar as notificações", "Unable to enable Notifications": "Não foi possível ativar as notificações",
@ -217,7 +217,7 @@
"Failed to reject invite": "Não foi possível recusar o convite", "Failed to reject invite": "Não foi possível recusar o convite",
"Failed to set display name": "Falha ao definir o nome e sobrenome", "Failed to set display name": "Falha ao definir o nome e sobrenome",
"Fill screen": "Tela cheia", "Fill screen": "Tela cheia",
"Incorrect verification code": "Código de verificação incorreto", "Incorrect verification code": "Código de confirmação incorreto",
"Join Room": "Ingressar na sala", "Join Room": "Ingressar na sala",
"Jump to first unread message.": "Ir diretamente para a primeira das mensagens não lidas.", "Jump to first unread message.": "Ir diretamente para a primeira das mensagens não lidas.",
"Kick": "Remover da sala", "Kick": "Remover da sala",
@ -285,7 +285,7 @@
"Add User": "Adicionar usuária(o)", "Add User": "Adicionar usuária(o)",
"Custom Server Options": "Opções para Servidor Personalizado", "Custom Server Options": "Opções para Servidor Personalizado",
"Dismiss": "Descartar", "Dismiss": "Descartar",
"Please check your email to continue registration.": "Por favor, verifique o seu e-mail para continuar a inscrição.", "Please check your email to continue registration.": "Por favor, confirme o seu e-mail para continuar a inscrição.",
"Token incorrect": "Token incorreto", "Token incorrect": "Token incorreto",
"Please enter the code it contains:": "Por favor, entre com o código que está na mensagem:", "Please enter the code it contains:": "Por favor, entre com o código que está na mensagem:",
"powered by Matrix": "oferecido por Matrix", "powered by Matrix": "oferecido por Matrix",
@ -310,13 +310,13 @@
"Incorrect username and/or password.": "Nome de usuário e/ou senha incorreto.", "Incorrect username and/or password.": "Nome de usuário e/ou senha incorreto.",
"Invited": "Convidada(o)", "Invited": "Convidada(o)",
"Results from DuckDuckGo": "Resultados de DuckDuckGo", "Results from DuckDuckGo": "Resultados de DuckDuckGo",
"Verified key": "Chave verificada", "Verified key": "Chave confirmada",
"%(senderDisplayName)s removed the room avatar.": "%(senderDisplayName)s removeu a foto da sala.", "%(senderDisplayName)s removed the room avatar.": "%(senderDisplayName)s removeu a foto da sala.",
"%(senderDisplayName)s changed the avatar for %(roomName)s": "%(senderDisplayName)s alterou a foto da sala %(roomName)s", "%(senderDisplayName)s changed the avatar for %(roomName)s": "%(senderDisplayName)s alterou a foto da sala %(roomName)s",
"%(senderDisplayName)s changed the room avatar to <img/>": "%(senderDisplayName)s alterou a foto da sala para <img/>", "%(senderDisplayName)s changed the room avatar to <img/>": "%(senderDisplayName)s alterou a foto da sala para <img/>",
"No Microphones detected": "Não foi detectado nenhum microfone", "No Microphones detected": "Não foi detectado nenhum microfone",
"No Webcams detected": "Nenhuma câmera detectada", "No Webcams detected": "Nenhuma câmera detectada",
"No media permissions": "Não há permissões de uso de vídeo/áudio no seu navegador", "No media permissions": "Não tem permissões para acessar a mídia",
"You may need to manually permit %(brand)s to access your microphone/webcam": "Pode ser necessário permitir manualmente ao %(brand)s acessar seu microfone ou sua câmera", "You may need to manually permit %(brand)s to access your microphone/webcam": "Pode ser necessário permitir manualmente ao %(brand)s acessar seu microfone ou sua câmera",
"Default Device": "Aparelho padrão", "Default Device": "Aparelho padrão",
"Microphone": "Microfone", "Microphone": "Microfone",
@ -338,7 +338,7 @@
"Uploading %(filename)s and %(count)s others|one": "Enviando o arquivo %(filename)s e %(count)s outros arquivos", "Uploading %(filename)s and %(count)s others|one": "Enviando o arquivo %(filename)s e %(count)s outros arquivos",
"Uploading %(filename)s and %(count)s others|other": "Enviando o arquivo %(filename)s e %(count)s outros arquivos", "Uploading %(filename)s and %(count)s others|other": "Enviando o arquivo %(filename)s e %(count)s outros arquivos",
"Username invalid: %(errMessage)s": "Nome de usuário inválido: %(errMessage)s", "Username invalid: %(errMessage)s": "Nome de usuário inválido: %(errMessage)s",
"You must <a>register</a> to use this functionality": "Você deve <a>se registrar</a> para poder usar esta funcionalidade", "You must <a>register</a> to use this functionality": "Você deve <a>se registrar</a> para usar este recurso",
"Create new room": "Criar nova sala", "Create new room": "Criar nova sala",
"Room directory": "Lista pública de salas", "Room directory": "Lista pública de salas",
"Start chat": "Iniciar conversa", "Start chat": "Iniciar conversa",
@ -380,7 +380,7 @@
"(no answer)": "(sem resposta)", "(no answer)": "(sem resposta)",
"(unknown failure: %(reason)s)": "(falha desconhecida: %(reason)s)", "(unknown failure: %(reason)s)": "(falha desconhecida: %(reason)s)",
"Your browser does not support the required cryptography extensions": "O seu navegador não suporta as extensões de criptografia necessárias", "Your browser does not support the required cryptography extensions": "O seu navegador não suporta as extensões de criptografia necessárias",
"Not a valid %(brand)s keyfile": "Não é um arquivo de chaves %(brand)s válido", "Not a valid %(brand)s keyfile": "Não é um arquivo de chave válido do %(brand)s",
"Authentication check failed: incorrect password?": "Falha ao checar a autenticação: senha incorreta?", "Authentication check failed: incorrect password?": "Falha ao checar a autenticação: senha incorreta?",
"Do you want to set an email address?": "Você deseja definir um endereço de e-mail?", "Do you want to set an email address?": "Você deseja definir um endereço de e-mail?",
"This will allow you to reset your password and receive notifications.": "Isso permitirá que você redefina sua senha e receba notificações.", "This will allow you to reset your password and receive notifications.": "Isso permitirá que você redefina sua senha e receba notificações.",
@ -394,7 +394,7 @@
"Failed to invite the following users to %(groupId)s:": "Falha ao convidar os seguintes usuários para %(groupId)s:", "Failed to invite the following users to %(groupId)s:": "Falha ao convidar os seguintes usuários para %(groupId)s:",
"Failed to add the following rooms to %(groupId)s:": "Falha ao adicionar as seguintes salas em %(groupId)s:", "Failed to add the following rooms to %(groupId)s:": "Falha ao adicionar as seguintes salas em %(groupId)s:",
"You are not in this room.": "Você não está nesta sala.", "You are not in this room.": "Você não está nesta sala.",
"You do not have permission to do that in this room.": "Você não tem permissão para fazer isto nesta sala.", "You do not have permission to do that in this room.": "Você não tem permissão para fazer isso nesta sala.",
"Ignored user": "Usuário bloqueado", "Ignored user": "Usuário bloqueado",
"You are no longer ignoring %(userId)s": "Você não está mais bloqueando %(userId)s", "You are no longer ignoring %(userId)s": "Você não está mais bloqueando %(userId)s",
"Edit": "Editar", "Edit": "Editar",
@ -411,7 +411,7 @@
"Call Failed": "A chamada falhou", "Call Failed": "A chamada falhou",
"PM": "PM", "PM": "PM",
"AM": "AM", "AM": "AM",
"%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s": "%(weekDayName)s, %(day)s de %(monthName)s de%(fullYear)s", "%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s": "%(weekDayName)s, %(day)s de %(monthName)s de %(fullYear)s",
"Who would you like to add to this community?": "Quem você gostaria de adicionar a esta comunidade?", "Who would you like to add to this community?": "Quem você gostaria de adicionar a esta comunidade?",
"Warning: any person you add to a community will be publicly visible to anyone who knows the community ID": "Atenção: qualquer pessoa que você adicionar a esta comunidade estará publicamente visível para todas as pessoas que conheçam o ID da comunidade", "Warning: any person you add to a community will be publicly visible to anyone who knows the community ID": "Atenção: qualquer pessoa que você adicionar a esta comunidade estará publicamente visível para todas as pessoas que conheçam o ID da comunidade",
"Invite new community members": "Convidar novos integrantes para a comunidade", "Invite new community members": "Convidar novos integrantes para a comunidade",
@ -449,8 +449,8 @@
"Jump to read receipt": "Ir para a confirmação de leitura", "Jump to read receipt": "Ir para a confirmação de leitura",
"Mention": "Mencionar", "Mention": "Mencionar",
"Invite": "Convidar", "Invite": "Convidar",
"Send an encrypted reply…": "Enviar uma resposta criptografada…", "Send an encrypted reply…": "Digite sua resposta criptografada…",
"Send an encrypted message…": "Enviar mensagem criptografada…", "Send an encrypted message…": "Digite uma mensagem criptografada…",
"Jump to message": "Pular para mensagem", "Jump to message": "Pular para mensagem",
"No pinned messages.": "Não há mensagens fixas.", "No pinned messages.": "Não há mensagens fixas.",
"Loading...": "Carregando...", "Loading...": "Carregando...",
@ -464,14 +464,14 @@
"Offline for %(duration)s": "Desconectado há %(duration)s", "Offline for %(duration)s": "Desconectado há %(duration)s",
"Unknown for %(duration)s": "Status desconhecido há %(duration)s", "Unknown for %(duration)s": "Status desconhecido há %(duration)s",
"Unknown": "Desconhecido", "Unknown": "Desconhecido",
"Replying": "Respondendo", "Replying": "Em resposta a",
"No rooms to show": "Nenhuma sala para mostrar", "No rooms to show": "Nenhuma sala para mostrar",
"Unnamed room": "Sala sem nome", "Unnamed room": "Sala sem nome",
"World readable": "Aberto publicamente à leitura", "World readable": "Aberto publicamente à leitura",
"Guests can join": "Convidadas/os podem entrar", "Guests can join": "Convidadas/os podem entrar",
"Community Invites": "Convites a comunidades", "Community Invites": "Convites a comunidades",
"Banned by %(displayName)s": "Banido por %(displayName)s", "Banned by %(displayName)s": "Banido por %(displayName)s",
"Publish this room to the public in %(domain)s's room directory?": "Quer publicar esta sala na lista pública de salas em %(domain)s's?", "Publish this room to the public in %(domain)s's room directory?": "Quer publicar esta sala na lista pública de salas da %(domain)s?",
"Members only (since the point in time of selecting this option)": "Apenas integrantes (a partir do momento em que esta opção for selecionada)", "Members only (since the point in time of selecting this option)": "Apenas integrantes (a partir do momento em que esta opção for selecionada)",
"Members only (since they were invited)": "Apenas integrantes (desde que foram convidadas/os)", "Members only (since they were invited)": "Apenas integrantes (desde que foram convidadas/os)",
"Members only (since they joined)": "Apenas integrantes (desde que entraram na sala)", "Members only (since they joined)": "Apenas integrantes (desde que entraram na sala)",
@ -640,7 +640,7 @@
"Failed to set direct chat tag": "Falha ao definir esta conversa como direta", "Failed to set direct chat tag": "Falha ao definir esta conversa como direta",
"Failed to remove tag %(tagName)s from room": "Falha ao remover a tag %(tagName)s da sala", "Failed to remove tag %(tagName)s from room": "Falha ao remover a tag %(tagName)s da sala",
"Failed to add tag %(tagName)s to room": "Falha ao adicionar a tag %(tagName)s para a sala", "Failed to add tag %(tagName)s to room": "Falha ao adicionar a tag %(tagName)s para a sala",
"Did you know: you can use communities to filter your %(brand)s experience!": "Você sabia? Você pode usar as comunidades para filtrar a sua experiência no %(brand)s!", "Did you know: you can use communities to filter your %(brand)s experience!": "Você sabia? Você pode usar comunidades para filtrar a sua experiência no %(brand)s!",
"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 criar um filtro, arraste a foto de uma comunidade sobre o painel de filtros na extrema esquerda da sua tela. Você pode clicar na foto de uma comunidade no painel de filtros a qualquer momento para ver apenas as salas e pessoas associadas com esta comunidade.", "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 criar um filtro, arraste a foto de uma comunidade sobre o painel de filtros na extrema esquerda da sua tela. Você pode clicar na foto de uma comunidade no painel de filtros a qualquer momento para ver apenas as salas e pessoas associadas com esta comunidade.",
"Key request sent.": "Requisição de chave enviada.", "Key request sent.": "Requisição de chave enviada.",
"Fetching third party location failed": "Falha ao acessar a localização de terceiros", "Fetching third party location failed": "Falha ao acessar a localização de terceiros",
@ -677,7 +677,7 @@
"Please set a password!": "Por favor, defina uma senha!", "Please set a password!": "Por favor, defina uma senha!",
"You have successfully set a password!": "Você definiu sua senha com sucesso!", "You have successfully set a password!": "Você definiu sua senha com sucesso!",
"An error occurred whilst saving your email notification preferences.": "Ocorreu um erro ao salvar sua configuração de notificações por e-mail.", "An error occurred whilst saving your email notification preferences.": "Ocorreu um erro ao salvar sua configuração de notificações por e-mail.",
"Explore Room State": "Explorar Estado da Sala", "Explore Room State": "Explorar estado da sala",
"Source URL": "Link do código-fonte", "Source URL": "Link do código-fonte",
"Messages sent by bot": "Mensagens enviadas por bots", "Messages sent by bot": "Mensagens enviadas por bots",
"Filter results": "Filtrar resultados", "Filter results": "Filtrar resultados",
@ -696,9 +696,9 @@
"Search…": "Buscar…", "Search…": "Buscar…",
"You have successfully set a password and an email address!": "Você definiu uma senha e um endereço de e-mail com sucesso!", "You have successfully set a password and an email address!": "Você definiu uma senha e um endereço de e-mail com sucesso!",
"Remove %(name)s from the directory?": "Remover %(name)s da lista pública de salas?", "Remove %(name)s from the directory?": "Remover %(name)s da lista pública de salas?",
"%(brand)s uses many advanced browser features, some of which are not available or experimental in your current browser.": "O %(brand)s usa muitas funcionalidades avançadas do navegador, algumas das quais não estão disponíveis ou ainda são experimentais no seu navegador atual.", "%(brand)s uses many advanced browser features, some of which are not available or experimental in your current browser.": "%(brand)s usa muitos recursos avançados, e alguns deles não estão disponíveis ou ainda são experimentais no seu navegador de internet atual.",
"Developer Tools": "Ferramentas do desenvolvedor", "Developer Tools": "Ferramentas do desenvolvedor",
"Explore Account Data": "Explorar Dados da Conta", "Explore Account Data": "Explorar dados da conta",
"Remove from Directory": "Remover da lista pública de salas", "Remove from Directory": "Remover da lista pública de salas",
"Saturday": "Sábado", "Saturday": "Sábado",
"Remember, you can always set an email address in user settings if you change your mind.": "Lembre-se: você pode sempre definir um endereço de e-mail nas configurações de usuário, se mudar de ideia.", "Remember, you can always set an email address in user settings if you change your mind.": "Lembre-se: você pode sempre definir um endereço de e-mail nas configurações de usuário, se mudar de ideia.",
@ -736,7 +736,7 @@
"Show message in desktop notification": "Mostrar a mensagem na notificação da área de trabalho", "Show message in desktop notification": "Mostrar a mensagem na notificação da área de trabalho",
"Unhide Preview": "Mostrar a pré-visualização", "Unhide Preview": "Mostrar a pré-visualização",
"Unable to join network": "Não foi possível conectar na rede", "Unable to join network": "Não foi possível conectar na rede",
"Sorry, your browser is <b>not</b> able to run %(brand)s.": "Perdão. O seu navegador <b>não</b> é capaz de rodar o %(brand)s.", "Sorry, your browser is <b>not</b> able to run %(brand)s.": "Infelizmente, o seu navegador <b>não</b> é capaz de rodar o %(brand)s.",
"Messages in group chats": "Mensagens em salas", "Messages in group chats": "Mensagens em salas",
"Yesterday": "Ontem", "Yesterday": "Ontem",
"Error encountered (%(errorDetail)s).": "Erro encontrado (%(errorDetail)s).", "Error encountered (%(errorDetail)s).": "Erro encontrado (%(errorDetail)s).",
@ -758,7 +758,7 @@
"Event Content": "Conteúdo do Evento", "Event Content": "Conteúdo do Evento",
"Thank you!": "Obrigado!", "Thank you!": "Obrigado!",
"Quote": "Citar", "Quote": "Citar",
"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!": "Com o seu navegador atual, a aparência e sensação de uso da aplicação podem estar completamente incorretas, e algumas das funcionalidades poderão não funcionar. Se você quiser tentar de qualquer maneira, pode continuar, mas aí vai ter que se virar sozinho(a) com os problemas que porventura encontrar!", "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!": "Com o seu navegador atual, a aparência e sensação de uso da aplicação podem estar completamente incorretas, e alguns dos recursos poderão não funcionar. Você ainda pode prosseguir, mas estará sozinho diante de problemas que possam surgir!",
"Checking for an update...": "Verificando se há atualizações...", "Checking for an update...": "Verificando se há atualizações...",
"Every page you use in the app": "Toda a página que você usa no aplicativo", "Every page you use in the app": "Toda a página que você usa no aplicativo",
"e.g. <CurrentPageURL>": "por exemplo: <CurrentPageURL>", "e.g. <CurrentPageURL>": "por exemplo: <CurrentPageURL>",
@ -766,9 +766,9 @@
"Call in Progress": "Chamada em andamento", "Call in Progress": "Chamada em andamento",
"A call is currently being placed!": "Uma chamada já está em andamento!", "A call is currently being placed!": "Uma chamada já está em andamento!",
"A call is already in progress!": "Uma chamada já está em andamento!", "A call is already in progress!": "Uma chamada já está em andamento!",
"Permission Required": "Permissão Exigida", "Permission Required": "Permissão necessária",
"You do not have permission to start a conference call in this room": "Você não tem permissão para iniciar uma chamada em grupo nesta sala", "You do not have permission to start a conference call in this room": "Você não tem permissão para iniciar uma chamada em grupo nesta sala",
"Unable to load! Check your network connectivity and try again.": "Incapaz de carregar! Verifique sua conectividade de rede e tente novamente.", "Unable to load! Check your network connectivity and try again.": "Não foi possível carregar! Verifique sua conexão de rede e tente novamente.",
"Failed to invite users to the room:": "Não foi possível convidar usuários para a sala:", "Failed to invite users to the room:": "Não foi possível convidar usuários para a sala:",
"Missing roomId.": "RoomId ausente.", "Missing roomId.": "RoomId ausente.",
"Opens the Developer Tools dialog": "Abre a caixa de diálogo Ferramentas do desenvolvedor", "Opens the Developer Tools dialog": "Abre a caixa de diálogo Ferramentas do desenvolvedor",
@ -867,7 +867,7 @@
"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.": "Os registros de depuração contêm dados de uso do aplicativo, incluindo seu nome de usuário, os IDs ou aliases das salas ou comunidades que você visitou e os nomes de usuários de outros usuários. Eles não contêm mensagens.", "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.": "Os registros de depuração contêm dados de uso do aplicativo, incluindo seu nome de usuário, os IDs ou aliases das salas ou comunidades que você visitou e os nomes de usuários de outros usuários. Eles não contêm mensagens.",
"Before submitting logs, you must <a>create a GitHub issue</a> to describe your problem.": "Antes de enviar os registros, você deve <a>criar um bilhete de erro no GitHub</a> para descrever seu problema.", "Before submitting logs, you must <a>create a GitHub issue</a> to describe your problem.": "Antes de enviar os registros, você deve <a>criar um bilhete de erro no GitHub</a> para descrever seu problema.",
"Unable to load commit detail: %(msg)s": "Não é possível carregar os detalhes do commit: %(msg)s", "Unable to load commit detail: %(msg)s": "Não é possível carregar os detalhes do commit: %(msg)s",
"To avoid losing your chat history, you must export your room keys before logging out. You will need to go back to the newer version of %(brand)s to do this": "Para evitar perder seu histórico de bate-papo, você deve exportar as chaves da sua sala antes de se desconectar. Para fazer isso, você precisará retornar na versão mais atual do %(brand)s", "To avoid losing your chat history, you must export your room keys before logging out. You will need to go back to the newer version of %(brand)s to do this": "Para evitar perder seu histórico de bate-papo, você precisa exportar as chaves da sua sala antes de se desconectar. Quando entrar novamente, você precisará usar a versão mais atual do %(brand)s",
"Incompatible Database": "Banco de dados incompatível", "Incompatible Database": "Banco de dados incompatível",
"Continue With Encryption Disabled": "Continuar com criptografia desativada", "Continue With Encryption Disabled": "Continuar com criptografia desativada",
"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>": "Isso tornará sua conta permanentemente inutilizável. Você não poderá efetuar login e ninguém poderá registrar novamente o mesmo ID de usuário. Isso fará com que sua conta deixe todas as salas nas quais está participando e removerá os detalhes da sua conta do seu servidor de identidade. <b>Esta ação é irreversível.</ b>", "This will make your account permanently unusable. You will not be able to log in, and no one will be able to re-register the same user ID. This will cause your account to leave all rooms it is participating in, and it will remove your account details from your identity server. <b>This action is irreversible.</b>": "Isso tornará sua conta permanentemente inutilizável. Você não poderá efetuar login e ninguém poderá registrar novamente o mesmo ID de usuário. Isso fará com que sua conta deixe todas as salas nas quais está participando e removerá os detalhes da sua conta do seu servidor de identidade. <b>Esta ação é irreversível.</ b>",
@ -877,16 +877,16 @@
"To continue, please enter your password:": "Para continuar, por favor digite sua senha:", "To continue, please enter your password:": "Para continuar, por favor digite sua senha:",
"Incompatible local cache": "Cache local incompatível", "Incompatible local cache": "Cache local incompatível",
"Clear cache and resync": "Limpar cache e ressincronizar", "Clear cache and resync": "Limpar cache e ressincronizar",
"%(brand)s now uses 3-5x less memory, by only loading information about other users when needed. Please wait whilst we resynchronise with the server!": "%(brand)s agora usa 3-5x menos memória, pois carrega informação sobre outros usuários apenas quando for necessário. Por favor, aguarde enquanto ressincronizamos com o servidor!", "%(brand)s now uses 3-5x less memory, by only loading information about other users when needed. Please wait whilst we resynchronise with the server!": "%(brand)s agora usa de 3 a 5 vezes menos memória, pois carrega as informações dos outros usuários apenas quando for necessário. Por favor, aguarde enquanto ressincronizamos com o servidor!",
"Updating %(brand)s": "Atualizando %(brand)s", "Updating %(brand)s": "Atualizando o %(brand)s",
"Failed to upgrade room": "Falha ao atualizar a sala", "Failed to upgrade room": "Falha ao atualizar a sala",
"The room upgrade could not be completed": "A atualização da sala não pode ser completada", "The room upgrade could not be completed": "A atualização da sala não pode ser completada",
"Upgrade this room to version %(version)s": "Atualize essa sala para versão %(version)s", "Upgrade this room to version %(version)s": "Atualize essa sala para versão %(version)s",
"Upgrade Room Version": "Atualize a Versão da Sala", "Upgrade Room Version": "Atualize a Versão da Sala",
"Create a new room with the same name, description and avatar": "Criar uma nova sala com o mesmo nome, descrição e foto", "Create a new room with the same name, description and avatar": "Criar uma nova sala com o mesmo nome, descrição e foto",
"Stop users from speaking in the old version of the room, and post a message advising users to move to the new room": "Impedir usuários de conversar na versão antiga da sala e postar uma mensagem aconselhando os usuários a migrarem para a nova sala", "Stop users from speaking in the old version of the room, and post a message advising users to move to the new room": "Impeça os usuários de conversarem na versão antiga da sala. Além disso, digite uma mensagem aconselhando os usuários a migrarem para a nova sala",
"Put a link back to the old room at the start of the new room so people can see old messages": "Colocar um link para a sala antiga no começo da sala nova de modo que as pessoas possam ver mensagens antigas", "Put a link back to the old room at the start of the new room so people can see old messages": "Colocar um link para a sala antiga no começo da sala nova de modo que as pessoas possam ver mensagens antigas",
"You've previously used %(brand)s on %(host)s with lazy loading of members enabled. In this version lazy loading is disabled. As the local cache is not compatible between these two settings, %(brand)s needs to resync your account.": "Você já usou o %(brand)s em %(host)s com o carregamento Lazy de membros ativado. Nesta versão, o carregamento Lazy está desativado. Como o cache local não é compatível entre essas duas configurações, a %(brand)s precisa ressincronizar sua conta.", "You've previously used %(brand)s on %(host)s with lazy loading of members enabled. In this version lazy loading is disabled. As the local cache is not compatible between these two settings, %(brand)s needs to resync your account.": "Você já usou o %(brand)s em %(host)s com o carregamento Lazy de membros ativado. Nesta versão, o carregamento Lazy está desativado. Como o cache local não é compatível entre essas duas configurações, o %(brand)s precisa ressincronizar sua conta.",
"If the other version of %(brand)s is still open in another tab, please close it as using %(brand)s on the same host with both lazy loading enabled and disabled simultaneously will cause issues.": "Se a outra versão do %(brand)s ainda estiver aberta em outra aba, por favor, feche-a pois usar o %(brand)s no mesmo host com o carregamento Lazy ativado e desativado simultaneamente causará problemas.", "If the other version of %(brand)s is still open in another tab, please close it as using %(brand)s on the same host with both lazy loading enabled and disabled simultaneously will cause issues.": "Se a outra versão do %(brand)s ainda estiver aberta em outra aba, por favor, feche-a pois usar o %(brand)s no mesmo host com o carregamento Lazy ativado e desativado simultaneamente causará problemas.",
"Update any local room aliases to point to the new room": "Atualize todos os aliases da sala local para apontar para a nova sala", "Update any local room aliases to point to the new room": "Atualize todos os aliases da sala local para apontar para a nova sala",
"Clear Storage and Sign Out": "Limpar armazenamento e sair", "Clear Storage and Sign Out": "Limpar armazenamento e sair",
@ -907,7 +907,7 @@
"Access your secure message history and set up secure messaging by entering your recovery passphrase.": "Acesse seu histórico de mensagens seguras e configure mensagens seguras digitando sua frase secreta de recuperação.", "Access your secure message history and set up secure messaging by entering your recovery passphrase.": "Acesse seu histórico de mensagens seguras e configure mensagens seguras digitando sua frase secreta de recuperação.",
"Next": "Próximo", "Next": "Próximo",
"If you've forgotten your recovery passphrase you can <button1>use your recovery key</button1> or <button2>set up new recovery options</button2>": "Se você esqueceu sua frase secreta de recuperação, você pode <button1>usar sua chave de recuperação</button1> ou <button2>configurar novas opções de recuperação</button2>", "If you've forgotten your recovery passphrase you can <button1>use your recovery key</button1> or <button2>set up new recovery options</button2>": "Se você esqueceu sua frase secreta de recuperação, você pode <button1>usar sua chave de recuperação</button1> ou <button2>configurar novas opções de recuperação</button2>",
"This looks like a valid recovery key!": "Isso parece uma chave de recuperação válida!", "This looks like a valid recovery key!": "A chave de recuperação está correta!",
"Not a valid recovery key": "Não é uma chave de recuperação válida", "Not a valid recovery key": "Não é uma chave de recuperação válida",
"Access your secure message history and set up secure messaging by entering your recovery key.": "Acesse seu histórico seguro de mensagens e configure mensagens seguras inserindo sua chave de recuperação.", "Access your secure message history and set up secure messaging by entering your recovery key.": "Acesse seu histórico seguro de mensagens e configure mensagens seguras inserindo sua chave de recuperação.",
"Share Message": "Compartilhar Mensagem", "Share Message": "Compartilhar Mensagem",
@ -984,28 +984,28 @@
"%(senderDisplayName)s made the room invite only.": "%(senderDisplayName)s tornou a sala disponível apenas por convite.", "%(senderDisplayName)s made the room invite only.": "%(senderDisplayName)s tornou a sala disponível apenas por convite.",
"%(senderDisplayName)s changed the join rule to %(rule)s": "%(senderDisplayName)s alterou a regra de entrada para %(rule)s", "%(senderDisplayName)s changed the join rule to %(rule)s": "%(senderDisplayName)s alterou a regra de entrada para %(rule)s",
"%(senderDisplayName)s has allowed guests to join the room.": "%(senderDisplayName)s permitiu que os convidados entrem na sala.", "%(senderDisplayName)s has allowed guests to join the room.": "%(senderDisplayName)s permitiu que os convidados entrem na sala.",
"%(senderDisplayName)s has prevented guests from joining the room.": "%(senderDisplayName)s impediu que os convidados entrassem na sala.", "%(senderDisplayName)s has prevented guests from joining the room.": "%(senderDisplayName)s impediu que convidados entrassem na sala.",
"%(senderDisplayName)s changed guest access to %(rule)s": "%(senderDisplayName)s alterou a permissão de acesso de convidados para %(rule)s", "%(senderDisplayName)s changed guest access to %(rule)s": "%(senderDisplayName)s alterou a permissão de acesso de convidados para %(rule)s",
"%(senderDisplayName)s enabled flair for %(groups)s in this room.": "%(senderDisplayName)s ativou o ícone de %(groups)s nesta sala.", "%(senderDisplayName)s enabled flair for %(groups)s in this room.": "%(senderDisplayName)s ativou o ícone de %(groups)s nesta sala.",
"%(senderDisplayName)s disabled flair for %(groups)s in this room.": "%(senderDisplayName)s desativou o ícone de %(groups)s nesta sala.", "%(senderDisplayName)s disabled flair for %(groups)s in this room.": "%(senderDisplayName)s desativou o ícone de %(groups)s nesta sala.",
"%(senderDisplayName)s enabled flair for %(newGroups)s and disabled flair for %(oldGroups)s in this room.": "%(senderDisplayName)s ativou o ícone de %(newGroups)s e desativou o ícone de %(oldGroups)s nesta sala.", "%(senderDisplayName)s enabled flair for %(newGroups)s and disabled flair for %(oldGroups)s in this room.": "%(senderDisplayName)s ativou o ícone de %(newGroups)s e desativou o ícone de %(oldGroups)s nesta sala.",
"%(displayName)s is typing …": "%(displayName)s está digitando…", "%(displayName)s is typing …": "%(displayName)s está digitando…",
"%(names)s and %(count)s others are typing …|other": "%(names)s e %(count)s outras pessoas estão digitando…", "%(names)s and %(count)s others are typing …|other": "%(names)s e %(count)s outras pessoas estão digitando…",
"%(names)s and %(count)s others are typing …|one": "%(names)s e outro está digitando …", "%(names)s and %(count)s others are typing …|one": "%(names)s e outra pessoa estão digitando…",
"%(names)s and %(lastPerson)s are typing …": "%(names)s e %(lastPerson)s estão digitando …", "%(names)s and %(lastPerson)s are typing …": "%(names)s e %(lastPerson)s estão digitando…",
"Show read receipts sent by other users": "Mostrar confirmações de leitura enviadas por outros usuários", "Show read receipts sent by other users": "Mostrar confirmações de leitura enviadas por outros usuários",
"Show avatars in user and room mentions": "Mostrar fotos de perfil em menções de usuários e de salas", "Show avatars in user and room mentions": "Mostrar fotos de perfil em menções de usuários e de salas",
"Enable big emoji in chat": "Ativar emojis grandes no bate-papo", "Enable big emoji in chat": "Ativar emojis grandes no bate-papo",
"Send typing notifications": "Enviar notificações de digitação", "Send typing notifications": "Permitir que saibam quando eu estiver digitando",
"Enable Community Filter Panel": "Ativar o painel de comunidades", "Enable Community Filter Panel": "Ativar o painel de comunidades",
"Allow Peer-to-Peer for 1:1 calls": "Permitir Peer-to-Peer para chamadas 1:1", "Allow Peer-to-Peer for 1:1 calls": "Permitir Peer-to-Peer para chamadas 1:1",
"Messages containing my username": "Mensagens contendo meu nome de usuário", "Messages containing my username": "Mensagens contendo meu nome de usuário",
"The other party cancelled the verification.": "Seu contato cancelou a verificação.", "The other party cancelled the verification.": "Seu contato cancelou a confirmação.",
"Verified!": "Verificado!", "Verified!": "Confirmado!",
"You've successfully verified this user.": "Você confirmou este usuário com sucesso.", "You've successfully verified this user.": "Você confirmou este usuário com sucesso.",
"Secure messages with this user are end-to-end encrypted and not able to be read by third parties.": "As mensagens com este usuário estão protegidas com a criptografia de ponta a ponta e não podem ser lidas por terceiros.", "Secure messages with this user are end-to-end encrypted and not able to be read by third parties.": "As mensagens com este usuário estão protegidas com a criptografia de ponta a ponta e não podem ser lidas por terceiros.",
"Got It": "Ok, entendi", "Got It": "Ok, entendi",
"Unable to find a supported verification method.": "Não é possível encontrar um método de confirmação suportado.", "Unable to find a supported verification method.": "Não um método de confirmação suportado.",
"Dog": "Cachorro", "Dog": "Cachorro",
"Cat": "Gato", "Cat": "Gato",
"Lion": "Leão", "Lion": "Leão",
@ -1046,8 +1046,8 @@
"User %(userId)s is already in the room": "O usuário %(userId)s já está na sala", "User %(userId)s is already in the room": "O usuário %(userId)s já está na sala",
"The user must be unbanned before they can be invited.": "O banimento do usuário precisa ser removido antes de ser convidado.", "The user must be unbanned before they can be invited.": "O banimento do usuário precisa ser removido antes de ser convidado.",
"Show display name changes": "Mostrar alterações de nome e sobrenome", "Show display name changes": "Mostrar alterações de nome e sobrenome",
"Verify this user by confirming the following emoji appear on their screen.": "Verifique este usuário confirmando os emojis a seguir exibidos na tela dele.", "Verify this user by confirming the following emoji appear on their screen.": "Confirme este usuário confirmando os emojis a seguir exibidos na tela dele.",
"Verify this user by confirming the following number appears on their screen.": "Confirme este usuário confirmando se o número a seguir aparece na tela dele.", "Verify this user by confirming the following number appears on their screen.": "Confirme este usuário, comparando os números a seguir que serão exibidos na sua e na tela dele.",
"Thumbs up": "Joinha", "Thumbs up": "Joinha",
"Umbrella": "Guarda-chuva", "Umbrella": "Guarda-chuva",
"Hourglass": "Ampulheta", "Hourglass": "Ampulheta",
@ -1087,8 +1087,8 @@
"All keys backed up": "O Backup de todas as chaves foi realizado", "All keys backed up": "O Backup de todas as chaves foi realizado",
"Start using Key Backup": "Comece a usar o Backup de chave", "Start using Key Backup": "Comece a usar o Backup de chave",
"Add an email address to configure email notifications": "Adicione um endereço de e-mail para configurar notificações por e-mail", "Add an email address to configure email notifications": "Adicione um endereço de e-mail para configurar notificações por e-mail",
"Unable to verify phone number.": "Não é possível verificar o número de telefone.", "Unable to verify phone number.": "Não foi possível confirmar o número de telefone.",
"Verification code": "Código de verificação", "Verification code": "Código de confirmação",
"Phone Number": "Número de telefone", "Phone Number": "Número de telefone",
"Profile picture": "Foto de perfil", "Profile picture": "Foto de perfil",
"<a>Upgrade</a> to your own domain": "<a>Atualize</a> para seu próprio domínio", "<a>Upgrade</a> to your own domain": "<a>Atualize</a> para seu próprio domínio",
@ -1101,7 +1101,7 @@
"Deactivating your account is a permanent action - be careful!": "Desativar sua conta é uma ação permanente - tenha cuidado!", "Deactivating your account is a permanent action - be careful!": "Desativar sua conta é uma ação permanente - tenha cuidado!",
"General": "Geral", "General": "Geral",
"Credits": "Créditos", "Credits": "Créditos",
"For help with using %(brand)s, click <a>here</a>.": "Para ajuda com o uso do %(brand)s, clique <a>aqui</a>.", "For help with using %(brand)s, click <a>here</a>.": "Para obter ajuda com o uso do %(brand)s, clique <a>aqui</a>.",
"For help with using %(brand)s, click <a>here</a> or start a chat with our bot using the button below.": "Para obter ajuda com o uso do %(brand)s, clique <a>aqui</a> ou inicie um bate-papo com nosso bot usando o botão abaixo.", "For help with using %(brand)s, click <a>here</a> or start a chat with our bot using the button below.": "Para obter ajuda com o uso do %(brand)s, clique <a>aqui</a> ou inicie um bate-papo com nosso bot usando o botão abaixo.",
"Chat with %(brand)s Bot": "Converse com o bot do %(brand)s", "Chat with %(brand)s Bot": "Converse com o bot do %(brand)s",
"Help & About": "Ajuda & Sobre", "Help & About": "Ajuda & Sobre",
@ -1146,9 +1146,9 @@
"Add Email Address": "Adicionar endereço de e-mail", "Add Email Address": "Adicionar endereço de e-mail",
"Confirm adding phone number": "Confirmar adição de número de telefone", "Confirm adding phone number": "Confirmar adição de número de telefone",
"Add Phone Number": "Adicionar número de telefone", "Add Phone Number": "Adicionar número de telefone",
"Whether you're using %(brand)s on a device where touch is the primary input mechanism": "Se estiver usando %(brand)s em um aparelho onde touch é o mecanismo primário de entrada de dados", "Whether you're using %(brand)s on a device where touch is the primary input mechanism": "Se estiver usando o %(brand)s em um aparelho onde a tela principal é touch",
"Whether or not you're using the 'breadcrumbs' feature (avatars above the room list)": "Se você está usando ou não o recurso 'breadcrumbs' (fotos acima da lista de salas)", "Whether or not you're using the 'breadcrumbs' feature (avatars above the room list)": "Se você está usando ou não o recurso 'breadcrumbs' (fotos acima da lista de salas)",
"Whether you're using %(brand)s as an installed Progressive Web App": "Se estiver usando %(brand)s como uma Progressive Web App (PWA)", "Whether you're using %(brand)s as an installed Progressive Web App": "Se estiver usando o %(brand)s como um Progressive Web App (PWA)",
"Your user agent": "Seu agente de usuária(o)", "Your user agent": "Seu agente de usuária(o)",
"Call failed due to misconfigured server": "A chamada falhou por conta de má configuração no servidor", "Call failed due to misconfigured server": "A chamada falhou por conta de má configuração no servidor",
"Please ask the administrator of your homeserver (<code>%(homeserverDomain)s</code>) to configure a TURN server in order for calls to work reliably.": "Por favor, peça ao administrador do seu servidor (<code>%(homeserverDomain)s</code>) para configurar um servidor TURN, de modo que as chamadas funcionem de maneira estável.", "Please ask the administrator of your homeserver (<code>%(homeserverDomain)s</code>) to configure a TURN server in order for calls to work reliably.": "Por favor, peça ao administrador do seu servidor (<code>%(homeserverDomain)s</code>) para configurar um servidor TURN, de modo que as chamadas funcionem de maneira estável.",
@ -1168,7 +1168,7 @@
"This action requires accessing the default identity server <server /> to validate an email address or phone number, but the server does not have any terms of service.": "Esta ação requer acesso ao servidor de identidade padrão <server /> para poder validar um endereço de e-mail ou número de telefone, mas este servidor não tem nenhum termo de uso.", "This action requires accessing the default identity server <server /> to validate an email address or phone number, but the server does not have any terms of service.": "Esta ação requer acesso ao servidor de identidade padrão <server /> para poder validar um endereço de e-mail ou número de telefone, mas este servidor não tem nenhum termo de uso.",
"Only continue if you trust the owner of the server.": "Continue apenas se você confia em quem possui este servidor.", "Only continue if you trust the owner of the server.": "Continue apenas se você confia em quem possui este servidor.",
"Trust": "Confiança", "Trust": "Confiança",
"%(name)s is requesting verification": "%(name)s está solicitando verificação", "%(name)s is requesting verification": "%(name)s está solicitando confirmação",
"Use your account to sign in to the latest version": "Use sua conta para logar na última versão", "Use your account to sign in to the latest version": "Use sua conta para logar na última versão",
"Were excited to announce Riot is now Element": "Estamos muito felizes em anunciar que Riot agora é Element", "Were excited to announce Riot is now Element": "Estamos muito felizes em anunciar que Riot agora é Element",
"Riot is now Element!": "Riot agora é Element!", "Riot is now Element!": "Riot agora é Element!",
@ -1185,7 +1185,7 @@
"Sends a message as html, without interpreting it as markdown": "Envia uma mensagem como HTML, sem interpretá-la como markdown", "Sends a message as html, without interpreting it as markdown": "Envia uma mensagem como HTML, sem interpretá-la como markdown",
"You do not have the required permissions to use this command.": "Você não tem as permissões necessárias para usar este comando.", "You do not have the required permissions to use this command.": "Você não tem as permissões necessárias para usar este comando.",
"Error upgrading room": "Erro atualizando a sala", "Error upgrading room": "Erro atualizando a sala",
"Double check that your server supports the room version chosen and try again.": "Verifique mais uma ver se seu servidor suporta a versão de sala escolhida e tente novamente.", "Double check that your server supports the room version chosen and try again.": "Verifique se seu servidor suporta a versão de sala escolhida e tente novamente.",
"Changes the avatar of the current room": "Altera a foto da sala atual", "Changes the avatar of the current room": "Altera a foto da sala atual",
"Changes your avatar in this current room only": "Altera a sua foto de perfil apenas nesta sala", "Changes your avatar in this current room only": "Altera a sua foto de perfil apenas nesta sala",
"Changes your avatar in all rooms": "Altera a sua foto de perfil em todas as salas", "Changes your avatar in all rooms": "Altera a sua foto de perfil em todas as salas",
@ -1201,12 +1201,12 @@
"Please supply a widget URL or embed code": "Forneça o link de um widget ou de um código de incorporação", "Please supply a widget URL or embed code": "Forneça o link de um widget ou de um código de incorporação",
"Please supply a https:// or http:// widget URL": "Forneça o link de um widget com https:// ou http://", "Please supply a https:// or http:// widget URL": "Forneça o link de um widget com https:// ou http://",
"You cannot modify widgets in this room.": "Você não pode modificar widgets nesta sala.", "You cannot modify widgets in this room.": "Você não pode modificar widgets nesta sala.",
"Verifies a user, session, and pubkey tuple": "Verifica um(a) usuário(a), e a tupla de chave pública", "Verifies a user, session, and pubkey tuple": "Confirma um usuário, sessão, e chave criptografada pública",
"Unknown (user, session) pair:": "Par (usuária(o), sessão) desconhecido:", "Unknown (user, session) pair:": "Par (usuária(o), sessão) desconhecido:",
"Session already verified!": "Sessão já verificada!", "Session already verified!": "Sessão já confirmada!",
"WARNING: Session already verified, but keys do NOT MATCH!": "ATENÇÃO: Sessão já verificada, mas as chaves NÃO SE CORRESPONDEM!", "WARNING: Session already verified, but keys do NOT MATCH!": "ATENÇÃO: Sessão já confirmada, mas as chaves NÃO SÃO IGUAIS!",
"WARNING: KEY VERIFICATION FAILED! The signing key for %(userId)s and session %(deviceId)s is \"%(fprint)s\" which does not match the provided key \"%(fingerprint)s\". This could mean your communications are being intercepted!": "ATENÇÃO: A VERIFICAÇÃO DA CHAVE FALHOU! A chave de assinatura para %(userId)s e sessão %(deviceId)s é \"%(fprint)s\", o que não corresponde à chave fornecida \"%(fingerprint)s\". Isso pode significar que suas comunicações estejam sendo interceptadas por terceiros!", "WARNING: KEY VERIFICATION FAILED! The signing key for %(userId)s and session %(deviceId)s is \"%(fprint)s\" which does not match the provided key \"%(fingerprint)s\". This could mean your communications are being intercepted!": "ATENÇÃO: A CONFIRMAÇÃO DA CHAVE FALHOU! A chave de assinatura para %(userId)s e sessão %(deviceId)s é \"%(fprint)s\", o que não corresponde à chave fornecida \"%(fingerprint)s\". Isso pode significar que suas comunicações estejam sendo interceptadas por terceiros!",
"The signing key you provided matches the signing key you received from %(userId)s's session %(deviceId)s. Session marked as verified.": "A chave de assinatura que você forneceu corresponde à chave de assinatura que você recebeu da sessão %(deviceId)s da(do) usuária(o) %(userId)s. Esta sessão foi marcada como verificada.", "The signing key you provided matches the signing key you received from %(userId)s's session %(deviceId)s. Session marked as verified.": "A chave de assinatura que você forneceu corresponde à chave de assinatura que você recebeu da sessão %(deviceId)s do usuário %(userId)s. Esta sessão foi marcada como confirmada.",
"Sends the given message coloured as a rainbow": "Envia a mensagem colorida como arco-íris", "Sends the given message coloured as a rainbow": "Envia a mensagem colorida como arco-íris",
"Sends the given emote coloured as a rainbow": "Envia o emoji colorido como um arco-íris", "Sends the given emote coloured as a rainbow": "Envia o emoji colorido como um arco-íris",
"Displays list of commands with usages and descriptions": "Exibe a lista de comandos com usos e descrições", "Displays list of commands with usages and descriptions": "Exibe a lista de comandos com usos e descrições",
@ -1247,22 +1247,22 @@
"%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s alterou uma regra que bania o que correspondia a %(oldGlob)s para corresponder a %(newGlob)s devido à %(reason)s", "%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s alterou uma regra que bania o que correspondia a %(oldGlob)s para corresponder a %(newGlob)s devido à %(reason)s",
"Light": "Claro", "Light": "Claro",
"Dark": "Escuro", "Dark": "Escuro",
"You signed in to a new session without verifying it:": "Você entrou em uma nova sessão sem verificá-la:", "You signed in to a new session without verifying it:": "Você entrou em uma nova sessão sem confirmá-la:",
"Verify your other session using one of the options below.": "Verifique suas outras sessões usando uma das opções abaixo.", "Verify your other session using one of the options below.": "Confirme suas outras sessões usando uma das opções abaixo.",
"%(name)s (%(userId)s) signed in to a new session without verifying it:": "%(name)s (%(userId)s) entrou em uma nova sessão sem verificá-la:", "%(name)s (%(userId)s) signed in to a new session without verifying it:": "%(name)s (%(userId)s) entrou em uma nova sessão sem confirmá-la:",
"Ask this user to verify their session, or manually verify it below.": "Peça a este usuário para verificar a sessão, ou verifique manualmente abaixo.", "Ask this user to verify their session, or manually verify it below.": "Peça a este usuário para confirmar a sessão dele, ou confirme-a manualmente abaixo.",
"Not Trusted": "Não confiável", "Not Trusted": "Não confiável",
"Manually Verify by Text": "Verifique manualmente por texto", "Manually Verify by Text": "Confirme manualmente por texto",
"Interactively verify by Emoji": "Verifiquem interativamente por emojis", "Interactively verify by Emoji": "Confirme interativamente por emojis",
"Done": "Pronto", "Done": "Fechar",
"Cannot reach homeserver": "Não consigo acessar o servidor", "Cannot reach homeserver": "Não consigo acessar o servidor",
"Ensure you have a stable internet connection, or get in touch with the server admin": "Verifique se está com uma conexão de internet estável, ou entre em contato com os administradores do servidor", "Ensure you have a stable internet connection, or get in touch with the server admin": "Verifique se está com uma conexão de internet estável, ou entre em contato com os administradores do servidor",
"Your %(brand)s is misconfigured": "O %(brand)s está mal configurado", "Your %(brand)s is misconfigured": "O %(brand)s está mal configurado",
"Ask your %(brand)s admin to check <a>your config</a> for incorrect or duplicate entries.": "Peça aos administradores do %(brand)s que verifique <a>suas configurações</a> por entradas incorretas ou duplicadas.", "Ask your %(brand)s admin to check <a>your config</a> for incorrect or duplicate entries.": "Entre em contato com o administrador do %(brand)s para verificar se há entradas inválidas ou duplicadas nas <a>suas configurações</a>.",
"Cannot reach identity server": "Não consigo acessar o servidor de identidade", "Cannot reach identity server": "Não consigo acessar o servidor de identidade",
"You can register, but some features will be unavailable until the identity server is back online. If you keep seeing this warning, check your configuration or contact a server admin.": "Você pode se registrar, mas algumas funcionalidades não estarão disponíveis até que o servidor de identidade esteja de volta online. Se você continuar vendo este alerta, verifique sua configuração ou entre em contato com um dos administradores do servidor.", "You can register, but some features will be unavailable until the identity server is back online. If you keep seeing this warning, check your configuration or contact a server admin.": "Você pode se registrar, mas alguns recursos não estarão disponíveis até que o servidor de identidade esteja no ar novamente. Se você continuar vendo este alerta, verifique sua configuração ou entre em contato com um dos administradores do servidor.",
"You can reset your password, but some features will be unavailable until the identity server is back online. If you keep seeing this warning, check your configuration or contact a server admin.": "Você pode trocar sua senha, mas algumas das funcionalidades não estarão mais disponíveis até que o servidor de identidade esteja de volta ao ar. Se você seguir vendo este alerta, verifique suas configurações ou entre em contato com um dos administradores do servidor.", "You can reset your password, but some features will be unavailable until the identity server is back online. If you keep seeing this warning, check your configuration or contact a server admin.": "Você pode trocar sua senha, mas alguns recursos não estarão disponíveis até que o servidor de identidade esteja no ar novamente. Se você seguir vendo este alerta, verifique suas configurações ou entre em contato com um dos administradores do servidor.",
"You can log in, but some features will be unavailable until the identity server is back online. If you keep seeing this warning, check your configuration or contact a server admin.": "Você pode fazer login, mas algumas funcionalidades estarão indisponíveis até que o servidor de identidade estiver de volta. Se você continuar vendo este alerta, verifique suas configurações ou entre em contato com os administradores do servidor.", "You can log in, but some features will be unavailable until the identity server is back online. If you keep seeing this warning, check your configuration or contact a server admin.": "Você pode fazer login, mas alguns recursos estarão indisponíveis até que o servidor de identidade estiver no ar novamente. Se você continuar vendo este alerta, verifique suas configurações ou entre em contato com os administradores do servidor.",
"No homeserver URL provided": "Nenhum endereço fornecido do servidor local", "No homeserver URL provided": "Nenhum endereço fornecido do servidor local",
"Unexpected error resolving homeserver configuration": "Erro inesperado buscando a configuração do servidor", "Unexpected error resolving homeserver configuration": "Erro inesperado buscando a configuração do servidor",
"Unexpected error resolving identity server configuration": "Erro inesperado buscando a configuração do servidor de identidade", "Unexpected error resolving identity server configuration": "Erro inesperado buscando a configuração do servidor de identidade",
@ -1283,11 +1283,11 @@
"%(num)s days from now": "dentro de %(num)s dias", "%(num)s days from now": "dentro de %(num)s dias",
"%(name)s (%(userId)s)": "%(name)s (%(userId)s)", "%(name)s (%(userId)s)": "%(name)s (%(userId)s)",
"The user's homeserver does not support the version of the room.": "O servidor desta(e) usuária(o) não suporta a versão desta sala.", "The user's homeserver does not support the version of the room.": "O servidor desta(e) usuária(o) não suporta a versão desta sala.",
"Help us improve %(brand)s": "Ajude-nos a melhorar %(brand)s", "Help us improve %(brand)s": "Ajude-nos a melhorar o %(brand)s",
"Send <UsageDataLink>anonymous usage data</UsageDataLink> which helps us improve %(brand)s. This will use a <PolicyLink>cookie</PolicyLink>.": "Envie <UsageDataLink>dados anônimos de uso</UsageDataLink> que nos ajudam a melhorar o %(brand)s. Isso necessitará do uso de um <PolicyLink>cookie</PolicyLink>.", "Send <UsageDataLink>anonymous usage data</UsageDataLink> which helps us improve %(brand)s. This will use a <PolicyLink>cookie</PolicyLink>.": "Envie <UsageDataLink>dados anônimos de uso</UsageDataLink> que nos ajudam a melhorar o %(brand)s. Isso necessitará do uso de um <PolicyLink>cookie</PolicyLink>.",
"I want to help": "Quero ajudar", "I want to help": "Quero ajudar",
"Review where youre logged in": "Revisar onde você está logada(o)", "Review where youre logged in": "Revisar onde você está logada(o)",
"Verify all your sessions to ensure your account & messages are safe": "Verifique todas as suas sessões para garantir que sua conta e mensagens estão seguras", "Verify all your sessions to ensure your account & messages are safe": "Confirme todas as suas sessões para garantir que sua conta e mensagens estão seguras",
"Review": "Revisar", "Review": "Revisar",
"Later": "Mais tarde", "Later": "Mais tarde",
"Your homeserver has exceeded its user limit.": "Seu servidor ultrapassou seu limite de usuárias(os).", "Your homeserver has exceeded its user limit.": "Seu servidor ultrapassou seu limite de usuárias(os).",
@ -1298,10 +1298,10 @@
"To return to your account in future you need to set a password": "Para retornar à sua conta no futuro, você precisa definir uma senha", "To return to your account in future you need to set a password": "Para retornar à sua conta no futuro, você precisa definir uma senha",
"Set up encryption": "Configurar a criptografia", "Set up encryption": "Configurar a criptografia",
"Encryption upgrade available": "Atualização de criptografia disponível", "Encryption upgrade available": "Atualização de criptografia disponível",
"Verify this session": "Verificar esta sessão", "Verify this session": "Confirmar esta sessão",
"Upgrade": "Atualizar", "Upgrade": "Atualizar",
"Verify": "Verificar", "Verify": "Confirmar",
"Verify yourself & others to keep your chats safe": "Verifique a sua conta e as dos seus contatos, para manter suas conversas seguras", "Verify yourself & others to keep your chats safe": "Confirme a sua conta e as dos seus contatos, para manter suas conversas seguras",
"Other users may not trust it": "Outras(os) usuárias(os) podem não confiar nela", "Other users may not trust it": "Outras(os) usuárias(os) podem não confiar nela",
"New login. Was this you?": "Novo login. Foi você?", "New login. Was this you?": "Novo login. Foi você?",
"Verify the new login accessing your account: %(name)s": "Verifique o novo login na sua conta: %(name)s", "Verify the new login accessing your account: %(name)s": "Verifique o novo login na sua conta: %(name)s",
@ -1323,7 +1323,7 @@
"%(senderName)s: %(message)s": "%(senderName)s: %(message)s", "%(senderName)s: %(message)s": "%(senderName)s: %(message)s",
"%(senderName)s: %(reaction)s": "%(senderName)s: %(reaction)s", "%(senderName)s: %(reaction)s": "%(senderName)s: %(reaction)s",
"%(senderName)s: %(stickerName)s": "%(senderName)s: %(stickerName)s", "%(senderName)s: %(stickerName)s": "%(senderName)s: %(stickerName)s",
"New spinner design": "Novo design do spinner", "New spinner design": "Nova aparência do símbolo de carregamento",
"Multiple integration managers": "Múltiplos gestores de integrações", "Multiple integration managers": "Múltiplos gestores de integrações",
"Try out new ways to ignore people (experimental)": "Tente novas maneiras de bloquear pessoas (experimental)", "Try out new ways to ignore people (experimental)": "Tente novas maneiras de bloquear pessoas (experimental)",
"Support adding custom themes": "Permite adicionar temas personalizados", "Support adding custom themes": "Permite adicionar temas personalizados",
@ -1332,12 +1332,12 @@
"Font size": "Tamanho da fonte", "Font size": "Tamanho da fonte",
"Use custom size": "Usar tamanho personalizado", "Use custom size": "Usar tamanho personalizado",
"Use a more compact Modern layout": "Usar um layout mais compacto 'Moderno'", "Use a more compact Modern layout": "Usar um layout mais compacto 'Moderno'",
"Show typing notifications": "Mostrar notificações de digitação", "Show typing notifications": "Mostrar quando alguém estiver digitando",
"Match system theme": "Se adaptar ao tema do sistema", "Match system theme": "Se adaptar ao tema do sistema",
"Use a system font": "Usar uma fonte do sistema", "Use a system font": "Usar uma fonte do sistema",
"System font name": "Nome da fonte do sistema", "System font name": "Nome da fonte do sistema",
"Never send encrypted messages to unverified sessions from this session": "Nunca envie mensagens criptografadas para sessões não verificadas desta sessão", "Never send encrypted messages to unverified sessions from this session": "Nunca envie mensagens criptografadas a partir desta sessão para sessões não confirmadas",
"Never send encrypted messages to unverified sessions in this room from this session": "Nunca envie mensagens criptografadas para sessões não verificadas nesta sala, desta sessão", "Never send encrypted messages to unverified sessions in this room from this session": "Nunca envie mensagens criptografadas a partir desta sessão para sessões não confirmadas nessa sala",
"Order rooms by name": "Ordenar salas por nome", "Order rooms by name": "Ordenar salas por nome",
"Show rooms with unread notifications first": "Mostrar primeiro as salas com notificações não lidas", "Show rooms with unread notifications first": "Mostrar primeiro as salas com notificações não lidas",
"Show shortcuts to recently viewed rooms above the room list": "Mostrar atalhos para salas recentemente visualizadas acima da lista de salas", "Show shortcuts to recently viewed rooms above the room list": "Mostrar atalhos para salas recentemente visualizadas acima da lista de salas",
@ -1358,7 +1358,7 @@
"Incoming voice call": "Recebendo chamada de voz", "Incoming voice call": "Recebendo chamada de voz",
"Incoming video call": "Recebendo chamada de vídeo", "Incoming video call": "Recebendo chamada de vídeo",
"Incoming call": "Recebendo chamada", "Incoming call": "Recebendo chamada",
"Verify this session by completing one of the following:": "Verifique esta sessão completando um dos seguintes:", "Verify this session by completing one of the following:": "Confirme esta sessão completando um dos seguintes:",
"Scan this unique code": "Escaneie este código único", "Scan this unique code": "Escaneie este código único",
"or": "ou", "or": "ou",
"Compare unique emoji": "Comparar emojis únicos", "Compare unique emoji": "Comparar emojis únicos",
@ -1366,9 +1366,9 @@
"Start": "Iniciar", "Start": "Iniciar",
"Confirm the emoji below are displayed on both sessions, in the same order:": "Confirme que os emojis abaixo estão sendo exibidos nas duas sessões, na mesma ordem:", "Confirm the emoji below are displayed on both sessions, in the same order:": "Confirme que os emojis abaixo estão sendo exibidos nas duas sessões, na mesma ordem:",
"Verify this session by confirming the following number appears on its screen.": "Verifique esta sessão confirmando que o seguinte número aparece na sua tela.", "Verify this session by confirming the following number appears on its screen.": "Verifique esta sessão confirmando que o seguinte número aparece na sua tela.",
"Waiting for your other session, %(deviceName)s (%(deviceId)s), to verify…": "Aguardando a outra sessão, %(deviceName)s (%(deviceId)s), verificar…", "Waiting for your other session, %(deviceName)s (%(deviceId)s), to verify…": "Aguardando a outra sessão, %(deviceName)s (%(deviceId)s), confirmar…",
"Waiting for your other session to verify…": "Aguardando a outra sessão verificar…", "Waiting for your other session to verify…": "Aguardando a outra sessão confirmar…",
"Waiting for %(displayName)s to verify…": "Aguardando %(displayName)s verificar…", "Waiting for %(displayName)s to verify…": "Aguardando %(displayName)s confirmar…",
"Cancelling…": "Cancelando…", "Cancelling…": "Cancelando…",
"They match": "São coincidentes", "They match": "São coincidentes",
"They don't match": "Elas não são correspondentes", "They don't match": "Elas não são correspondentes",
@ -1405,7 +1405,7 @@
"Session backup key:": "Chave de cópia (backup) da sessão:", "Session backup key:": "Chave de cópia (backup) da sessão:",
"Secret storage public key:": "Chave pública do armazenamento secreto:", "Secret storage public key:": "Chave pública do armazenamento secreto:",
"in account data": "nos dados de conta", "in account data": "nos dados de conta",
"Homeserver feature support:": "Funcionalidades suportadas pelo servidor:", "Homeserver feature support:": "Recursos suportados pelo servidor:",
"exists": "existe", "exists": "existe",
"Your homeserver does not support session management.": "Seu servidor não suporta gerenciamento de sessões.", "Your homeserver does not support session management.": "Seu servidor não suporta gerenciamento de sessões.",
"Unable to load session list": "Não foi possível carregar a lista de sessões", "Unable to load session list": "Não foi possível carregar a lista de sessões",
@ -1420,15 +1420,15 @@
"Delete %(count)s sessions|one": "Apagar %(count)s sessão", "Delete %(count)s sessions|one": "Apagar %(count)s sessão",
"ID": "ID", "ID": "ID",
"Public Name": "Nome público", "Public Name": "Nome público",
"Individually verify each session used by a user to mark it as trusted, not trusting cross-signed devices.": "Verificar individualmente cada sessão usada por um usuário para marcá-la como confiável, em vez de confiar em aparelhos autoverificados.", "Individually verify each session used by a user to mark it as trusted, not trusting cross-signed devices.": "Verifique individualmente cada sessão usada por um usuário para marcá-la como confiável, em vez de confirmar em aparelhos autoverificados.",
"Securely cache encrypted messages locally for them to appear in search results, using ": "Armazene mensagens criptografadas localmente para que elas apareçam nas buscas, usando· ", "Securely cache encrypted messages locally for them to appear in search results, using ": "Armazene mensagens criptografadas localmente para que elas apareçam nas buscas, usando· ",
" to store messages from ": " para armazenar mensagens de ", " to store messages from ": " para armazenar mensagens de ",
"rooms.": "salas.", "rooms.": "salas.",
"Manage": "Gerenciar", "Manage": "Gerenciar",
"Securely cache encrypted messages locally for them to appear in search results.": "Armazene mensagens criptografadas de forma segura localmente para que possam aparecer nos resultados das buscas.", "Securely cache encrypted messages locally for them to appear in search results.": "Armazene mensagens criptografadas de forma segura localmente para que possam aparecer nos resultados das buscas.",
"Enable": "Ativar", "Enable": "Ativar",
"%(brand)s is missing some components required for securely caching encrypted messages locally. If you'd like to experiment with this feature, build a custom %(brand)s Desktop with <nativeLink>search components added</nativeLink>.": "%(brand)s não está com alguns dos componentes necessários para armazenar com segurança mensagens criptografadas localmente. Se você quer fazer testes com esta funcionalidade, construa uma versão Desktop do %(brand)s com <nativeLink>componentes de busca ativos</nativeLink>.", "%(brand)s is missing some components required for securely caching encrypted messages locally. If you'd like to experiment with this feature, build a custom %(brand)s Desktop with <nativeLink>search components added</nativeLink>.": "%(brand)s precisa de componentes adicionais para pesquisar as mensagens criptografadas armazenadas localmente. Se quiser testar esse recurso, construa uma versão do %(brand)s para Computador com <nativeLink>componentes de busca ativados</nativeLink>.",
"%(brand)s can't securely cache encrypted messages locally while running in a web browser. Use <desktopLink>%(brand)s Desktop</desktopLink> for encrypted messages to appear in search results.": "%(brand)s não consegue armazenar de forma segura as mensagens criptografadas localmente enquanto funciona em um navegador web. Use <desktopLink>%(brand)s Desktop</desktopLink> para que mensagens criptografadas sejam exibidas nos resultados de buscas.", "%(brand)s can't securely cache encrypted messages locally while running in a web browser. Use <desktopLink>%(brand)s Desktop</desktopLink> for encrypted messages to appear in search results.": "%(brand)s não consegue pesquisar as mensagens criptografadas armazenadas localmente em um navegador de internet. Use o <desktopLink>%(brand)s para Computador</desktopLink> para que as mensagens criptografadas sejam exibidas nos resultados de buscas.",
"Connecting to integration manager...": "Conectando ao gestor de integrações...", "Connecting to integration manager...": "Conectando ao gestor de integrações...",
"Cannot connect to integration manager": "Não foi possível conectar ao gerenciador de integrações", "Cannot connect to integration manager": "Não foi possível conectar ao gerenciador de integrações",
"The integration manager is offline or it cannot reach your homeserver.": "Ou o gerenciador de integrações está desconectado, ou ele não conseguiu acessar o seu servidor.", "The integration manager is offline or it cannot reach your homeserver.": "Ou o gerenciador de integrações está desconectado, ou ele não conseguiu acessar o seu servidor.",
@ -1439,14 +1439,14 @@
"not stored": "não armazenado", "not stored": "não armazenado",
"Backup has a <validity>valid</validity> signature from this user": "A cópia de segurança (backup) tem uma assinatura <validity>válida</validity> deste(a) usuário(a)", "Backup has a <validity>valid</validity> signature from this user": "A cópia de segurança (backup) tem uma assinatura <validity>válida</validity> deste(a) usuário(a)",
"Backup has a <validity>invalid</validity> signature from this user": "A cópia de segurança (backup) tem uma assinatura <validity>inválida</validity> deste(a) usuário(a)", "Backup has a <validity>invalid</validity> signature from this user": "A cópia de segurança (backup) tem uma assinatura <validity>inválida</validity> deste(a) usuário(a)",
"Backup has a signature from <verify>unknown</verify> user with ID %(deviceId)s": "A cópia de segurança tem uma assinatura de um(a) usuário <verify>desconhecido</verify> com ID %(deviceId)s", "Backup has a signature from <verify>unknown</verify> user with ID %(deviceId)s": "A cópia de segurança tem uma assinatura de um usuário <verify>desconhecido</verify> com ID %(deviceId)s",
"Backup has a signature from <verify>unknown</verify> session with ID %(deviceId)s": "A cópia de segurança tem uma assinatura de uma sessão <verify>desconhecida</verify> com ID %(deviceId)s", "Backup has a signature from <verify>unknown</verify> session with ID %(deviceId)s": "A cópia de segurança tem uma assinatura de uma sessão <verify>desconhecida</verify> com ID %(deviceId)s",
"Backup has a <validity>valid</validity> signature from this session": "A cópia de segurança (backup) tem uma assinatura <validity>válida</validity> desta sessão", "Backup has a <validity>valid</validity> signature from this session": "A cópia de segurança (backup) tem uma assinatura <validity>válida</validity> desta sessão",
"Backup has an <validity>invalid</validity> signature from this session": "A cópia de segurança (backup) tem uma assinatura <validity>inválida</validity> desta sessão", "Backup has an <validity>invalid</validity> signature from this session": "A cópia de segurança (backup) tem uma assinatura <validity>inválida</validity> desta sessão",
"Backup has a <validity>valid</validity> signature from <verify>verified</verify> session <device></device>": "A cópia de segurança (backup) tem uma assinatura <validity>válida</validity> da sessão <verify>verificada</verify> <device></device>", "Backup has a <validity>valid</validity> signature from <verify>verified</verify> session <device></device>": "A cópia de segurança (backup) tem uma assinatura <validity>válida</validity> da sessão <verify>confirmada</verify> <device></device>",
"Backup has a <validity>valid</validity> signature from <verify>unverified</verify> session <device></device>": "A cópia de segurança tem uma assinatura <validity>válida</validity> de uma sessão <verify>não verificada</verify> <device></device>", "Backup has a <validity>valid</validity> signature from <verify>unverified</verify> session <device></device>": "A cópia de segurança tem uma assinatura <validity>válida</validity> de uma sessão <verify>não confirmada</verify> <device></device>",
"Backup has an <validity>invalid</validity> signature from <verify>verified</verify> session <device></device>": "A cópia de segurança tem uma assinatura <validity>inválida</validity> de uma sessão <verify>verificada</verify> <device></device>", "Backup has an <validity>invalid</validity> signature from <verify>verified</verify> session <device></device>": "A cópia de segurança tem uma assinatura <validity>inválida</validity> de uma sessão <verify>confirmada</verify> <device></device>",
"Backup has an <validity>invalid</validity> signature from <verify>unverified</verify> session <device></device>": "A cópia de segurança (backup) tem uma assinatura <validity>inválida</validity> de uma sessão <verify>não verificada</verify> <device></device>", "Backup has an <validity>invalid</validity> signature from <verify>unverified</verify> session <device></device>": "A cópia de segurança (backup) tem uma assinatura <validity>inválida</validity> de uma sessão <verify>não confirmada</verify> <device></device>",
"Backup is not signed by any of your sessions": "A cópia de segurança (backup) não foi assinada por nenhuma de suas sessões", "Backup is not signed by any of your sessions": "A cópia de segurança (backup) não foi assinada por nenhuma de suas sessões",
"This backup is trusted because it has been restored on this session": "Esta cópia de segurança (backup) é confiável, pois foi restaurada nesta sessão", "This backup is trusted because it has been restored on this session": "Esta cópia de segurança (backup) é confiável, pois foi restaurada nesta sessão",
"Backup key stored: ": "Chave de segurança (backup) armazenada: ", "Backup key stored: ": "Chave de segurança (backup) armazenada: ",
@ -1464,15 +1464,15 @@
"Encryption": "Criptografia", "Encryption": "Criptografia",
"Once enabled, encryption cannot be disabled.": "Uma vez ativada, a criptografia não poderá ser desativada.", "Once enabled, encryption cannot be disabled.": "Uma vez ativada, a criptografia não poderá ser desativada.",
"Encrypted": "Criptografada", "Encrypted": "Criptografada",
"Click the link in the email you received to verify and then click continue again.": "Clique no link no e-mail que você recebeu para verificar e então clique novamente em continuar.", "Click the link in the email you received to verify and then click continue again.": "Clique no link no e-mail que você recebeu para confirmar e então clique novamente em continuar.",
"Verify the link in your inbox": "Verifique o link na sua caixa de e-mails", "Verify the link in your inbox": "Verifique o link na sua caixa de e-mails",
"This room is end-to-end encrypted": "Esta sala é criptografada de ponta a ponta", "This room is end-to-end encrypted": "Esta sala é criptografada de ponta a ponta",
"Your key share request has been sent - please check your other sessions for key share requests.": "Sua solicitação de compartilhamento de chaves foi enviada - por favor, verifique a existência de solicitações de compartilhamento de chaves em suas outras sessões .", "Your key share request has been sent - please check your other sessions for key share requests.": "Sua solicitação de compartilhamento de chaves foi enviada - por favor, confirme a existência de solicitações de compartilhamento de chaves em suas outras sessões.",
"Key share requests are sent to your other sessions automatically. If you rejected or dismissed the key share request on your other sessions, click here to request the keys for this session again.": "Solicitações de compartilhamento de chaves são enviadas para suas outras sessões automaticamente. Se você recusou ou ignorou a solicitação de compartilhamento de chaves em suas outras sessões, clique aqui para solicitar as chaves para esta sessão novamente.", "Key share requests are sent to your other sessions automatically. If you rejected or dismissed the key share request on your other sessions, click here to request the keys for this session again.": "Solicitações de compartilhamento de chaves são enviadas para suas outras sessões automaticamente. Se você recusou ou ignorou a solicitação de compartilhamento de chaves em suas outras sessões, clique aqui para solicitar as chaves para esta sessão novamente.",
"If your other sessions do not have the key for this message you will not be able to decrypt them.": "Se suas outras sessões não possuem a chave para esta mensagem, você não será capaz de descriptografá-la.", "If your other sessions do not have the key for this message you will not be able to decrypt them.": "Se suas outras sessões não possuem a chave para esta mensagem, você não será capaz de descriptografá-la.",
"<requestLink>Re-request encryption keys</requestLink> from your other sessions.": "<requestLink>Solicitar novamente as chaves de criptografia</requestLink> das suas outras sessões.", "<requestLink>Re-request encryption keys</requestLink> from your other sessions.": "<requestLink>Solicitar novamente as chaves de criptografia</requestLink> das suas outras sessões.",
"This message cannot be decrypted": "Esta mensagem não pode ser descriptografada", "This message cannot be decrypted": "Esta mensagem não pode ser descriptografada",
"Encrypted by an unverified session": "Criptografada por uma sessão não verificada", "Encrypted by an unverified session": "Criptografada por uma sessão não confirmada",
"Unencrypted": "Descriptografada", "Unencrypted": "Descriptografada",
"Encrypted by a deleted session": "Criptografada por uma sessão já apagada", "Encrypted by a deleted session": "Criptografada por uma sessão já apagada",
"The authenticity of this encrypted message can't be guaranteed on this device.": "A autenticidade desta mensagem criptografada não pode ser garantida neste aparelho.", "The authenticity of this encrypted message can't be guaranteed on this device.": "A autenticidade desta mensagem criptografada não pode ser garantida neste aparelho.",
@ -1484,29 +1484,29 @@
"Messages in this room are secured with end-to-end encryption. Only you and the recipient(s) have the keys to read these messages.": "As mensagens nesta sala estão protegidas com a criptografia de ponta a ponta. Apenas você e a(s) demais pessoa(s) desta sala têm a chave para ler estas mensagens.", "Messages in this room are secured with end-to-end encryption. Only you and the recipient(s) have the keys to read these messages.": "As mensagens nesta sala estão protegidas com a criptografia de ponta a ponta. Apenas você e a(s) demais pessoa(s) desta sala têm a chave para ler estas mensagens.",
"Upgrading this room will shut down the current instance of the room and create an upgraded room with the same name.": "Atualizar esta sala irá fechar a instância atual da sala e criar uma sala atualizada com o mesmo nome.", "Upgrading this room will shut down the current instance of the room and create an upgraded room with the same name.": "Atualizar esta sala irá fechar a instância atual da sala e criar uma sala atualizada com o mesmo nome.",
"Hint: Begin your message with <code>//</code> to start it with a slash.": "Dica: Inicie sua mensagem com <code>//</code> para iniciar com uma barra.", "Hint: Begin your message with <code>//</code> to start it with a slash.": "Dica: Inicie sua mensagem com <code>//</code> para iniciar com uma barra.",
"Start Verification": "Iniciar verificação", "Start Verification": "Iniciar confirmação",
"Messages in this room are end-to-end encrypted.": "As mensagens nesta sala estão criptografadas de ponta a ponta.", "Messages in this room are end-to-end encrypted.": "As mensagens nesta sala estão criptografadas de ponta a ponta.",
"Messages in this room are not end-to-end encrypted.": "As mensagens nesta sala não estão criptografadas de ponta a ponta.", "Messages in this room are not end-to-end encrypted.": "As mensagens nesta sala não estão criptografadas de ponta a ponta.",
"In encrypted rooms, your messages are secured and only you and the recipient have the unique keys to unlock them.": "Em salas criptografadas, suas mensagens estão seguras e apenas você e a pessoa que a recebe têm as chaves únicas que permitem a sua leitura.", "In encrypted rooms, your messages are secured and only you and the recipient have the unique keys to unlock them.": "Em salas criptografadas, suas mensagens estão seguras e apenas você e a pessoa que a recebe têm as chaves únicas que permitem a sua leitura.",
"Verify User": "Verificar usuária(o)", "Verify User": "Confirmar usuário",
"For extra security, verify this user by checking a one-time code on both of your devices.": "Para maior segurança, verifique esta(e) usuária(o) verificando um código único em ambos aparelhos.", "For extra security, verify this user by checking a one-time code on both of your devices.": "Para maior segurança, confirme este usuário comparando um código único em ambos os aparelhos.",
"You are about to remove %(count)s messages by %(user)s. This cannot be undone. Do you wish to continue?|other": "Você apagará para todos as %(count)s mensagens de %(user)s na sala. Isso não pode ser desfeito. Deseja continuar?", "You are about to remove %(count)s messages by %(user)s. This cannot be undone. Do you wish to continue?|other": "Você apagará para todos as %(count)s mensagens de %(user)s na sala. Isso não pode ser desfeito. Deseja continuar?",
"You are about to remove %(count)s messages by %(user)s. This cannot be undone. Do you wish to continue?|one": "Você está a ponto de remover 1 mensagem de %(user)s. Isso não poderá ser desfeito. Quer continuar?", "You are about to remove %(count)s messages by %(user)s. This cannot be undone. Do you wish to continue?|one": "Você está a ponto de remover 1 mensagem de %(user)s. Isso não poderá ser desfeito. Quer continuar?",
"This client does not support end-to-end encryption.": "A sua versão do aplicativo não suporta a criptografia de ponta a ponta.", "This client does not support end-to-end encryption.": "A sua versão do aplicativo não suporta a criptografia de ponta a ponta.",
"The session you are trying to verify doesn't support scanning a QR code or emoji verification, which is what %(brand)s supports. Try with a different client.": "A sessão que você está tentando verificar não permite escanear QR code ou verificação via emojis, que é o que %(brand)s permite. Tente um cliente diferente.", "The session you are trying to verify doesn't support scanning a QR code or emoji verification, which is what %(brand)s supports. Try with a different client.": "A sessão que você deseja confirmar não é compatível com o escaneamento de código QR ou a confirmação via emojis do %(brand)s. Tente confirmar a partir de outro aplicativo do Element.",
"Verify by scanning": "Verificar através de QR Code", "Verify by scanning": "Confirmar através de QR Code",
"If you can't scan the code above, verify by comparing unique emoji.": "Se você não consegue escanear o código acima, verifique comparando os emojis únicos.", "If you can't scan the code above, verify by comparing unique emoji.": "Se você não consegue escanear o código acima, confirme comparando emojis únicos.",
"Verify by comparing unique emoji.": "Verificar comparando emoji único.", "Verify by comparing unique emoji.": "Confirmar comparando emojis únicos.",
"Verify by emoji": "Verificar por emoji", "Verify by emoji": "Confirmar por emojis",
"Verify all users in a room to ensure it's secure.": "Verificar todas(os) as(os) usuárias(os) em uma sala para se certificar que ela é segura.", "Verify all users in a room to ensure it's secure.": "Verifique todos os usuários em uma sala para se certificar de que ela está segura.",
"In encrypted rooms, verify all users to ensure its secure.": "Em salas criptografadas, verificar todas(os) as(os) usuárias(os) para garantir que elas são seguras.", "In encrypted rooms, verify all users to ensure its secure.": "Em salas criptografadas, verifique todos os usuários para garantir que a sala está segura.",
"Start verification again from the notification.": "Iniciar verificação novamente, após a notificação.", "Start verification again from the notification.": "Iniciar a confirmação novamente, após a notificação.",
"Start verification again from their profile.": "Iniciar a verificação novamente a partir do perfil deste usuário.", "Start verification again from their profile.": "Iniciar a confirmação novamente, a partir do perfil deste usuário.",
"Encryption enabled": "Criptografia ativada", "Encryption enabled": "Criptografia ativada",
"Messages in this room are end-to-end encrypted. Learn more & verify this user in their user profile.": "As mensagens nesta sala estão criptografadas de ponta a ponta. Lembre-se de verificar este usuário no perfil dele/dela.", "Messages in this room are end-to-end encrypted. Learn more & verify this user in their user profile.": "As mensagens nesta sala estão criptografadas de ponta a ponta. Lembre-se de confirmar este usuário no perfil dele/dela.",
"Encryption not enabled": "Criptografia desativada", "Encryption not enabled": "Criptografia desativada",
"The encryption used by this room isn't supported.": "A criptografia usada nesta sala não é suportada.", "The encryption used by this room isn't supported.": "A criptografia usada nesta sala não é suportada.",
"%(name)s wants to verify": "%(name)s deseja verificar", "%(name)s wants to verify": "%(name)s solicita confirmação",
"Smileys & People": "Sorrisos e pessoas", "Smileys & People": "Sorrisos e pessoas",
"Widgets do not use message encryption.": "Widgets não usam criptografia de mensagens.", "Widgets do not use message encryption.": "Widgets não usam criptografia de mensagens.",
"Please <newIssueLink>create a new issue</newIssueLink> on GitHub so that we can investigate this bug.": "Por favor, <newIssueLink>crie um novo bilhete de erro</newIssueLink> no GitHub para que possamos investigar esta falha.", "Please <newIssueLink>create a new issue</newIssueLink> on GitHub so that we can investigate this bug.": "Por favor, <newIssueLink>crie um novo bilhete de erro</newIssueLink> no GitHub para que possamos investigar esta falha.",
@ -1520,9 +1520,9 @@
"Create a private room": "Criar uma sala privada", "Create a private room": "Criar uma sala privada",
"Block users on other matrix homeservers from joining this room (This setting cannot be changed later!)": "Impedir usuários de outros servidores na rede Matrix de entrarem nesta sala (Essa configuração não pode ser alterada posteriormente!)", "Block users on other matrix homeservers from joining this room (This setting cannot be changed later!)": "Impedir usuários de outros servidores na rede Matrix de entrarem nesta sala (Essa configuração não pode ser alterada posteriormente!)",
"You've previously used a newer version of %(brand)s with this session. To use this version again with end to end encryption, you will need to sign out and back in again.": "Você já usou uma versão mais recente do %(brand)s nesta sessão. Para usar esta versão novamente com a criptografia de ponta a ponta, você terá que se desconectar e entrar novamente.", "You've previously used a newer version of %(brand)s with this session. To use this version again with end to end encryption, you will need to sign out and back in again.": "Você já usou uma versão mais recente do %(brand)s nesta sessão. Para usar esta versão novamente com a criptografia de ponta a ponta, você terá que se desconectar e entrar novamente.",
"Verify this user to mark them as trusted. Trusting users gives you extra peace of mind when using end-to-end encrypted messages.": "Verifique este usuário para torná-lo confiável. Confiar nos usuários fornece segurança adicional ao trocar mensagens criptografadas de ponta a ponta.", "Verify this user to mark them as trusted. Trusting users gives you extra peace of mind when using end-to-end encrypted messages.": "Confirme este usuário para torná-lo confiável. Confiar nos usuários fornece segurança adicional ao trocar mensagens criptografadas de ponta a ponta.",
"Verify this device to mark it as trusted. Trusting this device gives you and other users extra peace of mind when using end-to-end encrypted messages.": "Verifique este aparelho para torná-lo confiável. Confiar neste aparelho fornecerá segurança adicional para você e aos outros ao trocarem mensagens criptografadas de ponta a ponta.", "Verify this device to mark it as trusted. Trusting this device gives you and other users extra peace of mind when using end-to-end encrypted messages.": "Confirme este aparelho para torná-lo confiável. Confiar neste aparelho fornecerá segurança adicional para você e aos outros ao trocarem mensagens criptografadas de ponta a ponta.",
"We couldn't create your DM. Please check the users you want to invite and try again.": "Não conseguimos criar sua mensagem direta. Por favor, verifique as(os) usuárias(os) que você quer convidar e tente novamente.", "We couldn't create your DM. Please check the users you want to invite and try again.": "Não conseguimos criar sua mensagem direta. Por favor, verifique os usuários que você deseja convidar e tente novamente.",
"Start a conversation with someone using their name, username (like <userId/>) or email address.": "Comece uma conversa com alguém usando o seu respectivo nome e sobrenome, nome de usuário (por exemplo: <userId/>) ou endereço de e-mail.", "Start a conversation with someone using their name, username (like <userId/>) or email address.": "Comece uma conversa com alguém usando o seu respectivo nome e sobrenome, nome de usuário (por exemplo: <userId/>) ou endereço de e-mail.",
"a new master key signature": "uma nova chave mestra de assinatura", "a new master key signature": "uma nova chave mestra de assinatura",
"a new cross-signing key signature": "uma nova chave de autoverificação", "a new cross-signing key signature": "uma nova chave de autoverificação",
@ -1530,9 +1530,9 @@
"I don't want my encrypted messages": "Não quero minhas mensagens criptografadas", "I don't want my encrypted messages": "Não quero minhas mensagens criptografadas",
"You'll lose access to your encrypted messages": "Você perderá acesso às suas mensagens criptografadas", "You'll lose access to your encrypted messages": "Você perderá acesso às suas mensagens criptografadas",
"Session key": "Chave da sessão", "Session key": "Chave da sessão",
"Verify session": "Verificar sessão", "Verify session": "Confirmar sessão",
"We recommend you change your password and recovery key in Settings immediately": "Nós recomendamos que você altere imediatamente sua senha e chave de recuperação nas Configurações", "We recommend you change your password and recovery key in Settings immediately": "Nós recomendamos que você altere imediatamente sua senha e chave de recuperação nas Configurações",
"Use this session to verify your new one, granting it access to encrypted messages:": "Use esta sessão para verificar a sua nova sessão, dando a ela acesso às mensagens criptografadas:", "Use this session to verify your new one, granting it access to encrypted messages:": "Use esta sessão para confirmar a sua nova sessão, dando a ela acesso às mensagens criptografadas:",
"Youre already signed in and good to go here, but you can also grab the latest versions of the app on all platforms at <a>element.io/get-started</a>.": "Você já está logada(o) e pode começar a usar à vontade, mas você também pode buscar pelas últimas versões do app em todas as plataformas em <a>element.io/get-started</a>.", "Youre already signed in and good to go here, but you can also grab the latest versions of the app on all platforms at <a>element.io/get-started</a>.": "Você já está logada(o) e pode começar a usar à vontade, mas você também pode buscar pelas últimas versões do app em todas as plataformas em <a>element.io/get-started</a>.",
"Go to Element": "Ir a Element", "Go to Element": "Ir a Element",
"Were excited to announce Riot is now Element!": "Estamos muito felizes de anunciar que agora Riot é Element!", "Were excited to announce Riot is now Element!": "Estamos muito felizes de anunciar que agora Riot é Element!",
@ -1541,18 +1541,18 @@
"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.": "Reportar esta mensagem enviará o seu 'event ID' único para o/a administrador/a do seu Homeserver. Se as mensagens nesta sala são criptografadas, o/a administrador/a não conseguirá ler o texto da mensagem nem ver nenhuma imagem ou arquivo.", "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.": "Reportar esta mensagem enviará o seu 'event ID' único para o/a administrador/a do seu Homeserver. Se as mensagens nesta sala são criptografadas, o/a administrador/a não conseguirá ler o texto da mensagem nem ver nenhuma imagem ou arquivo.",
"Sign out and remove encryption keys?": "Fazer logout e remover as chaves de criptografia?", "Sign out and remove encryption keys?": "Fazer logout e remover as chaves de criptografia?",
"Some session data, including encrypted message keys, is missing. Sign out and sign in to fix this, restoring keys from backup.": "Alguns dados de sessão, incluindo chaves de mensagens criptografadas, estão faltando. Faça logout e entre novamente para resolver isso, restaurando as chaves do backup.", "Some session data, including encrypted message keys, is missing. Sign out and sign in to fix this, restoring keys from backup.": "Alguns dados de sessão, incluindo chaves de mensagens criptografadas, estão faltando. Faça logout e entre novamente para resolver isso, restaurando as chaves do backup.",
"Verify other session": "Verificar outra sessão", "Verify other session": "Confirmar outra sessão",
"A widget would like to verify your identity": "Um Widget quer verificar sua identidade", "A widget would like to verify your identity": "Um widget deseja confirmar sua identidade",
"A widget located at %(widgetUrl)s would like to verify your identity. By allowing this, the widget will be able to verify your user ID, but not perform actions as you.": "Um widget localizado em %(widgetUrl)s deseja verificar sua identidade. Permitindo isso, o widget poderá verificar sua ID de usuário, mas não poderá realizar nenhuma ação em seu nome.", "A widget located at %(widgetUrl)s would like to verify your identity. By allowing this, the widget will be able to verify your user ID, but not perform actions as you.": "Um widget localizado em %(widgetUrl)s deseja confirmar sua identidade. Permitindo isso, o widget poderá verificar sua ID de usuário, mas não poderá realizar nenhuma ação em seu nome.",
"Wrong Recovery Key": "Chave de recuperação errada", "Wrong Recovery Key": "Chave de recuperação errada",
"Invalid Recovery Key": "Chave de recuperação inválida", "Invalid Recovery Key": "Chave de recuperação inválida",
"Unable to access secret storage. Please verify that you entered the correct recovery passphrase.": "Não foi possível acessar o armazenamento secreto. Por favor, verifique que você entrou com a frase de recuperação correta.", "Unable to access secret storage. Please verify that you entered the correct recovery passphrase.": "Não foi possível acessar o armazenamento secreto. Por favor, verifique que você digitou a frase de recuperação correta.",
"Enter your Security Phrase or <button>Use your Security Key</button> to continue.": "Entre com sua Frase de Segurança ou <button>use sua Chave de Segurança</button> para continuar.", "Enter your Security Phrase or <button>Use your Security Key</button> to continue.": "Entre com sua Frase de Segurança ou <button>use sua Chave de Segurança</button> para continuar.",
"Security Key": "Chave de Segurança", "Security Key": "Chave de Segurança",
"Use your Security Key to continue.": "Use sua Chave de Segurança para continuar.", "Use your Security Key to continue.": "Use sua Chave de Segurança para continuar.",
"Recovery key mismatch": "A chave de segurança não corresponde à correta", "Recovery key mismatch": "Chave de recuperação incorreta",
"Backup could not be decrypted with this recovery key: please verify that you entered the correct recovery key.": "O backup não pôde ser descriptografado com esta chave de recuperação: por favor, verifique se você entrou com a chave de recuperação correta.", "Backup could not be decrypted with this recovery key: please verify that you entered the correct recovery key.": "O backup não pôde ser descriptografado com esta chave de recuperação: por favor, verifique se você digitou a chave de recuperação correta.",
"Backup could not be decrypted with this recovery passphrase: please verify that you entered the correct recovery passphrase.": "O backup não pôde ser descriptografado com esta frase de recuperação: por favor, verifique se você entrou com a frase de recuperação correta.", "Backup could not be decrypted with this recovery passphrase: please verify that you entered the correct recovery passphrase.": "O backup não pôde ser descriptografado com esta frase de recuperação: por favor, verifique se você digitou a frase de recuperação correta.",
"<b>Warning</b>: you should only set up key backup from a trusted computer.": "<b>Atenção</b>: você só deve configurar a cópia de segurança (backup) das chaves em um computador de sua confiança.", "<b>Warning</b>: you should only set up key backup from a trusted computer.": "<b>Atenção</b>: você só deve configurar a cópia de segurança (backup) das chaves em um computador de sua confiança.",
"Enter recovery key": "Digite a chave de recuperação", "Enter recovery key": "Digite a chave de recuperação",
"<b>Warning</b>: You should only set up key backup from a trusted computer.": "<b>Atenção</b>: Você só deve configurar a cópia de segurança (backup) das chaves em um computador de sua confiança.", "<b>Warning</b>: You should only set up key backup from a trusted computer.": "<b>Atenção</b>: Você só deve configurar a cópia de segurança (backup) das chaves em um computador de sua confiança.",
@ -1564,20 +1564,20 @@
"Welcome to %(appName)s": "Bem-vinda/o ao %(appName)s", "Welcome to %(appName)s": "Bem-vinda/o ao %(appName)s",
"Liberate your communication": "Liberte sua comunicação", "Liberate your communication": "Liberte sua comunicação",
"Send a Direct Message": "Enviar uma mensagem", "Send a Direct Message": "Enviar uma mensagem",
"Explore Public Rooms": "Explore as salas públicas", "Explore Public Rooms": "Explorar salas públicas",
"Create a Group Chat": "Criar um chat de grupo", "Create a Group Chat": "Criar um chat de grupo",
"Explore rooms": "Explorar salas", "Explore rooms": "Explorar salas",
"Data from an older version of %(brand)s 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.": "Detectamos uma versão mais antiga do %(brand)s. Isso fará com que a criptografia de ponta a ponta não funcione corretamente. As mensagens criptografadas de ponta a ponta trocadas recentemente, enquanto você usava a versão mais antiga, talvez não sejam descriptografáveis na nova versão. Isso também poderá fazer com que as mensagens trocadas nesta sessão falhem na mais atual. Se você tiver problemas, desconecte-se e entre novamente. Para manter o histórico de mensagens, exporte e reimporte suas chaves.", "Data from an older version of %(brand)s 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.": "Detectamos uma versão mais antiga do %(brand)s. Isso fará com que a criptografia de ponta a ponta não funcione corretamente. As mensagens criptografadas de ponta a ponta trocadas recentemente, enquanto você usava a versão mais antiga, talvez não sejam descriptografáveis na nova versão. Isso também poderá fazer com que as mensagens trocadas nesta sessão falhem na mais atual. Se você tiver problemas, desconecte-se e entre novamente. Para manter o histórico de mensagens, exporte e reimporte suas chaves.",
"%(creator)s created and configured the room.": "%(creator)s criou e configurou esta sala.", "%(creator)s created and configured the room.": "%(creator)s criou e configurou esta sala.",
"If you can't find the room you're looking for, ask for an invite or <a>Create a new room</a>.": "Se você não conseguir encontrar a sala que está procurando, peça um convite para a sala ou <a>Crie uma nova sala</a>.", "If you can't find the room you're looking for, ask for an invite or <a>Create a new room</a>.": "Se você não conseguir encontrar a sala que está procurando, peça um convite para a sala ou <a>Crie uma nova sala</a>.",
"Verify this login": "Verificar este login", "Verify this login": "Confirmar este login",
"Changing your password will reset any end-to-end encryption keys on all of your sessions, making encrypted chat history unreadable. Set up Key Backup or export your room keys from another session before resetting your password.": "Alterar a sua senha redefinirá todas as chaves de criptografia de ponta a ponta existentes em todas as suas sessões, tornando o histórico de mensagens criptografadas ilegível. Faça uma cópia (backup) das suas chaves, ou exporte as chaves de outra sessão antes de alterar a sua senha.", "Changing your password will reset any end-to-end encryption keys on all of your sessions, making encrypted chat history unreadable. Set up Key Backup or export your room keys from another session before resetting your password.": "Alterar a sua senha redefinirá todas as chaves de criptografia de ponta a ponta existentes em todas as suas sessões, tornando o histórico de mensagens criptografadas ilegível. Faça uma cópia (backup) das suas chaves, ou exporte as chaves de outra sessão antes de alterar a sua senha.",
"Create account": "Criar conta", "Create account": "Criar conta",
"Create your account": "Criar sua conta", "Create your account": "Criar sua conta",
"Use Recovery Key or Passphrase": "Use a chave de recuperação, ou a frase de recuperação", "Use Recovery Key or Passphrase": "Use a chave de recuperação, ou a frase de recuperação",
"Use Recovery Key": "Use a chave de recuperação", "Use Recovery Key": "Usar a chave de recuperação",
"Confirm your identity by verifying this login from one of your other sessions, granting it access to encrypted messages.": "Confirme sua identidade através da verificação deste login em qualquer uma de suas outras sessões, garantindo a elas acesso a mensagens criptografadas.", "Confirm your identity by verifying this login from one of your other sessions, granting it access to encrypted messages.": "Confirme sua identidade através da confirmação deste login em qualquer uma de suas outras sessões, garantindo a elas acesso a mensagens criptografadas.",
"Your new session is now verified. It has access to your encrypted messages, and other users will see it as trusted.": "Sua nova sessão está agora verificada. Ela tem acesso às suas mensagens criptografadas, e outras(os) usuárias(os) poderão ver esta sessão como confiável.", "Your new session is now verified. It has access to your encrypted messages, and other users will see it as trusted.": "Sua nova sessão está agora confirmada. Ela tem acesso às suas mensagens criptografadas, e outros usuários poderão ver esta sessão como confiável.",
"Without completing security on this session, it wont have access to encrypted messages.": "Sem completar os procedimentos de segurança nesta sessão, você não terá acesso a mensagens criptografadas.", "Without completing security on this session, it wont have access to encrypted messages.": "Sem completar os procedimentos de segurança nesta sessão, você não terá acesso a mensagens criptografadas.",
"Regain access to your account and recover encryption keys stored in this session. Without them, you wont be able to read all of your secure messages in any session.": "Recupere acesso à sua conta e restaure as chaves de criptografia armazenadas nesta sessão. Sem elas, você não conseguirá ler todas as suas mensagens seguras em nenhuma sessão.", "Regain access to your account and recover encryption keys stored in this session. Without them, you wont be able to read all of your secure messages in any session.": "Recupere acesso à sua conta e restaure as chaves de criptografia armazenadas nesta sessão. Sem elas, você não conseguirá ler todas as suas mensagens seguras em nenhuma sessão.",
"Warning: Your personal data (including encryption keys) is still stored in this session. Clear it if you're finished using this session, or want to sign in to another account.": "Atenção: Seus dados pessoais (incluindo chaves de criptografia) ainda estão armazenados nesta sessão. Apague-os quando tiver finalizado esta sessão, ou se quer entrar com outra conta.", "Warning: Your personal data (including encryption keys) is still stored in this session. Clear it if you're finished using this session, or want to sign in to another account.": "Atenção: Seus dados pessoais (incluindo chaves de criptografia) ainda estão armazenados nesta sessão. Apague-os quando tiver finalizado esta sessão, ou se quer entrar com outra conta.",
@ -1588,7 +1588,7 @@
"Well generate a Security Key for you to store somewhere safe, like a password manager or a safe.": "Nós geramos uma Chave de Segurança para você. Por favor, guarde-a em um lugar seguro, como um gerenciador de senhas ou um cofre.", "Well generate a Security Key for you to store somewhere safe, like a password manager or a safe.": "Nós geramos uma Chave de Segurança para você. Por favor, guarde-a em um lugar seguro, como um gerenciador de senhas ou um cofre.",
"Use a secret phrase only you know, and optionally save a Security Key to use for backup.": "Use uma frase secreta que apenas você conhece, e opcionalmente salve uma Chave de Segurança para usar como cópia de segurança (backup).", "Use a secret phrase only you know, and optionally save a Security Key to use for backup.": "Use uma frase secreta que apenas você conhece, e opcionalmente salve uma Chave de Segurança para usar como cópia de segurança (backup).",
"Restore your key backup to upgrade your encryption": "Restaurar a sua cópia segura (backup) de chaves para atualizar a sua criptografia", "Restore your key backup to upgrade your encryption": "Restaurar a sua cópia segura (backup) de chaves para atualizar a sua criptografia",
"Upgrade this session to allow it to verify other sessions, granting them access to encrypted messages and marking them as trusted for other users.": "Atualize esta sessão para permitir que ela verifique outras sessões, dando a elas acesso às mensagens criptografadas e marcando-as como confiáveis para as(os) demais usuárias(os).", "Upgrade this session to allow it to verify other sessions, granting them access to encrypted messages and marking them as trusted for other users.": "Atualize esta sessão para permitir que ela confirme outras sessões, dando a elas acesso às mensagens criptografadas e marcando-as como confiáveis para os seus contatos.",
"Store your Security Key somewhere safe, like a password manager or a safe, as its used to safeguard your encrypted data.": "Guarde sua Chave de Segurança em algum lugar seguro, como por exemplo um gestor de senhas ou um cofre, já que esta chave é a proteção para seus dados criptografados.", "Store your Security Key somewhere safe, like a password manager or a safe, as its used to safeguard your encrypted data.": "Guarde sua Chave de Segurança em algum lugar seguro, como por exemplo um gestor de senhas ou um cofre, já que esta chave é a proteção para seus dados criptografados.",
"If you cancel now, you may lose encrypted messages & data if you lose access to your logins.": "Se você cancelar agora, poderá perder mensagens e dados criptografados se você perder acesso aos seus logins atuais.", "If you cancel now, you may lose encrypted messages & data if you lose access to your logins.": "Se você cancelar agora, poderá perder mensagens e dados criptografados se você perder acesso aos seus logins atuais.",
"Upgrade your encryption": "Atualizar sua criptografia", "Upgrade your encryption": "Atualizar sua criptografia",
@ -1608,7 +1608,7 @@
"This session has detected that your recovery passphrase and key for Secure Messages have been removed.": "Esta sessão detectou que sua frase e chave de recuperação para Mensagens Seguras foram removidas.", "This session has detected that your recovery passphrase and key for Secure Messages have been removed.": "Esta sessão detectou que sua frase e chave de recuperação para Mensagens Seguras foram removidas.",
"If you did this accidentally, you can setup Secure Messages on this session which will re-encrypt this session's message history with a new recovery method.": "Se você fez isso acidentalmente, você pode configurar Mensagens Seguras nesta sessão, o que vai re-criptografar o histórico de mensagens desta sessão com um novo método de recuperação.", "If you did this accidentally, you can setup Secure Messages on this session which will re-encrypt this session's message history with a new recovery method.": "Se você fez isso acidentalmente, você pode configurar Mensagens Seguras nesta sessão, o que vai re-criptografar o histórico de mensagens desta sessão com um novo método de recuperação.",
"If disabled, messages from encrypted rooms won't appear in search results.": "Se desativado, as mensagens de salas criptografadas não aparecerão em resultados de buscas.", "If disabled, messages from encrypted rooms won't appear in search results.": "Se desativado, as mensagens de salas criptografadas não aparecerão em resultados de buscas.",
"%(brand)s is securely caching encrypted messages locally for them to appear in search results:": "%(brand)s está armazenando de forma segura as mensagens criptografadas localmente, para que possam aparecer em resultados das buscas:", "%(brand)s is securely caching encrypted messages locally for them to appear in search results:": "%(brand)s está armazenando de forma segura as mensagens criptografadas localmente, para que possam aparecer nos resultados das buscas:",
"%(doneRooms)s out of %(totalRooms)s": "%(doneRooms)s de %(totalRooms)s", "%(doneRooms)s out of %(totalRooms)s": "%(doneRooms)s de %(totalRooms)s",
"Jump to start/end of the composer": "Pule para o início/fim do compositor", "Jump to start/end of the composer": "Pule para o início/fim do compositor",
"Click the button below to confirm adding this phone number.": "Clique no botão abaixo para confirmar a adição deste número de telefone.", "Click the button below to confirm adding this phone number.": "Clique no botão abaixo para confirmar a adição deste número de telefone.",
@ -1620,7 +1620,7 @@
"Leave Room": "Sair da sala", "Leave Room": "Sair da sala",
"Forget Room": "Esquecer Sala", "Forget Room": "Esquecer Sala",
"Favourited": "Favoritado", "Favourited": "Favoritado",
"You cancelled verifying %(name)s": "Você cancelou a verificação do %(name)s", "You cancelled verifying %(name)s": "Você cancelou a confirmação de %(name)s",
"You accepted": "Você aceitou", "You accepted": "Você aceitou",
"%(name)s accepted": "%(name)s aceitou", "%(name)s accepted": "%(name)s aceitou",
"You declined": "Você recusou", "You declined": "Você recusou",
@ -1629,7 +1629,7 @@
"%(name)s cancelled": "%(name)s cancelou", "%(name)s cancelled": "%(name)s cancelou",
"Accepting …": "Aceitando…", "Accepting …": "Aceitando…",
"Declining …": "Recusando…", "Declining …": "Recusando…",
"You sent a verification request": "Você enviou uma solicitação de verificação", "You sent a verification request": "Você enviou uma solicitação de confirmação",
"Show all": "Mostrar tudo", "Show all": "Mostrar tudo",
"Reactions": "Reações", "Reactions": "Reações",
"<reactors/><reactedWith> reacted with %(content)s</reactedWith>": "<reactors/><reactedWith> reagiu com %(content)s</reactedWith>", "<reactors/><reactedWith> reacted with %(content)s</reactedWith>": "<reactors/><reactedWith> reagiu com %(content)s</reactedWith>",
@ -1697,7 +1697,7 @@
"Confirm account deactivation": "Confirmar desativação da conta", "Confirm account deactivation": "Confirmar desativação da conta",
"Server did not return valid authentication information.": "O servidor não retornou informações de autenticação válidas.", "Server did not return valid authentication information.": "O servidor não retornou informações de autenticação válidas.",
"View Servers in Room": "Ver Servidores na Sala", "View Servers in Room": "Ver Servidores na Sala",
"Verification Requests": "Solicitações de verificação", "Verification Requests": "Solicitações de confirmação",
"Integrations are disabled": "As integrações estão desativadas", "Integrations are disabled": "As integrações estão desativadas",
"Integrations not allowed": "As integrações não estão permitidas", "Integrations not allowed": "As integrações não estão permitidas",
"End": "Fim", "End": "Fim",
@ -1724,11 +1724,11 @@
"Other published addresses:": "Outros endereços publicados:", "Other published addresses:": "Outros endereços publicados:",
"New published address (e.g. #alias:server)": "Novo endereço publicado (por exemplo, #apelido:server)", "New published address (e.g. #alias:server)": "Novo endereço publicado (por exemplo, #apelido:server)",
"Local Addresses": "Endereços locais", "Local Addresses": "Endereços locais",
"%(name)s cancelled verifying": "%(name)s cancelou a verificação", "%(name)s cancelled verifying": "%(name)s cancelou a confirmação",
"Your display name": "Seu nome e sobrenome", "Your display name": "Seu nome e sobrenome",
"Your avatar URL": "Link da sua foto de perfil", "Your avatar URL": "Link da sua foto de perfil",
"Your user ID": "Sua ID de usuário", "Your user ID": "Sua ID de usuário",
"%(brand)s URL": "Link de %(brand)s", "%(brand)s URL": "Link do %(brand)s",
"Using this widget may share data <helpIcon /> with %(widgetDomain)s & your Integration Manager.": "Se você usar esse widget, os dados poderão ser compartilhados <helpIcon /> com %(widgetDomain)s & seu Gerenciador de Integrações.", "Using this widget may share data <helpIcon /> with %(widgetDomain)s & your Integration Manager.": "Se você usar esse widget, os dados poderão ser compartilhados <helpIcon /> com %(widgetDomain)s & seu Gerenciador de Integrações.",
"Using this widget may share data <helpIcon /> with %(widgetDomain)s.": "Se você usar esse widget, os dados <helpIcon /> poderão ser compartilhados com %(widgetDomain)s.", "Using this widget may share data <helpIcon /> with %(widgetDomain)s.": "Se você usar esse widget, os dados <helpIcon /> poderão ser compartilhados com %(widgetDomain)s.",
"%(severalUsers)smade no changes %(count)s times|other": "%(severalUsers)s não fizeram alterações %(count)s vezes", "%(severalUsers)smade no changes %(count)s times|other": "%(severalUsers)s não fizeram alterações %(count)s vezes",
@ -1747,8 +1747,8 @@
"Topic (optional)": "Descrição (opcional)", "Topic (optional)": "Descrição (opcional)",
"There was a problem communicating with the server. Please try again.": "Ocorreu um problema na comunicação com o servidor. Por favor, tente novamente.", "There was a problem communicating with the server. Please try again.": "Ocorreu um problema na comunicação com o servidor. Por favor, tente novamente.",
"Server did not require any authentication": "O servidor não exigiu autenticação", "Server did not require any authentication": "O servidor não exigiu autenticação",
"Verifying this user will mark their session as trusted, and also mark your session as trusted to them.": "Se você verificar esse usuário, a sessão será marcada como confiável para você e para ele.", "Verifying this user will mark their session as trusted, and also mark your session as trusted to them.": "Se você confirmar esse usuário, a sessão será marcada como confiável para você e para ele.",
"Verifying this device will mark it as trusted, and users who have verified with you will trust this device.": "Verificar este aparelho o marcará como confiável, e os usuários que confirmaram com você também confiarão neste aparelho.", "Verifying this device will mark it as trusted, and users who have verified with you will trust this device.": "Confirmar este aparelho o marcará como confiável para você e para os usuários que se confirmaram com você.",
"Keep going...": "Continue...", "Keep going...": "Continue...",
"The username field must not be blank.": "O campo do nome de usuário não pode ficar em branco.", "The username field must not be blank.": "O campo do nome de usuário não pode ficar em branco.",
"Username": "Nome de usuário", "Username": "Nome de usuário",
@ -1767,7 +1767,7 @@
"You cannot sign in to your account. Please contact your homeserver admin for more information.": "Você não pôde se conectar na sua conta. Entre em contato com o administrador do servidor para obter mais informações.", "You cannot sign in to your account. Please contact your homeserver admin for more information.": "Você não pôde se conectar na sua conta. Entre em contato com o administrador do servidor para obter mais informações.",
"Confirm adding this phone number by using Single Sign On to prove your identity.": "Confirme a adição deste número de telefone usando o Login Único para provar sua identidade.", "Confirm adding this phone number by using Single Sign On to prove your identity.": "Confirme a adição deste número de telefone usando o Login Único para provar sua identidade.",
"Use an identity server to invite by email. Click continue to use the default identity server (%(defaultIdentityServerName)s) or manage in Settings.": "Use um servidor de identidade para convidar por e-mail. Clique em continuar para usar o servidor de identidade padrão (%(defaultIdentityServerName)s) ou gerencie nas Configurações.", "Use an identity server to invite by email. Click continue to use the default identity server (%(defaultIdentityServerName)s) or manage in Settings.": "Use um servidor de identidade para convidar por e-mail. Clique em continuar para usar o servidor de identidade padrão (%(defaultIdentityServerName)s) ou gerencie nas Configurações.",
"You might have configured them in a client other than %(brand)s. You cannot tune them in %(brand)s but they still apply.": "Você pode ter configurado estas opções em um cliente que não seja %(brand)s. Você não pode ajustar essas opções no %(brand)s, mas elas ainda se aplicam.", "You might have configured them in a client other than %(brand)s. You cannot tune them in %(brand)s but they still apply.": "Você pode ter configurado estas opções em um aplicativo que não seja o %(brand)s. Você não pode ajustar essas opções no %(brand)s, mas elas ainda se aplicam.",
"Enable audible notifications for this session": "Ativar o som de notificações nesta sessão", "Enable audible notifications for this session": "Ativar o som de notificações nesta sessão",
"Display Name": "Nome e sobrenome", "Display Name": "Nome e sobrenome",
"Identity Server URL must be HTTPS": "O link do servidor de identidade deve começar com HTTPS", "Identity Server URL must be HTTPS": "O link do servidor de identidade deve começar com HTTPS",
@ -1797,7 +1797,7 @@
"Disconnecting from your identity server will mean you won't be discoverable by other users and you won't be able to invite others by email or phone.": "Desconectar-se do servidor de identidade significa que você não poderá ser descoberto por outros usuários e não poderá convidar outras pessoas por e-mail ou número de celular.", "Disconnecting from your identity server will mean you won't be discoverable by other users and you won't be able to invite others by email or phone.": "Desconectar-se do servidor de identidade significa que você não poderá ser descoberto por outros usuários e não poderá convidar outras pessoas por e-mail ou número de celular.",
"Using an identity server is optional. If you choose not to use an identity server, you won't be discoverable by other users and you won't be able to invite others by email or phone.": "Usar um servidor de identidade é opcional. Se você optar por não usar um servidor de identidade, não poderá ser descoberto por outros usuários e não poderá convidar outras pessoas por e-mail ou por número de celular.", "Using an identity server is optional. If you choose not to use an identity server, you won't be discoverable by other users and you won't be able to invite others by email or phone.": "Usar um servidor de identidade é opcional. Se você optar por não usar um servidor de identidade, não poderá ser descoberto por outros usuários e não poderá convidar outras pessoas por e-mail ou por número de celular.",
"Do not use an identity server": "Não usar um servidor de identidade", "Do not use an identity server": "Não usar um servidor de identidade",
"Enter a new identity server": "Digitar um novo servidor de identidade", "Enter a new identity server": "Digite um novo servidor de identidade",
"Change": "Alterar", "Change": "Alterar",
"Manage integrations": "Gerenciar integrações", "Manage integrations": "Gerenciar integrações",
"New version available. <a>Update now.</a>": "Nova versão disponível. <a>Atualize agora.</a>", "New version available. <a>Update now.</a>": "Nova versão disponível. <a>Atualize agora.</a>",
@ -1813,9 +1813,9 @@
"Message layout": "Aparência da mensagem", "Message layout": "Aparência da mensagem",
"Compact": "Compacto", "Compact": "Compacto",
"Modern": "Moderno", "Modern": "Moderno",
"Set the name of a font installed on your system & %(brand)s will attempt to use it.": "Defina o nome de uma fonte instalada no seu sistema e %(brand)s tentará usá-la.", "Set the name of a font installed on your system & %(brand)s will attempt to use it.": "Defina o nome de uma fonte instalada no seu sistema e o %(brand)s tentará usá-la.",
"Customise your appearance": "Personalize sua aparência", "Customise your appearance": "Personalize sua aparência",
"Appearance Settings only affect this %(brand)s session.": "As Configurações de aparência afetam apenas esta sessão do %(brand)s.", "Appearance Settings only affect this %(brand)s session.": "As configurações de aparência afetam apenas esta sessão do %(brand)s.",
"Your password was successfully changed. You will not receive push notifications on other sessions until you log back in to them": "Sua senha foi alterada com sucesso. Você não receberá notificações pop-up em outras sessões até fazer login novamente nelas", "Your password was successfully changed. You will not receive push notifications on other sessions until you log back in to them": "Sua senha foi alterada com sucesso. Você não receberá notificações pop-up em outras sessões até fazer login novamente nelas",
"Agree to the identity server (%(serverName)s) Terms of Service to allow yourself to be discoverable by email address or phone number.": "Concorde com os Termos de Serviço do servidor de identidade (%(serverName)s), para que você possa ser descoberto por endereço de e-mail ou por número de celular.", "Agree to the identity server (%(serverName)s) Terms of Service to allow yourself to be discoverable by email address or phone number.": "Concorde com os Termos de Serviço do servidor de identidade (%(serverName)s), para que você possa ser descoberto por endereço de e-mail ou por número de celular.",
"Discovery": "Contatos", "Discovery": "Contatos",
@ -1852,10 +1852,10 @@
"You can still join it because this is a public room.": "Você ainda pode entrar, porque esta é uma sala pública.", "You can still join it because this is a public room.": "Você ainda pode entrar, porque esta é uma sala pública.",
"Join the discussion": "Participar da discussão", "Join the discussion": "Participar da discussão",
"This invite to %(roomName)s was sent to %(email)s which is not associated with your account": "Este convite para %(roomName)s foi enviado para %(email)s, que não está associado à sua conta", "This invite to %(roomName)s was sent to %(email)s which is not associated with your account": "Este convite para %(roomName)s foi enviado para %(email)s, que não está associado à sua conta",
"Link this email with your account in Settings to receive invites directly in %(brand)s.": "Vincule esse e-mail à sua conta em Configurações, para receber convites diretamente em %(brand)s.", "Link this email with your account in Settings to receive invites directly in %(brand)s.": "Vincule esse e-mail à sua conta em Configurações, para receber convites diretamente no %(brand)s.",
"This invite to %(roomName)s was sent to %(email)s": "Este convite para %(roomName)s foi enviado para %(email)s", "This invite to %(roomName)s was sent to %(email)s": "Este convite para %(roomName)s foi enviado para %(email)s",
"Use an identity server in Settings to receive invites directly in %(brand)s.": "Use um servidor de identidade em Configurações para receber convites diretamente em %(brand)s.", "Use an identity server in Settings to receive invites directly in %(brand)s.": "Use um servidor de identidade em Configurações para receber convites diretamente no %(brand)s.",
"Share this email in Settings to receive invites directly in %(brand)s.": "Compartilhe este e-mail em Configurações para receber convites diretamente em %(brand)s.", "Share this email in Settings to receive invites directly in %(brand)s.": "Compartilhe este e-mail em Configurações para receber convites diretamente no %(brand)s.",
"Do you want to chat with %(user)s?": "Deseja conversar com %(user)s?", "Do you want to chat with %(user)s?": "Deseja conversar com %(user)s?",
"<userName/> wants to chat": "<userName/> quer conversar", "<userName/> wants to chat": "<userName/> quer conversar",
"Do you want to join %(roomName)s?": "Deseja se juntar a %(roomName)s?", "Do you want to join %(roomName)s?": "Deseja se juntar a %(roomName)s?",
@ -1867,9 +1867,9 @@
"Securely back up your keys to avoid losing them. <a>Learn more.</a>": "Faça backup de suas chaves com segurança para evitar perdê-las. <a>Saiba mais.</a>", "Securely back up your keys to avoid losing them. <a>Learn more.</a>": "Faça backup de suas chaves com segurança para evitar perdê-las. <a>Saiba mais.</a>",
"Not now": "Agora não", "Not now": "Agora não",
"Don't ask me again": "Não pergunte novamente", "Don't ask me again": "Não pergunte novamente",
"Appearance": "Mostrar", "Appearance": "Aparência",
"Show rooms with unread messages first": "Salas não lidas primeiro", "Show rooms with unread messages first": "Mostrar salas não lidas em primeiro",
"Show previews of messages": "Pré-visualizações de mensagens", "Show previews of messages": "Mostrar pré-visualizações de mensagens",
"Sort by": "Ordenar por", "Sort by": "Ordenar por",
"Activity": "Atividade recente", "Activity": "Atividade recente",
"A-Z": "A-Z", "A-Z": "A-Z",
@ -1954,25 +1954,25 @@
"Ban users": "Banir usuários", "Ban users": "Banir usuários",
"Remove messages": "Apagar mensagens dos outros", "Remove messages": "Apagar mensagens dos outros",
"Notify everyone": "Notificar todos", "Notify everyone": "Notificar todos",
"Your email address hasn't been verified yet": "Seu endereço de e-mail ainda não foi verificado", "Your email address hasn't been verified yet": "Seu endereço de e-mail ainda não foi confirmado",
"Revoke": "Revogar", "Revoke": "Revogar",
"Share": "Compartilhar", "Share": "Compartilhar",
"Unable to revoke sharing for phone number": "Não foi possível revogar o compartilhamento do número de celular", "Unable to revoke sharing for phone number": "Não foi possível revogar o compartilhamento do número de celular",
"Unable to share phone number": "Não foi possível compartilhar o número de celular", "Unable to share phone number": "Não foi possível compartilhar o número de celular",
"Please enter verification code sent via text.": "Digite o código de verificação enviado por mensagem de texto.", "Please enter verification code sent via text.": "Digite o código de confirmação enviado por mensagem de texto.",
"Remove %(email)s?": "Remover %(email)s?", "Remove %(email)s?": "Remover %(email)s?",
"Remove %(phone)s?": "Remover %(phone)s?", "Remove %(phone)s?": "Remover %(phone)s?",
"A text message has been sent to +%(msisdn)s. Please enter the verification code it contains.": "Digite o código de verificação enviado por mensagem de texto para +%(msisdn)s.", "A text message has been sent to +%(msisdn)s. Please enter the verification code it contains.": "Digite o código de confirmação enviado por mensagem de texto para +%(msisdn)s.",
"This user has not verified all of their sessions.": "Este usuário não verificou todas as próprias sessões.", "This user has not verified all of their sessions.": "Este usuário não confirmou todas as próprias sessões.",
"You have not verified this user.": "Você não verificou este usuário.", "You have not verified this user.": "Você não confirmou este usuário.",
"You have verified this user. This user has verified all of their sessions.": "Você confirmou este usuário. Este usuário verificou todas as próprias sessões.", "You have verified this user. This user has verified all of their sessions.": "Você confirmou este usuário. Este usuário confirmou todas as próprias sessões.",
"Someone is using an unknown session": "Alguém está usando uma sessão desconhecida", "Someone is using an unknown session": "Alguém está usando uma sessão desconhecida",
"Everyone in this room is verified": "Todos nesta sala estão verificados", "Everyone in this room is verified": "Todos nesta sala estão confirmados",
"Edit message": "Editar mensagem", "Edit message": "Editar mensagem",
"Mod": "Moderador", "Mod": "Moderador",
"Scroll to most recent messages": "Ir para as mensagens mais recentes", "Scroll to most recent messages": "Ir para as mensagens mais recentes",
"Close preview": "Fechar a visualização", "Close preview": "Fechar a visualização",
"Send a reply…": "Enviar uma resposta…", "Send a reply…": "Digite sua resposta…",
"Send a message…": "Digite uma mensagem…", "Send a message…": "Digite uma mensagem…",
"Bold": "Negrito", "Bold": "Negrito",
"Italics": "Itálico", "Italics": "Itálico",
@ -2003,9 +2003,9 @@
"Your homeserver": "Seu servidor local", "Your homeserver": "Seu servidor local",
"Trusted": "Confiável", "Trusted": "Confiável",
"Not trusted": "Não confiável", "Not trusted": "Não confiável",
"%(count)s verified sessions|other": "%(count)s sessões verificadas", "%(count)s verified sessions|other": "%(count)s sessões confirmadas",
"%(count)s verified sessions|one": "1 sessão verificada", "%(count)s verified sessions|one": "1 sessão confirmada",
"Hide verified sessions": "Esconder sessões verificadas", "Hide verified sessions": "Esconder sessões confirmadas",
"%(count)s sessions|other": "%(count)s sessões", "%(count)s sessions|other": "%(count)s sessões",
"%(count)s sessions|one": "%(count)s sessão", "%(count)s sessions|one": "%(count)s sessão",
"Hide sessions": "Esconder sessões", "Hide sessions": "Esconder sessões",
@ -2019,22 +2019,22 @@
"Deactivate user": "Desativar usuário", "Deactivate user": "Desativar usuário",
"Failed to deactivate user": "Falha ao desativar o usuário", "Failed to deactivate user": "Falha ao desativar o usuário",
"Security": "Segurança", "Security": "Segurança",
"You've successfully verified your device!": "Você verificou o seu aparelho com êxito!", "You've successfully verified your device!": "Você confirmou o seu aparelho com êxito!",
"Verification timed out.": "O tempo de verificação se esgotou.", "Verification timed out.": "O tempo de confirmação se esgotou.",
"You cancelled verification on your other session.": "Você cancelou a verificação em sua outra sessão.", "You cancelled verification on your other session.": "Você cancelou a confirmação em sua outra sessão.",
"%(displayName)s cancelled verification.": "%(displayName)s cancelou a verificação.", "%(displayName)s cancelled verification.": "%(displayName)s cancelou a confirmação.",
"You cancelled verification.": "Você cancelou a verificação.", "You cancelled verification.": "Você cancelou a confirmação.",
"Verification cancelled": "Verificação cancelada", "Verification cancelled": "Confirmação cancelada",
"Compare emoji": "Compare os emojis", "Compare emoji": "Compare os emojis",
"Show image": "Mostrar imagem", "Show image": "Mostrar imagem",
"You have ignored this user, so their message is hidden. <a>Show anyways.</a>": "Você bloqueou este usuário, portanto, a mensagem dele foi escondida. <a>Mostrar mesmo assim.</a>", "You have ignored this user, so their message is hidden. <a>Show anyways.</a>": "Você bloqueou este usuário, portanto, a mensagem dele foi escondida. <a>Mostrar mesmo assim.</a>",
"You verified %(name)s": "Você verificou %(name)s", "You verified %(name)s": "Você confirmou %(name)s",
"Use an identity server to invite by email. <default>Use the default (%(defaultIdentityServerName)s)</default> or manage in <settings>Settings</settings>.": "Use um servidor de identidade para convidar por e-mail. <default>Use o padrão (%(defaultIdentityServerName)s)</default> ou um servidor personalizado em <settings>Configurações</settings>.", "Use an identity server to invite by email. <default>Use the default (%(defaultIdentityServerName)s)</default> or manage in <settings>Settings</settings>.": "Use um servidor de identidade para convidar por e-mail. <default>Use o padrão (%(defaultIdentityServerName)s)</default> ou um servidor personalizado em <settings>Configurações</settings>.",
"Use an identity server to invite by email. Manage in <settings>Settings</settings>.": "Use um servidor de identidade para convidar por e-mail. Gerencie o servidor em <settings>Configurações</settings>.", "Use an identity server to invite by email. Manage in <settings>Settings</settings>.": "Use um servidor de identidade para convidar por e-mail. Gerencie o servidor em <settings>Configurações</settings>.",
"Destroy cross-signing keys?": "Destruir chaves autoverificadas?", "Destroy cross-signing keys?": "Destruir chaves autoverificadas?",
"Waiting for partner to confirm...": "Aguardando seu contato confirmar...", "Waiting for partner to confirm...": "Aguardando seu contato confirmar...",
"Enable 'Manage Integrations' in Settings to do this.": "Para fazer isso, ative 'Gerenciar Integrações' nas Configurações.", "Enable 'Manage Integrations' in Settings to do this.": "Para fazer isso, ative 'Gerenciar Integrações' nas Configurações.",
"Your %(brand)s doesn't allow you to use an Integration Manager to do this. Please contact an admin.": "Seu %(brand)s não permite que você use o Gerenciador de Integrações para fazer isso. Entre em contato com um administrador.", "Your %(brand)s doesn't allow you to use an Integration Manager to do this. Please contact an admin.": "Seu %(brand)s não permite que você use o Gerenciador de Integrações para fazer isso. Entre em contato com o administrador.",
"Confirm to continue": "Confirme para continuar", "Confirm to continue": "Confirme para continuar",
"Click the button below to confirm your identity.": "Clique no botão abaixo para confirmar sua identidade.", "Click the button below to confirm your identity.": "Clique no botão abaixo para confirmar sua identidade.",
"Failed to invite the following users to chat: %(csvUsers)s": "Falha ao convidar os seguintes usuários para a conversa: %(csvUsers)s", "Failed to invite the following users to chat: %(csvUsers)s": "Falha ao convidar os seguintes usuários para a conversa: %(csvUsers)s",
@ -2076,7 +2076,7 @@
"Upload %(count)s other files|one": "Enviar %(count)s outros arquivos", "Upload %(count)s other files|one": "Enviar %(count)s outros arquivos",
"Cancel All": "Cancelar tudo", "Cancel All": "Cancelar tudo",
"Upload Error": "Erro no envio", "Upload Error": "Erro no envio",
"Verification Request": "Solicitação de verificação", "Verification Request": "Solicitação de confirmação",
"Remember my selection for this widget": "Lembrar minha escolha para este widget", "Remember my selection for this widget": "Lembrar minha escolha para este widget",
"Deny": "Rejeitar", "Deny": "Rejeitar",
"Wrong file type": "Tipo errado de arquivo", "Wrong file type": "Tipo errado de arquivo",
@ -2125,7 +2125,7 @@
"Feedback": "Fale conosco", "Feedback": "Fale conosco",
"User menu": "Menu do usuário", "User menu": "Menu do usuário",
"Could not load user profile": "Não foi possível carregar o perfil do usuário", "Could not load user profile": "Não foi possível carregar o perfil do usuário",
"Session verified": "Sessão verificada", "Session verified": "Sessão confirmada",
"Your Matrix account on %(serverName)s": "Sua conta Matrix em %(serverName)s", "Your Matrix account on %(serverName)s": "Sua conta Matrix em %(serverName)s",
"Your Matrix account on <underlinedServerName />": "Sua conta Matrix em <underlinedServerName />", "Your Matrix account on <underlinedServerName />": "Sua conta Matrix em <underlinedServerName />",
"No identity server is configured: add one in server settings to reset your password.": "Nenhum servidor de identidade está configurado: adicione um nas configurações do servidor para redefinir sua senha.", "No identity server is configured: add one in server settings to reset your password.": "Nenhum servidor de identidade está configurado: adicione um nas configurações do servidor para redefinir sua senha.",
@ -2164,7 +2164,7 @@
"Unable to revoke sharing for email address": "Não foi possível revogar o compartilhamento do endereço de e-mail", "Unable to revoke sharing for email address": "Não foi possível revogar o compartilhamento do endereço de e-mail",
"Unable to share email address": "Não foi possível compartilhar o endereço de e-mail", "Unable to share email address": "Não foi possível compartilhar o endereço de e-mail",
"Direct message": "Enviar mensagem", "Direct message": "Enviar mensagem",
"Incoming Verification Request": "Recebendo solicitação de verificação", "Incoming Verification Request": "Recebendo solicitação de confirmação",
"Recently Direct Messaged": "Conversas recentes", "Recently Direct Messaged": "Conversas recentes",
"Direct Messages": "Conversas", "Direct Messages": "Conversas",
"Your account is not secure": "Sua conta não está segura", "Your account is not secure": "Sua conta não está segura",
@ -2193,7 +2193,7 @@
"Reload": "Recarregar", "Reload": "Recarregar",
"Take picture": "Tirar uma foto", "Take picture": "Tirar uma foto",
"Country Dropdown": "Selecione o país", "Country Dropdown": "Selecione o país",
"You can use the custom server options to sign into other Matrix servers by specifying a different homeserver URL. This allows you to use %(brand)s with an existing Matrix account on a different homeserver.": "Você pode usar as opções personalizadas do servidor para entrar em outros servidores Matrix especificando um endereço de servidor local diferente. Isso permite que você use %(brand)s com uma conta Matrix existente em um servidor local diferente.", "You can use the custom server options to sign into other Matrix servers by specifying a different homeserver URL. This allows you to use %(brand)s with an existing Matrix account on a different homeserver.": "Você pode usar as opções personalizadas do servidor para entrar em outros servidores Matrix especificando um endereço de servidor local diferente. Isso permite que você use o %(brand)s com uma conta Matrix existente em um servidor local diferente.",
"No identity server is configured so you cannot add an email address in order to reset your password in the future.": "Nenhum servidor de identidade está configurado, portanto você não pode adicionar um endereço de e-mail para redefinir sua senha no futuro.", "No identity server is configured so you cannot add an email address in order to reset your password in the future.": "Nenhum servidor de identidade está configurado, portanto você não pode adicionar um endereço de e-mail para redefinir sua senha no futuro.",
"Enter your custom identity server URL <a>What does this mean?</a>": "Digite o endereço do servidor de identidade personalizado <a>O que isso significa?</a>", "Enter your custom identity server URL <a>What does this mean?</a>": "Digite o endereço do servidor de identidade personalizado <a>O que isso significa?</a>",
"Join millions for free on the largest public server": "Junte-se a milhões de pessoas gratuitamente no maior servidor público", "Join millions for free on the largest public server": "Junte-se a milhões de pessoas gratuitamente no maior servidor público",
@ -2209,7 +2209,7 @@
"Changes to who can read history will only apply to future messages in this room. The visibility of existing history will be unchanged.": "Alterações em quem pode ler o histórico de conversas aplica-se apenas para mensagens futuras nesta sala. A visibilidade do histórico existente não será alterada.", "Changes to who can read history will only apply to future messages in this room. The visibility of existing history will be unchanged.": "Alterações em quem pode ler o histórico de conversas aplica-se apenas para mensagens futuras nesta sala. A visibilidade do histórico existente não será alterada.",
"Ask %(displayName)s to scan your code:": "Peça para %(displayName)s escanear o seu código:", "Ask %(displayName)s to scan your code:": "Peça para %(displayName)s escanear o seu código:",
"Almost there! Is %(displayName)s showing the same shield?": "Quase lá! Este escudo também aparece para %(displayName)s?", "Almost there! Is %(displayName)s showing the same shield?": "Quase lá! Este escudo também aparece para %(displayName)s?",
"You've successfully verified %(displayName)s!": "Você verificou %(displayName)s com sucesso!", "You've successfully verified %(displayName)s!": "Você confirmou %(displayName)s com sucesso!",
"Confirm this user's session by comparing the following with their User Settings:": "Confirme a sessão deste usuário comparando o seguinte com as configurações deste usuário:", "Confirm this user's session by comparing the following with their User Settings:": "Confirme a sessão deste usuário comparando o seguinte com as configurações deste usuário:",
"Report Content to Your Homeserver Administrator": "Denunciar conteúdo ao administrador do seu servidor principal", "Report Content to Your Homeserver Administrator": "Denunciar conteúdo ao administrador do seu servidor principal",
"Cross-signing": "Autoverificação", "Cross-signing": "Autoverificação",
@ -2217,7 +2217,7 @@
"Error updating flair": "Falha ao atualizar o ícone", "Error updating flair": "Falha ao atualizar o ícone",
"There was an error updating the flair for this room. The server may not allow it or a temporary error occurred.": "Ocorreu um erro ao atualizar o ícone nesta sala. O servidor pode não permitir ou ocorreu um erro temporário.", "There was an error updating the flair for this room. The server may not allow it or a temporary error occurred.": "Ocorreu um erro ao atualizar o ícone nesta sala. O servidor pode não permitir ou ocorreu um erro temporário.",
"Deactivating this user will log them out and prevent them from logging back in. Additionally, they will leave all the rooms they are in. This action cannot be reversed. Are you sure you want to deactivate this user?": "Desativar este usuário irá desconectá-lo e impedi-lo de fazer o login novamente. Além disso, ele sairá de todas as salas em que estiver. Esta ação não pode ser revertida. Tem certeza de que deseja desativar este usuário?", "Deactivating this user will log them out and prevent them from logging back in. Additionally, they will leave all the rooms they are in. This action cannot be reversed. Are you sure you want to deactivate this user?": "Desativar este usuário irá desconectá-lo e impedi-lo de fazer o login novamente. Além disso, ele sairá de todas as salas em que estiver. Esta ação não pode ser revertida. Tem certeza de que deseja desativar este usuário?",
"Deleting cross-signing keys is permanent. Anyone you have verified with will see security alerts. You almost certainly don't want to do this, unless you've lost every device you can cross-sign from.": "Apagar chaves de autoverificação é permanente. Qualquer pessoa com quem você fez a verificação receberá alertas de segurança. Não é aconselhável fazer isso, a menos que você tenha perdido todos os aparelhos nos quais fez a autoverificação.", "Deleting cross-signing keys is permanent. Anyone you have verified with will see security alerts. You almost certainly don't want to do this, unless you've lost every device you can cross-sign from.": "Apagar chaves de autoverificação é permanente. Qualquer pessoa com quem você se confirmou receberá alertas de segurança. Não é aconselhável fazer isso, a menos que você tenha perdido todos os aparelhos nos quais fez a autoverificação.",
"Clear cross-signing keys": "Limpar chaves autoverificadas", "Clear cross-signing keys": "Limpar chaves autoverificadas",
"a device cross-signing signature": "um aparelho autoverificado", "a device cross-signing signature": "um aparelho autoverificado",
"Homeserver URL does not appear to be a valid Matrix homeserver": "O endereço do servidor local não parece indicar um servidor local válido na Matrix", "Homeserver URL does not appear to be a valid Matrix homeserver": "O endereço do servidor local não parece indicar um servidor local válido na Matrix",
@ -2235,7 +2235,7 @@
"No other published addresses yet, add one below": "Nenhum endereço publicado ainda, adicione um abaixo", "No other published addresses yet, add one below": "Nenhum endereço publicado ainda, adicione um abaixo",
"Set addresses for this room so users can find this room through your homeserver (%(localDomain)s)": "Defina endereços para esta sala, de modo que os usuários possam encontrar esta sala em seu servidor local (%(localDomain)s)", "Set addresses for this room so users can find this room through your homeserver (%(localDomain)s)": "Defina endereços para esta sala, de modo que os usuários possam encontrar esta sala em seu servidor local (%(localDomain)s)",
"One of the following may be compromised:": "Um dos seguintes pode estar comprometido:", "One of the following may be compromised:": "Um dos seguintes pode estar comprometido:",
"The homeserver the user youre verifying is connected to": "O servidor local no qual o usuário que você está verificando está conectado", "The homeserver the user youre verifying is connected to": "O servidor local no qual o usuário que você está confirmando está conectado",
"Yours, or the other users internet connection": "A sua conexão de internet ou a dos outros usuários", "Yours, or the other users internet connection": "A sua conexão de internet ou a dos outros usuários",
"Yours, or the other users session": "A sua sessão ou a dos outros usuários", "Yours, or the other users session": "A sua sessão ou a dos outros usuários",
"Got it": "Ok, entendi", "Got it": "Ok, entendi",
@ -2278,5 +2278,10 @@
"Enter a security phrase only you know, as its used to safeguard your data. To be secure, you shouldnt re-use your account password.": "Digite uma frase de segurança que só você conheça, usada para proteger segredos em seu servidor.", "Enter a security phrase only you know, as its used to safeguard your data. To be secure, you shouldnt re-use your account password.": "Digite uma frase de segurança que só você conheça, usada para proteger segredos em seu servidor.",
"Use a different passphrase?": "Usar uma frase secreta diferente?", "Use a different passphrase?": "Usar uma frase secreta diferente?",
"Enter your recovery passphrase a second time to confirm it.": "Digite sua senha de recuperação uma segunda vez para confirmá-la.", "Enter your recovery passphrase a second time to confirm it.": "Digite sua senha de recuperação uma segunda vez para confirmá-la.",
"Confirm your recovery passphrase": "Confirme a sua frase de recuperação" "Confirm your recovery passphrase": "Confirme a sua frase de recuperação",
"Page Up": "Page Up",
"Page Down": "Page Down",
"You've successfully verified %(deviceName)s (%(deviceId)s)!": "Você confirmou %(deviceName)s (%(deviceId)s) com êxito!",
"Verified": "Confirmado",
"Close dialog or context menu": "Fechar caixa de diálogo ou menu"
} }

View file

@ -975,7 +975,7 @@
"Developer options": "Параметры разработчика", "Developer options": "Параметры разработчика",
"General": "Общие", "General": "Общие",
"Set a new account password...": "Установить новый пароль учётной записи...", "Set a new account password...": "Установить новый пароль учётной записи...",
"Legal": "Законный", "Legal": "Правовая информация",
"Room avatar": "Аватар комнаты", "Room avatar": "Аватар комнаты",
"The following users may not exist": "Следующих пользователей может не существовать", "The following users may not exist": "Следующих пользователей может не существовать",
"Invite anyway and never warn me again": "Пригласить и больше не предупреждать", "Invite anyway and never warn me again": "Пригласить и больше не предупреждать",
@ -1590,7 +1590,7 @@
"Error subscribing to list": "Ошибка при подписке на список", "Error subscribing to list": "Ошибка при подписке на список",
"Error upgrading room": "Ошибка обновления комнаты", "Error upgrading room": "Ошибка обновления комнаты",
"Match system theme": "Тема системы", "Match system theme": "Тема системы",
"Show tray icon and minimize window to it on close": "Показать иконку в панели задач и свернуть окно при закрытии", "Show tray icon and minimize window to it on close": "Показать иконку в трее и сворачивать окно при закрытии",
"Show typing notifications": "Показывать уведомления о наборе", "Show typing notifications": "Показывать уведомления о наборе",
"Delete %(count)s sessions|other": "Удалить %(count)s сессий", "Delete %(count)s sessions|other": "Удалить %(count)s сессий",
"Enable desktop notifications for this session": "Включить уведомления для рабочего стола для этой сессии", "Enable desktop notifications for this session": "Включить уведомления для рабочего стола для этой сессии",
@ -2405,5 +2405,20 @@
"Youre all caught up": "Нет непрочитанных сообщений", "Youre all caught up": "Нет непрочитанных сообщений",
"You have no visible notifications in this room.": "Нет видимых уведомлений в этой комнате.", "You have no visible notifications in this room.": "Нет видимых уведомлений в этой комнате.",
"%(brand)s Android": "%(brand)s Android", "%(brand)s Android": "%(brand)s Android",
"Master private key:": "Приватный мастер-ключ:" "Master private key:": "Приватный мастер-ключ:",
"Show message previews for reactions in DMs": "Показывать превью сообщений для реакций в ЛС",
"Show message previews for reactions in all rooms": "Показывать предварительный просмотр сообщений для реакций во всех комнатах",
"Explore public rooms": "Просмотреть публичные комнаты",
"Uploading logs": "Загрузка журналов",
"Downloading logs": "Скачивание журналов",
"Can't see what youre looking for?": "Не видите то, что ищете?",
"Explore all public rooms": "Просмотреть все публичные комнаты",
"%(count)s results|other": "%(count)s результатов",
"Preparing to download logs": "Подготовка к загрузке журналов",
"Download logs": "Скачать журналы",
"Unexpected server error trying to leave the room": "Неожиданная ошибка сервера при попытке покинуть комнату",
"Error leaving room": "Ошибка при выходе из комнаты",
"Communities v2 prototypes. Requires compatible homeserver. Highly experimental - use with caution.": "Прототипы сообщества v2. Требуется совместимый домашний сервер. Очень экспериментально - используйте с осторожностью.",
"Explore rooms in %(communityName)s": "Посмотреть комнаты в %(communityName)s",
"Set up Secure Backup": "Настроить безопасное резервное копирование"
} }

View file

@ -9,5 +9,7 @@
"Sign In": "Prijava", "Sign In": "Prijava",
"powered by Matrix": "poganja Matrix", "powered by Matrix": "poganja Matrix",
"Custom Server Options": "Možnosti strežnika po meri", "Custom Server Options": "Možnosti strežnika po meri",
"Your language of choice": "Vaš jezik po izbiri" "Your language of choice": "Vaš jezik po izbiri",
"Use Single Sign On to continue": "Uporabi Single Sign On za prijavo",
"Confirm adding this email address by using Single Sign On to prove your identity.": ""
} }

View file

@ -2407,5 +2407,20 @@
"Attach files from chat or just drag and drop them anywhere in a room.": "Bashkëngjitni kartela prej fjalosjeje ose thjesht tërhiqini dhe lërini kudo qoftë brenda dhomës.", "Attach files from chat or just drag and drop them anywhere in a room.": "Bashkëngjitni kartela prej fjalosjeje ose thjesht tërhiqini dhe lërini kudo qoftë brenda dhomës.",
"You have no visible notifications in this room.": "Ska njoftime të dukshme për ju në këtë dhomë.", "You have no visible notifications in this room.": "Ska njoftime të dukshme për ju në këtë dhomë.",
"Master private key:": "Kyç privat i përgjithshëm:", "Master private key:": "Kyç privat i përgjithshëm:",
"%(brand)s Android": "%(brand)s Android" "%(brand)s Android": "%(brand)s Android",
"Show message previews for reactions in DMs": "Shfaq paraparje mesazhi për reagime në MD",
"Show message previews for reactions in all rooms": "Shfaq paraparje mesazhi për reagime në krejt dhomat",
"Uploading logs": "Po ngarkohen regjistra",
"Downloading logs": "Po shkarkohen regjistra",
"Explore public rooms": "Eksploroni dhoma publike",
"Can't see what youre looking for?": "Sshihni çpo kërkoni?",
"Explore all public rooms": "Eksploroni krejt dhomat publike",
"%(count)s results|other": "%(count)s përfundime",
"Preparing to download logs": "Po bëhet gati për shkarkim regjistrash",
"Download logs": "Shkarko regjistra",
"Unexpected server error trying to leave the room": "Gabim i papritur shërbyesi në përpjekje për dalje nga dhoma",
"Error leaving room": "Gabim në dalje nga dhoma",
"Communities v2 prototypes. Requires compatible homeserver. Highly experimental - use with caution.": "Prototipe bashkësie v2. Lyp shërbyes Home të përputhshëm. Tejet eksperimentale - përdoreni me kujdes.",
"Explore rooms in %(communityName)s": "Eksploroni dhoma në %(communityName)s",
"Set up Secure Backup": "Ujdisni Kopjeruajtje të Sigurt"
} }

View file

@ -12,7 +12,7 @@
"Microphone": "Mikrofon", "Microphone": "Mikrofon",
"Camera": "Kamera", "Camera": "Kamera",
"Advanced": "Avancerat", "Advanced": "Avancerat",
"Always show message timestamps": "Visa alltid tidsstämpel för meddelanden", "Always show message timestamps": "Visa alltid tidsstämplar för meddelanden",
"Authentication": "Autentisering", "Authentication": "Autentisering",
"%(items)s and %(lastItem)s": "%(items)s och %(lastItem)s", "%(items)s and %(lastItem)s": "%(items)s och %(lastItem)s",
"and %(count)s others...|other": "och %(count)s andra...", "and %(count)s others...|other": "och %(count)s andra...",
@ -25,11 +25,11 @@
"An error has occurred.": "Ett fel har inträffat.", "An error has occurred.": "Ett fel har inträffat.",
"Are you sure?": "Är du säker?", "Are you sure?": "Är du säker?",
"Are you sure you want to leave the room '%(roomName)s'?": "Vill du lämna rummet '%(roomName)s'?", "Are you sure you want to leave the room '%(roomName)s'?": "Vill du lämna rummet '%(roomName)s'?",
"Autoplay GIFs and videos": "Spela automatiskt upp GIFar och videor", "Autoplay GIFs and videos": "Spela automatiskt upp GIF:ar och videor",
"Are you sure you want to reject the invitation?": "Är du säker på att du vill avböja inbjudan?", "Are you sure you want to reject the invitation?": "Är du säker på att du vill avböja inbjudan?",
"%(senderName)s banned %(targetName)s.": "%(senderName)s bannade %(targetName)s.", "%(senderName)s banned %(targetName)s.": "%(senderName)s bannade %(targetName)s.",
"Banned users": "Bannade användare", "Banned users": "Bannade användare",
"Bans user with given id": "Bannar användare med givet id", "Bans user with given id": "Bannar användaren med givet ID",
"Ban": "Banna", "Ban": "Banna",
"Attachment": "Bilaga", "Attachment": "Bilaga",
"Call Timeout": "Samtalstimeout", "Call Timeout": "Samtalstimeout",
@ -57,7 +57,7 @@
"/ddg is not a command": "/ddg är inte ett kommando", "/ddg is not a command": "/ddg är inte ett kommando",
"Deactivate Account": "Inaktivera konto", "Deactivate Account": "Inaktivera konto",
"Decrypt %(text)s": "Dekryptera %(text)s", "Decrypt %(text)s": "Dekryptera %(text)s",
"Deops user with given id": "Degraderar användare med givet id", "Deops user with given id": "Degraderar användaren med givet ID",
"Default": "Standard", "Default": "Standard",
"Disinvite": "Häv inbjudan", "Disinvite": "Häv inbjudan",
"Displays action": "Visar åtgärd", "Displays action": "Visar åtgärd",
@ -86,7 +86,7 @@
"Failed to send request.": "Det gick inte att sända begäran.", "Failed to send request.": "Det gick inte att sända begäran.",
"Failed to set display name": "Det gick inte att ange visningsnamn", "Failed to set display name": "Det gick inte att ange visningsnamn",
"Failed to unban": "Det gick inte att avbanna", "Failed to unban": "Det gick inte att avbanna",
"Failed to verify email address: make sure you clicked the link in the email": "Det gick inte att bekräfta e-postadressen, klicka på länken i e-postmeddelandet", "Failed to verify email address: make sure you clicked the link in the email": "Det gick inte att bekräfta e-postadressen: set till att du klickade på länken i e-postmeddelandet",
"Favourite": "Favorit", "Favourite": "Favorit",
"Accept": "Godkänn", "Accept": "Godkänn",
"Access Token:": "Åtkomsttoken:", "Access Token:": "Åtkomsttoken:",
@ -103,7 +103,7 @@
"Error: Problem communicating with the given homeserver.": "Fel: Det gick inte att kommunicera med den angivna hemservern.", "Error: Problem communicating with the given homeserver.": "Fel: Det gick inte att kommunicera med den angivna hemservern.",
"Failed to fetch avatar URL": "Det gick inte att hämta avatar-URL", "Failed to fetch avatar URL": "Det gick inte att hämta avatar-URL",
"Failed to upload profile picture!": "Det gick inte att ladda upp profilbild!", "Failed to upload profile picture!": "Det gick inte att ladda upp profilbild!",
"Failure to create room": "Det gick inte att skapa rum", "Failure to create room": "Det gick inte att skapa rummet",
"Favourites": "Favoriter", "Favourites": "Favoriter",
"Fill screen": "Fyll skärmen", "Fill screen": "Fyll skärmen",
"Filter room members": "Filtrera rumsmedlemmar", "Filter room members": "Filtrera rumsmedlemmar",
@ -129,7 +129,7 @@
"%(senderName)s invited %(targetName)s.": "%(senderName)s bjöd in %(targetName)s.", "%(senderName)s invited %(targetName)s.": "%(senderName)s bjöd in %(targetName)s.",
"Invited": "Inbjuden", "Invited": "Inbjuden",
"Invites": "Inbjudningar", "Invites": "Inbjudningar",
"Invites user with given id to current room": "Bjuder in användare med givet id till nuvarande rum", "Invites user with given id to current room": "Bjuder in användare med givet ID till detta rum",
"Sign in with": "Logga in med", "Sign in with": "Logga in med",
"Join as <voiceText>voice</voiceText> or <videoText>video</videoText>.": "Gå med som <voiceText>röst</voiceText> eller <videoText>video</videoText>.", "Join as <voiceText>voice</voiceText> or <videoText>video</videoText>.": "Gå med som <voiceText>röst</voiceText> eller <videoText>video</videoText>.",
"Join Room": "Gå med i rum", "Join Room": "Gå med i rum",
@ -137,7 +137,7 @@
"Jump to first unread message.": "Hoppa till första olästa meddelande.", "Jump to first unread message.": "Hoppa till första olästa meddelande.",
"%(senderName)s kicked %(targetName)s.": "%(senderName)s kickade %(targetName)s.", "%(senderName)s kicked %(targetName)s.": "%(senderName)s kickade %(targetName)s.",
"Kick": "Kicka", "Kick": "Kicka",
"Kicks user with given id": "Kickar användaren med givet id", "Kicks user with given id": "Kickar användaren med givet ID",
"Labs": "Labb", "Labs": "Labb",
"Last seen": "Senast sedd", "Last seen": "Senast sedd",
"Leave room": "Lämna rummet", "Leave room": "Lämna rummet",
@ -185,7 +185,7 @@
"%(senderName)s removed their display name (%(oldDisplayName)s).": "%(senderName)s tog bort sitt visningsnamn (%(oldDisplayName)s).", "%(senderName)s removed their display name (%(oldDisplayName)s).": "%(senderName)s tog bort sitt visningsnamn (%(oldDisplayName)s).",
"%(senderName)s removed their profile picture.": "%(senderName)s tog bort sin profilbild.", "%(senderName)s removed their profile picture.": "%(senderName)s tog bort sin profilbild.",
"Remove": "Ta bort", "Remove": "Ta bort",
"%(senderName)s requested a VoIP conference.": "%(senderName)s begärde en VoIP-konferens.", "%(senderName)s requested a VoIP conference.": "%(senderName)s begärde ett VoIP-gruppsamtal.",
"Results from DuckDuckGo": "Resultat från DuckDuckGo", "Results from DuckDuckGo": "Resultat från DuckDuckGo",
"Return to login screen": "Tillbaka till login-skärmen", "Return to login screen": "Tillbaka till login-skärmen",
"%(brand)s does not have permission to send you notifications - please check your browser settings": "%(brand)s har inte tillstånd att skicka aviseringar - kontrollera webbläsarens inställningar", "%(brand)s does not have permission to send you notifications - please check your browser settings": "%(brand)s har inte tillstånd att skicka aviseringar - kontrollera webbläsarens inställningar",
@ -203,16 +203,16 @@
"Seen by %(userName)s at %(dateTime)s": "Sedd av %(userName)s %(dateTime)s", "Seen by %(userName)s at %(dateTime)s": "Sedd av %(userName)s %(dateTime)s",
"Send Reset Email": "Skicka återställningsmeddelande", "Send Reset Email": "Skicka återställningsmeddelande",
"%(senderDisplayName)s sent an image.": "%(senderDisplayName)s skickade en bild.", "%(senderDisplayName)s sent an image.": "%(senderDisplayName)s skickade en bild.",
"%(senderName)s sent an invitation to %(targetDisplayName)s to join the room.": "%(senderName)s bjöd in %(targetDisplayName)s med i rummet.", "%(senderName)s sent an invitation to %(targetDisplayName)s to join the room.": "%(senderName)s bjöd in %(targetDisplayName)s att gå med i rummet.",
"Server error": "Serverfel", "Server error": "Serverfel",
"Server may be unavailable, overloaded, or search timed out :(": "Servern kan vara otillgänglig, överbelastad, eller så tog sökningen för lång tid :(", "Server may be unavailable, overloaded, or search timed out :(": "Servern kan vara otillgänglig, överbelastad, eller så tog sökningen för lång tid :(",
"Server may be unavailable, overloaded, or you hit a bug.": "Servern kan vara otillgänglig, överbelastad, eller så stötte du på en bugg.", "Server may be unavailable, overloaded, or you hit a bug.": "Servern kan vara otillgänglig eller överbelastad, eller så stötte du på en bugg.",
"Server unavailable, overloaded, or something else went wrong.": "Servern är otillgänglig, överbelastad, eller så gick något annat fel.", "Server unavailable, overloaded, or something else went wrong.": "Servern är otillgänglig, överbelastad, eller så gick något annat fel.",
"Session ID": "Sessions-ID", "Session ID": "Sessions-ID",
"%(senderName)s set a profile picture.": "%(senderName)s satte en profilbild.", "%(senderName)s set a profile picture.": "%(senderName)s satte en profilbild.",
"%(senderName)s set their display name to %(displayName)s.": "%(senderName)s bytte sitt visningnamn till %(displayName)s.", "%(senderName)s set their display name to %(displayName)s.": "%(senderName)s bytte sitt visningnamn till %(displayName)s.",
"Settings": "Inställningar", "Settings": "Inställningar",
"Show timestamps in 12 hour format (e.g. 2:30pm)": "Visa tidsstämplar i 12-timmarsformat (t.ex. 2:30pm)", "Show timestamps in 12 hour format (e.g. 2:30pm)": "Visa tidsstämplar i 12-timmarsformat (t.ex. 2:30em)",
"Signed Out": "Loggade ut", "Signed Out": "Loggade ut",
"Sign in": "Logga in", "Sign in": "Logga in",
"Sign out": "Logga ut", "Sign out": "Logga ut",
@ -235,13 +235,13 @@
"Edit": "Ändra", "Edit": "Ändra",
"Enable automatic language detection for syntax highlighting": "Aktivera automatisk språkdetektering för syntaxmarkering", "Enable automatic language detection for syntax highlighting": "Aktivera automatisk språkdetektering för syntaxmarkering",
"Publish this room to the public in %(domain)s's room directory?": "Publicera rummet i den offentliga rumskatalogen på %(domain)s?", "Publish this room to the public in %(domain)s's room directory?": "Publicera rummet i den offentliga rumskatalogen på %(domain)s?",
"AM": "AM", "AM": "FM",
"PM": "PM", "PM": "EM",
"Submit": "Lämna in", "Submit": "Lämna in",
"The maximum permitted number of widgets have already been added to this room.": "Den största tillåtna mängden widgetar har redan tillsats till rummet.", "The maximum permitted number of widgets have already been added to this room.": "Den största tillåtna mängden widgetar har redan tillsats till rummet.",
"The phone number entered looks invalid": "Det angivna telefonnumret är ogiltigt", "The phone number entered looks invalid": "Det angivna telefonnumret är ogiltigt",
"This email address is already in use": "Den här e-postadressen används redan", "This email address is already in use": "Den här e-postadressen används redan",
"This email address was not found": "Den här epostadressen finns inte", "This email address was not found": "Den här e-postadressen finns inte",
"The email address linked to your account must be entered.": "Epostadressen som är kopplad till ditt konto måste anges.", "The email address linked to your account must be entered.": "Epostadressen som är kopplad till ditt konto måste anges.",
"Online": "Online", "Online": "Online",
"Unnamed room": "Namnlöst rum", "Unnamed room": "Namnlöst rum",
@ -274,13 +274,13 @@
"Oct": "Okt", "Oct": "Okt",
"Nov": "Nov", "Nov": "Nov",
"Dec": "Dec", "Dec": "Dec",
"Invite to Community": "Bjud in till community", "Invite to Community": "Bjud in till gemenskap",
"Unable to enable Notifications": "Det går inte att aktivera aviseringar", "Unable to enable Notifications": "Det går inte att aktivera aviseringar",
"The information being sent to us to help make %(brand)s better includes:": "Informationen som skickas till oss för att förbättra %(brand)s inkluderar:", "The information being sent to us to help make %(brand)s better includes:": "Informationen som skickas till oss för att förbättra %(brand)s inkluderar:",
"VoIP is unsupported": "VoIP stöds ej", "VoIP is unsupported": "VoIP stöds ej",
"Failed to invite": "Inbjudan misslyckades", "Failed to invite": "Inbjudan misslyckades",
"You need to be logged in.": "Du måste vara inloggad.", "You need to be logged in.": "Du måste vara inloggad.",
"You need to be able to invite users to do that.": "Du måste kunna bjuda in användare för att göra det.", "You need to be able to invite users to do that.": "Du behöver kunna bjuda in användare för att göra det där.",
"You are not in this room.": "Du är inte i det här rummet.", "You are not in this room.": "Du är inte i det här rummet.",
"You do not have permission to do that in this room.": "Du har inte behörighet att göra det i det här rummet.", "You do not have permission to do that in this room.": "Du har inte behörighet att göra det i det här rummet.",
"Fetching third party location failed": "Det gick inte att hämta platsdata från tredje part", "Fetching third party location failed": "Det gick inte att hämta platsdata från tredje part",
@ -320,7 +320,7 @@
"An error occurred whilst saving your email notification preferences.": "Ett fel uppstod då epostaviseringsinställningarna sparades.", "An error occurred whilst saving your email notification preferences.": "Ett fel uppstod då epostaviseringsinställningarna sparades.",
"Explore Room State": "Utforska rumläget", "Explore Room State": "Utforska rumläget",
"Source URL": "Käll-URL", "Source URL": "Käll-URL",
"Failed to add tag %(tagName)s to room": "Det gick inte att lägga till \"%(tagName)s\" till rummet", "Failed to add tag %(tagName)s to room": "Det gick inte att lägga till etiketten \"%(tagName)s\" till rummet",
"Filter results": "Filtrera resultaten", "Filter results": "Filtrera resultaten",
"Members": "Medlemmar", "Members": "Medlemmar",
"No update available.": "Ingen uppdatering tillgänglig.", "No update available.": "Ingen uppdatering tillgänglig.",
@ -383,7 +383,7 @@
"Off": "Av", "Off": "Av",
"%(brand)s does not know how to join a room on this network": "%(brand)s kan inte gå med i ett rum på det här nätverket", "%(brand)s does not know how to join a room on this network": "%(brand)s kan inte gå med i ett rum på det här nätverket",
"Mentions only": "Endast omnämnande", "Mentions only": "Endast omnämnande",
"Failed to remove tag %(tagName)s from room": "Det gick inte att radera taggen %(tagName)s från rummet", "Failed to remove tag %(tagName)s from room": "Det gick inte att radera etiketten %(tagName)s från rummet",
"You can now return to your account after signing out, and sign in on other devices.": "Du kan nu återgå till ditt konto efter att ha loggat ut och logga in på andra enheter.", "You can now return to your account after signing out, and sign in on other devices.": "Du kan nu återgå till ditt konto efter att ha loggat ut och logga in på andra enheter.",
"Enable email notifications": "Aktivera epostaviseringar", "Enable email notifications": "Aktivera epostaviseringar",
"Download this file": "Ladda ner filen", "Download this file": "Ladda ner filen",
@ -404,17 +404,17 @@
"The platform you're on": "Plattformen du använder", "The platform you're on": "Plattformen du använder",
"Your homeserver's URL": "Din hemservers URL", "Your homeserver's URL": "Din hemservers URL",
"Every page you use in the app": "Varje sida du använder i appen", "Every page you use in the app": "Varje sida du använder i appen",
"Whether or not you're using the Richtext mode of the Rich Text Editor": "Om du använder Richtext-läget i Rich-Text-editorn eller inte", "Whether or not you're using the Richtext mode of the Rich Text Editor": "Om du använder Richtext-läget i Richtext-redigeraren eller inte",
"e.g. <CurrentPageURL>": "t.ex. <CurrentPageURL>", "e.g. <CurrentPageURL>": "t.ex. <CurrentPageURL>",
"Your device resolution": "Din enhetsupplösning", "Your device resolution": "Din skärmupplösning",
"You cannot place VoIP calls in this browser.": "Du kan inte ringa VoIP-samtal i den här webbläsaren.", "You cannot place VoIP calls in this browser.": "Du kan inte ringa VoIP-samtal i den här webbläsaren.",
"Your email address does not appear to be associated with a Matrix ID on this Homeserver.": "Din epostadress verkar inte vara kopplad till något Matrix-ID på den här hemservern.", "Your email address does not appear to be associated with a Matrix ID on this Homeserver.": "Din e-postadress verkar inte vara kopplad till något Matrix-ID på den här hemservern.",
"Restricted": "Begränsad", "Restricted": "Begränsad",
"Failed to invite the following users to the %(roomName)s room:": "Det gick inte att bjuda in följande användare till %(roomName)s-rummet:", "Failed to invite the following users to the %(roomName)s room:": "Det gick inte att bjuda in följande användare till rummet %(roomName)s:",
"Unable to create widget.": "Det går inte att skapa widget.", "Unable to create widget.": "Det gick inte att skapa widgeten.",
"Ignored user": "Ignorerad användare", "Ignored user": "Ignorerad användare",
"You are now ignoring %(userId)s": "Du ignorerar nu %(userId)s", "You are now ignoring %(userId)s": "Du ignorerar nu %(userId)s",
"Unignored user": "Oignorerad användare", "Unignored user": "Avignorerad användare",
"You are no longer ignoring %(userId)s": "Du ignorerar inte längre %(userId)s", "You are no longer ignoring %(userId)s": "Du ignorerar inte längre %(userId)s",
"%(oldDisplayName)s changed their display name to %(displayName)s.": "%(oldDisplayName)s bytte sitt visningsnamn till %(displayName)s.", "%(oldDisplayName)s changed their display name to %(displayName)s.": "%(oldDisplayName)s bytte sitt visningsnamn till %(displayName)s.",
"%(senderName)s unbanned %(targetName)s.": "%(senderName)s avbannade %(targetName)s.", "%(senderName)s unbanned %(targetName)s.": "%(senderName)s avbannade %(targetName)s.",
@ -517,7 +517,7 @@
"%(senderDisplayName)s changed the avatar for %(roomName)s": "%(senderDisplayName)s bytte avatar för %(roomName)s", "%(senderDisplayName)s changed the avatar for %(roomName)s": "%(senderDisplayName)s bytte avatar för %(roomName)s",
"%(senderDisplayName)s removed the room avatar.": "%(senderDisplayName)s tog bort rummets avatar.", "%(senderDisplayName)s removed the room avatar.": "%(senderDisplayName)s tog bort rummets avatar.",
"%(senderDisplayName)s changed the room avatar to <img/>": "%(senderDisplayName)s ändrade rummets avatar till <img/>", "%(senderDisplayName)s changed the room avatar to <img/>": "%(senderDisplayName)s ändrade rummets avatar till <img/>",
"Automatically replace plain text Emoji": "Ersätt text-emojis automatiskt", "Automatically replace plain text Emoji": "Ersätt automatiskt textemotikoner med emojier",
"%(weekDayName)s %(time)s": "%(weekDayName)s %(time)s", "%(weekDayName)s %(time)s": "%(weekDayName)s %(time)s",
"%(weekDayName)s, %(monthName)s %(day)s %(time)s": "%(weekDayName)s, %(day)s %(monthName)s %(time)s", "%(weekDayName)s, %(monthName)s %(day)s %(time)s": "%(weekDayName)s, %(day)s %(monthName)s %(time)s",
"%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s": "%(weekDayName)s, %(day)s %(monthName)s %(fullYear)s", "%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s": "%(weekDayName)s, %(day)s %(monthName)s %(fullYear)s",
@ -550,7 +550,7 @@
"Failed to invite users to %(groupId)s": "Det gick inte att bjuda in användare till %(groupId)s", "Failed to invite users to %(groupId)s": "Det gick inte att bjuda in användare till %(groupId)s",
"This room is not public. You will not be able to rejoin without an invite.": "Detta rum är inte offentligt. Du kommer inte kunna gå med igen utan en inbjudan.", "This room is not public. You will not be able to rejoin without an invite.": "Detta rum är inte offentligt. Du kommer inte kunna gå med igen utan en inbjudan.",
"Ignores a user, hiding their messages from you": "Ignorerar en användare och döljer dess meddelanden för dig", "Ignores a user, hiding their messages from you": "Ignorerar en användare och döljer dess meddelanden för dig",
"Stops ignoring a user, showing their messages going forward": "Slutar ignorera en användare och visar dess meddelanden för framöver", "Stops ignoring a user, showing their messages going forward": "Slutar ignorera en användare och visar dess meddelanden framöver",
"Opens the Developer Tools dialog": "Öppna dialogrutan Utvecklarverktyg", "Opens the Developer Tools dialog": "Öppna dialogrutan Utvecklarverktyg",
"Notify the whole room": "Meddela hela rummet", "Notify the whole room": "Meddela hela rummet",
"Room Notification": "Rumsavisering", "Room Notification": "Rumsavisering",
@ -563,7 +563,7 @@
"(could not connect media)": "(det gick inte ansluta media)", "(could not connect media)": "(det gick inte ansluta media)",
" (unsupported)": " (stöds ej)", " (unsupported)": " (stöds ej)",
"Drop file here to upload": "Släpp fil här för att ladda upp", "Drop file here to upload": "Släpp fil här för att ladda upp",
"Ongoing conference call%(supportedText)s.": "Pågående konferenssamtal%(supportedText)s.", "Ongoing conference call%(supportedText)s.": "Pågående gruppsamtal%(supportedText)s.",
"%(senderName)s sent an image": "%(senderName)s skickade en bild", "%(senderName)s sent an image": "%(senderName)s skickade en bild",
"%(senderName)s sent a video": "%(senderName)s skickade en video", "%(senderName)s sent a video": "%(senderName)s skickade en video",
"%(senderName)s uploaded a file": "%(senderName)s laddade upp en fil", "%(senderName)s uploaded a file": "%(senderName)s laddade upp en fil",
@ -608,14 +608,14 @@
"Failed to add the following rooms to %(groupId)s:": "Det gick inte att lägga till följande rum till %(groupId)s:", "Failed to add the following rooms to %(groupId)s:": "Det gick inte att lägga till följande rum till %(groupId)s:",
"Missing roomId.": "Rums-ID saknas.", "Missing roomId.": "Rums-ID saknas.",
"This room is not recognised.": "Detta rum känns inte igen.", "This room is not recognised.": "Detta rum känns inte igen.",
"Usage": "Användning", "Usage": "Användande",
"Verified key": "Verifierad nyckel", "Verified key": "Verifierade nyckeln",
"VoIP conference started.": "VoIP-konferens startad.", "VoIP conference started.": "VoIP-gruppsamtal startat.",
"VoIP conference finished.": "VoIP-konferens avslutad.", "VoIP conference finished.": "VoIP-gruppsamtal avslutat.",
"%(senderName)s made future room history visible to unknown (%(visibility)s).": "%(senderName)s gjorde framtida rumshistorik synligt för okänd (%(visibility)s).", "%(senderName)s made future room history visible to unknown (%(visibility)s).": "%(senderName)s satte framtida rumshistorik till okänd synlighet (%(visibility)s).",
"Where this page includes identifiable information, such as a room, user or group ID, that data is removed before being sent to the server.": "Där denna sida innehåller identifierbar information, till exempel ett rums-, användar- eller grupp-ID, tas data bort innan den skickas till servern.", "Where this page includes identifiable information, such as a room, user or group ID, that data is removed before being sent to the server.": "Där denna sida innehåller identifierbar information, till exempel ett rums-, användar- eller grupp-ID, tas datan bort innan den skickas till servern.",
"The remote side failed to pick up": "Mottagaren kunde inte svara", "The remote side failed to pick up": "Mottagaren svarade inte",
"Jump to read receipt": "Hoppa till läskvitto", "Jump to read receipt": "Hoppa till läsindikation",
"This process allows you to export the keys for messages you have received in encrypted rooms to a local file. You will then be able to import the file into another Matrix client in the future, so that client will also be able to decrypt these messages.": "Denna process låter dig exportera nycklarna för meddelanden som du har fått i krypterade rum till en lokal fil. Du kommer sedan att kunna importera filen i en annan Matrix-klient i framtiden, så att den klienten också kan dekryptera meddelandena.", "This process allows you to export the keys for messages you have received in encrypted rooms to a local file. You will then be able to import the file into another Matrix client in the future, so that client will also be able to decrypt these messages.": "Denna process låter dig exportera nycklarna för meddelanden som du har fått i krypterade rum till en lokal fil. Du kommer sedan att kunna importera filen i en annan Matrix-klient i framtiden, så att den klienten också kan dekryptera meddelandena.",
"Unknown for %(duration)s": "Okänt i %(duration)s", "Unknown for %(duration)s": "Okänt i %(duration)s",
"Unknown": "Okänt", "Unknown": "Okänt",
@ -659,69 +659,69 @@
"%(severalUsers)schanged their avatar %(count)s times|one": "%(severalUsers)sändrade sin avatar", "%(severalUsers)schanged their avatar %(count)s times|one": "%(severalUsers)sändrade sin avatar",
"%(oneUser)schanged their avatar %(count)s times|other": "%(oneUser)sändrade sin avatar %(count)s gånger", "%(oneUser)schanged their avatar %(count)s times|other": "%(oneUser)sändrade sin avatar %(count)s gånger",
"%(oneUser)schanged their avatar %(count)s times|one": "%(oneUser)sändrade sin avatar", "%(oneUser)schanged their avatar %(count)s times|one": "%(oneUser)sändrade sin avatar",
"%(items)s and %(count)s others|other": "%(items)s och %(count)s andra", "%(items)s and %(count)s others|other": "%(items)s och %(count)s till",
"%(items)s and %(count)s others|one": "%(items)s och en annan", "%(items)s and %(count)s others|one": "%(items)s och en till",
"collapse": "fäll ihop", "collapse": "fäll ihop",
"expand": "fäll ut", "expand": "fäll ut",
"<a>In reply to</a> <pill>": "<a>Som svar på</a> <pill>", "<a>In reply to</a> <pill>": "<a>Som svar på</a> <pill>",
"Who would you like to add to this community?": "Vem vill du lägga till i denna community?", "Who would you like to add to this community?": "Vem vill du lägga till i denna gemenskap?",
"Warning: any person you add to a community will be publicly visible to anyone who knows the community ID": "Varning: En person du lägger till i en community kommer att vara synlig för alla som känner till community-ID:t", "Warning: any person you add to a community will be publicly visible to anyone who knows the community ID": "Varning: En person du lägger till i en gemenskap kommer att vara synlig för alla som känner till gemenskaps-ID:t",
"Invite new community members": "Bjud in nya community-medlemmar", "Invite new community members": "Bjud in nya gemenskapsmedlemmar",
"Which rooms would you like to add to this community?": "Vilka rum vill du lägga till i denna community?", "Which rooms would you like to add to this community?": "Vilka rum vill du lägga till i denna gemenskap?",
"Show these rooms to non-members on the community page and room list?": "Visa dessa rum för icke-medlemmar på community-sidan och -rumslistan?", "Show these rooms to non-members on the community page and room list?": "Visa dessa rum för icke-medlemmar på gemenskapssidan och -rumslistan?",
"Add rooms to the community": "Lägg till rum i communityn", "Add rooms to the community": "Lägg till rum i gemenskapen",
"Add to community": "Lägg till i community", "Add to community": "Lägg till i gemenskap",
"Failed to invite users to community": "Det gick inte att bjuda in användare till communityn", "Failed to invite users to community": "Det gick inte att bjuda in användare till gemenskapen",
"Mirror local video feed": "Speglad lokal-video", "Mirror local video feed": "Spegla den lokala videoströmmen",
"Community Invites": "Community-inbjudningar", "Community Invites": "Community-inbjudningar",
"Invalid community ID": "Ogiltigt community-ID", "Invalid community ID": "Ogiltigt gemenskaps-ID",
"'%(groupId)s' is not a valid community ID": "%(groupId)s är inte ett giltigt community-ID", "'%(groupId)s' is not a valid community ID": "%(groupId)s är inte ett giltigt gemenskaps-ID",
"New community ID (e.g. +foo:%(localDomain)s)": "Nytt community-ID (t.ex. +foo:%(localDomain)s)", "New community ID (e.g. +foo:%(localDomain)s)": "Nytt gemenskaps-ID (t.ex. +foo:%(localDomain)s)",
"Remove from community": "Ta bort från community", "Remove from community": "Ta bort från gemenskapen",
"Disinvite this user from community?": "Ta bort användarens inbjudan till community?", "Disinvite this user from community?": "Ta bort användarens inbjudan till gemenskapen?",
"Remove this user from community?": "Ta bort användaren från community?", "Remove this user from community?": "Ta bort användaren från gemenskapen?",
"Failed to remove user from community": "Det gick inte att ta bort användaren från community", "Failed to remove user from community": "Det gick inte att ta bort användaren från gemenskapen",
"Filter community members": "Filtrera community-medlemmar", "Filter community members": "Filtrera gemenskapsmedlemmar",
"Removing a room from the community will also remove it from the community page.": "Om du tar bort ett rum från communityn tas det även bort från communityns sida.", "Removing a room from the community will also remove it from the community page.": "Om du tar bort ett rum från gemenskapen tas det även bort från gemenskapens sida.",
"Failed to remove room from community": "Det gick inte att ta bort rum från community", "Failed to remove room from community": "Det gick inte att ta bort rummet från gemenskapen",
"Only visible to community members": "Endast synlig för community-medlemmar", "Only visible to community members": "Endast synlig för gemenskapsmedlemmar",
"Filter community rooms": "Filtrera community-rum", "Filter community rooms": "Filtrera gemenskapsrum",
"Community IDs cannot be empty.": "Community-ID kan inte vara tomt.", "Community IDs cannot be empty.": "Gemenskaps-ID kan inte vara tomt.",
"Community IDs may only contain characters a-z, 0-9, or '=_-./'": "Community-ID får endast innehålla tecknen a-z, 0-9 och '=_-./'", "Community IDs may only contain characters a-z, 0-9, or '=_-./'": "Gemenskaps-ID får endast innehålla tecknen a-z, 0-9 och '=_-./'",
"Something went wrong whilst creating your community": "Något gick fel när din community skapades", "Something went wrong whilst creating your community": "Något gick fel när din gemenskap skapades",
"Create Community": "Skapa community", "Create Community": "Skapa gemenskap",
"Community Name": "Community-namn", "Community Name": "Gemenskapsnamn",
"Community ID": "Community-ID", "Community ID": "Gemenskaps-ID",
"View Community": "Visa community", "View Community": "Visa gemenskap",
"<h1>HTML for your community's page</h1>\n<p>\n Use the long description to introduce new members to the community, or distribute\n some important <a href=\"foo\">links</a>\n</p>\n<p>\n You can even use 'img' tags\n</p>\n": "<h1>HTML för din community-sida</h1>\n<p>\n Använd den långa beskrivningen för att introducera nya medlemmar till communityn, eller dela\n några viktiga <a href=\"foo\">länkar</a>\n</p>\n<p>\n Du kan även använda 'img'-taggar\n</p>\n", "<h1>HTML for your community's page</h1>\n<p>\n Use the long description to introduce new members to the community, or distribute\n some important <a href=\"foo\">links</a>\n</p>\n<p>\n You can even use 'img' tags\n</p>\n": "<h1>HTML för din gemenskapssida</h1>\n<p>\n Använd den långa beskrivningen för att introducera nya medlemmar till gemenskapen, eller dela\n några viktiga <a href=\"foo\">länkar</a>\n</p>\n<p>\n Du kan även använda 'img'-taggar\n</p>\n",
"Add rooms to the community summary": "Lägg till rum i community-översikten", "Add rooms to the community summary": "Lägg till rum i gemenskapsöversikten",
"Add users to the community summary": "Lägg till användare i community-översikten", "Add users to the community summary": "Lägg till användare i gemenskapsöversikten",
"Failed to update community": "Det gick inte att uppdatera community", "Failed to update community": "Det gick inte att uppdatera gemenskapen",
"Unable to join community": "Det gick inte att gå med i communityn", "Unable to join community": "Det gick inte att gå med i gemenskapen",
"Leave Community": "Lämna community", "Leave Community": "Lämna gemenskapen",
"Unable to leave community": "Det gick inte att lämna community", "Unable to leave community": "Det gick inte att lämna gemenskap",
"Community Settings": "Community-inställningar", "Community Settings": "Gemenskapsinställningar",
"Changes made to your community <bold1>name</bold1> and <bold2>avatar</bold2> might not be seen by other users for up to 30 minutes.": "Det kan dröja upp till 30 minuter innan ändringar på communityns <bold1>namn</bold1> och <bold2>avatar</bold2> blir synliga för andra användare.", "Changes made to your community <bold1>name</bold1> and <bold2>avatar</bold2> might not be seen by other users for up to 30 minutes.": "Det kan dröja upp till 30 minuter innan ändringar på gemenskapens <bold1>namn</bold1> och <bold2>avatar</bold2> blir synliga för andra användare.",
"These rooms are displayed to community members on the community page. Community members can join the rooms by clicking on them.": "Dessa rum visas för community-medlemmar på community-sidan. Community-medlemmar kan gå med i rummen genom att klicka på dem.", "These rooms are displayed to community members on the community page. Community members can join the rooms by clicking on them.": "Dessa rum visas för gemenskapsmedlemmar på gemenskapssidan. Gemenskapsmedlemmar kan gå med i rummen genom att klicka på dem.",
"Add rooms to this community": "Lägg till rum i denna community", "Add rooms to this community": "Lägg till rum i denna gemenskap",
"%(inviter)s has invited you to join this community": "%(inviter)s har bjudit in dig till denna community", "%(inviter)s has invited you to join this community": "%(inviter)s har bjudit in dig till denna gemenskap",
"Join this community": "Gå med i denna community", "Join this community": "Gå med i denna gemenskap",
"Leave this community": "Lämna denna community", "Leave this community": "Lämna denna gemenskap",
"You are an administrator of this community": "Du är administratör för denna community", "You are an administrator of this community": "Du är administratör för denna gemenskap",
"You are a member of this community": "Du är medlem i denna community", "You are a member of this community": "Du är medlem i denna gemenskap",
"Who can join this community?": "Vem kan gå med i denna community?", "Who can join this community?": "Vem kan gå med i denna gemenskap?",
"Your community hasn't got a Long Description, a HTML page to show to community members.<br />Click here to open settings and give it one!": "Din community har ingen lång beskrivning eller HTML-sida att visa för medlemmar.<br />Klicka här för att öppna inställningar och lägga till det!", "Your community hasn't got a Long Description, a HTML page to show to community members.<br />Click here to open settings and give it one!": "Din gemenskap har ingen lång beskrivning eller HTML-sida att visa för medlemmar.<br />Klicka här för att öppna inställningarna och lägga till det!",
"Community %(groupId)s not found": "Community %(groupId)s hittades inte", "Community %(groupId)s not found": "Gemenskapen %(groupId)s hittades inte",
"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.": "För att skapa ett filter, dra en community-avatar till filterpanelen längst till vänster på skärmen. Du kan när som helst klicka på en avatar i filterpanelen för att bara se rum och personer som är associerade med den communityn.", "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.": "För att skapa ett filter, dra en gemenskapsavatar till filterpanelen längst till vänster på skärmen. Du kan när som helst klicka på en avatar i filterpanelen för att bara se rum och personer som är associerade med den gemenskapen.",
"Create a new community": "Skapa en ny community", "Create a new community": "Skapa en ny gemenskap",
"Create a community to group together users and rooms! Build a custom homepage to mark out your space in the Matrix universe.": "Skapa en community för att gruppera användare och rum! Bygg en anpassad hemsida för att markera er plats i Matrix-universumet.", "Create a community to group together users and rooms! Build a custom homepage to mark out your space in the Matrix universe.": "Skapa en gemenskap för att gruppera användare och rum! Bygg en anpassad hemsida för att markera er plats i Matrix-universumet.",
"Invite to this community": "Bjud in till denna community", "Invite to this community": "Bjud in till denna gemenskap",
"Something went wrong when trying to get your communities.": "Något gick fel vid hämtning av dina communityn.", "Something went wrong when trying to get your communities.": "Något gick fel vid hämtning av dina gemenskaper.",
"You're not currently a member of any communities.": "Du är för närvarande inte medlem i någon community.", "You're not currently a member of any communities.": "Du är för närvarande inte medlem i någon gemenskap.",
"Communities": "Communityn", "Communities": "Gemenskaper",
"Your Communities": "Dina communityn", "Your Communities": "Dina gemenskaper",
"Did you know: you can use communities to filter your %(brand)s experience!": "Visste du att: du kan använda communityn för att filtrera din %(brand)s-upplevelse!", "Did you know: you can use communities to filter your %(brand)s experience!": "Visste du att: du kan använda gemenskaper för att filtrera din %(brand)s-upplevelse!",
"Error whilst fetching joined communities": "Fel vid hämtning av anslutna communityn", "Error whilst fetching joined communities": "Fel vid hämtning av anslutna gemenskaper",
"Featured Rooms:": "Utvalda rum:", "Featured Rooms:": "Utvalda rum:",
"Featured Users:": "Utvalda användare:", "Featured Users:": "Utvalda användare:",
"Everyone": "Alla", "Everyone": "Alla",
@ -741,7 +741,7 @@
"You will not be able to undo this change as you are promoting the user to have the same power level as yourself.": "Du kommer inte att kunna ångra den här ändringen eftersom du höjer användaren till samma behörighetsnivå som dig själv.", "You will not be able to undo this change as you are promoting the user to have the same power level as yourself.": "Du kommer inte att kunna ångra den här ändringen eftersom du höjer användaren till samma behörighetsnivå som dig själv.",
"unknown caller": "okänd uppringare", "unknown caller": "okänd uppringare",
"To use it, just wait for autocomplete results to load and tab through them.": "För att använda detta, vänta på att autokompletteringen laddas och tabba igenom resultatet.", "To use it, just wait for autocomplete results to load and tab through them.": "För att använda detta, vänta på att autokompletteringen laddas och tabba igenom resultatet.",
"Enable inline URL previews by default": "Aktivera URL-förhandsvisning som standard", "Enable inline URL previews by default": "Aktivera inbäddad URL-förhandsvisning som standard",
"Enable URL previews for this room (only affects you)": "Aktivera URL-förhandsvisning för detta rum (påverkar bara dig)", "Enable URL previews for this room (only affects you)": "Aktivera URL-förhandsvisning för detta rum (påverkar bara dig)",
"Enable URL previews by default for participants in this room": "Aktivera URL-förhandsvisning som standard för deltagare i detta rum", "Enable URL previews by default for participants in this room": "Aktivera URL-förhandsvisning som standard för deltagare i detta rum",
"You have <a>enabled</a> URL previews by default.": "Du har <a>aktiverat</a> URL-förhandsvisning som standard.", "You have <a>enabled</a> URL previews by default.": "Du har <a>aktiverat</a> URL-förhandsvisning som standard.",
@ -788,16 +788,16 @@
"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)": "Glöm alla meddelanden som jag har skickat när mitt konto inaktiveras (<b>Varning:</b> detta kommer att göra så att framtida användare får se ofullständiga konversationer)", "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)": "Glöm alla meddelanden som jag har skickat när mitt konto inaktiveras (<b>Varning:</b> detta kommer att göra så att framtida användare får se ofullständiga konversationer)",
"To continue, please enter your password:": "För att fortsätta, ange ditt lösenord:", "To continue, please enter your password:": "För att fortsätta, ange ditt lösenord:",
"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.": "Om du har anmält en bugg via GitHub, kan felsökningsloggar hjälpa oss spåra problemet. Felsökningsloggarna innehåller användningsdata för applikationen inklusive ditt användarnamn, ID eller alias för rum och grupper du besökt och användarnamn för andra användare. De innehåller inte meddelanden.", "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.": "Om du har anmält en bugg via GitHub, kan felsökningsloggar hjälpa oss spåra problemet. Felsökningsloggarna innehåller användningsdata för applikationen inklusive ditt användarnamn, ID eller alias för rum och grupper du besökt och användarnamn för andra användare. De innehåller inte meddelanden.",
"%(brand)s collects anonymous analytics to allow us to improve the application.": "%(brand)s samlar in anonym analysdata för att vi ska kunna förbättra applikationen.", "%(brand)s collects anonymous analytics to allow us to improve the application.": "%(brand)s samlar in anonym statistik för att vi ska kunna förbättra applikationen.",
"Privacy is important to us, so we don't collect any personal or identifiable data for our analytics.": "Integritet är viktig för oss, så vi samlar inte in några personliga eller identifierbara uppgifter för våra analyser.", "Privacy is important to us, so we don't collect any personal or identifiable data for our analytics.": "Integritet är viktig för oss, så vi samlar inte in några personliga eller identifierbara uppgifter i våran statistik.",
"Learn more about how we use analytics.": "Läs mer om hur vi använder analysdata.", "Learn more about how we use analytics.": "Läs mer om hur vi använder statistik.",
"Analytics": "Analysdata", "Analytics": "Statistik",
"Send analytics data": "Skicka analysdata", "Send analytics data": "Skicka statistik",
"Passphrases must match": "Passfraser måste matcha", "Passphrases must match": "Passfraser måste matcha",
"Passphrase must not be empty": "Lösenfras får inte vara tom", "Passphrase must not be empty": "Lösenfras får inte vara tom",
"Confirm passphrase": "Bekräfta lösenfrasen", "Confirm passphrase": "Bekräfta lösenfrasen",
"%(senderName)s changed the pinned messages for the room.": "%(senderName)s ändrade fastnålade meddelanden för rummet.", "%(senderName)s changed the pinned messages for the room.": "%(senderName)s ändrade fastnålade meddelanden för rummet.",
"Message Pinning": "Nåla fast meddelanden", "Message Pinning": "Fastnålning av meddelanden",
"Unpin Message": "Ta bort fastnålning", "Unpin Message": "Ta bort fastnålning",
"No pinned messages.": "Inga fastnålade meddelanden.", "No pinned messages.": "Inga fastnålade meddelanden.",
"Pinned Messages": "Fastnålade meddelanden", "Pinned Messages": "Fastnålade meddelanden",
@ -806,15 +806,15 @@
"This process allows you to import encryption keys that you had previously exported from another Matrix client. You will then be able to decrypt any messages that the other client could decrypt.": "Denna process möjliggör import av krypteringsnycklar som tidigare exporterats från en annan Matrix-klient. Du kommer då kunna dekryptera alla meddelanden som den andra klienten kunde dekryptera.", "This process allows you to import encryption keys that you had previously exported from another Matrix client. You will then be able to decrypt any messages that the other client could decrypt.": "Denna process möjliggör import av krypteringsnycklar som tidigare exporterats från en annan Matrix-klient. Du kommer då kunna dekryptera alla meddelanden som den andra klienten kunde dekryptera.",
"The export file will be protected with a passphrase. You should enter the passphrase here, to decrypt the file.": "Den exporterade filen kommer vara skyddad med en lösenfras. Du måste ange lösenfrasen här, för att dekryptera filen.", "The export file will be protected with a passphrase. You should enter the passphrase here, to decrypt the file.": "Den exporterade filen kommer vara skyddad med en lösenfras. Du måste ange lösenfrasen här, för att dekryptera filen.",
"Flair": "Emblem", "Flair": "Emblem",
"Showing flair for these communities:": "Visar emblem för dessa communityn:", "Showing flair for these communities:": "Visar emblem för dessa gemenskaper:",
"This room is not showing flair for any communities": "Detta rum visar inte emblem för några communityn", "This room is not showing flair for any communities": "Detta rum visar inte emblem för några gemenskaper",
"Display your community flair in rooms configured to show it.": "Visa ditt community-emblem i rum som är konfigurerade för att visa det.", "Display your community flair in rooms configured to show it.": "Visa ditt gemenskapsemblem i rum som är konfigurerade för att visa det.",
"Share Link to User": "Dela länk till användare", "Share Link to User": "Dela länk till användare",
"Share room": "Dela rum", "Share room": "Dela rum",
"Share Room": "Dela rum", "Share Room": "Dela rum",
"Link to most recent message": "Länk till senaste meddelandet", "Link to most recent message": "Länk till senaste meddelandet",
"Share User": "Dela användare", "Share User": "Dela användare",
"Share Community": "Dela community", "Share Community": "Dela gemenskap",
"Share Room Message": "Dela rumsmeddelande", "Share Room Message": "Dela rumsmeddelande",
"Link to selected message": "Länk till valt meddelande", "Link to selected message": "Länk till valt meddelande",
"COPY": "KOPIERA", "COPY": "KOPIERA",
@ -825,7 +825,7 @@
"A call is currently being placed!": "Ett samtal håller på att upprättas!", "A call is currently being placed!": "Ett samtal håller på att upprättas!",
"A call is already in progress!": "Ett samtal pågår redan!", "A call is already in progress!": "Ett samtal pågår redan!",
"Permission Required": "Behörighet krävs", "Permission Required": "Behörighet krävs",
"You do not have permission to start a conference call in this room": "Du har inte behörighet att starta ett konferenssamtal i detta rum", "You do not have permission to start a conference call in this room": "Du har inte behörighet att starta ett gruppsamtal i detta rum",
"This event could not be displayed": "Den här händelsen kunde inte visas", "This event could not be displayed": "Den här händelsen kunde inte visas",
"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.": "I krypterade rum, som detta, är URL-förhandsvisning inaktiverad som standard för att säkerställa att din hemserver (där förhandsvisningar genereras) inte kan samla information om länkar du ser i rummet.", "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.": "I krypterade rum, som detta, är URL-förhandsvisning inaktiverad som standard för att säkerställa att din hemserver (där förhandsvisningar genereras) inte kan samla information om länkar du ser i rummet.",
"The email field must not be blank.": "Epost-fältet får inte vara tomt.", "The email field must not be blank.": "Epost-fältet får inte vara tomt.",
@ -838,9 +838,9 @@
"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.": "När någon postar en URL i sitt meddelande, kan URL-förhandsvisning ge mer information om länken, såsom titel, beskrivning, och en bild från webbplatsen.", "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.": "När någon postar en URL i sitt meddelande, kan URL-förhandsvisning ge mer information om länken, såsom titel, beskrivning, och en bild från webbplatsen.",
"You can't send any messages until you review and agree to <consentLink>our terms and conditions</consentLink>.": "Du kan inte skicka några meddelanden innan du granskar och godkänner <consentLink>våra villkor</consentLink>.", "You can't send any messages until you review and agree to <consentLink>our terms and conditions</consentLink>.": "Du kan inte skicka några meddelanden innan du granskar och godkänner <consentLink>våra villkor</consentLink>.",
"System Alerts": "Systemvarningar", "System Alerts": "Systemvarningar",
"Sorry, your homeserver is too old to participate in this room.": "Tyvärr, din hemserver är för gammal för att delta i detta rum.", "Sorry, your homeserver is too old to participate in this room.": "Tyvärr, din hemserver är för gammal för att delta i det här rummet.",
"Please contact your homeserver administrator.": "Vänligen kontakta din hemserver-administratör.", "Please contact your homeserver administrator.": "Vänligen kontakta din hemserveradministratör.",
"Please <a>contact your service administrator</a> to continue using the service.": "<a>Kontakta din serviceadministratör</a> för att fortsätta använda tjänsten.", "Please <a>contact your service administrator</a> to continue using the service.": "<a>Kontakta din tjänstadministratör</a> för att fortsätta använda tjänsten.",
"This homeserver has hit its Monthly Active User limit.": "Hemservern har nått sin månatliga gräns för användaraktivitet.", "This homeserver has hit its Monthly Active User limit.": "Hemservern har nått sin månatliga gräns för användaraktivitet.",
"This homeserver has exceeded one of its resource limits.": "Hemservern har överskridit en av sina resursgränser.", "This homeserver has exceeded one of its resource limits.": "Hemservern har överskridit en av sina resursgränser.",
"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.": "Ditt meddelande skickades inte för hemservern har nått sin månatliga gräns för användaraktivitet. <a>Kontakta din serviceadministratör</a> för att fortsätta använda servicen.", "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.": "Ditt meddelande skickades inte för hemservern har nått sin månatliga gräns för användaraktivitet. <a>Kontakta din serviceadministratör</a> för att fortsätta använda servicen.",
@ -861,7 +861,7 @@
"Stop users from speaking in the old version of the room, and post a message advising users to move to the new room": "Hindra användare från att prata i den gamla rumsversionen och posta ett meddelande som rekommenderar användare att flytta till det nya rummet", "Stop users from speaking in the old version of the room, and post a message advising users to move to the new room": "Hindra användare från att prata i den gamla rumsversionen och posta ett meddelande som rekommenderar användare att flytta till det nya rummet",
"Put a link back to the old room at the start of the new room so people can see old messages": "Sätta en länk tillbaka till det gamla rummet i början av det nya rummet så att folk kan se gamla meddelanden", "Put a link back to the old room at the start of the new room so people can see old messages": "Sätta en länk tillbaka till det gamla rummet i början av det nya rummet så att folk kan se gamla meddelanden",
"Forces the current outbound group session in an encrypted room to be discarded": "Tvingar den aktuella utgående gruppsessionen i ett krypterat rum att överges", "Forces the current outbound group session in an encrypted room to be discarded": "Tvingar den aktuella utgående gruppsessionen i ett krypterat rum att överges",
"Unable to connect to Homeserver. Retrying...": "Det gick inte att ansluta till hemserver. Försöker igen ...", "Unable to connect to Homeserver. Retrying...": "Det gick inte att ansluta till hemservern. Försöker igen…",
"%(senderName)s set the main address for this room to %(address)s.": "%(senderName)s satte huvudadressen för detta rum till %(address)s.", "%(senderName)s set the main address for this room to %(address)s.": "%(senderName)s satte huvudadressen för detta rum till %(address)s.",
"%(senderName)s removed the main address for this room.": "%(senderName)s tog bort huvudadressen för detta rum.", "%(senderName)s removed the main address for this room.": "%(senderName)s tog bort huvudadressen för detta rum.",
"Add some now": "Lägg till några nu", "Add some now": "Lägg till några nu",
@ -869,39 +869,39 @@
"Before submitting logs, you must <a>create a GitHub issue</a> to describe your problem.": "Innan du skickar in loggar måste du <a>skapa en GitHub-bugg</a> för att beskriva problemet.", "Before submitting logs, you must <a>create a GitHub issue</a> to describe your problem.": "Innan du skickar in loggar måste du <a>skapa en GitHub-bugg</a> för att beskriva problemet.",
"Updating %(brand)s": "Uppdaterar %(brand)s", "Updating %(brand)s": "Uppdaterar %(brand)s",
"Open Devtools": "Öppna Devtools", "Open Devtools": "Öppna Devtools",
"Show developer tools": "Visa utvecklingsverktyg", "Show developer tools": "Visa utvecklarverktyg",
"You are an administrator of this community. You will not be able to rejoin without an invite from another administrator.": "Du är administratör för denna community. Du kommer inte kunna gå med igen utan en inbjudan från en annan administratör.", "You are an administrator of this community. You will not be able to rejoin without an invite from another administrator.": "Du är administratör för denna gemenskap. Du kommer inte kunna gå med igen utan en inbjudan från en annan administratör.",
"The file '%(fileName)s' exceeds this homeserver's size limit for uploads": "Filen '%(fileName)s' överstiger denna hemserverns storleksgräns för uppladdningar", "The file '%(fileName)s' exceeds this homeserver's size limit for uploads": "Filen '%(fileName)s' överstiger denna hemserverns storleksgräns för uppladdningar",
"Unable to load! Check your network connectivity and try again.": "Kan inte ladda! Kolla din nätverksuppkoppling och försök igen.", "Unable to load! Check your network connectivity and try again.": "Kan inte ladda! Kolla din nätverksuppkoppling och försök igen.",
"Whether or not you're logged in (we don't record your username)": "Om du är inloggad eller inte (vi sparar inte ditt användarnamn)", "Whether or not you're logged in (we don't record your username)": "Om du är inloggad eller inte (vi sparar inte ditt användarnamn)",
"Failed to invite users to the room:": "Kunde inte bjuda in användare till rummet:", "Failed to invite users to the room:": "Kunde inte bjuda in användare till rummet:",
"Upgrades a room to a new version": "Uppgraderar ett num till en ny version", "Upgrades a room to a new version": "Uppgraderar ett rum till en ny version",
"Gets or sets the room topic": "Ger eller sätter ämnet för ett rum", "Gets or sets the room topic": "Hämtar eller sätter ämnet för ett rum",
"This room has no topic.": "Det här rummet har inget ämne.", "This room has no topic.": "Det här rummet har inget ämne.",
"Sets the room name": "Sätter rumnamnet", "Sets the room name": "Sätter rumsnamnet",
"%(senderDisplayName)s upgraded this room.": "%(senderDisplayName)s uppgraderade det här rummet.", "%(senderDisplayName)s upgraded this room.": "%(senderDisplayName)s uppgraderade det här rummet.",
"%(senderDisplayName)s made the room public to whoever knows the link.": "%(senderDisplayName)s gjorde rummet publikt för alla som kan länken.", "%(senderDisplayName)s made the room public to whoever knows the link.": "%(senderDisplayName)s gjorde rummet publikt för alla som har länken.",
"%(senderDisplayName)s has allowed guests to join the room.": "%(senderDisplayName)s har tillåtit gäster att gå med i rummet.", "%(senderDisplayName)s has allowed guests to join the room.": "%(senderDisplayName)s har tillåtit gäster att gå med i rummet.",
"%(senderDisplayName)s changed the join rule to %(rule)s": "%(senderDisplayName)s ändrade regeln för att gå med till %(rule)s", "%(senderDisplayName)s changed the join rule to %(rule)s": "%(senderDisplayName)s ändrade regeln för att gå med till %(rule)s",
"%(senderDisplayName)s has prevented guests from joining the room.": "%(senderDisplayName)s har nekat gäster att gå med i rummet.", "%(senderDisplayName)s has prevented guests from joining the room.": "%(senderDisplayName)s har nekat gäster att gå med i rummet.",
"%(senderDisplayName)s changed guest access to %(rule)s": "%(senderDisplayName)s ändrade gäst-åtkomst till %(rule)s", "%(senderDisplayName)s changed guest access to %(rule)s": "%(senderDisplayName)s ändrade gäståtkomst till %(rule)s",
"%(displayName)s is typing …": "%(displayName)s skriver …", "%(displayName)s is typing …": "%(displayName)s skriver …",
"%(names)s and %(count)s others are typing …|other": "%(names)s och %(count)s andra skriver …", "%(names)s and %(count)s others are typing …|other": "%(names)s och %(count)s andra skriver …",
"%(names)s and %(count)s others are typing …|one": "%(names)s och en till skriver …", "%(names)s and %(count)s others are typing …|one": "%(names)s och en till skriver …",
"%(names)s and %(lastPerson)s are typing …": "%(names)s och %(lastPerson)s skriver …", "%(names)s and %(lastPerson)s are typing …": "%(names)s och %(lastPerson)s skriver …",
"Unrecognised address": "Okänd address", "Unrecognised address": "Okänd adress",
"You do not have permission to invite people to this room.": "Du har inte tillåtelse att bjuda in användare till det här rummet.", "You do not have permission to invite people to this room.": "Du har inte behörighet att bjuda in användare till det här rummet.",
"User %(user_id)s does not exist": "Användare %(user_id)s existerar inte", "User %(user_id)s does not exist": "Användaren %(user_id)s existerar inte",
"User %(user_id)s may or may not exist": "Användare %(user_id)s existerar möjligtvis", "User %(user_id)s may or may not exist": "Användaren %(user_id)s kanske eller kanske inte existerar",
"Unknown server error": "Okänt server-fel", "Unknown server error": "Okänt serverfel",
"Use a few words, avoid common phrases": "Använd ett par ord, undvik vanliga fraser", "Use a few words, avoid common phrases": "Använd några ord, undvik vanliga fraser",
"No need for symbols, digits, or uppercase letters": "Symboler, siffror eller stora bokstäver krävs ej", "No need for symbols, digits, or uppercase letters": "Specialtecken, siffror eller stora bokstäver behövs inte",
"Avoid repeated words and characters": "Undvik upprepade ord och bokstäver", "Avoid repeated words and characters": "Undvik upprepade ord och bokstäver",
"Avoid sequences": "Undvik sekvenser", "Avoid sequences": "Undvik sekvenser",
"Avoid recent years": "Undvik senare år", "Avoid recent years": "Undvik nyliga år",
"Avoid years that are associated with you": "Undvik årtal som associeras med dig", "Avoid years that are associated with you": "Undvik årtal som associeras med dig",
"Avoid dates and years that are associated with you": "Undvik datum och årtal som associeras med dig", "Avoid dates and years that are associated with you": "Undvik datum och årtal som associeras med dig",
"Capitalization doesn't help very much": "Kapitalisering hjälper inte särskilt mycket", "Capitalization doesn't help very much": "Versaler hjälper inte särskilt mycket",
"All-uppercase is almost as easy to guess as all-lowercase": "Endast stora bokstäver är nästan lika enkelt att gissa som endast små bokstäver", "All-uppercase is almost as easy to guess as all-lowercase": "Endast stora bokstäver är nästan lika enkelt att gissa som endast små bokstäver",
"Reversed words aren't much harder to guess": "Ord skrivna baklänges är inte mycket svårare att gissa", "Reversed words aren't much harder to guess": "Ord skrivna baklänges är inte mycket svårare att gissa",
"Predictable substitutions like '@' instead of 'a' don't help very much": "Förutsägbara ersättningar som '@' istället för 'a' hjälper inte särskilt mycket", "Predictable substitutions like '@' instead of 'a' don't help very much": "Förutsägbara ersättningar som '@' istället för 'a' hjälper inte särskilt mycket",
@ -909,32 +909,32 @@
"Repeats like \"aaa\" are easy to guess": "Upprepningar som \"aaa\" är enkla att gissa", "Repeats like \"aaa\" are easy to guess": "Upprepningar som \"aaa\" är enkla att gissa",
"Repeats like \"abcabcabc\" are only slightly harder to guess than \"abc\"": "Upprepningar som \"abcabcabc\" är bara aningen svårare att gissa än \"abc\"", "Repeats like \"abcabcabc\" are only slightly harder to guess than \"abc\"": "Upprepningar som \"abcabcabc\" är bara aningen svårare att gissa än \"abc\"",
"Sequences like abc or 6543 are easy to guess": "Sekvenser som abc eller 6543 är enkla att gissa", "Sequences like abc or 6543 are easy to guess": "Sekvenser som abc eller 6543 är enkla att gissa",
"Recent years are easy to guess": "Senare årtal är enka att gissa", "Recent years are easy to guess": "Nyliga årtal är enkla att gissa",
"Dates are often easy to guess": "Datum är ofta enkla att gissa", "Dates are often easy to guess": "Datum är ofta enkla att gissa",
"This is a top-10 common password": "Det här är ett av de topp 10 vanligaste lösenorden", "This is a top-10 common password": "Det här är ett av de 10 vanligaste lösenorden",
"This is a top-100 common password": "Det här är ett av de topp 100 vanligaste lösenorden", "This is a top-100 common password": "Det här är ett av de 100 vanligaste lösenorden",
"This is a very common password": "Det här är ett väldigt vanligt lösenord", "This is a very common password": "Det här är ett väldigt vanligt lösenord",
"This is similar to a commonly used password": "Det här liknar ett vanligt lösenord", "This is similar to a commonly used password": "Det här liknar ett vanligt lösenord",
"A word by itself is easy to guess": "Enstaka ord är enkla att gissa", "A word by itself is easy to guess": "Enstaka ord är enkla att gissa",
"Names and surnames by themselves are easy to guess": "Enstaka för- och efternamn är enkla att gissa", "Names and surnames by themselves are easy to guess": "Enstaka för- och efternamn är enkla att gissa",
"Common names and surnames are easy to guess": "Vanliga namn och efternamn är enkla att gissa", "Common names and surnames are easy to guess": "Vanliga för- och efternamn är enkla att gissa",
"Straight rows of keys are easy to guess": "Tangenter i rad på tangentbordet är enkla att gissa", "Straight rows of keys are easy to guess": "Raka rader på tangentbordet är enkla att gissa",
"Short keyboard patterns are easy to guess": "Korta tangentbordsmönster är enkla att gissa", "Short keyboard patterns are easy to guess": "Korta tangentbordsmönster är enkla att gissa",
"There was an error joining the room": "Det gick fel när vi försökte gå med i rummet", "There was an error joining the room": "Ett fel inträffade vid försök att gå med i rummet",
"Changes your display nickname in the current room only": "Ändrar ditt visningsnamn endast i det aktuella rummet", "Changes your display nickname in the current room only": "Ändrar ditt visningsnamn endast i detta rum",
"Use a longer keyboard pattern with more turns": "Använd ett längre tangentbordsmönster med fler varv", "Use a longer keyboard pattern with more turns": "Använd ett längre tangentbordsmönster med fler riktningsbyten",
"Custom user status messages": "Anpassade användarstatusmeddelanden", "Custom user status messages": "Anpassade användarstatusmeddelanden",
"Enable Emoji suggestions while typing": "Aktivera Emoji-förslag medan du skriver", "Enable Emoji suggestions while typing": "Aktivera emojiförslag medan du skriver",
"Show a placeholder for removed messages": "Visa en platshållare för borttagna meddelanden", "Show a placeholder for removed messages": "Visa en platshållare för borttagna meddelanden",
"Show join/leave messages (invites/kicks/bans unaffected)": "Visa \"gå med\"/lämna-meddelanden (inbjudningar/kickningar/banningar opåverkat)", "Show join/leave messages (invites/kicks/bans unaffected)": "Visa \"gå med\"/lämna-meddelanden (inbjudningar/kickningar/banningar opåverkat)",
"Show avatar changes": "Visa avatarändringar", "Show avatar changes": "Visa avatarändringar",
"Show display name changes": "Visa visningsnamnsändringar", "Show display name changes": "Visa visningsnamnsändringar",
"Show read receipts sent by other users": "Visa läskvitton som skickats av andra användare", "Show read receipts sent by other users": "Visa läsindikationer som skickats av andra användare",
"Show avatars in user and room mentions": "Visa avatarer i användar- och rumsnämningar", "Show avatars in user and room mentions": "Visa avatarer i användar- och rumsbenämningar",
"Enable big emoji in chat": "Aktivera stor emoji i chatt", "Enable big emoji in chat": "Aktivera stora emojier i chatt",
"Send typing notifications": "Skicka \"skriver\"-statusar", "Send typing notifications": "Skicka \"skriver\"-statusar",
"Enable Community Filter Panel": "Aktivera community-filterpanel", "Enable Community Filter Panel": "Aktivera gemenskapsfilterpanel",
"Allow Peer-to-Peer for 1:1 calls": "Tillåt peer-to-peer kommunikation för 1:1 samtal", "Allow Peer-to-Peer for 1:1 calls": "Tillåt peer-to-peer-kommunikation för 1:1-samtal",
"Messages containing my username": "Meddelanden som innehåller mitt användarnamn", "Messages containing my username": "Meddelanden som innehåller mitt användarnamn",
"Messages containing @room": "Meddelanden som innehåller @room", "Messages containing @room": "Meddelanden som innehåller @room",
"Encrypted messages in one-to-one chats": "Krypterade meddelanden i privata chattar", "Encrypted messages in one-to-one chats": "Krypterade meddelanden i privata chattar",
@ -1062,7 +1062,7 @@
"Join millions for free on the largest public server": "Bli medlem gratis på den största offentliga servern", "Join millions for free on the largest public server": "Bli medlem gratis på den största offentliga servern",
"Premium": "Premium", "Premium": "Premium",
"Premium hosting for organisations <a>Learn more</a>": "Premium-hosting för organisationer <a>Läs mer</a>", "Premium hosting for organisations <a>Learn more</a>": "Premium-hosting för organisationer <a>Läs mer</a>",
"Other": "Andra", "Other": "Annat",
"Find other public servers or use a custom server": "Hitta andra offentliga servrar eller använd en anpassad server", "Find other public servers or use a custom server": "Hitta andra offentliga servrar eller använd en anpassad server",
"Your Matrix account on %(serverName)s": "Ditt Matrix-konto på %(serverName)s", "Your Matrix account on %(serverName)s": "Ditt Matrix-konto på %(serverName)s",
"Sign in instead": "Logga in istället", "Sign in instead": "Logga in istället",
@ -1081,9 +1081,9 @@
"%(senderDisplayName)s enabled flair for %(groups)s in this room.": "%(senderDisplayName)s aktiverade emblem för %(groups)s i detta rum.", "%(senderDisplayName)s enabled flair for %(groups)s in this room.": "%(senderDisplayName)s aktiverade emblem för %(groups)s i detta rum.",
"%(senderDisplayName)s disabled flair for %(groups)s in this room.": "%(senderDisplayName)s inaktiverade emblem för %(groups)s i detta rum.", "%(senderDisplayName)s disabled flair for %(groups)s in this room.": "%(senderDisplayName)s inaktiverade emblem för %(groups)s i detta rum.",
"%(senderDisplayName)s enabled flair for %(newGroups)s and disabled flair for %(oldGroups)s in this room.": "%(senderDisplayName)s aktiverade emblem för %(newGroups)s och inaktiverade emblem för %(oldGroups)s i detta rum.", "%(senderDisplayName)s enabled flair for %(newGroups)s and disabled flair for %(oldGroups)s in this room.": "%(senderDisplayName)s aktiverade emblem för %(newGroups)s och inaktiverade emblem för %(oldGroups)s i detta rum.",
"User %(userId)s is already in the room": "Användare %(userId)s är redan i rummet", "User %(userId)s is already in the room": "Användaren %(userId)s är redan i rummet",
"The user must be unbanned before they can be invited.": "Användare behöver avbannas innan de kan bjudas in.", "The user must be unbanned before they can be invited.": "Användaren behöver avbannas innan den kan bjudas in.",
"Group & filter rooms by custom tags (refresh to apply changes)": "Gruppera och filtrera rum med anpassade taggar (ladda om för att visa ändringar)", "Group & filter rooms by custom tags (refresh to apply changes)": "Gruppera och filtrera rum med anpassade etiketter (ladda om för att visa ändringar)",
"Render simple counters in room header": "Rendera enkla räknare i rumsrubriken", "Render simple counters in room header": "Rendera enkla räknare i rumsrubriken",
"Yes": "Ja", "Yes": "Ja",
"No": "Nej", "No": "Nej",
@ -1124,7 +1124,7 @@
"Please supply a https:// or http:// widget URL": "Ange en widget-URL med https:// eller http://", "Please supply a https:// or http:// widget URL": "Ange en widget-URL med https:// eller http://",
"You cannot modify widgets in this room.": "Du kan inte ändra widgets i detta rum.", "You cannot modify widgets in this room.": "Du kan inte ändra widgets i detta rum.",
"%(senderName)s revoked the invitation for %(targetDisplayName)s to join the room.": "%(senderName)s återkallade inbjudan för %(targetDisplayName)s att gå med i rummet.", "%(senderName)s revoked the invitation for %(targetDisplayName)s to join the room.": "%(senderName)s återkallade inbjudan för %(targetDisplayName)s att gå med i rummet.",
"Show a reminder to enable Secure Message Recovery in encrypted rooms": "Visa en påminnelse för att sätta på säker meddelande återhämtning i krypterade rum", "Show a reminder to enable Secure Message Recovery in encrypted rooms": "Visa en påminnelse att sätta på säker meddelandeåterställning i krypterade rum",
"The other party cancelled the verification.": "Den andra parten avbröt verifieringen.", "The other party cancelled the verification.": "Den andra parten avbröt verifieringen.",
"Verified!": "Verifierad!", "Verified!": "Verifierad!",
"You've successfully verified this user.": "Du har verifierat den här användaren.", "You've successfully verified this user.": "Du har verifierat den här användaren.",
@ -1160,7 +1160,7 @@
"Unable to load backup status": "Det går inte att ladda backupstatus", "Unable to load backup status": "Det går inte att ladda backupstatus",
"Guest": "Gäst", "Guest": "Gäst",
"Could not load user profile": "Kunde inte ladda användarprofil", "Could not load user profile": "Kunde inte ladda användarprofil",
"Whether or not you're using the 'breadcrumbs' feature (avatars above the room list)": "Om du använder 'breadcrumbs' eller inte (avatarer ovanför rumslistan)", "Whether or not you're using the 'breadcrumbs' feature (avatars above the room list)": "Om du använder 'brödsmulor' eller inte (avatarer ovanför rumslistan)",
"Replying With Files": "Svarar med filer", "Replying With Files": "Svarar med filer",
"At this time it is not possible to reply with a file. Would you like to upload this file without replying?": "Just nu är det inte möjligt att svara med en fil. Vill du ladda upp filen utan att svara?", "At this time it is not possible to reply with a file. Would you like to upload this file without replying?": "Just nu är det inte möjligt att svara med en fil. Vill du ladda upp filen utan att svara?",
"The file '%(fileName)s' failed to upload.": "Filen '%(fileName)s' kunde inte laddas upp.", "The file '%(fileName)s' failed to upload.": "Filen '%(fileName)s' kunde inte laddas upp.",
@ -1208,26 +1208,26 @@
"Upload %(count)s other files|one": "Ladda upp %(count)s annan fil", "Upload %(count)s other files|one": "Ladda upp %(count)s annan fil",
"Cancel All": "Avbryt alla", "Cancel All": "Avbryt alla",
"Upload Error": "Uppladdningsfel", "Upload Error": "Uppladdningsfel",
"Name or Matrix ID": "Namn eller Martix-ID", "Name or Matrix ID": "Namn eller Matrix-ID",
"Your %(brand)s is misconfigured": "%(brand)s är felkonfigurerat", "Your %(brand)s is misconfigured": "Din %(brand)s är felkonfigurerad",
"Call failed due to misconfigured server": "Anrop misslyckades på grund av felkonfigurerad server", "Call failed due to misconfigured server": "Anrop misslyckades på grund av felkonfigurerad server",
"Try using turn.matrix.org": "Prova att använda turn.matrix.org", "Try using turn.matrix.org": "Prova att använda turn.matrix.org",
"The server does not support the room version specified.": "Servern stöder inte den angivna rumsversionen.", "The server does not support the room version specified.": "Servern stöder inte den angivna rumsversionen.",
"Messages": "Meddelanden", "Messages": "Meddelanden",
"Actions": "Åtgärder", "Actions": "Åtgärder",
"Sends a message as plain text, without interpreting it as markdown": "Skickar ett meddelande som vanlig text, utan att tolka det som markdown", "Sends a message as plain text, without interpreting it as markdown": "Skickar ett meddelande som vanlig text, utan att tolka det som Markdown",
"You do not have the required permissions to use this command.": "Du har inte de behörigheter som krävs för att använda det här kommandot.", "You do not have the required permissions to use this command.": "Du har inte de behörigheter som krävs för att använda det här kommandot.",
"Changes your avatar in this current room only": "Ändrar din avatar endast i det aktuella rummet", "Changes your avatar in this current room only": "Ändrar din avatar endast i detta rum",
"Changes your avatar in all rooms": "Ändrar din avatar i alla rum", "Changes your avatar in all rooms": "Ändrar din avatar i alla rum",
"Use an identity server": "Använd en identitetsserver", "Use an identity server": "Använd en identitetsserver",
"Unbans user with given ID": "Avbannar användare med givet id", "Unbans user with given ID": "Avbannar användaren med givet ID",
"Sends the given message coloured as a rainbow": "Skickar angivet meddelandet färgat som en regnbåge", "Sends the given message coloured as a rainbow": "Skickar angivet meddelande i regnbågsfärg",
"Sends the given emote coloured as a rainbow": "Skickar angiven emoji färgad som en regnbåge", "Sends the given emote coloured as a rainbow": "Skickar angiven emoji i regnbågsfärg",
"Displays list of commands with usages and descriptions": "Visar lista över kommandon med beskrivningar", "Displays list of commands with usages and descriptions": "Visar lista över kommandon med användande beskrivningar",
"%(senderName)s made no change.": "%(senderName)s gjorde ingen ändring.", "%(senderName)s made no change.": "%(senderName)s gjorde ingen ändring.",
"Cannot reach homeserver": "Kan inte nå hemservern", "Cannot reach homeserver": "Kan inte nå hemservern",
"Ensure you have a stable internet connection, or get in touch with the server admin": "Se till att du har en stabil internetanslutning, eller kontakta serveradministratören", "Ensure you have a stable internet connection, or get in touch with the server admin": "Se till att du har en stabil internetanslutning, eller kontakta serveradministratören",
"Ask your %(brand)s admin to check <a>your config</a> for incorrect or duplicate entries.": "Be din %(brand)s-administratör att kontrollera <a>din konfiguration</a> efter felaktiga eller duplicerade poster.", "Ask your %(brand)s admin to check <a>your config</a> for incorrect or duplicate entries.": "Be din %(brand)s-administratör att kolla <a>din konfiguration</a> efter felaktiga eller duplicerade poster.",
"Cannot reach identity server": "Kan inte nå identitetsservern", "Cannot reach identity server": "Kan inte nå identitetsservern",
"You can register, but some features will be unavailable until the identity server is back online. If you keep seeing this warning, check your configuration or contact a server admin.": "Du kan registrera dig, men vissa funktioner kommer inte att vara tillgängliga förrän identitetsservern är online igen. Om du fortsätter att se den här varningen, kontrollera din konfiguration eller kontakta en serveradministratör.", "You can register, but some features will be unavailable until the identity server is back online. If you keep seeing this warning, check your configuration or contact a server admin.": "Du kan registrera dig, men vissa funktioner kommer inte att vara tillgängliga förrän identitetsservern är online igen. Om du fortsätter att se den här varningen, kontrollera din konfiguration eller kontakta en serveradministratör.",
"You can reset your password, but some features will be unavailable until the identity server is back online. If you keep seeing this warning, check your configuration or contact a server admin.": "Du kan återställa ditt lösenord, men vissa funktioner kommer inte att vara tillgängliga förrän identitetsservern är online igen. Om du fortsätter att se den här varningen, kontrollera din konfiguration eller kontakta en serveradministratör.", "You can reset your password, but some features will be unavailable until the identity server is back online. If you keep seeing this warning, check your configuration or contact a server admin.": "Du kan återställa ditt lösenord, men vissa funktioner kommer inte att vara tillgängliga förrän identitetsservern är online igen. Om du fortsätter att se den här varningen, kontrollera din konfiguration eller kontakta en serveradministratör.",
@ -1237,7 +1237,7 @@
"Multiple integration managers": "Flera integrationshanterare", "Multiple integration managers": "Flera integrationshanterare",
"Show hidden events in timeline": "Visa dolda händelser i tidslinjen", "Show hidden events in timeline": "Visa dolda händelser i tidslinjen",
"Low bandwidth mode": "Läge för låg bandbredd", "Low bandwidth mode": "Läge för låg bandbredd",
"Send read receipts for messages (requires compatible homeserver to disable)": "Skicka läskvitton för meddelanden (kräver kompatibel hemserver för att inaktivera)", "Send read receipts for messages (requires compatible homeserver to disable)": "Skicka läsindikationer för meddelanden (kräver kompatibel hemserver för att inaktivera)",
"When rooms are upgraded": "När rum uppgraderas", "When rooms are upgraded": "När rum uppgraderas",
"Accept <policyLink /> to continue:": "Acceptera <policyLink /> för att fortsätta:", "Accept <policyLink /> to continue:": "Acceptera <policyLink /> för att fortsätta:",
"ID": "ID", "ID": "ID",
@ -1304,7 +1304,7 @@
"Join the conversation with an account": "Gå med i konversationen med ett konto", "Join the conversation with an account": "Gå med i konversationen med ett konto",
"Sign Up": "Registrera dig", "Sign Up": "Registrera dig",
"Sign In": "Logga in", "Sign In": "Logga in",
"Prompt before sending invites to potentially invalid matrix IDs": "Fråga innan inbjudningar skickas till potentiellt ogiltiga matrix-IDn", "Prompt before sending invites to potentially invalid matrix IDs": "Fråga innan inbjudningar skickas till potentiellt ogiltiga Matrix-ID:n",
"Show all": "Visa alla", "Show all": "Visa alla",
"<reactors/><reactedWith>reacted with %(shortName)s</reactedWith>": "<reactors/><reactedWith>reagerade med %(shortName)s</reactedWith>", "<reactors/><reactedWith>reacted with %(shortName)s</reactedWith>": "<reactors/><reactedWith>reagerade med %(shortName)s</reactedWith>",
"Edited at %(date)s. Click to view edits.": "Ändrad %(date)s. Klicka för att visa ändringar.", "Edited at %(date)s. Click to view edits.": "Ändrad %(date)s. Klicka för att visa ändringar.",
@ -1312,32 +1312,32 @@
"Sign in to your Matrix account on <underlinedServerName />": "Logga in med ditt Matrix-konto på <underlinedServerName />", "Sign in to your Matrix account on <underlinedServerName />": "Logga in med ditt Matrix-konto på <underlinedServerName />",
"Please install <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, or <safariLink>Safari</safariLink> for the best experience.": "Installera <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, eller <safariLink>Safari</safariLink> för den bästa upplevelsen.", "Please install <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, or <safariLink>Safari</safariLink> for the best experience.": "Installera <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, eller <safariLink>Safari</safariLink> för den bästa upplevelsen.",
"Couldn't load page": "Det gick inte att ladda sidan", "Couldn't load page": "Det gick inte att ladda sidan",
"Want more than a community? <a>Get your own server</a>": "Vill du ha mer än en community? <a>Skaffa din egen server</a>", "Want more than a community? <a>Get your own server</a>": "Vill du ha mer än en gemenskap? <a>Skaffa din egen server</a>",
"This homeserver does not support communities": "Denna hemserver stöder inte communityn", "This homeserver does not support communities": "Denna hemserver stöder inte gemenskaper",
"Explore": "Utforska", "Explore": "Utforska",
"Filter": "Filtrera", "Filter": "Filtrera",
"Filter rooms…": "Filtrera rum…", "Filter rooms…": "Filtrera rum…",
"Please ask the administrator of your homeserver (<code>%(homeserverDomain)s</code>) to configure a TURN server in order for calls to work reliably.": "Be administratören för din hemserver (<code>%(homeserverDomain)s</code>) att konfigurera en TURN-server för att samtal ska fungera pålitligt.", "Please ask the administrator of your homeserver (<code>%(homeserverDomain)s</code>) to configure a TURN server in order for calls to work reliably.": "Be administratören för din hemserver (<code>%(homeserverDomain)s</code>) att konfigurera en TURN-server för att samtal ska fungera pålitligt.",
"Alternatively, you can try to use the public server at <code>turn.matrix.org</code>, but this will not be as reliable, and it will share your IP address with that server. You can also manage this in Settings.": "Alternativt kan du testa att använda den offentliga servern <code>turn.matrix.org</code>, men det är inte lika pålitligt och det kommer att dela din IP-adress med den servern. Du kan också hantera detta under Inställningar.", "Alternatively, you can try to use the public server at <code>turn.matrix.org</code>, but this will not be as reliable, and it will share your IP address with that server. You can also manage this in Settings.": "Alternativt kan du testa att använda den offentliga servern <code>turn.matrix.org</code>, men det är inte lika pålitligt och det kommer att dela din IP-adress med den servern. Du kan också hantera detta under Inställningar.",
"<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>Varning</b>: Uppgradering av ett rum <i>flyttar inte automatiskt rumsmedlemmar till den nya versionen av rummet.</i> Vi lägger ut en länk till det nya rummet i den gamla versionen av rummet - rumsmedlemmar måste klicka på den här länken för att gå med i det nya rummet.", "<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>Varning</b>: Uppgradering av ett rum <i>flyttar inte automatiskt rumsmedlemmar till den nya versionen av rummet.</i> Vi lägger ut en länk till det nya rummet i den gamla versionen av rummet - rumsmedlemmar måste klicka på den här länken för att gå med i det nya rummet.",
"Changes the avatar of the current room": "Ändrar avataren i det aktuella rummet", "Changes the avatar of the current room": "Ändrar avataren i detta rum",
"Use an identity server to invite by email. Click continue to use the default identity server (%(defaultIdentityServerName)s) or manage in Settings.": "Använd en identitetsserver för att bjuda in via epost. Klicka på Fortsätt för att använda standardidentitetsservern (%(defaultIdentityServerName)s) eller hantera det i Inställningar.", "Use an identity server to invite by email. Click continue to use the default identity server (%(defaultIdentityServerName)s) or manage in Settings.": "Använd en identitetsserver för att bjuda in via e-post. Klicka på Fortsätt för att använda standardidentitetsservern (%(defaultIdentityServerName)s) eller hantera det i Inställningar.",
"Use an identity server to invite by email. Manage in Settings.": "Använd en identitetsserver för att bjuda in via epost. Hantera det i inställningar.", "Use an identity server to invite by email. Manage in Settings.": "Använd en identitetsserver för att bjuda in via e-post. Hantera det i inställningar.",
"Unexpected error resolving homeserver configuration": "Oväntat fel vid inläsning av hemserverkonfiguration", "Unexpected error resolving homeserver configuration": "Oväntat fel vid inläsning av hemserverkonfiguration",
"Unexpected error resolving identity server configuration": "Oväntat fel vid inläsning av identitetsserverkonfiguration", "Unexpected error resolving identity server configuration": "Oväntat fel vid inläsning av identitetsserverkonfiguration",
"Allow fallback call assist server turn.matrix.org when your homeserver does not offer one (your IP address would be shared during a call)": "Tillåt samtalsserver turn.matrix.org som reserv när din hemserver inte erbjuder en (din IP-adress delades under ett samtal)", "Allow fallback call assist server turn.matrix.org when your homeserver does not offer one (your IP address would be shared during a call)": "Tillåt assistansservern turn.matrix.org för samtal som reserv när din hemserver inte erbjuder en (din IP-adress kommer delas under ett samtal)",
"Unable to load key backup status": "Det går inte att ladda status för nyckelsäkerhetskopiering", "Unable to load key backup status": "Det går inte att ladda status för nyckelsäkerhetskopiering",
"Restore from Backup": "Återställ från säkerhetskopiering", "Restore from Backup": "Återställ från säkerhetskopiering",
"Backing up %(sessionsRemaining)s keys...": "Säkerhetskopierar %(sessionsRemaining)s nycklar...", "Backing up %(sessionsRemaining)s keys...": "Säkerhetskopierar %(sessionsRemaining)s nycklar...",
"All keys backed up": "Alla nycklar säkerhetskopierade", "All keys backed up": "Alla nycklar säkerhetskopierade",
"Add Email Address": "Lägg till e-postadress", "Add Email Address": "Lägg till e-postadress",
"Add Phone Number": "Lägg till telefonnummer", "Add Phone Number": "Lägg till telefonnummer",
"Identity server has no terms of service": "Identitetsserver har inga användarvillkor", "Identity server has no terms of service": "Identitetsservern har inga användarvillkor",
"This action requires accessing the default identity server <server /> to validate an email address or phone number, but the server does not have any terms of service.": "Den här åtgärden kräver åtkomst till standardidentitetsservern <server /> för att validera en e-postadress eller telefonnummer, men servern har inga användarvillkor.", "This action requires accessing the default identity server <server /> to validate an email address or phone number, but the server does not have any terms of service.": "Den här åtgärden kräver åtkomst till standardidentitetsservern <server /> för att validera en e-postadress eller ett telefonnummer, men servern har inga användarvillkor.",
"Trust": "Förtroende", "Trust": "Förtroende",
"%(name)s (%(userId)s)": "%(name)s (%(userId)s)", "%(name)s (%(userId)s)": "%(name)s (%(userId)s)",
"Try out new ways to ignore people (experimental)": "Testa nya sätt att ignorera personer (experimentalt)", "Try out new ways to ignore people (experimental)": "Testa nya sätt att ignorera personer (experimentellt)",
"Show previews/thumbnails for images": "Visa förhandsvisning/tumnagel för bilder", "Show previews/thumbnails for images": "Visa förhandsvisning/miniatyr för bilder",
"Custom (%(level)s)": "Anpassad (%(level)s)", "Custom (%(level)s)": "Anpassad (%(level)s)",
"Error upgrading room": "Fel vid uppgradering av rum", "Error upgrading room": "Fel vid uppgradering av rum",
"Double check that your server supports the room version chosen and try again.": "Dubbelkolla att din server stöder den valda rumsversionen och försök igen.", "Double check that your server supports the room version chosen and try again.": "Dubbelkolla att din server stöder den valda rumsversionen och försök igen.",
@ -1354,8 +1354,8 @@
"Connecting to integration manager...": "Ansluter till integrationshanterare...", "Connecting to integration manager...": "Ansluter till integrationshanterare...",
"Cannot connect to integration manager": "Det går inte att ansluta till integrationshanterare", "Cannot connect to integration manager": "Det går inte att ansluta till integrationshanterare",
"The integration manager is offline or it cannot reach your homeserver.": "Integrationshanteraren är offline eller kan inte nå din hemserver.", "The integration manager is offline or it cannot reach your homeserver.": "Integrationshanteraren är offline eller kan inte nå din hemserver.",
"Use an Integration Manager <b>(%(serverName)s)</b> to manage bots, widgets, and sticker packs.": "Använd en Integrationshanterare <b>(%(serverName)s)</b> för att hantera bots, widgets och klistermärkespaket.", "Use an Integration Manager <b>(%(serverName)s)</b> to manage bots, widgets, and sticker packs.": "Använd en integrationshanterare <b>(%(serverName)s)</b> för att hantera bottar, widgets och dekalpaket.",
"Use an Integration Manager to manage bots, widgets, and sticker packs.": "Använd en Integrationshanterare för att hantera bots, widgets och klistermärkespaket.", "Use an Integration Manager to manage bots, widgets, and sticker packs.": "Använd en integrationshanterare för att hantera bottar, widgets och dekalpaket.",
"Manage integrations": "Hantera integrationer", "Manage integrations": "Hantera integrationer",
"Integration Managers receive configuration data, and can modify widgets, send room invites, and set power levels on your behalf.": "Integrationshanterare får konfigurationsdata och kan ändra widgetar, skicka ruminbjudningar och ställa in behörighetsnivåer via ditt konto.", "Integration Managers receive configuration data, and can modify widgets, send room invites, and set power levels on your behalf.": "Integrationshanterare får konfigurationsdata och kan ändra widgetar, skicka ruminbjudningar och ställa in behörighetsnivåer via ditt konto.",
"Close preview": "Stäng förhandsvisning", "Close preview": "Stäng förhandsvisning",
@ -1458,16 +1458,16 @@
"Your user agent": "Din användaragent", "Your user agent": "Din användaragent",
"If you cancel now, you won't complete verifying the other user.": "Om du avbryter nu kommer du inte att verifiera den andra användaren.", "If you cancel now, you won't complete verifying the other user.": "Om du avbryter nu kommer du inte att verifiera den andra användaren.",
"If you cancel now, you won't complete verifying your other session.": "Om du avbryter nu kommer du inte att verifiera din andra session.", "If you cancel now, you won't complete verifying your other session.": "Om du avbryter nu kommer du inte att verifiera din andra session.",
"Cancel entering passphrase?": "Avbryta att ange lösenfras?", "Cancel entering passphrase?": "Avbryta inmatning av lösenfras?",
"Setting up keys": "Sätter upp nycklar", "Setting up keys": "Sätter upp nycklar",
"Verify this session": "Verifiera denna session", "Verify this session": "Verifiera denna session",
"Encryption upgrade available": "Krypteringsuppgradering tillgänglig", "Encryption upgrade available": "Krypteringsuppgradering tillgänglig",
"Set up encryption": "Ställ in kryptering", "Set up encryption": "Sätt upp kryptering",
"Sign In or Create Account": "Logga in eller skapa konto", "Sign In or Create Account": "Logga in eller skapa konto",
"Use your account or create a new one to continue.": "Använd ditt konto eller skapa ett nytt för att fortsätta.", "Use your account or create a new one to continue.": "Använd ditt konto eller skapa ett nytt för att fortsätta.",
"Create Account": "Skapa konto", "Create Account": "Skapa konto",
"Verifies a user, session, and pubkey tuple": "Verifierar en användar-, session- och pubkey-tupel", "Verifies a user, session, and pubkey tuple": "Verifierar en användar-, sessions- och pubkey-tupel",
"Unknown (user, session) pair:": "Okänt par (användare, session):", "Unknown (user, session) pair:": "Okänt (användare, session)-par:",
"Session already verified!": "Sessionen är redan verifierad!", "Session already verified!": "Sessionen är redan verifierad!",
"WARNING: Session already verified, but keys do NOT MATCH!": "VARNING: Sessionen har redan verifierats, men nycklarna MATCHAR INTE!", "WARNING: Session already verified, but keys do NOT MATCH!": "VARNING: Sessionen har redan verifierats, men nycklarna MATCHAR INTE!",
"Unable to revoke sharing for email address": "Det gick inte att återkalla delning för e-postadress", "Unable to revoke sharing for email address": "Det gick inte att återkalla delning för e-postadress",
@ -1519,25 +1519,151 @@
"Page Down": "Page Down", "Page Down": "Page Down",
"Esc": "Esc", "Esc": "Esc",
"Enter": "Enter", "Enter": "Enter",
"Space": "Space", "Space": "Mellanslag",
"End": "End", "End": "End",
"You have been logged out of all sessions and will no longer receive push notifications. To re-enable notifications, sign in again on each device.": "Du har blivit utloggad från alla dina sessioner och kommer inte längre att motta pushnotiser. För att återaktivera pushnotiser, logga in igen på varje enhet.", "You have been logged out of all sessions and will no longer receive push notifications. To re-enable notifications, sign in again on each device.": "Du har blivit utloggad från alla dina sessioner och kommer inte längre att motta pushnotiser. För att återaktivera pushnotiser, logga in igen på varje enhet.",
"Use Single Sign On to continue": "Använd Engångs Inloggning för att fortsätta", "Use Single Sign On to continue": "Använd single sign-on för att fortsätta",
"Confirm adding this email address by using Single Sign On to prove your identity.": "Bekräfta att du lägger till e-postadressen genom att använda Engångs Inloggning för att bevisa din identitet.", "Confirm adding this email address by using Single Sign On to prove your identity.": "Bekräfta tilläggning av e-postadressen genom att använda single sign-on för att bevisa din identitet.",
"Single Sign On": "Engångs Inloggning", "Single Sign On": "Single sign-on",
"Confirm adding email": "Bekräfta att du lägger till e-posten", "Confirm adding email": "Bekräfta tilläggning av e-postadressen",
"Click the button below to confirm adding this email address.": "Klicka på knappen nedan för att bekräfta att du lägger till e-postadressen.", "Click the button below to confirm adding this email address.": "Klicka på knappen nedan för att bekräfta tilläggning av e-postadressen.",
"Confirm adding this phone number by using Single Sign On to prove your identity.": "Bekräfta att du lägger till telefon numret genom att använda Engångs Inloggning för att bevisa din identitet.", "Confirm adding this phone number by using Single Sign On to prove your identity.": "Bekräfta tilläggning av telefonnumret genom att använda single sign-on för att bevisa din identitet.",
"Confirm adding phone number": "Bekräfta att du lägger till telefon numret", "Confirm adding phone number": "Bekräfta tilläggning av telefonnumret",
"Click the button below to confirm adding this phone number.": "Klicka på knappen nedan för att bekräfta att du lägger till telefon numret.", "Click the button below to confirm adding this phone number.": "Klicka på knappen nedan för att bekräfta tilläggning av telefonnumret.",
"Are you sure you want to cancel entering passphrase?": "Är du säker på att du bill avbryta inmatning av lösenordet?", "Are you sure you want to cancel entering passphrase?": "Är du säker på att du vill avbryta inmatning av lösenfrasen?",
"Go Back": "Gå tillbaka", "Go Back": "Gå tillbaka",
"Room name or address": "Rum namn eller adress", "Room name or address": "Rummets namn eller adress",
"%(name)s is requesting verification": "%(name)s begär verifiering", "%(name)s is requesting verification": "%(name)s begär verifiering",
"Use your account to sign in to the latest version": "Använd ditt konto för att logga in till den senaste versionen", "Use your account to sign in to the latest version": "Använd ditt konto för att logga in till den senaste versionen",
"Were excited to announce Riot is now Element": "Vi är glada att meddela att Riot är nu Element", "Were excited to announce Riot is now Element": "Vi är glada att meddela att Riot är nu Element",
"Riot is now Element!": "Riot är nu Element!", "Riot is now Element!": "Riot är nu Element!",
"Learn More": "Lär mer", "Learn More": "Lär mer",
"Sends a message as html, without interpreting it as markdown": "Skicka ett meddelande som html, utan att tolka det som markdown", "Sends a message as html, without interpreting it as markdown": "Skicka ett meddelande som HTML, utan att tolka det som Markdown",
"Failed to set topic": "Misslyckades med att ställa in ämnet" "Failed to set topic": "Misslyckades med att ställa in ämnet",
"Community Autocomplete": "Autokomplettering av gemenskaper",
"Joins room with given address": "Går med i rummet med den givna adressen",
"Unrecognised room address:": "Okänd rumsadress:",
"Command failed": "Kommandot misslyckades",
"Could not find user in room": "Kunde inte hitta användaren i rummet",
"Please supply a widget URL or embed code": "Ange en widget-URL eller inbäddningskod",
"WARNING: KEY VERIFICATION FAILED! The signing key for %(userId)s and session %(deviceId)s is \"%(fprint)s\" which does not match the provided key \"%(fingerprint)s\". This could mean your communications are being intercepted!": "VARNING: NYCKELVERIFIERING MISSLYCKADES! Den signerade nyckeln för %(userId)s och sessionen %(deviceId)s är \"%(fprint)s\" vilket inte matchar den givna nyckeln \"%(fingerprint)s\". Detta kan betyda att kommunikationen är övervakad!",
"The signing key you provided matches the signing key you received from %(userId)s's session %(deviceId)s. Session marked as verified.": "Signeringsnyckeln du gav matchar signeringsnyckeln du fick av %(userId)ss session %(deviceId)s. Sessionen markerades som verifierad.",
"Displays information about a user": "Visar information om en användare",
"Send a bug report with logs": "Skicka en buggrapport med loggar",
"Opens chat with the given user": "Öppnar en chatt med den valda användaren",
"Sends a message to the given user": "Skickar ett meddelande till den valda användaren",
"%(senderDisplayName)s changed the room name from %(oldRoomName)s to %(newRoomName)s.": "%(senderDisplayName)s bytte rummets namn från %(oldRoomName)s till %(newRoomName)s.",
"%(senderName)s added the alternative addresses %(addresses)s for this room.|other": "%(senderName)s lade till de alternativa adresserna %(addresses)s till det här rummet.",
"%(senderName)s added the alternative addresses %(addresses)s for this room.|one": "%(senderName)s lade till den alternativa adressen %(addresses)s till det här rummet.",
"%(senderName)s removed the alternative addresses %(addresses)s for this room.|other": "%(senderName)s tog bort de alternativa adresserna %(addresses)s från det här rummet.",
"%(senderName)s removed the alternative addresses %(addresses)s for this room.|one": "%(senderName)s tog bort den alternativa adressen %(addresses)s från det här rummet.",
"%(senderName)s changed the alternative addresses for this room.": "%(senderName)s ändrade de alternativa adresserna för det här rummet.",
"%(senderName)s changed the main and alternative addresses for this room.": "%(senderName)s ändrade huvudadressen och de alternativa adresserna för det här rummet.",
"%(senderName)s changed the addresses for this room.": "%(senderName)s ändrade adresserna för det här rummet.",
"%(senderName)s removed a ban rule matching %(glob)s": "%(senderName)s tog bort en bannregel som matchar %(glob)s",
"%(senderName)s updated an invalid ban rule": "%(senderName)s uppdaterade en ogiltig bannregel",
"%(senderName)s updated the rule banning users matching %(glob)s for %(reason)s": "%(senderName)s uppdaterade regeln som bannar användare som matchar %(glob)s på grund av %(reason)s",
"%(senderName)s updated the rule banning rooms matching %(glob)s for %(reason)s": "%(senderName)s uppdaterade regeln som bannar rum som matchar %(glob)s på grund av %(reason)s",
"%(senderName)s updated the rule banning servers matching %(glob)s for %(reason)s": "%(senderName)s uppdaterade regeln som bannar servrar som matchar %(glob)s på grund av %(reason)s",
"%(senderName)s updated a ban rule matching %(glob)s for %(reason)s": "%(senderName)s uppdaterade en bannregel som matchar %(glob)s på grund av %(reason)s",
"Use bots, bridges, widgets and sticker packs": "Använd bottar, bryggor, widgets och dekalpaket",
"%(senderName)s created a rule banning users matching %(glob)s for %(reason)s": "%(senderName)s skapade en regel som bannar användare som matchar %(glob)s på grund av %(reason)s",
"%(senderName)s created a rule banning rooms matching %(glob)s for %(reason)s": "%(senderName)s skapade en regel som bannar rum som matchar %(glob)s på grund av %(reason)s",
"%(senderName)s created a rule banning servers matching %(glob)s for %(reason)s": "%(senderName)s skapade en regel som bannar servrar som matchar %(glob)s på grund av %(reason)s",
"%(senderName)s created a ban rule matching %(glob)s for %(reason)s": "%(senderName)s skapade en bannregel som matchar %(glob)s på grund av %(reason)s",
"%(senderName)s changed a rule that was banning users matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s ändrade en regel som bannade användare som matchade %(oldGlob)s till att matcha %(newGlob)s på grund av %(reason)s",
"%(senderName)s changed a rule that was banning rooms matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s ändrade en regel som bannade rum som matchade %(oldGlob)s till att matcha %(newGlob)s på grund av %(reason)s",
"%(senderName)s changed a rule that was banning servers matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s ändrade en regel som bannade servrar som matchade %(oldGlob)s till att matcha %(newGlob)s på grund av %(reason)s",
"%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s uppdaterade en bannregel som matchade %(oldGlob)s till att matcha %(newGlob)s på grund av %(reason)s",
"Light": "Ljust",
"Dark": "Mörkt",
"You signed in to a new session without verifying it:": "Du loggade in i en ny session utan att verifiera den:",
"Verify your other session using one of the options below.": "Verifiera din andra session med ett av alternativen nedan.",
"%(name)s (%(userId)s) signed in to a new session without verifying it:": "%(name)s (%(userId)s) loggade in i en ny session utan att verifiera den:",
"Ask this user to verify their session, or manually verify it below.": "Be den här användaren att verifiera sin session, eller verifiera den manuellt nedan.",
"Not Trusted": "Inte betrodd",
"Manually Verify by Text": "Verifiera manuellt med text",
"Interactively verify by Emoji": "Verifiera interaktivt med emoji",
"Done": "Klar",
"a few seconds ago": "några sekunder sedan",
"about a minute ago": "cirka en minut sedan",
"%(num)s minutes ago": "%(num)s minuter sedan",
"about an hour ago": "cirka en timme sedan",
"%(num)s hours ago": "%(num)s timmar sedan",
"about a day ago": "cirka en dag sedan",
"%(num)s days ago": "%(num)s dagar sedan",
"a few seconds from now": "om några sekunder",
"about a minute from now": "om cirka en minut",
"%(num)s minutes from now": "om %(num)s minuter",
"about an hour from now": "om cirka en timme",
"%(num)s hours from now": "om %(num)s timmar",
"about a day from now": "om cirka en dag",
"%(num)s days from now": "om %(num)s dagar",
"Unexpected server error trying to leave the room": "Oväntat serverfel vid försök att lämna rummet",
"Error leaving room": "Fel när rummet lämnades",
"Help us improve %(brand)s": "Hjälp oss att förbättra %(brand)s",
"Send <UsageDataLink>anonymous usage data</UsageDataLink> which helps us improve %(brand)s. This will use a <PolicyLink>cookie</PolicyLink>.": "Skicka <UsageDataLink>anonym användningsdata</UsageDataLink> vilken hjälper oss att förbättra %(brand)s. Detta kommer att använda en <PolicyLink>kaka</PolicyLink>.",
"I want to help": "Jag vill hjälpa till",
"Review where youre logged in": "Granska var du är inloggad",
"Verify all your sessions to ensure your account & messages are safe": "Verifiera alla dina sessioner för att försäkra att ditt konto och dina meddelanden är säkra",
"Review": "Granska",
"Later": "Senare",
"Your homeserver has exceeded its user limit.": "Din hemserver har överskridit sin användargräns.",
"Your homeserver has exceeded one of its resource limits.": "Din hemserver har överskridit en av sina resursgränser.",
"Contact your <a>server admin</a>.": "Kontakta din <a>serveradministratör</a>.",
"Ok": "OK",
"Set password": "Sätt lösenord",
"To return to your account in future you need to set a password": "För att komma tillbaka till ditt konto i framtiden behöver du sätta ett lösenord",
"Set up": "Sätt upp",
"Upgrade": "Uppgradera",
"Verify": "Verifiera",
"Verify yourself & others to keep your chats safe": "Verifiera dig själv och andra för att hålla dina chattar säkra",
"Other users may not trust it": "Andra användare kanske inta litar på den",
"New login. Was this you?": "Ny inloggning. Var det du?",
"Verify the new login accessing your account: %(name)s": "Verifiera den nya inloggningen på ditt konto: %(name)s",
"Restart": "Starta om",
"Upgrade your %(brand)s": "Uppgradera din %(brand)s",
"A new version of %(brand)s is available!": "En ny version av %(brand)s är tillgänglig!",
"The person who invited you already left the room.": "Personen som bjöd in dig har redan lämnat rummet.",
"The person who invited you already left the room, or their server is offline.": "Personen som bjöd in dig har redan lämnat rummet, eller så är deras server offline.",
"You joined the call": "Du gick med i samtalet",
"%(senderName)s joined the call": "%(senderName)s gick med i samtalet",
"Call in progress": "Samtal pågår",
"You left the call": "Du lämnade samtalet",
"%(senderName)s left the call": "%(senderName)s lämnade samtalet",
"Call ended": "Samtalet avslutades",
"You started a call": "Du startade ett samtal",
"%(senderName)s started a call": "%(senderName)s startade ett samtal",
"Waiting for answer": "Väntar på svar",
"%(senderName)s is calling": "%(senderName)s ringer",
"* %(senderName)s %(emote)s": "* %(senderName)s %(emote)s",
"%(senderName)s: %(message)s": "%(senderName)s: %(message)s",
"%(senderName)s: %(reaction)s": "%(senderName)s: %(reaction)s",
"%(senderName)s: %(stickerName)s": "%(senderName)s: %(stickerName)s",
"Change notification settings": "Ändra aviseringsinställningar",
"Communities v2 prototypes. Requires compatible homeserver. Highly experimental - use with caution.": "Gemenskap-v2-prototyper. Kräver kompatibel hemserver. Väldigt experimentellt - använd varsamt.",
"New spinner design": "Ny spinnerdesign",
"Support adding custom themes": "Stöd tilläggning av anpassade teman",
"Show message previews for reactions in DMs": "Visa meddelandeförhandsvisningar för reaktioner i DM:er",
"Show message previews for reactions in all rooms": "Visa meddelandeförhandsvisningar för reaktioner i alla rum",
"Enable advanced debugging for the room list": "Aktivera avancerad avbuggning för rumslistan",
"Show info about bridges in room settings": "Visa info om bryggor i rumsinställningar",
"Font size": "Teckenstorlek",
"Use custom size": "Använd anpassad storlek",
"Use a more compact Modern layout": "Använd ett mer kompakt modernt arrangemang",
"Show typing notifications": "Visa \"skriver\"-statusar",
"Use a system font": "Använd systemets teckensnitt",
"System font name": "Namn på systemets teckensnitt",
"Never send encrypted messages to unverified sessions from this session": "Skicka aldrig krypterade meddelanden till overifierade sessioner från den här sessionen",
"Never send encrypted messages to unverified sessions in this room from this session": "Skicka aldrig krypterade meddelanden till overifierade sessioner i det här rummet från den här sessionen",
"Order rooms by name": "Sortera rum efter namn",
"Show rooms with unread notifications first": "Visa rum med olästa aviseringar först",
"Show shortcuts to recently viewed rooms above the room list": "Visa genvägar till nyligen visade rum över rumslistan",
"Enable message search in encrypted rooms": "Aktivera meddelandesökning i krypterade rum",
"How fast should messages be downloaded.": "Hur snabbt ska meddelanden laddas ner.",
"Manually verify all remote sessions": "Verifiera alla fjärrsessioner manuellt",
"IRC display name width": "Bredd för IRC-visningsnamn",
"Enable experimental, compact IRC style layout": "Aktivera experimentellt kompakt IRC-likt arrangemang",
"Uploading logs": "Laddar upp loggar",
"Downloading logs": "Laddar ner loggar"
} }

View file

@ -67,7 +67,7 @@
"Cannot add any more widgets": "Неможливо додати більше віджетів", "Cannot add any more widgets": "Неможливо додати більше віджетів",
"Change Password": "Змінити пароль", "Change Password": "Змінити пароль",
"%(senderName)s changed their profile picture.": "%(senderName)s змінив/ла зображення профілю.", "%(senderName)s changed their profile picture.": "%(senderName)s змінив/ла зображення профілю.",
"%(senderName)s changed the power level of %(powerLevelDiffText)s.": "%(senderName)s змінив(ла) рівень повноважень %(powerLevelDiffText)s.", "%(senderName)s changed the power level of %(powerLevelDiffText)s.": "%(senderName)s змінив(-ла) рівень повноважень %(powerLevelDiffText)s.",
"%(senderDisplayName)s changed the room name to %(roomName)s.": "%(senderDisplayName)s змінив/ла назву кімнати на %(roomName)s.", "%(senderDisplayName)s changed the room name to %(roomName)s.": "%(senderDisplayName)s змінив/ла назву кімнати на %(roomName)s.",
"%(senderDisplayName)s removed the room name.": "%(senderDisplayName)s видалив ім'я кімнати.", "%(senderDisplayName)s removed the room name.": "%(senderDisplayName)s видалив ім'я кімнати.",
"%(senderDisplayName)s changed the topic to \"%(topic)s\".": "%(senderDisplayName)s змінив тему на %(topic)s.", "%(senderDisplayName)s changed the topic to \"%(topic)s\".": "%(senderDisplayName)s змінив тему на %(topic)s.",
@ -82,7 +82,7 @@
"This email address is already in use": "Ця е-пошта вже використовується", "This email address is already in use": "Ця е-пошта вже використовується",
"This phone number is already in use": "Цей телефонний номер вже використовується", "This phone number is already in use": "Цей телефонний номер вже використовується",
"Fetching third party location failed": "Не вдалось отримати стороннє місцеперебування", "Fetching third party location failed": "Не вдалось отримати стороннє місцеперебування",
"Messages in one-to-one chats": "Повідомлення у чатах \"сам на сам\"", "Messages in one-to-one chats": "Повідомлення у балачках віч-на-віч",
"Send Account Data": "Надіслати дані облікового запису", "Send Account Data": "Надіслати дані облікового запису",
"Advanced notification settings": "Додаткові налаштування сповіщень", "Advanced notification settings": "Додаткові налаштування сповіщень",
"Uploading report": "Завантаження звіту", "Uploading report": "Завантаження звіту",
@ -109,7 +109,7 @@
"Cancel Sending": "Скасувати надсилання", "Cancel Sending": "Скасувати надсилання",
"Warning": "Попередження", "Warning": "Попередження",
"This Room": "Ця кімната", "This Room": "Ця кімната",
"Noisy": "Шумний", "Noisy": "Шумно",
"Error saving email notification preferences": "Помилка при збереженні параметрів сповіщень е-поштою", "Error saving email notification preferences": "Помилка при збереженні параметрів сповіщень е-поштою",
"Messages containing my display name": "Повідомлення, що містять моє видиме ім'я", "Messages containing my display name": "Повідомлення, що містять моє видиме ім'я",
"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.": "Пам'ятайте, що ви завжди можете встановити адресу е-пошти у користувацьких налаштуваннях, якщо передумаєте.",
@ -124,7 +124,7 @@
"Explore Room State": "Перегляд статуса кімнати", "Explore Room State": "Перегляд статуса кімнати",
"Source URL": "Джерельне посилання", "Source URL": "Джерельне посилання",
"Messages sent by bot": "Повідомлення, надіслані ботом", "Messages sent by bot": "Повідомлення, надіслані ботом",
"Filter results": "Фільтр результатів", "Filter results": "Відцідити результати",
"Members": "Учасники", "Members": "Учасники",
"No update available.": "Оновлення відсутні.", "No update available.": "Оновлення відсутні.",
"Resend": "Перенадіслати", "Resend": "Перенадіслати",
@ -188,7 +188,7 @@
"Unable to join network": "Неможливо приєднатись до мережі", "Unable to join network": "Неможливо приєднатись до мережі",
"Sorry, your browser is <b>not</b> able to run %(brand)s.": "Вибачте, ваш оглядач <b>не</b> спроможний запустити %(brand)s.", "Sorry, your browser is <b>not</b> able to run %(brand)s.": "Вибачте, ваш оглядач <b>не</b> спроможний запустити %(brand)s.",
"Uploaded on %(date)s by %(user)s": "Завантажено %(date)s користувачем %(user)s", "Uploaded on %(date)s by %(user)s": "Завантажено %(date)s користувачем %(user)s",
"Messages in group chats": "Повідомлення у групових чатах", "Messages in group chats": "Повідомлення у групових балачках",
"Yesterday": "Вчора", "Yesterday": "Вчора",
"Error encountered (%(errorDetail)s).": "Трапилась помилка (%(errorDetail)s).", "Error encountered (%(errorDetail)s).": "Трапилась помилка (%(errorDetail)s).",
"Low Priority": "Неважливі", "Low Priority": "Неважливі",
@ -298,7 +298,7 @@
"Missing roomId.": "Бракує ідентифікатора кімнати.", "Missing roomId.": "Бракує ідентифікатора кімнати.",
"Failed to send request.": "Не вдалося надіслати запит.", "Failed to send request.": "Не вдалося надіслати запит.",
"This room is not recognised.": "Кімнату не знайдено.", "This room is not recognised.": "Кімнату не знайдено.",
"Power level must be positive integer.": "Рівень повноважень мусить бути додатнім цілим числом.", "Power level must be positive integer.": "Рівень повноважень мусить бути додатним цілим числом.",
"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.": "У вас немає прав виконувати для цього в цій кімнаті.",
"Missing room_id in request": "У запиті бракує room_id", "Missing room_id in request": "У запиті бракує room_id",
@ -348,19 +348,19 @@
"(no answer)": "(немає відповіді)", "(no answer)": "(немає відповіді)",
"(unknown failure: %(reason)s)": "(невідома помилка: %(reason)s)", "(unknown failure: %(reason)s)": "(невідома помилка: %(reason)s)",
"%(senderName)s ended the call.": "%(senderName)s завершив/ла дзвінок.", "%(senderName)s ended the call.": "%(senderName)s завершив/ла дзвінок.",
"%(senderName)s sent an invitation to %(targetDisplayName)s to join the room.": "%(senderName)s надіслав/ла запрошення %(targetDisplayName)s приєднатися до кімнати.", "%(senderName)s sent an invitation to %(targetDisplayName)s to join the room.": "%(senderName)s надіслав(-ла) запрошення %(targetDisplayName)s приєднатися до кімнати.",
"Show developer tools": "Показувати розробницькі засоби", "Show developer tools": "Показувати розробницькі засоби",
"Default": "Типово", "Default": "Типово",
"%(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 are invited.": "%(senderName)s зробив(-ла) майбутню історію кімнати видимою для всіх учасників з моменту, коли вони приєдналися.",
"%(senderName)s made future room history visible to all room members, from the point they joined.": "%(senderName)s зробив/ла майбутню історію кімнати видимою для всіх учасників, з моменту, коли вони приєдналися.", "%(senderName)s made future room history visible to all room members, from the point they joined.": "%(senderName)s зробив(-ла) майбутню історію кімнати видимою для всіх учасників з моменту, коли вони приєдналися.",
"%(senderName)s made future room history visible to all room members.": "%(senderName)s зробив/ла майбутню історію видимою для всіх учасників кімнати.", "%(senderName)s made future room history visible to all room members.": "%(senderName)s зробив(-ла) майбутню історію видимою для всіх учасників кімнати.",
"%(senderName)s made future room history visible to anyone.": "%(senderName)s зробив/ла майбутню історію кімнати видимою для всіх.", "%(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).", "%(senderName)s made future room history visible to unknown (%(visibility)s).": "%(senderName)s зробив(-ла) майбутню історію видимою для невідомого значення (%(visibility)s).",
"%(userId)s from %(fromPowerLevel)s to %(toPowerLevel)s": "%(userId)s з %(fromPowerLevel)s до %(toPowerLevel)s", "%(userId)s from %(fromPowerLevel)s to %(toPowerLevel)s": "%(userId)s з %(fromPowerLevel)s до %(toPowerLevel)s",
"%(senderName)s changed the pinned messages for the room.": "%(senderName)s змінив/ла прикріплені повідомлення для кімнати.", "%(senderName)s changed the pinned messages for the room.": "%(senderName)s змінив(-ла) приколоті повідомлення у кімнаті.",
"%(widgetName)s widget modified by %(senderName)s": "%(senderName)s змінив/ла %(widgetName)s", "%(widgetName)s widget modified by %(senderName)s": "%(senderName)s змінив(-ла) знадіб %(widgetName)s",
"%(widgetName)s widget added by %(senderName)s": "%(senderName)s додав/ла %(widgetName)s", "%(widgetName)s widget added by %(senderName)s": "%(senderName)s додав(-ла) знадіб %(widgetName)s",
"%(widgetName)s widget removed by %(senderName)s": "%(senderName)s вилучив/ла %(widgetName)s", "%(widgetName)s widget removed by %(senderName)s": "%(senderName)s вилучив(-ла) знадіб %(widgetName)s",
"Failure to create room": "Не вдалося створити кімнату", "Failure to create room": "Не вдалося створити кімнату",
"Server may be unavailable, overloaded, or you hit a bug.": "Сервер може бути недоступний, перевантажений, або ж ви натрапили на ваду.", "Server may be unavailable, overloaded, or you hit a bug.": "Сервер може бути недоступний, перевантажений, або ж ви натрапили на ваду.",
"Unnamed Room": "Кімната без назви", "Unnamed Room": "Кімната без назви",
@ -556,9 +556,9 @@
"Decline (%(counter)s)": "Відхилити (%(counter)s)", "Decline (%(counter)s)": "Відхилити (%(counter)s)",
"Language and region": "Мова та регіон", "Language and region": "Мова та регіон",
"Account management": "Керування обліковим записом", "Account management": "Керування обліковим записом",
"Deactivating your account is a permanent action - be careful!": "Деактивація вашого облікового запису є безповоротною дією — будьте обережні!", "Deactivating your account is a permanent action - be careful!": "Знедіяння вашого облікового запису є безповоротним — будьте обережні!",
"Deactivate Account": "Деактивувати обліковий запис", "Deactivate Account": "Знедіяти обліковий запис",
"Deactivate account": "Знедіяти обліківку", "Deactivate account": "Знедіяти обліковий запис",
"Legal": "Правова інформація", "Legal": "Правова інформація",
"Credits": "Подяки", "Credits": "Подяки",
"For help with using %(brand)s, click <a>here</a>.": "Якщо необхідна допомога у користуванні %(brand)s'ом, клацніть <a>тут</a>.", "For help with using %(brand)s, click <a>here</a>.": "Якщо необхідна допомога у користуванні %(brand)s'ом, клацніть <a>тут</a>.",
@ -572,7 +572,7 @@
"Clear notifications": "Очистити сповіщення", "Clear notifications": "Очистити сповіщення",
"Add an email address to configure email notifications": "Додати адресу е-пошти для налаштування поштових сповіщень", "Add an email address to configure email notifications": "Додати адресу е-пошти для налаштування поштових сповіщень",
"Theme added!": "Тему додано!", "Theme added!": "Тему додано!",
"Email addresses": "Адреса е-пошти", "Email addresses": "Адреси е-пошти",
"Phone numbers": "Номери телефонів", "Phone numbers": "Номери телефонів",
"Set a new account password...": "Встановити новий пароль облікового запису…", "Set a new account password...": "Встановити новий пароль облікового запису…",
"Forget this room": "Забути цю кімнату", "Forget this room": "Забути цю кімнату",
@ -582,7 +582,7 @@
"This invite to %(roomName)s was sent to %(email)s": "Це запрошення до %(roomName)s було надіслане на %(email)s", "This invite to %(roomName)s was sent to %(email)s": "Це запрошення до %(roomName)s було надіслане на %(email)s",
"Use an identity server in Settings to receive invites directly in %(brand)s.": "Використовувати сервер ідентифікації у Налаштуваннях щоб отримувати запрошення прямо у %(brand)s.", "Use an identity server in Settings to receive invites directly in %(brand)s.": "Використовувати сервер ідентифікації у Налаштуваннях щоб отримувати запрошення прямо у %(brand)s.",
"Are you sure you want to deactivate your account? This is irreversible.": "Ви впевнені у тому, що бажаєте знедіяти ваш обліковий запис? Ця дія безповоротна.", "Are you sure you want to deactivate your account? This is irreversible.": "Ви впевнені у тому, що бажаєте знедіяти ваш обліковий запис? Ця дія безповоротна.",
"Confirm account deactivation": "Підтвердьте деактивацію облікового запису", "Confirm account deactivation": "Підтвердьте знедіювання облікового запису",
"To continue, please enter your password:": "Щоб продовжити, введіть, будь ласка, ваш пароль:", "To continue, please enter your password:": "Щоб продовжити, введіть, будь ласка, ваш пароль:",
"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>": "Ваш обліковий запис стане назавжди невикористовним. Ви не матимете змоги увійти в нього і ніхто не зможе перереєструватись під цим користувацьким ID. Це призведе до виходу вашого облікового запису з усіх кімнат та до видалення деталей вашого облікового запису з вашого серверу ідентифікації. <b>Ця дія є безповоротною.</b>", "This will make your account permanently unusable. You will not be able to log in, and no one will be able to re-register the same user ID. This will cause your account to leave all rooms it is participating in, and it will remove your account details from your identity server. <b>This action is irreversible.</b>": "Ваш обліковий запис стане назавжди невикористовним. Ви не матимете змоги увійти в нього і ніхто не зможе перереєструватись під цим користувацьким ID. Це призведе до виходу вашого облікового запису з усіх кімнат та до видалення деталей вашого облікового запису з вашого серверу ідентифікації. <b>Ця дія є безповоротною.</b>",
"Verify session": "Звірити сесію", "Verify session": "Звірити сесію",
@ -680,18 +680,18 @@
"%(senderName)s placed a video call.": "%(senderName)s розпочав(-ла) відеовиклик.", "%(senderName)s placed a video call.": "%(senderName)s розпочав(-ла) відеовиклик.",
"%(senderName)s placed a video call. (not supported by this browser)": "%(senderName)s розпочав(-ла) відеовиклик. (не підтримується цим переглядачем)", "%(senderName)s placed a video call. (not supported by this browser)": "%(senderName)s розпочав(-ла) відеовиклик. (не підтримується цим переглядачем)",
"%(senderName)s revoked the invitation for %(targetDisplayName)s to join the room.": "%(senderName)s відкликав(-ла) запрошення %(targetDisplayName)s приєднання до кімнати.", "%(senderName)s revoked the invitation for %(targetDisplayName)s to join the room.": "%(senderName)s відкликав(-ла) запрошення %(targetDisplayName)s приєднання до кімнати.",
"%(senderName)s removed the rule banning users matching %(glob)s": "%(senderName)s видалив(-ла) правило блокування користувачів за шаблоном %(glob)s", "%(senderName)s removed the rule banning users matching %(glob)s": "%(senderName)s видалив(-ла) правило блокування користувачів зі збігом з %(glob)s",
"%(senderName)s removed the rule banning rooms matching %(glob)s": "%(senderName)s видалив(ла) правило блокування кімнат по шаблону %(glob)s", "%(senderName)s removed the rule banning rooms matching %(glob)s": "%(senderName)s видалив(-ла) правило блокування кімнат зі збігом з %(glob)s",
"%(senderName)s removed the rule banning servers matching %(glob)s": "%(senderName)s видалив(ла) правило блокування серверів по шаблону %(glob)s", "%(senderName)s removed the rule banning servers matching %(glob)s": "%(senderName)s видалив(-ла) правило блокування серверів зі збігом з %(glob)s",
"%(senderName)s removed a ban rule matching %(glob)s": "%(senderName)s видалив(ла) правило блокування по шаблону %(glob)s", "%(senderName)s removed a ban rule matching %(glob)s": "%(senderName)s видалив(-ла) правило блокування зі збігом з %(glob)s",
"%(senderName)s updated an invalid ban rule": "%(senderName)s оновив(ла) неправильне правило блокування", "%(senderName)s updated an invalid ban rule": "%(senderName)s оновив(-ла) хибне правило блокування",
"%(senderName)s updated the rule banning users matching %(glob)s for %(reason)s": "%(senderName)s оновив(ла) правило блокування користувачів по шаблону %(glob)s за %(reason)s", "%(senderName)s updated the rule banning users matching %(glob)s for %(reason)s": "%(senderName)s оновив(-ла) правило блокування користувачів зі збігом з %(glob)s через %(reason)s",
"%(senderName)s updated the rule banning rooms matching %(glob)s for %(reason)s": "%(senderName)s оновив(ла) правило блокування кімнат по шаблону %(glob)s за %(reason)s", "%(senderName)s updated the rule banning rooms matching %(glob)s for %(reason)s": "%(senderName)s оновив(-ла) правило блокування кімнат зі збігом з %(glob)s через %(reason)s",
"%(senderName)s updated the rule banning servers matching %(glob)s for %(reason)s": "%(senderName)s оновив(ла) правило блокування серверів по шаблону %(glob)s за %(reason)s", "%(senderName)s updated the rule banning servers matching %(glob)s for %(reason)s": "%(senderName)s оновив(-ла) правило блокування серверів зі збігом з %(glob)s через %(reason)s",
"%(senderName)s updated a ban rule matching %(glob)s for %(reason)s": "%(senderName)s оновив(ла) правило блокування по шаблону %(glob)s за %(reason)s", "%(senderName)s updated a ban rule matching %(glob)s for %(reason)s": "%(senderName)s оновив(-ла) правило блокування зі збігом з %(glob)s через %(reason)s",
"%(senderName)s created a rule banning users matching %(glob)s for %(reason)s": "%(senderName)s створив(ла) правило блокування користувачів по шаблону %(glob)s за %(reason)s", "%(senderName)s created a rule banning users matching %(glob)s for %(reason)s": "%(senderName)s створив(-ла) правило блокування користувачів зі збігом з %(glob)s через %(reason)s",
"%(senderName)s created a rule banning rooms matching %(glob)s for %(reason)s": "%(senderName)s створив(ла) правило блокування кімнат по шаблону %(glob)s за %(reason)s", "%(senderName)s created a rule banning rooms matching %(glob)s for %(reason)s": "%(senderName)s створив(-ла) правило блокування кімнат зі збігом з %(glob)s через %(reason)s",
"%(senderName)s created a rule banning servers matching %(glob)s for %(reason)s": "%(senderName)s створив(ла) правило блокування серверів по шаблону %(glob)s за %(reason)s", "%(senderName)s created a rule banning servers matching %(glob)s for %(reason)s": "%(senderName)s створив(-ла) правило блокування серверів зі збігом з %(glob)s через %(reason)s",
"Light": "Світла", "Light": "Світла",
"Dark": "Темна", "Dark": "Темна",
"You signed in to a new session without verifying it:": "Ви увійшли в нову сесію, не підтвердивши її:", "You signed in to a new session without verifying it:": "Ви увійшли в нову сесію, не підтвердивши її:",
@ -794,7 +794,7 @@
"%(senderName)s: %(reaction)s": "%(senderName)s: %(reaction)s", "%(senderName)s: %(reaction)s": "%(senderName)s: %(reaction)s",
"%(senderName)s: %(stickerName)s": "%(senderName)s: %(stickerName)s", "%(senderName)s: %(stickerName)s": "%(senderName)s: %(stickerName)s",
"Custom user status messages": "користувацький статус", "Custom user status messages": "користувацький статус",
"Group & filter rooms by custom tags (refresh to apply changes)": "Групувати та фільтрувати кімнати за кастомними тегами (оновіть для застосування змін)", "Group & filter rooms by custom tags (refresh to apply changes)": "Групувати та проціджувати кімнати за нетиповими наличками (оновіть щоб застосувати зміни)",
"Multiple integration managers": "Декілька менджерів інтеграції", "Multiple integration managers": "Декілька менджерів інтеграції",
"Try out new ways to ignore people (experimental)": "Спробуйте нові способи ігнорувати людей (експериментальні)", "Try out new ways to ignore people (experimental)": "Спробуйте нові способи ігнорувати людей (експериментальні)",
"Support adding custom themes": "Підтримка користувацьких тем", "Support adding custom themes": "Підтримка користувацьких тем",
@ -805,14 +805,14 @@
"Enable Emoji suggestions while typing": "Увімкнути пропонування емодзі при друкуванні", "Enable Emoji suggestions while typing": "Увімкнути пропонування емодзі при друкуванні",
"Use a more compact Modern layout": "Використовувати компактнішу \"Сучасну\" тему", "Use a more compact Modern layout": "Використовувати компактнішу \"Сучасну\" тему",
"General": "Загальні", "General": "Загальні",
"Discovery": "Відкриття", "Discovery": "Виявлення",
"Help & About": "Допомога та про програму", "Help & About": "Допомога та про програму",
"Bug reporting": "Повідомити про помилку", "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, журнали можуть допомогти нам виявити проблеми. Журнали відладки, що містять інформацію про використані додатки, включають ваше ім’я користувача, ідентифікатори або псевдоніми кімнат або груп, які ви відвідували, а також імена інших користувачів. Вони не містять повідомлень.", "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": "Відправити відладочні журнали (debug logs)", "Submit debug logs": "Надіслати журнал зневадження",
"Clear cache and reload": "Очистити кеш та перезавантажити", "Clear cache and reload": "Очистити кеш та перезавантажити",
"To report a Matrix-related security issue, please read the Matrix.org <a>Security Disclosure Policy</a>.": "Щоб повідомити про проблеми безпеки Matrix, будь ласка, прочитайте <a>Політику розкриття інформації</a> Matrix.org.", "To report a Matrix-related security issue, please read the Matrix.org <a>Security Disclosure Policy</a>.": "Щоб повідомити про проблеми безпеки Matrix, будь ласка, прочитайте <a>Політику розкриття інформації</a> Matrix.org.",
"FAQ": "Часті питання", "FAQ": "ЧаПи",
"Keyboard Shortcuts": "Гарячі клавіші", "Keyboard Shortcuts": "Гарячі клавіші",
"Versions": "Версії", "Versions": "Версії",
"%(brand)s version:": "версія %(brand)s:", "%(brand)s version:": "версія %(brand)s:",
@ -992,7 +992,7 @@
"Backup version: ": "Версія резервної копії: ", "Backup version: ": "Версія резервної копії: ",
"Algorithm: ": "Алгоритм: ", "Algorithm: ": "Алгоритм: ",
"Backup key stored: ": "Резервна копія ключа збережена ", "Backup key stored: ": "Резервна копія ключа збережена ",
"Enable audible notifications for this session": "Ввімкнути звукові сповіщення для цього сеансу", "Enable audible notifications for this session": "Увімкнути звукові сповіщення для цього сеансу",
"Save": "Зберегти", "Save": "Зберегти",
"Checking server": "Перевірка серверу", "Checking server": "Перевірка серверу",
"Disconnect": "Відключити", "Disconnect": "Відключити",
@ -1017,7 +1017,7 @@
"Unable to revoke sharing for email address": "Не вдалось відкликати оприлюднювання адреси е-пошти", "Unable to revoke sharing for email address": "Не вдалось відкликати оприлюднювання адреси е-пошти",
"Revoke": "Відкликати", "Revoke": "Відкликати",
"Unable to revoke sharing for phone number": "Не вдалось відкликати оприлюднювання телефонного номеру", "Unable to revoke sharing for phone number": "Не вдалось відкликати оприлюднювання телефонного номеру",
"Filter room members": "Відфільтрувати учасників кімнати", "Filter room members": "Відцідити учасників кімнати",
"Voice call": "Голосовий виклик", "Voice call": "Голосовий виклик",
"Video call": "Відеовиклик", "Video call": "Відеовиклик",
"Not now": "Не зараз", "Not now": "Не зараз",
@ -1180,5 +1180,54 @@
"or another cross-signing capable Matrix client": "або інший здатний до перехресного підписування Matrix-клієнт", "or another cross-signing capable Matrix client": "або інший здатний до перехресного підписування Matrix-клієнт",
"Your new session is now verified. It has access to your encrypted messages, and other users will see it as trusted.": "Ваш новий сеанс тепер є звірений. Він має доступ до ваших зашифрованих повідомлень, а інші користувачі бачитимуть його як довірений.", "Your new session is now verified. It has access to your encrypted messages, and other users will see it as trusted.": "Ваш новий сеанс тепер є звірений. Він має доступ до ваших зашифрованих повідомлень, а інші користувачі бачитимуть його як довірений.",
"Emoji": "Емодзі", "Emoji": "Емодзі",
"Emoji Autocomplete": "Самодоповнення емодзі" "Emoji Autocomplete": "Самодоповнення емодзі",
"%(senderName)s created a ban rule matching %(glob)s for %(reason)s": "%(senderName)s створив(-ла) правило блокування зі збігом з %(glob)s через %(reason)s",
"%(senderName)s changed a rule that was banning users matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s змінив(-ла) правило блокування користувачів зі збігу з %(oldGlob)s на збіг з %(newGlob)s через %(reason)s",
"%(senderName)s changed a rule that was banning rooms matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s змінив(-ла) правило блокування кімнат зі збігу з %(oldGlob)s на збіг з %(newGlob)s через %(reason)s",
"%(senderName)s changed a rule that was banning servers matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s змінив(-ла) правило блокування серверів зі збігу з %(oldGlob)s на збіг з %(newGlob)s через %(reason)s",
"%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s змінив(-ла) правило блокування зі збігу з %(oldGlob)s на збіг з %(newGlob)s через %(reason)s",
"Enable Community Filter Panel": "Увімкнути панель спільнот",
"Messages containing my username": "Повідомлення, що містять моє користувацьке ім'я",
"Messages containing @room": "Повідомлення, що містять @room",
"When rooms are upgraded": "Коли кімнати поліпшено",
"Unknown caller": "Невідомий викликач",
"The integration manager is offline or it cannot reach your homeserver.": "Менеджер інтеграцій непід'єднаний або не може досягти вашого домашнього сервера.",
"Enable desktop notifications for this session": "Увімкнути стільничні сповіщення для цього сеансу",
"Profile picture": "Зображення профілю",
"Use an Integration Manager <b>(%(serverName)s)</b> to manage bots, widgets, and sticker packs.": "Використовувати менеджер інтеграцій <b>%(serverName)s</b> для керування ботами, знадобами та паками наліпок.",
"Use an Integration Manager to manage bots, widgets, and sticker packs.": "Використовувати менеджер інтеграцій для керування ботами, знадобами та паками наліпок.",
"Integration Managers receive configuration data, and can modify widgets, send room invites, and set power levels on your behalf.": "Менеджери інтеграцій отримують дані конфігурації та можуть змінювати знадоби, надсилати запрошення у кімнати й встановлювати рівні повноважень від вашого імені.",
"Show %(count)s more|other": "Показати ще %(count)s",
"Show %(count)s more|one": "Показати ще %(count)s",
"Failed to connect to integration manager": "Не вдалось з'єднатись з менеджером інтеграцій",
"Show image": "Показати зображення",
"You have ignored this user, so their message is hidden. <a>Show anyways.</a>": "Ви ігноруєте цього користувача, тож його повідомлення приховано. <a>Все одно показати.</a>",
"Show all": "Показати все",
"Add an Integration": "Додати інтеграцію",
"Filter community members": "Відцідити учасників спільноти",
"Filter community rooms": "Відцідити кімнати спільноти",
"Display your community flair in rooms configured to show it.": "Відбивати ваш спільнотний значок у кімнатах, що налаштовані показувати його.",
"Using this widget may share data <helpIcon /> with %(widgetDomain)s & your Integration Manager.": "Користування цим знадобом може призвести до поширення ваших даних <helpIcon /> з %(widgetDomain)s та вашим менеджером інтеграцій.",
"Show advanced": "Показати розширені",
"Your %(brand)s doesn't allow you to use an Integration Manager to do this. Please contact an admin.": "Ваш %(brand)s не дозволяє вам використовувати для цього менеджер інтеграцій. Зверніться, будь ласка, до адміністратора.",
"Integration Manager": "Менеджер інтеграцій",
"Your community hasn't got a Long Description, a HTML page to show to community members.<br />Click here to open settings and give it one!": "Ваша спільнота не має великого опису (HTML-сторінки, показуваної членам спільноти). <br />Клацніть тут щоб відкрити налаштування й створити цей опис!",
"Review terms and conditions": "Переглянути умови користування",
"Old cryptography data detected": "Виявлено старі криптографічні дані",
"Logout": "Вийти",
"Your Communities": "Ваші спільноти",
"Did you know: you can use communities to filter your %(brand)s experience!": "Чи знаєте ви, що спільноти можна використовувати для припасування %(brand)s під ваші потреби?",
"Communities": "Спільноти",
"Create a new community": "Створити нову спільноту",
"Clear filter": "Очистити цідило",
"Syncing...": "Синхронізування…",
"Signing In...": "Входження…",
"If you've joined lots of rooms, this might take a while": "Якщо ви приєднались до багатьох кімнат, це може зайняти деякий час",
"Create account": "Створити обліковий запис",
"Failed to fetch avatar URL": "Не вдалось вибрати URL личини",
"Clear room list filter field": "Очистити поле цідила списку кімнат",
"Cancel autocomplete": "Скасувати самодоповнення",
"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.": "Журнали зневадження містять дані використання застосунку, включно з вашим користувацьким ім’ям, ідентифікаторами або псевдонімами відвіданих вами кімнат або груп, а також іменами інших користувачів. Вони не містять повідомлень.",
"Confirm your account deactivation by using Single Sign On to prove your identity.": "Підтвердьте знедіяння вашого облікового запису через Single Sign On щоб підтвердити вашу особу.",
"This account has been deactivated.": "Цей обліковий запис було знедіяно."
} }

View file

@ -1530,8 +1530,8 @@
"Backup has a <validity>valid</validity> signature from this session": "备份有来自此会话的<validity>有效</validity>签名", "Backup has a <validity>valid</validity> signature from this session": "备份有来自此会话的<validity>有效</validity>签名",
"Backup has an <validity>invalid</validity> signature from this session": "备份有来自此会话的<validity>无效</validity>签名", "Backup has an <validity>invalid</validity> signature from this session": "备份有来自此会话的<validity>无效</validity>签名",
"Backup has a <validity>valid</validity> signature from <verify>verified</verify> session <device></device>": "备份有来自<verify>已验证的</verify>会话 <device></device> 的<validity>有效</validity>签名", "Backup has a <validity>valid</validity> signature from <verify>verified</verify> session <device></device>": "备份有来自<verify>已验证的</verify>会话 <device></device> 的<validity>有效</validity>签名",
"Backup has a <validity>valid</validity> signature from <verify>unverified</verify> session <device></device>": "备份有来自<verify>未验证</verify>会话 <device></device> 的<validity>无效</validity>签名", "Backup has a <validity>valid</validity> signature from <verify>unverified</verify> session <device></device>": "备份有来自<verify>未验证</verify>会话 <device></device> 的<validity>无效</validity>签名",
"Backup has an <validity>invalid</validity> signature from <verify>verified</verify> session <device></device>": "备份有来自<verify>已验证</verify>会话 <device></device> 的 <validity>无效</validity>签名", "Backup has an <validity>invalid</validity> signature from <verify>verified</verify> session <device></device>": "备份有来自<verify>已验证</verify>会话 <device></device> 的<validity>无效</validity>签名",
"Backup has an <validity>invalid</validity> signature from <verify>unverified</verify> session <device></device>": "备份有来自<verify>未验证的</verify>会话 <device></device> 的 <validity>无效</validity>签名", "Backup has an <validity>invalid</validity> signature from <verify>unverified</verify> session <device></device>": "备份有来自<verify>未验证的</verify>会话 <device></device> 的 <validity>无效</validity>签名",
"Backup is not signed by any of your sessions": "备份没有被您的任何一个会话签名", "Backup is not signed by any of your sessions": "备份没有被您的任何一个会话签名",
"This backup is trusted because it has been restored on this session": "此备份是受信任的因为它被恢复到了此会话上", "This backup is trusted because it has been restored on this session": "此备份是受信任的因为它被恢复到了此会话上",
@ -2307,9 +2307,69 @@
"Page Up": "Page Up", "Page Up": "Page Up",
"Page Down": "Page Down", "Page Down": "Page Down",
"Esc": "Esc", "Esc": "Esc",
"Enter": "Enter", "Enter": "回车",
"Space": "Space", "Space": "空格",
"How fast should messages be downloaded.": "消息下载速度。", "How fast should messages be downloaded.": "消息下载速度。",
"IRC display name width": "IRC 显示名称宽度", "IRC display name width": "IRC 显示名称宽度",
"When rooms are upgraded": "聊天室升级时间" "When rooms are upgraded": "聊天室升级时间",
"Unexpected server error trying to leave the room": "试图离开聊天室时发生意外服务器错误",
"Error leaving room": "离开聊天室时出错",
"New spinner design": "新的下拉列表设计",
"Show message previews for reactions in DMs": "显示私聊消息预览以回复",
"Show message previews for reactions in all rooms": "显示所有聊天室的消息预览以回复",
"Uploading logs": "正在上传日志",
"Downloading logs": "正在下载日志",
"This bridge was provisioned by <user />.": "桥接由 <user /> 准备。",
"Workspace: %(networkName)s": "工作区:%(networkName)s",
"Channel: %(channelName)s": "频道:%(channelName)s",
"well formed": "格式正确",
"Master private key:": "主私钥:",
"Self signing private key:": "自签名私钥:",
"User signing private key:": "用户签名私钥:",
"Securely cache encrypted messages locally for them to appear in search results, using ": "在本地安全缓存已加密消息以使其出现在搜索结果中,使用 ",
" to store messages from ": " 存储来自 ",
"rooms.": "聊天室的消息。",
"This session is <b>not backing up your keys</b>, but you do have an existing backup you can restore from and add to going forward.": "此会话<b>未备份您的密钥</b>,但您已有备份,您可以继续并从中恢复和向其添加。",
"Invalid theme schema.": "无效主题方案。",
"Read Marker lifetime (ms)": "已读标记生存期 (ms)",
"Read Marker off-screen lifetime (ms)": "已读标记屏幕外生存期 (ms)",
"Unable to revoke sharing for email address": "无法撤消电子邮件地址共享",
"Revoke": "撤销",
"Unable to revoke sharing for phone number": "无法撤销电话号码共享",
"Mod": "管理员",
"Explore public rooms": "探索公共聊天室",
"Can't see what youre looking for?": "看不到您要找的吗?",
"Explore all public rooms": "探索所有公共聊天室",
"%(count)s results|other": "%(count)s 个结果",
"You can only join it with a working invite.": "您只能通过有效邀请加入。",
"The session you are trying to verify doesn't support scanning a QR code or emoji verification, which is what %(brand)s supports. Try with a different client.": "您尝试验证的会话不支持 %(brand)s 支持的扫描二维码或表情符号验证。尝试使用其他客户端。",
"Language Dropdown": "语言下拉菜单",
"%(severalUsers)smade no changes %(count)s times|other": "%(severalUsers)s %(count)s 次未做更改",
"%(severalUsers)smade no changes %(count)s times|one": "%(severalUsers)s 未做更改",
"%(oneUser)smade no changes %(count)s times|other": "%(oneUser)s %(count)s 次未做更改",
"%(oneUser)smade no changes %(count)s times|one": "%(oneUser)s 未做更改",
"Preparing to download logs": "正在准备下载日志",
"Download logs": "下载日志",
"We couldn't create your DM. Please check the users you want to invite and try again.": "我们无法创建您的私聊。请检查您想要邀请的用户并重试。",
"%(brand)s encountered an error during upload of:": "%(brand)s 在上传此文件时出错:",
"Country Dropdown": "国家下拉菜单",
"Attach files from chat or just drag and drop them anywhere in a room.": "附加聊天中的文件,或将其拖放到聊天室的任何地方。",
"Changing your password will reset any end-to-end encryption keys on all of your sessions, making encrypted chat history unreadable. Set up Key Backup or export your room keys from another session before resetting your password.": "更改密码将重置所有会话上的所有端到端加密密钥,从而使加密的聊天记录不可读。在重置密码之前,请设置密钥备份或从其他会话导出聊天室密钥。",
"%(brand)s Android": "%(brand)s Android",
"Message downloading sleep time(ms)": "消息下载休眠时间 (ms)",
"Toggle Bold": "切换粗体",
"Toggle Italics": "切换斜体",
"Toggle Quote": "切换引用",
"Navigate recent messages to edit": "浏览最近的消息以进行编辑",
"Toggle microphone mute": "切换麦克风静音",
"Toggle video on/off": "切换视频开/关",
"Navigate up/down in the room list": "在聊天室列表中上/下导航",
"Previous/next unread room or DM": "上一个/下一个未读聊天室或私聊消息",
"Previous/next room or DM": "上一个/下一个聊天室或私聊消息",
"Toggle the top left menu": "切换左上方的菜单",
"Toggle right panel": "切换右侧面板",
"Toggle this dialog": "切换此对话框",
"End": "End",
"The server is not configured to indicate what the problem is (CORS).": "服务器没有配置为提示错误是什么CORS。",
"Activate selected button": "激活选择的按钮"
} }

View file

@ -2413,5 +2413,20 @@
"Youre all caught up": "您都設定好了", "Youre all caught up": "您都設定好了",
"You have no visible notifications in this room.": "您在此聊天室沒有可見的通知。", "You have no visible notifications in this room.": "您在此聊天室沒有可見的通知。",
"%(brand)s Android": "%(brand)s Android", "%(brand)s Android": "%(brand)s Android",
"Master private key:": "主控私鑰:" "Master private key:": "主控私鑰:",
"Show message previews for reactions in DMs": "在直接訊息中顯示反應的訊息預覽",
"Show message previews for reactions in all rooms": "在所有聊天室中顯示反應的訊息預覽",
"Explore public rooms": "探索公開聊天室",
"Uploading logs": "正在上傳紀錄檔",
"Downloading logs": "正在下載紀錄檔",
"Can't see what youre looking for?": "看不到您要找的東西嗎?",
"Explore all public rooms": "探索所有公開聊天室",
"%(count)s results|other": "%(count)s 個結果",
"Preparing to download logs": "正在準備下載紀錄檔",
"Download logs": "下載紀錄檔",
"Unexpected server error trying to leave the room": "試圖離開聊天室時發生意外的伺服器錯誤",
"Error leaving room": "離開聊天室時發生錯誤",
"Communities v2 prototypes. Requires compatible homeserver. Highly experimental - use with caution.": "社群 v2 原型。需要相容的家伺服器。高度實驗性,小心使用。",
"Explore rooms in %(communityName)s": "在 %(communityName)s 中探索聊天室",
"Set up Secure Backup": "設定安全備份"
} }

View file

@ -115,6 +115,7 @@ async function collectBugReport(opts: IOpts = {}, gzipLogs = true) {
body.append("cross_signing_supported_by_hs", body.append("cross_signing_supported_by_hs",
String(await client.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing"))); String(await client.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing")));
body.append("cross_signing_ready", String(await client.isCrossSigningReady())); body.append("cross_signing_ready", String(await client.isCrossSigningReady()));
body.append("secret_storage_ready", String(await client.isSecretStorageReady()));
} }
} }
@ -123,7 +124,7 @@ async function collectBugReport(opts: IOpts = {}, gzipLogs = true) {
} }
// add labs options // add labs options
const enabledLabs = SettingsStore.getLabsFeatures().filter(f => SettingsStore.isFeatureEnabled(f)); const enabledLabs = SettingsStore.getFeatureSettingNames().filter(f => SettingsStore.getValue(f));
if (enabledLabs.length) { if (enabledLabs.length) {
body.append('enabled_labs', enabledLabs.join(', ')); body.append('enabled_labs', enabledLabs.join(', '));
} }
@ -162,6 +163,8 @@ async function collectBugReport(opts: IOpts = {}, gzipLogs = true) {
} }
} }
body.append("mx_local_settings", localStorage.getItem('mx_local_settings'));
if (opts.sendLogs) { if (opts.sendLogs) {
progressCallback(_t("Collecting logs")); progressCallback(_t("Collecting logs"));
const logs = await rageshake.getLogsForReport(); const logs = await rageshake.getLogsForReport();

View file

@ -109,6 +109,15 @@ export interface ISetting {
} }
export const SETTINGS: {[setting: string]: ISetting} = { export const SETTINGS: {[setting: string]: ISetting} = {
"feature_communities_v2_prototypes": {
isFeature: true,
displayName: _td(
"Communities v2 prototypes. Requires compatible homeserver. " +
"Highly experimental - use with caution.",
),
supportedLevels: LEVELS_FEATURE,
default: false,
},
"feature_new_spinner": { "feature_new_spinner": {
isFeature: true, isFeature: true,
displayName: _td("New spinner design"), displayName: _td("New spinner design"),

View file

@ -23,7 +23,6 @@ import AccountSettingsHandler from "./handlers/AccountSettingsHandler";
import RoomSettingsHandler from "./handlers/RoomSettingsHandler"; import RoomSettingsHandler from "./handlers/RoomSettingsHandler";
import ConfigSettingsHandler from "./handlers/ConfigSettingsHandler"; import ConfigSettingsHandler from "./handlers/ConfigSettingsHandler";
import { _t } from '../languageHandler'; import { _t } from '../languageHandler';
import SdkConfig from "../SdkConfig";
import dis from '../dispatcher/dispatcher'; import dis from '../dispatcher/dispatcher';
import { ISetting, SETTINGS } from "./Settings"; import { ISetting, SETTINGS } from "./Settings";
import LocalEchoWrapper from "./handlers/LocalEchoWrapper"; import LocalEchoWrapper from "./handlers/LocalEchoWrapper";
@ -53,7 +52,7 @@ const LEVEL_HANDLERS = {
[SettingLevel.ROOM_ACCOUNT]: new RoomAccountSettingsHandler(defaultWatchManager), [SettingLevel.ROOM_ACCOUNT]: new RoomAccountSettingsHandler(defaultWatchManager),
[SettingLevel.ACCOUNT]: new AccountSettingsHandler(defaultWatchManager), [SettingLevel.ACCOUNT]: new AccountSettingsHandler(defaultWatchManager),
[SettingLevel.ROOM]: new RoomSettingsHandler(defaultWatchManager), [SettingLevel.ROOM]: new RoomSettingsHandler(defaultWatchManager),
[SettingLevel.CONFIG]: new ConfigSettingsHandler(), [SettingLevel.CONFIG]: new ConfigSettingsHandler(featureNames),
[SettingLevel.DEFAULT]: new DefaultSettingsHandler(defaultSettings, invertedDefaultSettings), [SettingLevel.DEFAULT]: new DefaultSettingsHandler(defaultSettings, invertedDefaultSettings),
}; };
@ -124,6 +123,14 @@ export default class SettingsStore {
// Counter used for generation of watcher IDs // Counter used for generation of watcher IDs
private static watcherCount = 1; private static watcherCount = 1;
/**
* Gets all the feature-style setting names.
* @returns {string[]} The names of the feature settings.
*/
public static getFeatureSettingNames(): string[] {
return Object.keys(SETTINGS).filter(n => SettingsStore.isFeature(n));
}
/** /**
* Watches for changes in a particular setting. This is done without any local echo * Watches for changes in a particular setting. This is done without any local echo
* wrapping and fires whenever a change is detected in a setting's value, at any level. * wrapping and fires whenever a change is detected in a setting's value, at any level.
@ -240,19 +247,6 @@ export default class SettingsStore {
return _t(displayName as string); return _t(displayName as string);
} }
/**
* Returns a list of all available labs feature names
* @returns {string[]} The list of available feature names
*/
public static getLabsFeatures(): string[] {
const possibleFeatures = Object.keys(SETTINGS).filter((s) => SettingsStore.isFeature(s));
const enableLabs = SdkConfig.get()["enableLabs"];
if (enableLabs) return possibleFeatures;
return possibleFeatures.filter((s) => SettingsStore.getFeatureState(s) === "labs");
}
/** /**
* Determines if a setting is also a feature. * Determines if a setting is also a feature.
* @param {string} settingName The setting to look up. * @param {string} settingName The setting to look up.
@ -263,39 +257,6 @@ export default class SettingsStore {
return SETTINGS[settingName].isFeature; return SETTINGS[settingName].isFeature;
} }
/**
* Determines if a given feature is enabled. The feature given must be a known
* feature.
* @param {string} settingName The name of the setting that is a feature.
* @param {String} roomId The optional room ID to validate in, may be null.
* @return {boolean} True if the feature is enabled, false otherwise
*/
public static isFeatureEnabled(settingName: string, roomId: string = null) {
if (!SettingsStore.isFeature(settingName)) {
throw new Error("Setting " + settingName + " is not a feature");
}
return SettingsStore.getValue(settingName, roomId);
}
/**
* Sets a feature as enabled or disabled on the current device.
* @param {string} settingName The name of the setting.
* @param {boolean} value True to enable the feature, false otherwise.
* @returns {Promise} Resolves when the setting has been set.
*/
public static setFeatureEnabled(settingName: string, value: any): Promise<void> {
// Verify that the setting is actually a setting
if (!SETTINGS[settingName]) {
throw new Error("Setting '" + settingName + "' does not appear to be a setting.");
}
if (!SettingsStore.isFeature(settingName)) {
throw new Error("Setting " + settingName + " is not a feature");
}
return SettingsStore.setValue(settingName, null, SettingLevel.DEVICE, value);
}
/** /**
* Gets the value of a setting. The room ID is optional if the setting is not to * Gets the value of a setting. The room ID is optional if the setting is not to
* be applied to any particular room, otherwise it should be supplied. * be applied to any particular room, otherwise it should be supplied.
@ -346,13 +307,6 @@ export default class SettingsStore {
const minIndex = levelOrder.indexOf(level); const minIndex = levelOrder.indexOf(level);
if (minIndex === -1) throw new Error("Level " + level + " is not prioritized"); if (minIndex === -1) throw new Error("Level " + level + " is not prioritized");
if (SettingsStore.isFeature(settingName)) {
const configValue = SettingsStore.getFeatureState(settingName);
if (configValue === "enable") return true;
if (configValue === "disable") return false;
// else let it fall through the default process
}
const handlers = SettingsStore.getHandlers(settingName); const handlers = SettingsStore.getHandlers(settingName);
// Check if we need to invert the setting at all. Do this after we get the setting // Check if we need to invert the setting at all. Do this after we get the setting
@ -480,6 +434,12 @@ export default class SettingsStore {
throw new Error("Setting '" + settingName + "' does not appear to be a setting."); throw new Error("Setting '" + settingName + "' does not appear to be a setting.");
} }
// When features are specified in the config.json, we force them as enabled or disabled.
if (SettingsStore.isFeature(settingName)) {
const configVal = SettingsStore.getValueAt(SettingLevel.CONFIG, settingName, roomId, true, true);
if (configVal === true || configVal === false) return false;
}
const handler = SettingsStore.getHandler(settingName, level); const handler = SettingsStore.getHandler(settingName, level);
if (!handler) return false; if (!handler) return false;
return handler.canSetValue(settingName, roomId); return handler.canSetValue(settingName, roomId);
@ -611,24 +571,6 @@ export default class SettingsStore {
return handlers; return handlers;
} }
private static getFeatureState(settingName: string): LabsFeatureState {
const featuresConfig = SdkConfig.get()['features'];
const enableLabs = SdkConfig.get()['enableLabs']; // we'll honour the old flag
let featureState = enableLabs ? "labs" : "disable";
if (featuresConfig && featuresConfig[settingName] !== undefined) {
featureState = featuresConfig[settingName];
}
const allowedStates = ['enable', 'disable', 'labs'];
if (!allowedStates.includes(featureState)) {
console.warn("Feature state '" + featureState + "' is invalid for " + settingName);
featureState = "disable"; // to prevent accidental features.
}
return featureState;
}
} }
// For debugging purposes // For debugging purposes

View file

@ -24,9 +24,24 @@ import {isNullOrUndefined} from "matrix-js-sdk/src/utils";
* roomId parameter. * roomId parameter.
*/ */
export default class ConfigSettingsHandler extends SettingsHandler { export default class ConfigSettingsHandler extends SettingsHandler {
public constructor(private featureNames: string[]) {
super();
}
public getValue(settingName: string, roomId: string): any { public getValue(settingName: string, roomId: string): any {
const config = SdkConfig.get() || {}; const config = SdkConfig.get() || {};
if (this.featureNames.includes(settingName)) {
const labsConfig = config["features"] || {};
const val = labsConfig[settingName];
if (isNullOrUndefined(val)) return null; // no definition at this level
if (val === true || val === false) return val; // new style: mapped as a boolean
if (val === "enable") return true; // backwards compat
if (val === "disable") return false; // backwards compat
if (val === "labs") return null; // backwards compat, no override
return null; // fallback in the case of invalid input
}
// Special case themes // Special case themes
if (settingName === "theme") { if (settingName === "theme") {
return config["default_theme"]; return config["default_theme"];

View file

@ -0,0 +1,100 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import { AsyncStoreWithClient } from "./AsyncStoreWithClient";
import defaultDispatcher from "../dispatcher/dispatcher";
import { ActionPayload } from "../dispatcher/payloads";
import { Room } from "matrix-js-sdk/src/models/room";
import { EffectiveMembership, getEffectiveMembership } from "../utils/membership";
import SettingsStore from "../settings/SettingsStore";
import * as utils from "matrix-js-sdk/src/utils";
import { UPDATE_EVENT } from "./AsyncStore";
interface IState {
// nothing of value - we use account data
}
export interface IRoomProfile {
displayName: string;
avatarMxc: string;
}
export class CommunityPrototypeStore extends AsyncStoreWithClient<IState> {
private static internalInstance = new CommunityPrototypeStore();
private constructor() {
super(defaultDispatcher, {});
}
public static get instance(): CommunityPrototypeStore {
return CommunityPrototypeStore.internalInstance;
}
protected async onAction(payload: ActionPayload): Promise<any> {
if (!this.matrixClient || !SettingsStore.getValue("feature_communities_v2_prototypes")) {
return;
}
if (payload.action === "MatrixActions.Room.myMembership") {
const room: Room = payload.room;
const membership = getEffectiveMembership(payload.membership);
const oldMembership = getEffectiveMembership(payload.oldMembership);
if (membership === oldMembership) return;
if (membership === EffectiveMembership.Invite) {
try {
const path = utils.encodeUri("/rooms/$roomId/group_info", {$roomId: room.roomId});
const profile = await this.matrixClient._http.authedRequest(
undefined, "GET", path,
undefined, undefined,
{prefix: "/_matrix/client/unstable/im.vector.custom"});
// we use global account data because per-room account data on invites is unreliable
await this.matrixClient.setAccountData("im.vector.group_info." + room.roomId, profile);
} catch (e) {
console.warn("Non-fatal error getting group information for invite:", e);
}
}
} else if (payload.action === "MatrixActions.accountData") {
if (payload.event_type.startsWith("im.vector.group_info.")) {
this.emit(UPDATE_EVENT, payload.event_type.substring("im.vector.group_info.".length));
}
}
}
public getInviteProfile(roomId: string): IRoomProfile {
if (!this.matrixClient) return {displayName: null, avatarMxc: null};
const room = this.matrixClient.getRoom(roomId);
if (SettingsStore.getValue("feature_communities_v2_prototypes")) {
const data = this.matrixClient.getAccountData("im.vector.group_info." + roomId);
if (data && data.getContent()) {
return {displayName: data.getContent().name, avatarMxc: data.getContent().avatar_url};
}
}
return {displayName: room.name, avatarMxc: room.avatar_url};
}
protected async onReady(): Promise<any> {
for (const room of this.matrixClient.getRooms()) {
const myMember = room.currentState.getMembers().find(m => m.userId === this.matrixClient.getUserId());
if (!myMember) continue;
if (getEffectiveMembership(myMember.membership) === EffectiveMembership.Invite) {
// Fake an update for anything that might have started listening before the invite
// data was available (eg: RoomPreviewBar after a refresh)
this.emit(UPDATE_EVENT, room.roomId);
}
}
}
}

View file

@ -137,7 +137,7 @@ class CustomRoomTagStore extends EventEmitter {
} }
_getUpdatedTags() { _getUpdatedTags() {
if (!SettingsStore.isFeatureEnabled("feature_custom_tags")) { if (!SettingsStore.getValue("feature_custom_tags")) {
return {}; // none return {}; // none
} }

View file

@ -115,9 +115,11 @@ class TagOrderStore extends Store {
break; break;
} }
case 'select_tag': { case 'select_tag': {
const allowMultiple = !SettingsStore.getValue("feature_communities_v2_prototypes");
let newTags = []; let newTags = [];
// Shift-click semantics // Shift-click semantics
if (payload.shiftKey) { if (payload.shiftKey && allowMultiple) {
// Select range of tags // Select range of tags
let start = this._state.orderedTags.indexOf(this._state.anchorTag); let start = this._state.orderedTags.indexOf(this._state.anchorTag);
let end = this._state.orderedTags.indexOf(payload.tag); let end = this._state.orderedTags.indexOf(payload.tag);
@ -135,7 +137,7 @@ class TagOrderStore extends Store {
this._state.orderedTags.slice(start, end + 1).concat(newTags), this._state.orderedTags.slice(start, end + 1).concat(newTags),
)]; )];
} else { } else {
if (payload.ctrlOrCmdKey) { if (payload.ctrlOrCmdKey && allowMultiple) {
// Toggle individual tag // Toggle individual tag
if (this._state.selectedTags.includes(payload.tag)) { if (this._state.selectedTags.includes(payload.tag)) {
newTags = this._state.selectedTags.filter((t) => t !== payload.tag); newTags = this._state.selectedTags.filter((t) => t !== payload.tag);
@ -164,6 +166,25 @@ class TagOrderStore extends Store {
selectedTags: newTags, selectedTags: newTags,
}); });
if (!allowMultiple && newTags.length === 1) {
// We're in prototype behaviour: select the general chat for the community
const rooms = GroupStore.getGroupRooms(newTags[0])
.map(r => MatrixClientPeg.get().getRoom(r.roomId))
.filter(r => !!r);
let chat = rooms.find(r => {
const idState = r.currentState.getStateEvents("im.vector.general_chat", "");
if (!idState || idState.getContent()['groupId'] !== newTags[0]) return false;
return true;
});
if (!chat) chat = rooms[0];
if (chat) {
dis.dispatch({
action: 'view_room',
room_id: chat.roomId,
});
}
}
Analytics.trackEvent('FilterStore', 'select_tag'); Analytics.trackEvent('FilterStore', 'select_tag');
} }
break; break;
@ -264,6 +285,13 @@ class TagOrderStore extends Store {
getSelectedTags() { getSelectedTags() {
return this._state.selectedTags; return this._state.selectedTags;
} }
getSelectedPrototypeTag() {
if (SettingsStore.getValue("feature_communities_v2_prototypes")) {
return this.getSelectedTags()[0];
}
return null; // no selection as far as this function is concerned
}
} }
if (global.singletonTagOrderStore === undefined) { if (global.singletonTagOrderStore === undefined) {

View file

@ -136,7 +136,7 @@ export class RoomListStoreClass extends AsyncStoreWithClient<IState> {
} }
private async readAndCacheSettingsFromStore() { private async readAndCacheSettingsFromStore() {
const tagsEnabled = SettingsStore.isFeatureEnabled("feature_custom_tags"); const tagsEnabled = SettingsStore.getValue("feature_custom_tags");
await this.updateState({ await this.updateState({
tagsEnabled, tagsEnabled,
}); });

View file

@ -24,8 +24,8 @@ import DMRoomMap from "../../../utils/DMRoomMap";
export class ReactionEventPreview implements IPreview { export class ReactionEventPreview implements IPreview {
public getTextFor(event: MatrixEvent, tagId?: TagID): string { public getTextFor(event: MatrixEvent, tagId?: TagID): string {
const showDms = SettingsStore.isFeatureEnabled("feature_roomlist_preview_reactions_dms"); const showDms = SettingsStore.getValue("feature_roomlist_preview_reactions_dms");
const showAll = SettingsStore.isFeatureEnabled("feature_roomlist_preview_reactions_all"); const showAll = SettingsStore.getValue("feature_roomlist_preview_reactions_all");
if (!showAll && (!showDms || DMRoomMap.shared().getUserIdForRoomId(event.getRoomId()))) return null; if (!showAll && (!showDms || DMRoomMap.shared().getUserIdForRoomId(event.getRoomId()))) return null;

View file

@ -0,0 +1,40 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import {MatrixClientPeg} from '../MatrixClientPeg';
const E2EE_WK_KEY = "io.element.e2ee";
const E2EE_WK_KEY_DEPRECATED = "im.vector.riot.e2ee";
export interface IE2EEWellKnown {
default?: boolean;
}
export function getE2EEWellKnown(): IE2EEWellKnown {
const clientWellKnown = MatrixClientPeg.get().getClientWellKnown();
if (clientWellKnown && clientWellKnown[E2EE_WK_KEY]) {
return clientWellKnown[E2EE_WK_KEY];
}
if (clientWellKnown && clientWellKnown[E2EE_WK_KEY_DEPRECATED]) {
return clientWellKnown[E2EE_WK_KEY_DEPRECATED]
}
return null;
}
export function isSecureBackupRequired(): boolean {
const wellKnown = getE2EEWellKnown();
return wellKnown && wellKnown["secure_backup_required"] === true;
}

View file

@ -15,6 +15,13 @@ limitations under the License.
*/ */
import { Room } from "matrix-js-sdk/src/models/room"; import { Room } from "matrix-js-sdk/src/models/room";
import { MatrixClientPeg } from "../MatrixClientPeg";
import { _t } from "../languageHandler";
import Modal from "../Modal";
import ErrorDialog from "../components/views/dialogs/ErrorDialog";
import React from "react";
import dis from "../dispatcher/dispatcher";
import RoomViewStore from "../stores/RoomViewStore";
/** /**
* Approximation of a membership status for a given room. * Approximation of a membership status for a given room.
@ -70,3 +77,64 @@ export function getEffectiveMembership(membership: string): EffectiveMembership
return EffectiveMembership.Leave; return EffectiveMembership.Leave;
} }
} }
export async function leaveRoomBehaviour(roomId: string) {
let leavingAllVersions = true;
const history = await MatrixClientPeg.get().getRoomUpgradeHistory(roomId);
if (history && history.length > 0) {
const currentRoom = history[history.length - 1];
if (currentRoom.roomId !== roomId) {
// The user is trying to leave an older version of the room. Let them through
// without making them leave the current version of the room.
leavingAllVersions = false;
}
}
let results: { [roomId: string]: Error & { errcode: string, message: string } } = {};
if (!leavingAllVersions) {
try {
await MatrixClientPeg.get().leave(roomId);
} catch (e) {
if (e && e.data && e.data.errcode) {
const message = e.data.error || _t("Unexpected server error trying to leave the room");
results[roomId] = Object.assign(new Error(message), {errcode: e.data.errcode});
} else {
results[roomId] = e || new Error("Failed to leave room for unknown causes");
}
}
} else {
results = await MatrixClientPeg.get().leaveRoomChain(roomId);
}
const errors = Object.entries(results).filter(r => !!r[1]);
if (errors.length > 0) {
const messages = [];
for (const roomErr of errors) {
const err = roomErr[1]; // [0] is the roomId
let message = _t("Unexpected server error trying to leave the room");
if (err.errcode && err.message) {
if (err.errcode === 'M_CANNOT_LEAVE_SERVER_NOTICE_ROOM') {
Modal.createTrackedDialog('Error Leaving Room', '', ErrorDialog, {
title: _t("Can't leave Server Notices room"),
description: _t(
"This room is used for important messages from the Homeserver, " +
"so you cannot leave it.",
),
});
return;
}
message = results[roomId].message;
}
messages.push(message, React.createElement('BR')); // createElement to avoid using a tsx file in utils
}
Modal.createTrackedDialog('Error Leaving Room', '', ErrorDialog, {
title: _t("Error leaving room"),
description: messages,
});
return;
}
if (RoomViewStore.getRoomId() === roomId) {
dis.dispatch({action: 'view_next_room'});
}
}

View file

@ -9,10 +9,7 @@
"integrations_ui_url": "https://scalar.vector.im/", "integrations_ui_url": "https://scalar.vector.im/",
"integrations_rest_url": "https://scalar.vector.im/api", "integrations_rest_url": "https://scalar.vector.im/api",
"bug_report_endpoint_url": "https://riot.im/bugreports/submit", "bug_report_endpoint_url": "https://riot.im/bugreports/submit",
"features": { "showLabsSettings": true,
"feature_groups": "labs",
"feature_pinning": "labs"
},
"default_federate": true, "default_federate": true,
"welcomePageUrl": "home.html", "welcomePageUrl": "home.html",
"default_theme": "light", "default_theme": "light",

View file

@ -18,9 +18,9 @@ limitations under the License.
const assert = require('assert'); const assert = require('assert');
async function openSettings(session, section) { async function openSettings(session, section) {
const menuButton = await session.query(".mx_TopLeftMenuButton_name"); const menuButton = await session.query(".mx_UserMenu");
await menuButton.click(); await menuButton.click();
const settingsItem = await session.query(".mx_TopLeftMenu_icon_settings"); const settingsItem = await session.query(".mx_UserMenu_iconSettings");
await settingsItem.click(); await settingsItem.click();
if (section) { if (section) {
const sectionButton = await session.query( const sectionButton = await session.query(