Migrate more strings to translation keys (#11671)
This commit is contained in:
parent
13aed62a91
commit
4d0d024e86
125 changed files with 7066 additions and 6607 deletions
|
@ -345,7 +345,7 @@ export default class LeftPanel extends React.Component<IProps, IState> {
|
|||
<AccessibleTooltipButton
|
||||
className="mx_LeftPanel_exploreButton"
|
||||
onClick={this.onExplore}
|
||||
title={_t("Explore rooms")}
|
||||
title={_t("action|explore_rooms")}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -384,7 +384,7 @@ export const showRoom = (cli: MatrixClient, hierarchy: RoomHierarchy, roomId: st
|
|||
oob_data: {
|
||||
avatarUrl: room?.avatar_url,
|
||||
// XXX: This logic is duplicated from the JS SDK which would normally decide what the name is.
|
||||
name: room?.name || roomAlias || _t("Unnamed room"),
|
||||
name: room?.name || roomAlias || _t("common|unnamed_room"),
|
||||
roomType,
|
||||
} as IOOBData,
|
||||
metricsTrigger: "RoomDirectory",
|
||||
|
|
|
@ -124,7 +124,7 @@ const SpaceLandingAddButton: React.FC<{ space: Room }> = ({ space }) => {
|
|||
{canCreateRoom && (
|
||||
<>
|
||||
<IconizedContextMenuOption
|
||||
label={_t("New room")}
|
||||
label={_t("action|new_room")}
|
||||
iconClassName="mx_RoomList_iconNewRoom"
|
||||
onClick={async (e): Promise<void> => {
|
||||
e.preventDefault();
|
||||
|
@ -139,7 +139,7 @@ const SpaceLandingAddButton: React.FC<{ space: Room }> = ({ space }) => {
|
|||
/>
|
||||
{videoRoomsEnabled && (
|
||||
<IconizedContextMenuOption
|
||||
label={_t("New video room")}
|
||||
label={_t("action|new_video_room")}
|
||||
iconClassName="mx_RoomList_iconNewVideoRoom"
|
||||
onClick={async (e): Promise<void> => {
|
||||
e.preventDefault();
|
||||
|
@ -164,7 +164,7 @@ const SpaceLandingAddButton: React.FC<{ space: Room }> = ({ space }) => {
|
|||
</>
|
||||
)}
|
||||
<IconizedContextMenuOption
|
||||
label={_t("Add existing room")}
|
||||
label={_t("action|add_existing_room")}
|
||||
iconClassName="mx_RoomList_iconAddExistingRoom"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
|
|
|
@ -174,11 +174,11 @@ const RoomContextMenu: React.FC<IProps> = ({ room, onFinished, ...props }) => {
|
|||
let iconClassName: string | undefined;
|
||||
switch (echoChamber.notificationVolume) {
|
||||
case RoomNotifState.AllMessages:
|
||||
notificationLabel = _t("Default");
|
||||
notificationLabel = _t("notifications|default");
|
||||
iconClassName = "mx_RoomTile_iconNotificationsDefault";
|
||||
break;
|
||||
case RoomNotifState.AllMessagesLoud:
|
||||
notificationLabel = _t("All messages");
|
||||
notificationLabel = _t("notifications|all_messages");
|
||||
iconClassName = "mx_RoomTile_iconNotificationsAllMessages";
|
||||
break;
|
||||
case RoomNotifState.MentionsOnly:
|
||||
|
|
|
@ -61,7 +61,7 @@ export const RoomNotificationContextMenu: React.FC<IProps> = ({ room, onFinished
|
|||
|
||||
const allMessagesOption: JSX.Element = (
|
||||
<IconizedContextMenuRadio
|
||||
label={_t("All messages")}
|
||||
label={_t("notifications|all_messages")}
|
||||
active={notificationState === RoomNotifState.AllMessagesLoud}
|
||||
iconClassName="mx_RoomNotificationContextMenu_iconBellDot"
|
||||
onClick={wrapHandler(() => setNotificationState(RoomNotifState.AllMessagesLoud))}
|
||||
|
|
|
@ -187,7 +187,7 @@ const SpaceContextMenu: React.FC<IProps> = ({ space, hideHeader, onFinished, ...
|
|||
<IconizedContextMenuOption
|
||||
data-testid="new-video-room-option"
|
||||
iconClassName="mx_SpacePanel_iconPlus"
|
||||
label={_t("Video room")}
|
||||
label={_t("common|video_room")}
|
||||
onClick={onNewVideoRoomClick}
|
||||
>
|
||||
<BetaPill />
|
||||
|
|
|
@ -95,7 +95,7 @@ export default class ConfirmUserActionDialog extends React.Component<IProps, ISt
|
|||
onChange={this.onReasonChange}
|
||||
value={this.state.reason}
|
||||
className="mx_ConfirmUserActionDialog_reasonField"
|
||||
label={_t("Reason")}
|
||||
label={_t("room_settings|permissions|ban_reason")}
|
||||
autoFocus={true}
|
||||
/>
|
||||
</form>
|
||||
|
|
|
@ -353,9 +353,7 @@ export default class CreateRoomDialog extends React.Component<IProps, IState> {
|
|||
microcopy = _t("create_room|encryption_forced");
|
||||
}
|
||||
} else {
|
||||
microcopy = _t(
|
||||
"Your server admin has disabled end-to-end encryption by default in private rooms & Direct Messages.",
|
||||
);
|
||||
microcopy = _t("settings|security|e2ee_default_disabled_warning");
|
||||
}
|
||||
e2eeSection = (
|
||||
<React.Fragment>
|
||||
|
@ -420,7 +418,7 @@ export default class CreateRoomDialog extends React.Component<IProps, IState> {
|
|||
labelKnock={
|
||||
this.askToJoinEnabled ? _t("room_settings|security|join_rule_knock") : undefined
|
||||
}
|
||||
labelPublic={_t("Public room")}
|
||||
labelPublic={_t("common|public_room")}
|
||||
labelRestricted={
|
||||
this.supportsRestricted ? _t("create_room|join_rule_restricted") : undefined
|
||||
}
|
||||
|
|
|
@ -163,7 +163,7 @@ const CreateSubspaceDialog: React.FC<IProps> = ({ space, onAddExistingSpaceClick
|
|||
<JoinRuleDropdown
|
||||
label={_t("Space visibility")}
|
||||
labelInvite={_t("Private space (invite only)")}
|
||||
labelPublic={_t("Public space")}
|
||||
labelPublic={_t("common|public_space")}
|
||||
labelRestricted={_t("create_room|join_rule_restricted")}
|
||||
width={478}
|
||||
value={joinRule}
|
||||
|
|
|
@ -214,7 +214,7 @@ export default class DeactivateAccountDialog extends React.Component<IProps, ISt
|
|||
className="mx_DeactivateAccountDialog"
|
||||
onFinished={this.props.onFinished}
|
||||
titleClass="danger"
|
||||
title={_t("Deactivate Account")}
|
||||
title={_t("settings|general|deactivate_section")}
|
||||
screenName="DeactivateAccount"
|
||||
>
|
||||
<div className="mx_Dialog_content">
|
||||
|
|
|
@ -47,7 +47,7 @@ export default class IntegrationsDisabledDialog extends React.Component<IProps>
|
|||
<div className="mx_IntegrationsDisabledDialog_content">
|
||||
<p>
|
||||
{_t("Enable '%(manageIntegrations)s' in Settings to do this.", {
|
||||
manageIntegrations: _t("Manage integrations"),
|
||||
manageIntegrations: _t("integration_manager|manage_title"),
|
||||
})}
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
@ -143,7 +143,7 @@ export default class InteractiveAuthDialog<T> extends React.Component<Interactiv
|
|||
// Let's pick a title, body, and other params text that we'll show to the user. The order
|
||||
// is most specific first, so stagePhase > our props > defaults.
|
||||
|
||||
let title = this.state.authError ? "Error" : this.props.title || _t("Authentication");
|
||||
let title = this.state.authError ? "Error" : this.props.title || _t("common|authentication");
|
||||
let body = this.state.authError ? null : this.props.body;
|
||||
let continueText: string | undefined;
|
||||
let continueKind: string | undefined;
|
||||
|
|
|
@ -417,7 +417,7 @@ export default class ReportEventDialog extends React.Component<IProps, IState> {
|
|||
<Field
|
||||
className="mx_ReportEventDialog_reason"
|
||||
element="textarea"
|
||||
label={_t("Reason")}
|
||||
label={_t("room_settings|permissions|ban_reason")}
|
||||
rows={5}
|
||||
onChange={this.onReasonChange}
|
||||
value={this.state.reason}
|
||||
|
@ -456,7 +456,7 @@ export default class ReportEventDialog extends React.Component<IProps, IState> {
|
|||
<Field
|
||||
className="mx_ReportEventDialog_reason"
|
||||
element="textarea"
|
||||
label={_t("Reason")}
|
||||
label={_t("room_settings|permissions|ban_reason")}
|
||||
rows={5}
|
||||
onChange={this.onReasonChange}
|
||||
value={this.state.reason}
|
||||
|
|
|
@ -154,7 +154,7 @@ class RoomSettingsDialog extends React.Component<IProps, IState> {
|
|||
tabs.push(
|
||||
new Tab(
|
||||
RoomSettingsTab.Voip,
|
||||
_td("Voice & Video"),
|
||||
_td("settings|voip|title"),
|
||||
"mx_RoomSettingsDialog_voiceIcon",
|
||||
<VoipRoomSettingsTab room={this.state.room} />,
|
||||
),
|
||||
|
@ -197,7 +197,7 @@ class RoomSettingsDialog extends React.Component<IProps, IState> {
|
|||
tabs.push(
|
||||
new Tab(
|
||||
RoomSettingsTab.Bridges,
|
||||
_td("Bridges"),
|
||||
_td("room_settings|bridges|title"),
|
||||
"mx_RoomSettingsDialog_bridgesIcon",
|
||||
<BridgeSettingsTab room={this.state.room} />,
|
||||
"RoomSettingsBridges",
|
||||
|
|
|
@ -67,8 +67,8 @@ export default class SetEmailDialog extends React.Component<IProps, IState> {
|
|||
const emailAddress = this.state.emailAddress;
|
||||
if (!Email.looksValid(emailAddress)) {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Invalid Email Address"),
|
||||
description: _t("This doesn't appear to be a valid email address"),
|
||||
title: _t("settings|general|error_invalid_email"),
|
||||
description: _t("settings|general|error_invalid_email_detail"),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ export default class SetEmailDialog extends React.Component<IProps, IState> {
|
|||
this.setState({ emailBusy: false });
|
||||
logger.error("Unable to add email address " + emailAddress + " " + err);
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Unable to add email address"),
|
||||
title: _t("settings|general|error_add_email"),
|
||||
description: extractErrorMessageFromError(err, _t("invite|failed_generic")),
|
||||
});
|
||||
},
|
||||
|
@ -123,7 +123,7 @@ export default class SetEmailDialog extends React.Component<IProps, IState> {
|
|||
|
||||
if (underlyingError instanceof MatrixError && underlyingError.errcode === "M_THREEPID_AUTH_FAILED") {
|
||||
const message =
|
||||
_t("Unable to verify email address.") +
|
||||
_t("settings|general|error_email_verification") +
|
||||
" " +
|
||||
_t(
|
||||
"Please check your email and click on the link it contains. Once this is done, click continue.",
|
||||
|
@ -137,7 +137,7 @@ export default class SetEmailDialog extends React.Component<IProps, IState> {
|
|||
} else {
|
||||
logger.error("Unable to verify email address: " + err);
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Unable to verify email address."),
|
||||
title: _t("settings|general|error_email_verification"),
|
||||
description: extractErrorMessageFromError(err, _t("invite|failed_generic")),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -133,7 +133,7 @@ export default class UserSettingsDialog extends React.Component<IProps, IState>
|
|||
tabs.push(
|
||||
new Tab(
|
||||
UserTab.Voice,
|
||||
_td("Voice & Video"),
|
||||
_td("settings|voip|title"),
|
||||
"mx_UserSettingsDialog_voiceIcon",
|
||||
<VoiceUserSettingsTab />,
|
||||
"UserSettingsVoiceVideo",
|
||||
|
|
|
@ -33,7 +33,9 @@ interface Props {
|
|||
|
||||
export function PublicRoomResultDetails({ room, labelId, descriptionId, detailsId }: Props): JSX.Element {
|
||||
let name =
|
||||
room.name || getDisplayAliasForAliasSet(room.canonical_alias ?? "", room.aliases ?? []) || _t("Unnamed room");
|
||||
room.name ||
|
||||
getDisplayAliasForAliasSet(room.canonical_alias ?? "", room.aliases ?? []) ||
|
||||
_t("common|unnamed_room");
|
||||
if (name.length > MAX_NAME_LENGTH) {
|
||||
name = `${name.substring(0, MAX_NAME_LENGTH)}...`;
|
||||
}
|
||||
|
|
|
@ -409,7 +409,7 @@ export const UserOptionsSection: React.FC<{
|
|||
kind="link"
|
||||
className={classNames("mx_UserInfo_field", { mx_UserInfo_destructive: !isIgnored })}
|
||||
>
|
||||
{isIgnored ? _t("Unignore") : _t("action|ignore")}
|
||||
{isIgnored ? _t("action|unignore") : _t("action|ignore")}
|
||||
</AccessibleButton>
|
||||
);
|
||||
|
||||
|
|
|
@ -762,7 +762,7 @@ export default class RoomHeader extends React.Component<IProps, IState> {
|
|||
|
||||
const buttons = this.props.showButtons ? this.renderButtons(isVideoRoom) : null;
|
||||
|
||||
let oobName = _t("Unnamed room");
|
||||
let oobName = _t("common|unnamed_room");
|
||||
if (this.props.oobData && this.props.oobData.name) {
|
||||
oobName = this.props.oobData.name;
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ const LinkPreviewGroup: React.FC<IProps> = ({ links, mxEvent, onCancelClick, onH
|
|||
<AccessibleButton onClick={toggleExpanded}>
|
||||
{expanded
|
||||
? _t("action|collapse")
|
||||
: _t("Show %(count)s other previews", { count: previews.length - showPreviews.length })}
|
||||
: _t("timeline|url_preview|show_n_more", { count: previews.length - showPreviews.length })}
|
||||
</AccessibleButton>
|
||||
);
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ const LinkPreviewGroup: React.FC<IProps> = ({ links, mxEvent, onCancelClick, onH
|
|||
<AccessibleButton
|
||||
className="mx_LinkPreviewGroup_hide"
|
||||
onClick={onCancelClick}
|
||||
aria-label={_t("Close preview")}
|
||||
aria-label={_t("timeline|url_preview|close")}
|
||||
>
|
||||
<img
|
||||
className="mx_filterFlipColor"
|
||||
|
|
|
@ -354,9 +354,9 @@ export default class MemberList extends React.Component<IProps, IState> {
|
|||
let inviteButton: JSX.Element | undefined;
|
||||
|
||||
if (room?.getMyMembership() === "join" && shouldShowComponent(UIComponent.InviteUsers)) {
|
||||
let inviteButtonText = _t("Invite to this room");
|
||||
let inviteButtonText = _t("room|invite_this_room");
|
||||
if (room.isSpaceRoom()) {
|
||||
inviteButtonText = _t("Invite to this space");
|
||||
inviteButtonText = _t("space|invite_this_space");
|
||||
}
|
||||
|
||||
if (this.state.canInvite) {
|
||||
|
|
|
@ -215,7 +215,7 @@ const NewRoomIntro: React.FC = () => {
|
|||
defaultDispatcher.dispatch({ action: "view_invite", roomId });
|
||||
}}
|
||||
>
|
||||
{_t("Invite to this room")}
|
||||
{_t("room|invite_this_room")}
|
||||
</AccessibleButton>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -50,7 +50,7 @@ const RoomBreadcrumbTile: React.FC<{ room: Room; onClick: (ev: ButtonEvent) => v
|
|||
<AccessibleTooltipButton
|
||||
className="mx_RoomBreadcrumbs_crumb"
|
||||
onClick={onClick}
|
||||
aria-label={_t("Room %(name)s", { name: room.name })}
|
||||
aria-label={_t("a11y|room_name", { name: room.name })}
|
||||
title={room.name}
|
||||
tooltipClassName="mx_RoomBreadcrumbs_Tooltip"
|
||||
onFocus={onFocus}
|
||||
|
@ -123,7 +123,7 @@ export default class RoomBreadcrumbs extends React.PureComponent<IProps, IState>
|
|||
// NOTE: The CSSTransition timeout MUST match the timeout in our CSS!
|
||||
return (
|
||||
<CSSTransition appear={true} in={this.state.doAnimation} timeout={640} classNames="mx_RoomBreadcrumbs">
|
||||
<Toolbar className="mx_RoomBreadcrumbs" aria-label={_t("Recently visited rooms")}>
|
||||
<Toolbar className="mx_RoomBreadcrumbs" aria-label={_t("room_list|breadcrumbs_label")}>
|
||||
{tiles.slice(this.state.skipFirst ? 1 : 0)}
|
||||
</Toolbar>
|
||||
</CSSTransition>
|
||||
|
@ -131,7 +131,7 @@ export default class RoomBreadcrumbs extends React.PureComponent<IProps, IState>
|
|||
} else {
|
||||
return (
|
||||
<div className="mx_RoomBreadcrumbs">
|
||||
<div className="mx_RoomBreadcrumbs_placeholder">{_t("No recently visited rooms")}</div>
|
||||
<div className="mx_RoomBreadcrumbs_placeholder">{_t("room_list|breadcrumbs_empty")}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -131,12 +131,12 @@ export default function RoomHeader({ room }: { room: Room }): JSX.Element {
|
|||
{roomName}
|
||||
|
||||
{!isDirectMessage && roomState.getJoinRule() === JoinRule.Public && (
|
||||
<Tooltip label={_t("Public room")}>
|
||||
<Tooltip label={_t("common|public_room")}>
|
||||
<PublicIcon
|
||||
width="16px"
|
||||
height="16px"
|
||||
className="text-secondary"
|
||||
aria-label={_t("Public room")}
|
||||
aria-label={_t("common|public_room")}
|
||||
/>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
@ -153,12 +153,12 @@ export default function RoomHeader({ room }: { room: Room }): JSX.Element {
|
|||
)}
|
||||
|
||||
{isDirectMessage && e2eStatus === E2EStatus.Warning && (
|
||||
<Tooltip label={_t("Untrusted")}>
|
||||
<Tooltip label={_t("room|header_untrusted_label")}>
|
||||
<ErrorIcon
|
||||
width="16px"
|
||||
height="16px"
|
||||
className="mx_Untrusted"
|
||||
aria-label={_t("Untrusted")}
|
||||
aria-label={_t("room|header_untrusted_label")}
|
||||
/>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
|
|
@ -51,13 +51,13 @@ const RoomInfoLine: FC<IProps> = ({ room }) => {
|
|||
let roomType: string;
|
||||
if (isVideoRoom) {
|
||||
iconClass = "mx_RoomInfoLine_video";
|
||||
roomType = _t("Video room");
|
||||
roomType = _t("common|video_room");
|
||||
} else if (joinRule === JoinRule.Public) {
|
||||
iconClass = "mx_RoomInfoLine_public";
|
||||
roomType = room.isSpaceRoom() ? _t("Public space") : _t("Public room");
|
||||
roomType = room.isSpaceRoom() ? _t("common|public_space") : _t("common|public_room");
|
||||
} else {
|
||||
iconClass = "mx_RoomInfoLine_private";
|
||||
roomType = room.isSpaceRoom() ? _t("Private space") : _t("Private room");
|
||||
roomType = room.isSpaceRoom() ? _t("common|private_space") : _t("common|private_room");
|
||||
}
|
||||
|
||||
let members: JSX.Element | undefined;
|
||||
|
|
|
@ -132,7 +132,7 @@ const DmAuxButton: React.FC<IAuxButtonProps> = ({ tabIndex, dispatcher = default
|
|||
<IconizedContextMenuOptionList first>
|
||||
{showCreateRooms && (
|
||||
<IconizedContextMenuOption
|
||||
label={_t("Start new chat")}
|
||||
label={_t("action|start_new_chat")}
|
||||
iconClassName="mx_RoomList_iconStartChat"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
|
@ -148,7 +148,7 @@ const DmAuxButton: React.FC<IAuxButtonProps> = ({ tabIndex, dispatcher = default
|
|||
)}
|
||||
{showInviteUsers && (
|
||||
<IconizedContextMenuOption
|
||||
label={_t("Invite to space")}
|
||||
label={_t("action|invite_to_space")}
|
||||
iconClassName="mx_RoomList_iconInvite"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
|
@ -172,8 +172,8 @@ const DmAuxButton: React.FC<IAuxButtonProps> = ({ tabIndex, dispatcher = default
|
|||
onClick={openMenu}
|
||||
className="mx_RoomSublist_auxButton"
|
||||
tooltipClassName="mx_RoomSublist_addRoomTooltip"
|
||||
aria-label={_t("Add people")}
|
||||
title={_t("Add people")}
|
||||
aria-label={_t("action|add_people")}
|
||||
title={_t("action|add_people")}
|
||||
isExpanded={menuDisplayed}
|
||||
inputRef={handle}
|
||||
/>
|
||||
|
@ -222,7 +222,7 @@ const UntaggedAuxButton: React.FC<IAuxButtonProps> = ({ tabIndex }) => {
|
|||
contextMenuContent = (
|
||||
<IconizedContextMenuOptionList first>
|
||||
<IconizedContextMenuOption
|
||||
label={_t("Explore rooms")}
|
||||
label={_t("action|explore_rooms")}
|
||||
iconClassName="mx_RoomList_iconExplore"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
|
@ -239,7 +239,7 @@ const UntaggedAuxButton: React.FC<IAuxButtonProps> = ({ tabIndex }) => {
|
|||
{showCreateRoom ? (
|
||||
<>
|
||||
<IconizedContextMenuOption
|
||||
label={_t("New room")}
|
||||
label={_t("action|new_room")}
|
||||
iconClassName="mx_RoomList_iconNewRoom"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
|
@ -253,7 +253,7 @@ const UntaggedAuxButton: React.FC<IAuxButtonProps> = ({ tabIndex }) => {
|
|||
/>
|
||||
{videoRoomsEnabled && (
|
||||
<IconizedContextMenuOption
|
||||
label={_t("New video room")}
|
||||
label={_t("action|new_video_room")}
|
||||
iconClassName="mx_RoomList_iconNewVideoRoom"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
|
@ -271,7 +271,7 @@ const UntaggedAuxButton: React.FC<IAuxButtonProps> = ({ tabIndex }) => {
|
|||
</IconizedContextMenuOption>
|
||||
)}
|
||||
<IconizedContextMenuOption
|
||||
label={_t("Add existing room")}
|
||||
label={_t("action|add_existing_room")}
|
||||
iconClassName="mx_RoomList_iconAddExistingRoom"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
|
@ -292,7 +292,7 @@ const UntaggedAuxButton: React.FC<IAuxButtonProps> = ({ tabIndex }) => {
|
|||
{showCreateRoom && (
|
||||
<>
|
||||
<IconizedContextMenuOption
|
||||
label={_t("New room")}
|
||||
label={_t("action|new_room")}
|
||||
iconClassName="mx_RoomList_iconNewRoom"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
|
@ -304,7 +304,7 @@ const UntaggedAuxButton: React.FC<IAuxButtonProps> = ({ tabIndex }) => {
|
|||
/>
|
||||
{videoRoomsEnabled && (
|
||||
<IconizedContextMenuOption
|
||||
label={_t("New video room")}
|
||||
label={_t("action|new_video_room")}
|
||||
iconClassName="mx_RoomList_iconNewVideoRoom"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
|
@ -325,7 +325,7 @@ const UntaggedAuxButton: React.FC<IAuxButtonProps> = ({ tabIndex }) => {
|
|||
)}
|
||||
{showExploreRooms ? (
|
||||
<IconizedContextMenuOption
|
||||
label={_t("Explore public rooms")}
|
||||
label={_t("action|explore_public_rooms")}
|
||||
iconClassName="mx_RoomList_iconExplore"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
|
|
|
@ -203,7 +203,7 @@ const RoomListHeader: React.FC<IProps> = ({ onVisibilityChange }) => {
|
|||
<>
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_RoomListHeader_iconNewRoom"
|
||||
label={_t("New room")}
|
||||
label={_t("action|new_room")}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
@ -215,7 +215,7 @@ const RoomListHeader: React.FC<IProps> = ({ onVisibilityChange }) => {
|
|||
{videoRoomsEnabled && (
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_RoomListHeader_iconNewVideoRoom"
|
||||
label={_t("New video room")}
|
||||
label={_t("action|new_video_room")}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
@ -243,7 +243,7 @@ const RoomListHeader: React.FC<IProps> = ({ onVisibilityChange }) => {
|
|||
{inviteOption}
|
||||
{newRoomOptions}
|
||||
<IconizedContextMenuOption
|
||||
label={_t("Explore rooms")}
|
||||
label={_t("action|explore_rooms")}
|
||||
iconClassName="mx_RoomListHeader_iconExplore"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
|
@ -258,7 +258,7 @@ const RoomListHeader: React.FC<IProps> = ({ onVisibilityChange }) => {
|
|||
}}
|
||||
/>
|
||||
<IconizedContextMenuOption
|
||||
label={_t("Add existing room")}
|
||||
label={_t("action|add_existing_room")}
|
||||
iconClassName="mx_RoomListHeader_iconPlus"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
|
@ -296,7 +296,7 @@ const RoomListHeader: React.FC<IProps> = ({ onVisibilityChange }) => {
|
|||
newRoomOpts = (
|
||||
<>
|
||||
<IconizedContextMenuOption
|
||||
label={_t("Start new chat")}
|
||||
label={_t("action|start_new_chat")}
|
||||
iconClassName="mx_RoomListHeader_iconStartChat"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
|
@ -307,7 +307,7 @@ const RoomListHeader: React.FC<IProps> = ({ onVisibilityChange }) => {
|
|||
}}
|
||||
/>
|
||||
<IconizedContextMenuOption
|
||||
label={_t("New room")}
|
||||
label={_t("action|new_room")}
|
||||
iconClassName="mx_RoomListHeader_iconNewRoom"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
|
@ -319,7 +319,7 @@ const RoomListHeader: React.FC<IProps> = ({ onVisibilityChange }) => {
|
|||
/>
|
||||
{videoRoomsEnabled && (
|
||||
<IconizedContextMenuOption
|
||||
label={_t("New video room")}
|
||||
label={_t("action|new_video_room")}
|
||||
iconClassName="mx_RoomListHeader_iconNewVideoRoom"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
|
|
|
@ -311,7 +311,11 @@ export default class SecureBackupPanel extends React.PureComponent<{}, IState> {
|
|||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{_t("settings|security|key_backup_active_version")}</th>
|
||||
<td>{this.state.activeBackupVersion === null ? _t("None") : this.state.activeBackupVersion}</td>
|
||||
<td>
|
||||
{this.state.activeBackupVersion === null
|
||||
? _t("settings|security|key_backup_active_version_none")
|
||||
: this.state.activeBackupVersion}
|
||||
</td>
|
||||
</tr>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -47,7 +47,7 @@ const REACHABILITY_TIMEOUT = 10000; // ms
|
|||
async function checkIdentityServerUrl(u: string): Promise<string | null> {
|
||||
const parsedUrl = parseUrl(u);
|
||||
|
||||
if (parsedUrl.protocol !== "https:") return _t("Identity server URL must be HTTPS");
|
||||
if (parsedUrl.protocol !== "https:") return _t("identity_server|url_not_https");
|
||||
|
||||
// XXX: duplicated logic from js-sdk but it's quite tied up in the validation logic in the
|
||||
// js-sdk so probably as easy to duplicate it than to separate it out so we can reuse it
|
||||
|
@ -56,12 +56,12 @@ async function checkIdentityServerUrl(u: string): Promise<string | null> {
|
|||
if (response.ok) {
|
||||
return null;
|
||||
} else if (response.status < 200 || response.status >= 300) {
|
||||
return _t("Not a valid identity server (status code %(code)s)", { code: response.status });
|
||||
return _t("identity_server|error_invalid", { code: response.status });
|
||||
} else {
|
||||
return _t("Could not connect to identity server");
|
||||
return _t("identity_server|error_connection");
|
||||
}
|
||||
} catch (e) {
|
||||
return _t("Could not connect to identity server");
|
||||
return _t("identity_server|error_connection");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,7 +133,7 @@ export default class SetIdServer extends React.Component<IProps, IState> {
|
|||
return (
|
||||
<div>
|
||||
<InlineSpinner />
|
||||
{_t("Checking server")}
|
||||
{_t("identity_server|checking")}
|
||||
</div>
|
||||
);
|
||||
} else if (this.state.error) {
|
||||
|
@ -191,9 +191,9 @@ export default class SetIdServer extends React.Component<IProps, IState> {
|
|||
// 3PIDs that would be left behind.
|
||||
if (save && currentClientIdServer && fullUrl !== currentClientIdServer) {
|
||||
const [confirmed] = await this.showServerChangeWarning({
|
||||
title: _t("Change identity server"),
|
||||
title: _t("identity_server|change"),
|
||||
unboundMessage: _t(
|
||||
"Disconnect from the identity server <current /> and connect to <new /> instead?",
|
||||
"identity_server|change_prompt",
|
||||
{},
|
||||
{
|
||||
current: (sub) => <b>{abbreviateUrl(currentClientIdServer)}</b>,
|
||||
|
@ -210,7 +210,7 @@ export default class SetIdServer extends React.Component<IProps, IState> {
|
|||
}
|
||||
} catch (e) {
|
||||
logger.error(e);
|
||||
errStr = _t("Terms of service not accepted or the identity server is invalid.");
|
||||
errStr = _t("identity_server|error_invalid_or_terms");
|
||||
}
|
||||
}
|
||||
this.setState({
|
||||
|
@ -226,9 +226,7 @@ export default class SetIdServer extends React.Component<IProps, IState> {
|
|||
title: _t("terms|identity_server_no_terms_title"),
|
||||
description: (
|
||||
<div>
|
||||
<span className="warning">
|
||||
{_t("The identity server you have chosen does not have any terms of service.")}
|
||||
</span>
|
||||
<span className="warning">{_t("identity_server|no_terms")}</span>
|
||||
<span> {_t("terms|identity_server_no_terms_description_2")}</span>
|
||||
</div>
|
||||
),
|
||||
|
@ -241,9 +239,9 @@ export default class SetIdServer extends React.Component<IProps, IState> {
|
|||
this.setState({ disconnectBusy: true });
|
||||
try {
|
||||
const [confirmed] = await this.showServerChangeWarning({
|
||||
title: _t("Disconnect identity server"),
|
||||
title: _t("identity_server|disconnect"),
|
||||
unboundMessage: _t(
|
||||
"Disconnect from the identity server <idserver />?",
|
||||
"identity_server|disconnect_server",
|
||||
{},
|
||||
{ idserver: (sub) => <b>{abbreviateUrl(this.state.currentClientIdServer)}</b> },
|
||||
),
|
||||
|
@ -294,54 +292,34 @@ export default class SetIdServer extends React.Component<IProps, IState> {
|
|||
if (!currentServerReachable) {
|
||||
message = (
|
||||
<div>
|
||||
<p>
|
||||
{_t(
|
||||
"You should <b>remove your personal data</b> from identity server <idserver /> before disconnecting. Unfortunately, identity server <idserver /> is currently offline or cannot be reached.",
|
||||
{},
|
||||
messageElements,
|
||||
)}
|
||||
</p>
|
||||
<p>{_t("You should:")}</p>
|
||||
<p>{_t("identity_server|disconnect_offline_warning", {}, messageElements)}</p>
|
||||
<p>{_t("identity_server|suggestions")}</p>
|
||||
<ul>
|
||||
<li>{_t("identity_server|suggestions_1")}</li>
|
||||
<li>
|
||||
{_t(
|
||||
"check your browser plugins for anything that might block the identity server (such as Privacy Badger)",
|
||||
)}
|
||||
</li>
|
||||
<li>
|
||||
{_t(
|
||||
"contact the administrators of identity server <idserver />",
|
||||
"identity_server|suggestions_2",
|
||||
{},
|
||||
{
|
||||
idserver: messageElements.idserver,
|
||||
},
|
||||
)}
|
||||
</li>
|
||||
<li>{_t("wait and try again later")}</li>
|
||||
<li>{_t("identity_server|suggestions_3")}</li>
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
danger = true;
|
||||
button = _t("Disconnect anyway");
|
||||
button = _t("identity_server|disconnect_anyway");
|
||||
} else if (boundThreepids.length) {
|
||||
message = (
|
||||
<div>
|
||||
<p>
|
||||
{_t(
|
||||
"You are still <b>sharing your personal data</b> on the identity server <idserver />.",
|
||||
{},
|
||||
messageElements,
|
||||
)}
|
||||
</p>
|
||||
<p>
|
||||
{_t(
|
||||
"We recommend that you remove your email addresses and phone numbers from the identity server before disconnecting.",
|
||||
)}
|
||||
</p>
|
||||
<p>{_t("identity_server|disconnect_personal_data_warning_1", {}, messageElements)}</p>
|
||||
<p>{_t("identity_server|disconnect_personal_data_warning_2")}</p>
|
||||
</div>
|
||||
);
|
||||
danger = true;
|
||||
button = _t("Disconnect anyway");
|
||||
button = _t("identity_server|disconnect_anyway");
|
||||
} else {
|
||||
message = unboundMessage;
|
||||
}
|
||||
|
@ -382,37 +360,31 @@ export default class SetIdServer extends React.Component<IProps, IState> {
|
|||
let sectionTitle;
|
||||
let bodyText;
|
||||
if (idServerUrl) {
|
||||
sectionTitle = _t("Identity server (%(server)s)", { server: abbreviateUrl(idServerUrl) });
|
||||
sectionTitle = _t("identity_server|url", { server: abbreviateUrl(idServerUrl) });
|
||||
bodyText = _t(
|
||||
"You are currently using <server></server> to discover and be discoverable by existing contacts you know. You can change your identity server below.",
|
||||
"identity_server|description_connected",
|
||||
{},
|
||||
{ server: (sub) => <b>{abbreviateUrl(idServerUrl)}</b> },
|
||||
);
|
||||
if (this.props.missingTerms) {
|
||||
bodyText = _t(
|
||||
"If you don't want to use <server /> to discover and be discoverable by existing contacts you know, enter another identity server below.",
|
||||
"identity_server|change_server_prompt",
|
||||
{},
|
||||
{ server: (sub) => <b>{abbreviateUrl(idServerUrl)}</b> },
|
||||
);
|
||||
}
|
||||
} else {
|
||||
sectionTitle = _t("common|identity_server");
|
||||
bodyText = _t(
|
||||
"You are not currently using an identity server. To discover and be discoverable by existing contacts you know, add one below.",
|
||||
);
|
||||
bodyText = _t("identity_server|description_disconnected");
|
||||
}
|
||||
|
||||
let discoSection;
|
||||
if (idServerUrl) {
|
||||
let discoButtonContent: React.ReactNode = _t("action|disconnect");
|
||||
let discoBodyText = _t(
|
||||
"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.",
|
||||
);
|
||||
let discoBodyText = _t("identity_server|disconnect_warning");
|
||||
if (this.props.missingTerms) {
|
||||
discoBodyText = _t(
|
||||
"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.",
|
||||
);
|
||||
discoButtonContent = _t("Do not use an identity server");
|
||||
discoBodyText = _t("identity_server|description_optional");
|
||||
discoButtonContent = _t("identity_server|do_not_use");
|
||||
}
|
||||
if (this.state.disconnectBusy) {
|
||||
discoButtonContent = <InlineSpinner />;
|
||||
|
@ -431,7 +403,7 @@ export default class SetIdServer extends React.Component<IProps, IState> {
|
|||
<SettingsFieldset legend={sectionTitle} description={bodyText}>
|
||||
<form className="mx_SetIdServer" onSubmit={this.checkIdServer}>
|
||||
<Field
|
||||
label={_t("Enter a new identity server")}
|
||||
label={_t("identity_server|url_field_label")}
|
||||
type="text"
|
||||
autoComplete="off"
|
||||
placeholder={this.state.defaultIdServer}
|
||||
|
|
|
@ -63,12 +63,12 @@ export default class SetIntegrationManager extends React.Component<IProps, IStat
|
|||
if (currentManager) {
|
||||
managerName = `(${currentManager.name})`;
|
||||
bodyText = _t(
|
||||
"Use an integration manager <b>(%(serverName)s)</b> to manage bots, widgets, and sticker packs.",
|
||||
"integration_manager|use_im_default",
|
||||
{ serverName: currentManager.name },
|
||||
{ b: (sub) => <b>{sub}</b> },
|
||||
);
|
||||
} else {
|
||||
bodyText = _t("Use an integration manager to manage bots, widgets, and sticker packs.");
|
||||
bodyText = _t("integration_manager|use_im");
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -79,7 +79,7 @@ export default class SetIntegrationManager extends React.Component<IProps, IStat
|
|||
>
|
||||
<div className="mx_SettingsFlag">
|
||||
<div className="mx_SetIntegrationManager_heading_manager">
|
||||
<Heading size="2">{_t("Manage integrations")}</Heading>
|
||||
<Heading size="2">{_t("integration_manager|manage_title")}</Heading>
|
||||
<Heading size="3">{managerName}</Heading>
|
||||
</div>
|
||||
<ToggleSwitch
|
||||
|
@ -90,11 +90,7 @@ export default class SetIntegrationManager extends React.Component<IProps, IStat
|
|||
/>
|
||||
</div>
|
||||
<SettingsSubsectionText>{bodyText}</SettingsSubsectionText>
|
||||
<SettingsSubsectionText>
|
||||
{_t(
|
||||
"Integration managers receive configuration data, and can modify widgets, send room invites, and set power levels on your behalf.",
|
||||
)}
|
||||
</SettingsSubsectionText>
|
||||
<SettingsSubsectionText>{_t("integration_manager|explainer")}</SettingsSubsectionText>
|
||||
</label>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -88,7 +88,7 @@ export class ExistingEmailAddress extends React.Component<IExistingEmailAddressP
|
|||
.catch((err) => {
|
||||
logger.error("Unable to remove contact information: " + err);
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Unable to remove contact information"),
|
||||
title: _t("settings|general|error_remove_3pid"),
|
||||
description: err && err.message ? err.message : _t("invite|failed_generic"),
|
||||
});
|
||||
});
|
||||
|
@ -99,7 +99,7 @@ export class ExistingEmailAddress extends React.Component<IExistingEmailAddressP
|
|||
return (
|
||||
<div className="mx_GeneralUserSettingsTab_section--discovery_existing">
|
||||
<span className="mx_GeneralUserSettingsTab_section--discovery_existing_promptText">
|
||||
{_t("Remove %(email)s?", { email: this.props.email.address })}
|
||||
{_t("settings|general|remove_email_prompt", { email: this.props.email.address })}
|
||||
</span>
|
||||
<AccessibleButton
|
||||
onClick={this.onActuallyRemove}
|
||||
|
@ -182,8 +182,8 @@ export default class EmailAddresses extends React.Component<IProps, IState> {
|
|||
// TODO: Inline field validation
|
||||
if (!Email.looksValid(email)) {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Invalid Email Address"),
|
||||
description: _t("This doesn't appear to be a valid email address"),
|
||||
title: _t("settings|general|error_invalid_email"),
|
||||
description: _t("settings|general|error_invalid_email_detail"),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
@ -199,7 +199,7 @@ export default class EmailAddresses extends React.Component<IProps, IState> {
|
|||
logger.error("Unable to add email address " + email + " " + err);
|
||||
this.setState({ verifying: false, continueDisabled: false, addTask: null });
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Unable to add email address"),
|
||||
title: _t("settings|general|error_add_email"),
|
||||
description: extractErrorMessageFromError(err, _t("invite|failed_generic")),
|
||||
});
|
||||
});
|
||||
|
@ -239,14 +239,12 @@ export default class EmailAddresses extends React.Component<IProps, IState> {
|
|||
|
||||
if (underlyingError instanceof MatrixError && underlyingError.errcode === "M_THREEPID_AUTH_FAILED") {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Your email address hasn't been verified yet"),
|
||||
description: _t(
|
||||
"Click the link in the email you received to verify and then click continue again.",
|
||||
),
|
||||
title: _t("settings|general|email_not_verified"),
|
||||
description: _t("settings|general|email_verification_instructions"),
|
||||
});
|
||||
} else {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Unable to verify email address."),
|
||||
title: _t("settings|general|error_email_verification"),
|
||||
description: extractErrorMessageFromError(err, _t("invite|failed_generic")),
|
||||
});
|
||||
}
|
||||
|
@ -273,11 +271,7 @@ export default class EmailAddresses extends React.Component<IProps, IState> {
|
|||
if (this.state.verifying) {
|
||||
addButton = (
|
||||
<div>
|
||||
<div>
|
||||
{_t(
|
||||
"We've sent you an email to verify your address. Please follow the instructions there and then click the button below.",
|
||||
)}
|
||||
</div>
|
||||
<div>{_t("settings|general|add_email_instructions")}</div>
|
||||
<AccessibleButton
|
||||
onClick={this.onContinueClick}
|
||||
kind="primary"
|
||||
|
@ -295,7 +289,7 @@ export default class EmailAddresses extends React.Component<IProps, IState> {
|
|||
<form onSubmit={this.onAddClick} autoComplete="off" noValidate={true}>
|
||||
<Field
|
||||
type="text"
|
||||
label={_t("Email Address")}
|
||||
label={_t("settings|general|email_address_label")}
|
||||
autoComplete="email"
|
||||
disabled={this.props.disabled || this.state.verifying}
|
||||
value={this.state.newEmailAddress}
|
||||
|
|
|
@ -84,7 +84,7 @@ export class ExistingPhoneNumber extends React.Component<IExistingPhoneNumberPro
|
|||
.catch((err) => {
|
||||
logger.error("Unable to remove contact information: " + err);
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Unable to remove contact information"),
|
||||
title: _t("settings|general|error_remove_3pid"),
|
||||
description: extractErrorMessageFromError(err, _t("invite|failed_generic")),
|
||||
});
|
||||
});
|
||||
|
@ -95,7 +95,7 @@ export class ExistingPhoneNumber extends React.Component<IExistingPhoneNumberPro
|
|||
return (
|
||||
<div className="mx_GeneralUserSettingsTab_section--discovery_existing">
|
||||
<span className="mx_GeneralUserSettingsTab_section--discovery_existing_promptText">
|
||||
{_t("Remove %(phone)s?", { phone: this.props.msisdn.address })}
|
||||
{_t("settings|general|remove_msisdn_prompt", { phone: this.props.msisdn.address })}
|
||||
</span>
|
||||
<AccessibleButton
|
||||
onClick={this.onActuallyRemove}
|
||||
|
@ -244,11 +244,11 @@ export default class PhoneNumbers extends React.Component<IProps, IState> {
|
|||
|
||||
if (underlyingError.errcode !== "M_THREEPID_AUTH_FAILED") {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Unable to verify phone number."),
|
||||
title: _t("settings|general|error_msisdn_verification"),
|
||||
description: extractErrorMessageFromError(err, _t("invite|failed_generic")),
|
||||
});
|
||||
} else {
|
||||
this.setState({ verifyError: _t("Incorrect verification code") });
|
||||
this.setState({ verifyError: _t("settings|general|incorrect_msisdn_verification") });
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -279,17 +279,14 @@ export default class PhoneNumbers extends React.Component<IProps, IState> {
|
|||
addVerifySection = (
|
||||
<div>
|
||||
<div>
|
||||
{_t(
|
||||
"A text message has been sent to +%(msisdn)s. Please enter the verification code it contains.",
|
||||
{ msisdn: msisdn },
|
||||
)}
|
||||
{_t("settings|general|add_msisdn_instructions", { msisdn: msisdn })}
|
||||
<br />
|
||||
{this.state.verifyError}
|
||||
</div>
|
||||
<form onSubmit={this.onContinueClick} autoComplete="off" noValidate={true}>
|
||||
<Field
|
||||
type="text"
|
||||
label={_t("Verification code")}
|
||||
label={_t("settings|general|msisdn_verification_field_label")}
|
||||
autoComplete="off"
|
||||
disabled={this.props.disabled || this.state.continueDisabled}
|
||||
value={this.state.newPhoneNumberCode}
|
||||
|
@ -329,7 +326,7 @@ export default class PhoneNumbers extends React.Component<IProps, IState> {
|
|||
<div className="mx_PhoneNumbers_input">
|
||||
<Field
|
||||
type="text"
|
||||
label={_t("Phone Number")}
|
||||
label={_t("settings|general|msisdn_label")}
|
||||
autoComplete="tel-national"
|
||||
disabled={this.props.disabled || this.state.verifying}
|
||||
prefixComponent={phoneCountry}
|
||||
|
|
|
@ -49,7 +49,7 @@ const DeviceNameEditor: React.FC<Props & { stopEditing: () => void }> = ({ devic
|
|||
await saveDeviceName(deviceName);
|
||||
stopEditing();
|
||||
} catch (error) {
|
||||
setError(_t("Failed to set display name"));
|
||||
setError(_t("settings|sessions|error_set_name"));
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -71,7 +71,7 @@ export const deleteDevicesWithInteractiveAuth = async (
|
|||
},
|
||||
};
|
||||
Modal.createDialog(InteractiveAuthDialog, {
|
||||
title: _t("Authentication"),
|
||||
title: _t("common|authentication"),
|
||||
matrixClient: matrixClient,
|
||||
authData: error.data as IAuthData,
|
||||
onFinished,
|
||||
|
|
|
@ -194,8 +194,8 @@ export const useOwnDevices = (): DevicesState => {
|
|||
await matrixClient.setDeviceDetails(deviceId, { display_name: deviceName });
|
||||
await refreshDevices();
|
||||
} catch (error) {
|
||||
logger.error("Error setting session display name", error);
|
||||
throw new Error(_t("Failed to set display name"));
|
||||
logger.error("Error setting device name", error);
|
||||
throw new Error(_t("settings|sessions|error_set_name"));
|
||||
}
|
||||
},
|
||||
[matrixClient, devices, refreshDevices],
|
||||
|
@ -217,7 +217,7 @@ export const useOwnDevices = (): DevicesState => {
|
|||
}
|
||||
} catch (error) {
|
||||
logger.error("Error setting pusher state", error);
|
||||
throw new Error(_t("Failed to set pusher state"));
|
||||
throw new Error(_t("settings|sessions|error_pusher_state"));
|
||||
} finally {
|
||||
await refreshDevices();
|
||||
}
|
||||
|
|
|
@ -116,7 +116,7 @@ export class EmailAddress extends React.Component<IEmailAddressProps, IEmailAddr
|
|||
this.changeBinding({
|
||||
bind: false,
|
||||
label: "revoke",
|
||||
errorTitle: _t("Unable to revoke sharing for email address"),
|
||||
errorTitle: _t("settings|general|error_revoke_email_discovery"),
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -126,7 +126,7 @@ export class EmailAddress extends React.Component<IEmailAddressProps, IEmailAddr
|
|||
this.changeBinding({
|
||||
bind: true,
|
||||
label: "share",
|
||||
errorTitle: _t("Unable to share email address"),
|
||||
errorTitle: _t("settings|general|error_share_email_discovery"),
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -152,15 +152,13 @@ export class EmailAddress extends React.Component<IEmailAddressProps, IEmailAddr
|
|||
|
||||
if (underlyingError instanceof MatrixError && underlyingError.errcode === "M_THREEPID_AUTH_FAILED") {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Your email address hasn't been verified yet"),
|
||||
description: _t(
|
||||
"Click the link in the email you received to verify and then click continue again.",
|
||||
),
|
||||
title: _t("settings|general|email_not_verified"),
|
||||
description: _t("settings|general|email_verification_instructions"),
|
||||
});
|
||||
} else {
|
||||
logger.error("Unable to verify email address: " + err);
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Unable to verify email address."),
|
||||
title: _t("settings|general|error_email_verification"),
|
||||
description: extractErrorMessageFromError(err, _t("invite|failed_generic")),
|
||||
});
|
||||
}
|
||||
|
@ -178,7 +176,7 @@ export class EmailAddress extends React.Component<IEmailAddressProps, IEmailAddr
|
|||
if (verifying) {
|
||||
status = (
|
||||
<span>
|
||||
{_t("Verify the link in your inbox")}
|
||||
{_t("settings|general|discovery_email_verification_instructions")}
|
||||
<AccessibleButton
|
||||
className="mx_GeneralUserSettingsTab_section--discovery_existing_button"
|
||||
kind="primary_sm"
|
||||
|
@ -242,10 +240,8 @@ export default class EmailAddresses extends React.Component<IProps> {
|
|||
|
||||
return (
|
||||
<SettingsSubsection
|
||||
heading={_t("Email addresses")}
|
||||
description={
|
||||
(!hasEmails && _t("Discovery options will appear once you have added an email above.")) || undefined
|
||||
}
|
||||
heading={_t("settings|general|emails_heading")}
|
||||
description={(!hasEmails && _t("settings|general|discovery_email_empty")) || undefined}
|
||||
stretchContent
|
||||
>
|
||||
{content}
|
||||
|
|
|
@ -117,7 +117,7 @@ export class PhoneNumber extends React.Component<IPhoneNumberProps, IPhoneNumber
|
|||
this.changeBinding({
|
||||
bind: false,
|
||||
label: "revoke",
|
||||
errorTitle: _t("Unable to revoke sharing for phone number"),
|
||||
errorTitle: _t("settings|general|error_revoke_msisdn_discovery"),
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -127,7 +127,7 @@ export class PhoneNumber extends React.Component<IPhoneNumberProps, IPhoneNumber
|
|||
this.changeBinding({
|
||||
bind: true,
|
||||
label: "share",
|
||||
errorTitle: _t("Unable to share phone number"),
|
||||
errorTitle: _t("settings|general|error_share_msisdn_discovery"),
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -163,11 +163,11 @@ export class PhoneNumber extends React.Component<IPhoneNumberProps, IPhoneNumber
|
|||
this.setState({ continueDisabled: false });
|
||||
if (underlyingError instanceof MatrixError && underlyingError.errcode !== "M_THREEPID_AUTH_FAILED") {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Unable to verify phone number."),
|
||||
title: _t("settings|general|error_msisdn_verification"),
|
||||
description: extractErrorMessageFromError(err, _t("invite|failed_generic")),
|
||||
});
|
||||
} else {
|
||||
this.setState({ verifyError: _t("Incorrect verification code") });
|
||||
this.setState({ verifyError: _t("settings|general|incorrect_msisdn_verification") });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -181,14 +181,14 @@ export class PhoneNumber extends React.Component<IPhoneNumberProps, IPhoneNumber
|
|||
status = (
|
||||
<span className="mx_GeneralUserSettingsTab_section--discovery_existing_verification">
|
||||
<span>
|
||||
{_t("Please enter verification code sent via text.")}
|
||||
{_t("settings|general|msisdn_verification_instructions")}
|
||||
<br />
|
||||
{this.state.verifyError}
|
||||
</span>
|
||||
<form onSubmit={this.onContinueClick} autoComplete="off" noValidate={true}>
|
||||
<Field
|
||||
type="text"
|
||||
label={_t("Verification code")}
|
||||
label={_t("settings|general|msisdn_verification_field_label")}
|
||||
autoComplete="off"
|
||||
disabled={this.state.continueDisabled}
|
||||
value={this.state.verificationCode}
|
||||
|
@ -247,13 +247,12 @@ export default class PhoneNumbers extends React.Component<IProps> {
|
|||
});
|
||||
}
|
||||
|
||||
const description =
|
||||
(!content && _t("Discovery options will appear once you have added a phone number above.")) || undefined;
|
||||
const description = (!content && _t("settings|general|discovery_msisdn_empty")) || undefined;
|
||||
|
||||
return (
|
||||
<SettingsSubsection
|
||||
data-testid="mx_DiscoveryPhoneNumbers"
|
||||
heading={_t("Phone numbers")}
|
||||
heading={_t("settings|general|msisdns_heading")}
|
||||
description={description}
|
||||
stretchContent
|
||||
>
|
||||
|
|
|
@ -51,7 +51,7 @@ export function NotificationPusherSettings(): JSX.Element {
|
|||
() => ({
|
||||
kind: "email",
|
||||
app_id: "m.email",
|
||||
app_display_name: _t("Email Notifications"),
|
||||
app_display_name: _t("notifications|email_pusher_app_display_name"),
|
||||
lang: navigator.language,
|
||||
data: {
|
||||
brand: SdkConfig.get().brand,
|
||||
|
@ -91,17 +91,16 @@ export function NotificationPusherSettings(): JSX.Element {
|
|||
|
||||
return (
|
||||
<>
|
||||
<SettingsSubsection className="mx_NotificationPusherSettings" heading={_t("Email summary")}>
|
||||
<SettingsSubsection
|
||||
className="mx_NotificationPusherSettings"
|
||||
heading={_t("settings|notifications|email_section")}
|
||||
>
|
||||
<SettingsSubsectionText className="mx_NotificationPusherSettings_description">
|
||||
{_t("Receive an email summary of missed notifications")}
|
||||
{_t("settings|notifications|email_description")}
|
||||
</SettingsSubsectionText>
|
||||
<div className="mx_SettingsSubsection_description mx_NotificationPusherSettings_detail">
|
||||
<SettingsSubsectionText>
|
||||
{_t(
|
||||
"Select which emails you want to send summaries to. Manage your emails in <button>General</button>.",
|
||||
{},
|
||||
{ button: generalTabButton },
|
||||
)}
|
||||
{_t("settings|notifications|email_select", {}, { button: generalTabButton })}
|
||||
</SettingsSubsectionText>
|
||||
</div>
|
||||
<SettingsIndent>
|
||||
|
|
|
@ -58,21 +58,6 @@ function toDefaultLevels(levels: NotificationSettings["defaultLevels"]): Notific
|
|||
}
|
||||
}
|
||||
|
||||
const NotificationOptions = [
|
||||
{
|
||||
value: NotificationDefaultLevels.AllMessages,
|
||||
label: _t("All messages"),
|
||||
},
|
||||
{
|
||||
value: NotificationDefaultLevels.PeopleMentionsKeywords,
|
||||
label: _t("People, Mentions and Keywords"),
|
||||
},
|
||||
{
|
||||
value: NotificationDefaultLevels.MentionsKeywords,
|
||||
label: _t("Mentions and Keywords only"),
|
||||
},
|
||||
];
|
||||
|
||||
function boldText(text: string): JSX.Element {
|
||||
return <strong>{text}</strong>;
|
||||
}
|
||||
|
@ -101,6 +86,21 @@ export default function NotificationSettings2(): JSX.Element {
|
|||
const [updatingUnread, setUpdatingUnread] = useState<boolean>(false);
|
||||
const hasUnreadNotifications = useHasUnreadNotifications();
|
||||
|
||||
const NotificationOptions = [
|
||||
{
|
||||
value: NotificationDefaultLevels.AllMessages,
|
||||
label: _t("notifications|all_messages"),
|
||||
},
|
||||
{
|
||||
value: NotificationDefaultLevels.PeopleMentionsKeywords,
|
||||
label: _t("settings|notifications|people_mentions_keywords"),
|
||||
},
|
||||
{
|
||||
value: NotificationDefaultLevels.MentionsKeywords,
|
||||
label: _t("settings|notifications|mentions_keywords_only"),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="mx_NotificationSettings2">
|
||||
{hasPendingChanges && model !== null && (
|
||||
|
@ -110,7 +110,7 @@ export default function NotificationSettings2(): JSX.Element {
|
|||
onAction={() => reconcile(model!)}
|
||||
>
|
||||
{_t(
|
||||
"<strong>Update:</strong>We’ve simplified Notifications Settings to make options easier to find. Some custom settings you’ve chosen in the past are not shown here, but they’re still active. If you proceed, some of your settings may change. <a>Learn more</a>",
|
||||
"settings|notifications|labs_notice_prompt",
|
||||
{},
|
||||
{
|
||||
strong: boldText,
|
||||
|
@ -140,7 +140,7 @@ export default function NotificationSettings2(): JSX.Element {
|
|||
}
|
||||
/>
|
||||
<LabelledToggleSwitch
|
||||
label={_t("Show message preview in desktop notification")}
|
||||
label={_t("settings|notifications|desktop_notification_message_preview")}
|
||||
value={desktopShowBody}
|
||||
onChange={(value) =>
|
||||
SettingsStore.setValue("notificationBodyEnabled", null, SettingLevel.DEVICE, value)
|
||||
|
@ -155,8 +155,8 @@ export default function NotificationSettings2(): JSX.Element {
|
|||
/>
|
||||
</div>
|
||||
<SettingsSubsection
|
||||
heading={_t("I want to be notified for (Default Setting)")}
|
||||
description={_t("This setting will be applied by default to all your rooms.")}
|
||||
heading={_t("settings|notifications|default_setting_section")}
|
||||
description={_t("settings|notifications|default_setting_description")}
|
||||
>
|
||||
<StyledRadioGroup
|
||||
name="defaultNotificationLevel"
|
||||
|
@ -182,8 +182,8 @@ export default function NotificationSettings2(): JSX.Element {
|
|||
/>
|
||||
</SettingsSubsection>
|
||||
<SettingsSubsection
|
||||
heading={_t("Play a sound for")}
|
||||
description={_t("Applied by default to all rooms on all devices.")}
|
||||
heading={_t("settings|notifications|play_sound_for_section")}
|
||||
description={_t("settings|notifications|play_sound_for_description")}
|
||||
>
|
||||
<LabelledCheckbox
|
||||
label="People"
|
||||
|
@ -200,7 +200,7 @@ export default function NotificationSettings2(): JSX.Element {
|
|||
}}
|
||||
/>
|
||||
<LabelledCheckbox
|
||||
label={_t("Mentions and Keywords")}
|
||||
label={_t("settings|notifications|mentions_keywords")}
|
||||
value={settings.sound.mentions !== undefined}
|
||||
disabled={disabled}
|
||||
onChange={(value) => {
|
||||
|
@ -214,7 +214,7 @@ export default function NotificationSettings2(): JSX.Element {
|
|||
}}
|
||||
/>
|
||||
<LabelledCheckbox
|
||||
label={_t("Audio and Video calls")}
|
||||
label={_t("settings|notifications|voip")}
|
||||
value={settings.sound.calls !== undefined}
|
||||
disabled={disabled}
|
||||
onChange={(value) => {
|
||||
|
@ -228,9 +228,9 @@ export default function NotificationSettings2(): JSX.Element {
|
|||
}}
|
||||
/>
|
||||
</SettingsSubsection>
|
||||
<SettingsSubsection heading={_t("Other things we think you might be interested in:")}>
|
||||
<SettingsSubsection heading={_t("settings|notifications|other_section")}>
|
||||
<LabelledCheckbox
|
||||
label={_t("Invited to a room")}
|
||||
label={_t("settings|notifications|invites")}
|
||||
value={settings.activity.invite}
|
||||
disabled={disabled}
|
||||
onChange={(value) => {
|
||||
|
@ -244,7 +244,7 @@ export default function NotificationSettings2(): JSX.Element {
|
|||
}}
|
||||
/>
|
||||
<LabelledCheckbox
|
||||
label={_t("New room activity, upgrades and status messages occur")}
|
||||
label={_t("settings|notifications|room_activity")}
|
||||
value={settings.activity.status_event}
|
||||
disabled={disabled}
|
||||
onChange={(value) => {
|
||||
|
@ -258,7 +258,7 @@ export default function NotificationSettings2(): JSX.Element {
|
|||
}}
|
||||
/>
|
||||
<LabelledCheckbox
|
||||
label={_t("Messages sent by bots")}
|
||||
label={_t("settings|notifications|notices")}
|
||||
value={settings.activity.bot_notices}
|
||||
disabled={disabled}
|
||||
onChange={(value) => {
|
||||
|
@ -273,9 +273,9 @@ export default function NotificationSettings2(): JSX.Element {
|
|||
/>
|
||||
</SettingsSubsection>
|
||||
<SettingsSubsection
|
||||
heading={_t("Mentions and Keywords")}
|
||||
heading={_t("settings|notifications|mentions_keywords")}
|
||||
description={_t(
|
||||
"Show a badge <badge/> when keywords are used in a room.",
|
||||
"settings|notifications|keywords",
|
||||
{},
|
||||
{
|
||||
badge: <StatelessNotificationBadge symbol="1" count={1} color={NotificationColor.Grey} />,
|
||||
|
@ -283,7 +283,7 @@ export default function NotificationSettings2(): JSX.Element {
|
|||
)}
|
||||
>
|
||||
<LabelledCheckbox
|
||||
label={_t("Notify when someone mentions using @room")}
|
||||
label={_t("settings|notifications|notify_at_room")}
|
||||
value={settings.mentions.room}
|
||||
disabled={disabled}
|
||||
onChange={(value) => {
|
||||
|
@ -297,7 +297,7 @@ export default function NotificationSettings2(): JSX.Element {
|
|||
}}
|
||||
/>
|
||||
<LabelledCheckbox
|
||||
label={_t("Notify when someone mentions using @displayname or %(mxid)s", {
|
||||
label={_t("settings|notifications|notify_mention", {
|
||||
mxid: cli.getUserId()!,
|
||||
})}
|
||||
value={settings.mentions.user}
|
||||
|
@ -313,8 +313,8 @@ export default function NotificationSettings2(): JSX.Element {
|
|||
}}
|
||||
/>
|
||||
<LabelledCheckbox
|
||||
label={_t("Notify when someone uses a keyword")}
|
||||
byline={_t("Enter keywords here, or use for spelling variations or nicknames")}
|
||||
label={_t("settings|notifications|notify_keyword")}
|
||||
byline={_t("settings|notifications|keywords_prompt")}
|
||||
value={settings.mentions.keywords}
|
||||
disabled={disabled}
|
||||
onChange={(value) => {
|
||||
|
@ -348,7 +348,7 @@ export default function NotificationSettings2(): JSX.Element {
|
|||
/>
|
||||
</SettingsSubsection>
|
||||
<NotificationPusherSettings />
|
||||
<SettingsSubsection heading={_t("Quick Actions")}>
|
||||
<SettingsSubsection heading={_t("settings|notifications|quick_actions_section")}>
|
||||
{hasUnreadNotifications && (
|
||||
<AccessibleButton
|
||||
kind="primary_outline"
|
||||
|
@ -359,7 +359,7 @@ export default function NotificationSettings2(): JSX.Element {
|
|||
setUpdatingUnread(false);
|
||||
}}
|
||||
>
|
||||
{_t("Mark all messages as read")}
|
||||
{_t("settings|notifications|quick_actions_mark_all_read")}
|
||||
</AccessibleButton>
|
||||
)}
|
||||
<AccessibleButton
|
||||
|
@ -369,7 +369,7 @@ export default function NotificationSettings2(): JSX.Element {
|
|||
reconcile(DefaultNotificationSettings);
|
||||
}}
|
||||
>
|
||||
{_t("Reset to default settings")}
|
||||
{_t("settings|notifications|quick_actions_reset")}
|
||||
</AccessibleButton>
|
||||
</SettingsSubsection>
|
||||
</SettingsSection>
|
||||
|
|
|
@ -156,7 +156,13 @@ export default class AdvancedRoomSettingsTab extends React.Component<IProps, ISt
|
|||
return (
|
||||
<SettingsTab>
|
||||
<SettingsSection heading={_t("common|advanced")}>
|
||||
<SettingsSubsection heading={room.isSpaceRoom() ? _t("Space information") : _t("Room information")}>
|
||||
<SettingsSubsection
|
||||
heading={
|
||||
room.isSpaceRoom()
|
||||
? _t("room_settings|advanced|information_section_space")
|
||||
: _t("room_settings|advanced|information_section_room")
|
||||
}
|
||||
>
|
||||
<div>
|
||||
<span>{_t("room_settings|advanced|room_id")}</span>
|
||||
<CopyableText getTextToCopy={() => this.props.room.roomId}>
|
||||
|
|
|
@ -63,7 +63,7 @@ export default class BridgeSettingsTab extends React.Component<IProps> {
|
|||
<div>
|
||||
<p>
|
||||
{_t(
|
||||
"This room is bridging messages to the following platforms. <a>Learn more.</a>",
|
||||
"room_settings|bridges|description",
|
||||
{},
|
||||
{
|
||||
// TODO: We don't have this link yet: this will prevent the translators
|
||||
|
@ -85,7 +85,7 @@ export default class BridgeSettingsTab extends React.Component<IProps> {
|
|||
content = (
|
||||
<p>
|
||||
{_t(
|
||||
"This room isn't bridging messages to any platforms. <a>Learn more.</a>",
|
||||
"room_settings|bridges|empty",
|
||||
{},
|
||||
{
|
||||
// TODO: We don't have this link yet: this will prevent the translators
|
||||
|
@ -103,7 +103,7 @@ export default class BridgeSettingsTab extends React.Component<IProps> {
|
|||
|
||||
return (
|
||||
<SettingsTab>
|
||||
<SettingsSection heading={_t("Bridges")}>{content}</SettingsSection>
|
||||
<SettingsSection heading={_t("room_settings|bridges|title")}>{content}</SettingsSection>
|
||||
</SettingsTab>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ export default class GeneralRoomSettingsTab extends React.Component<IProps, ISta
|
|||
<RoomProfileSettings roomId={room.roomId} />
|
||||
</SettingsSection>
|
||||
|
||||
<SettingsSection heading={_t("Room Addresses")}>
|
||||
<SettingsSection heading={_t("room_settings|general|aliases_section")}>
|
||||
<AliasSettings
|
||||
roomId={room.roomId}
|
||||
canSetCanonicalAlias={canSetCanonical}
|
||||
|
@ -98,7 +98,7 @@ export default class GeneralRoomSettingsTab extends React.Component<IProps, ISta
|
|||
/>
|
||||
</SettingsSection>
|
||||
|
||||
<SettingsSection heading={_t("Other")}>
|
||||
<SettingsSection heading={_t("room_settings|general|other_section")}>
|
||||
{urlPreviewSettings}
|
||||
{leaveSection}
|
||||
</SettingsSection>
|
||||
|
|
|
@ -163,7 +163,7 @@ export default class NotificationsSettingsTab extends React.Component<IProps, IS
|
|||
currentUploadedFile = (
|
||||
<div>
|
||||
<span>
|
||||
{_t("Uploaded sound")}: <code>{this.state.uploadedFile.name}</code>
|
||||
{_t("room_settings|notifications|uploaded_sound")}: <code>{this.state.uploadedFile.name}</code>
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
|
@ -181,10 +181,10 @@ export default class NotificationsSettingsTab extends React.Component<IProps, IS
|
|||
className: "mx_NotificationSettingsTab_defaultEntry",
|
||||
label: (
|
||||
<>
|
||||
{_t("Default")}
|
||||
{_t("notifications|default")}
|
||||
<div className="mx_NotificationSettingsTab_microCopy">
|
||||
{_t(
|
||||
"Get notifications as set up in your <a>settings</a>",
|
||||
"room_settings|notifications|settings_link",
|
||||
{},
|
||||
{
|
||||
a: (sub) => (
|
||||
|
@ -206,9 +206,9 @@ export default class NotificationsSettingsTab extends React.Component<IProps, IS
|
|||
className: "mx_NotificationSettingsTab_allMessagesEntry",
|
||||
label: (
|
||||
<>
|
||||
{_t("All messages")}
|
||||
{_t("notifications|all_messages")}
|
||||
<div className="mx_NotificationSettingsTab_microCopy">
|
||||
{_t("Get notified for every message")}
|
||||
{_t("notifications|all_messages_description")}
|
||||
</div>
|
||||
</>
|
||||
),
|
||||
|
@ -218,10 +218,10 @@ export default class NotificationsSettingsTab extends React.Component<IProps, IS
|
|||
className: "mx_NotificationSettingsTab_mentionsKeywordsEntry",
|
||||
label: (
|
||||
<>
|
||||
{_t("@mentions & keywords")}
|
||||
{_t("notifications|mentions_and_keywords")}
|
||||
<div className="mx_NotificationSettingsTab_microCopy">
|
||||
{_t(
|
||||
"Get notified only with mentions and keywords as set up in your <a>settings</a>",
|
||||
"notifications|mentions_and_keywords_description",
|
||||
{},
|
||||
{
|
||||
a: (sub) => (
|
||||
|
@ -245,7 +245,7 @@ export default class NotificationsSettingsTab extends React.Component<IProps, IS
|
|||
<>
|
||||
{_t("common|off")}
|
||||
<div className="mx_NotificationSettingsTab_microCopy">
|
||||
{_t("You won't get any notifications")}
|
||||
{_t("notifications|mute_description")}
|
||||
</div>
|
||||
</>
|
||||
),
|
||||
|
@ -256,11 +256,12 @@ export default class NotificationsSettingsTab extends React.Component<IProps, IS
|
|||
/>
|
||||
</div>
|
||||
|
||||
<SettingsSubsection heading={_t("Sounds")}>
|
||||
<SettingsSubsection heading={_t("room_settings|notifications|sounds_section")}>
|
||||
<div>
|
||||
<div className="mx_SettingsTab_subsectionText">
|
||||
<span>
|
||||
{_t("Notification sound")}: <code>{this.state.currentSound}</code>
|
||||
{_t("room_settings|notifications|notification_sound")}:{" "}
|
||||
<code>{this.state.currentSound}</code>
|
||||
</span>
|
||||
</div>
|
||||
<AccessibleButton
|
||||
|
@ -273,7 +274,7 @@ export default class NotificationsSettingsTab extends React.Component<IProps, IS
|
|||
</AccessibleButton>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="mx_Heading_h4">{_t("Set a new custom sound")}</h4>
|
||||
<h4 className="mx_Heading_h4">{_t("room_settings|notifications|custom_sound_prompt")}</h4>
|
||||
<div className="mx_SettingsFlag">
|
||||
<form autoComplete="off" noValidate={true}>
|
||||
<input
|
||||
|
@ -283,7 +284,7 @@ export default class NotificationsSettingsTab extends React.Component<IProps, IS
|
|||
onClick={chromeFileInputFix}
|
||||
onChange={this.onSoundUploadChanged}
|
||||
accept="audio/*"
|
||||
aria-label={_t("Upload custom sound")}
|
||||
aria-label={_t("room_settings|notifications|upload_sound_label")}
|
||||
/>
|
||||
</form>
|
||||
|
||||
|
@ -295,7 +296,7 @@ export default class NotificationsSettingsTab extends React.Component<IProps, IS
|
|||
onClick={this.triggerUploader}
|
||||
kind="primary"
|
||||
>
|
||||
{_t("Browse")}
|
||||
{_t("room_settings|notifications|browse_button")}
|
||||
</AccessibleButton>
|
||||
|
||||
<AccessibleButton
|
||||
|
|
|
@ -52,7 +52,7 @@ const SeeMoreOrLess: VFC<{ roomMember: RoomMember }> = ({ roomMember }) => {
|
|||
</p>
|
||||
{shouldTruncate && (
|
||||
<AccessibleButton kind="link" onClick={() => setSeeMore(!seeMore)}>
|
||||
{seeMore ? _t("See less") : _t("See more")}
|
||||
{seeMore ? _t("room_settings|people|see_less") : _t("room_settings|people|see_more")}
|
||||
</AccessibleButton>
|
||||
)}
|
||||
</>
|
||||
|
@ -151,7 +151,7 @@ export const PeopleRoomSettingsTab: VFC<{ room: Room }> = ({ room }) => {
|
|||
return (
|
||||
<SettingsTab>
|
||||
<SettingsSection heading={_t("common|people")}>
|
||||
<SettingsFieldset legend={_t("Asking to join")}>
|
||||
<SettingsFieldset legend={_t("room_settings|people|knock_section")}>
|
||||
{knockMembers.length ? (
|
||||
knockMembers.map((knockMember) => (
|
||||
<Knock
|
||||
|
@ -164,7 +164,7 @@ export const PeopleRoomSettingsTab: VFC<{ room: Room }> = ({ room }) => {
|
|||
/>
|
||||
))
|
||||
) : (
|
||||
<p className="mx_PeopleRoomSettingsTab_paragraph">{_t("No requests")}</p>
|
||||
<p className="mx_PeopleRoomSettingsTab_paragraph">{_t("room_settings|people|knock_empty")}</p>
|
||||
)}
|
||||
</SettingsFieldset>
|
||||
</SettingsSection>
|
||||
|
|
|
@ -95,7 +95,7 @@ export class BannedUser extends React.Component<IBannedUserProps> {
|
|||
logger.error("Failed to unban: " + err);
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("common|error"),
|
||||
description: _t("Failed to unban"),
|
||||
description: _t("room_settings|permissions|error_unbanning"),
|
||||
});
|
||||
});
|
||||
};
|
||||
|
@ -119,9 +119,11 @@ export class BannedUser extends React.Component<IBannedUserProps> {
|
|||
return (
|
||||
<li>
|
||||
{unbanButton}
|
||||
<span title={_t("Banned by %(displayName)s", { displayName: this.props.by })}>
|
||||
<span title={_t("room_settings|permissions|banned_by", { displayName: this.props.by })}>
|
||||
<strong>{this.props.member.name}</strong> {userId}
|
||||
{this.props.reason ? " " + _t("Reason") + ": " + this.props.reason : ""}
|
||||
{this.props.reason
|
||||
? " " + _t("room_settings|permissions|ban_reason") + ": " + this.props.reason
|
||||
: ""}
|
||||
</span>
|
||||
</li>
|
||||
);
|
||||
|
@ -205,10 +207,8 @@ export default class RolesRoomSettingsTab extends React.Component<IProps> {
|
|||
logger.error(e);
|
||||
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Error changing power level requirement"),
|
||||
description: _t(
|
||||
"An error occurred changing the room's power level requirements. Ensure you have sufficient permissions and try again.",
|
||||
),
|
||||
title: _t("room_settings|permissions|error_changing_pl_reqs_title"),
|
||||
description: _t("room_settings|permissions|error_changing_pl_reqs_description"),
|
||||
});
|
||||
});
|
||||
};
|
||||
|
@ -230,10 +230,8 @@ export default class RolesRoomSettingsTab extends React.Component<IProps> {
|
|||
logger.error(e);
|
||||
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Error changing power level"),
|
||||
description: _t(
|
||||
"An error occurred changing the user's power level. Ensure you have sufficient permissions and try again.",
|
||||
),
|
||||
title: _t("room_settings|permissions|error_changing_pl_title"),
|
||||
description: _t("room_settings|permissions|error_changing_pl_description"),
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
|
@ -301,8 +301,8 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
|
|||
|
||||
private onJoinRuleChangeError = (error: Error): void => {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Failed to update the join rules"),
|
||||
description: error.message ?? _t("Unknown failure"),
|
||||
title: _t("room_settings|security|error_join_rule_change_title"),
|
||||
description: error.message ?? _t("room_settings|security|error_join_rule_change_unknown"),
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -81,14 +81,14 @@ const ElementCallSwitch: React.FC<ElementCallSwitchProps> = ({ room }) => {
|
|||
return (
|
||||
<LabelledToggleSwitch
|
||||
data-testid="element-call-switch"
|
||||
label={_t("Enable %(brand)s as an additional calling option in this room", { brand })}
|
||||
caption={_t("%(brand)s is end-to-end encrypted, but is currently limited to smaller numbers of users.", {
|
||||
label={_t("room_settings|voip|enable_element_call_label", { brand })}
|
||||
caption={_t("room_settings|voip|enable_element_call_caption", {
|
||||
brand,
|
||||
})}
|
||||
value={elementCallEnabled}
|
||||
onChange={onChange}
|
||||
disabled={!maySend}
|
||||
tooltip={_t("You do not have sufficient permissions to change this.")}
|
||||
tooltip={_t("room_settings|voip|enable_element_call_no_permissions_tooltip")}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
@ -100,8 +100,8 @@ interface Props {
|
|||
export const VoipRoomSettingsTab: React.FC<Props> = ({ room }) => {
|
||||
return (
|
||||
<SettingsTab>
|
||||
<SettingsSection heading={_t("Voice & Video")}>
|
||||
<SettingsSubsection heading={_t("Call type")}>
|
||||
<SettingsSection heading={_t("settings|voip|title")}>
|
||||
<SettingsSubsection heading={_t("room_settings|voip|call_type_section")}>
|
||||
<ElementCallSwitch room={room} />
|
||||
</SettingsSubsection>
|
||||
</SettingsSection>
|
||||
|
|
|
@ -282,16 +282,16 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
|
|||
|
||||
const errorMessage = extractErrorMessageFromError(
|
||||
err,
|
||||
_t("Unknown password change error (%(stringifiedError)s)", {
|
||||
_t("settings|general|error_password_change_unknown", {
|
||||
stringifiedError: String(err),
|
||||
}),
|
||||
);
|
||||
|
||||
let errorMessageToDisplay = errorMessage;
|
||||
if (underlyingError instanceof HTTPError && underlyingError.httpStatus === 403) {
|
||||
errorMessageToDisplay = _t("Failed to change password. Is your password correct?");
|
||||
errorMessageToDisplay = _t("settings|general|error_password_change_403");
|
||||
} else if (underlyingError instanceof HTTPError) {
|
||||
errorMessageToDisplay = _t("%(errorMessage)s (HTTP status %(httpStatus)s)", {
|
||||
errorMessageToDisplay = _t("settings|general|error_password_change_http", {
|
||||
errorMessage,
|
||||
httpStatus: underlyingError.httpStatus,
|
||||
});
|
||||
|
@ -299,13 +299,13 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
|
|||
|
||||
// TODO: Figure out a design that doesn't involve replacing the current dialog
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Error changing password"),
|
||||
title: _t("settings|general|error_password_change_title"),
|
||||
description: errorMessageToDisplay,
|
||||
});
|
||||
};
|
||||
|
||||
private onPasswordChanged = (): void => {
|
||||
const description = _t("Your password was successfully changed.");
|
||||
const description = _t("settings|general|password_change_success");
|
||||
// TODO: Figure out a design that doesn't involve replacing the current dialog
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("common|success"),
|
||||
|
@ -346,7 +346,7 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
|
|||
threepidSection = (
|
||||
<>
|
||||
<SettingsSubsection
|
||||
heading={_t("Email addresses")}
|
||||
heading={_t("settings|general|emails_heading")}
|
||||
stretchContent
|
||||
data-testid="mx_AccountEmailAddresses"
|
||||
>
|
||||
|
@ -354,7 +354,7 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
|
|||
</SettingsSubsection>
|
||||
|
||||
<SettingsSubsection
|
||||
heading={_t("Phone numbers")}
|
||||
heading={_t("settings|general|msisdns_heading")}
|
||||
stretchContent
|
||||
data-testid="mx_AccountPhoneNumbers"
|
||||
>
|
||||
|
@ -368,7 +368,7 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
|
|||
if (this.state.canChangePassword) {
|
||||
passwordChangeSection = (
|
||||
<>
|
||||
<SettingsSubsectionText>{_t("Set a new account password…")}</SettingsSubsectionText>
|
||||
<SettingsSubsectionText>{_t("settings|general|password_change_section")}</SettingsSubsectionText>
|
||||
<ChangePassword
|
||||
className="mx_GeneralUserSettingsTab_section--account_changePassword"
|
||||
rowClassName=""
|
||||
|
@ -388,7 +388,7 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
|
|||
<>
|
||||
<SettingsSubsectionText data-testid="external-account-management-outer">
|
||||
{_t(
|
||||
"Your account details are managed separately at <code>%(hostname)s</code>.",
|
||||
"settings|general|external_account_management",
|
||||
{ hostname },
|
||||
{ code: (sub) => <code>{sub}</code> },
|
||||
)}
|
||||
|
@ -457,10 +457,7 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
|
|||
if (this.state.requiredPolicyInfo.hasTerms) {
|
||||
const intro = (
|
||||
<SettingsSubsectionText>
|
||||
{_t(
|
||||
"Agree to the identity server (%(serverName)s) Terms of Service to allow yourself to be discoverable by email address or phone number.",
|
||||
{ serverName: this.state.idServerName },
|
||||
)}
|
||||
{_t("settings|general|discovery_needs_terms", { serverName: this.state.idServerName })}
|
||||
</SettingsSubsectionText>
|
||||
);
|
||||
return (
|
||||
|
@ -504,14 +501,14 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
|
|||
private renderManagementSection(): JSX.Element {
|
||||
// TODO: Improve warning text for account deactivation
|
||||
return (
|
||||
<SettingsSection heading={_t("Deactivate account")}>
|
||||
<SettingsSection heading={_t("settings|general|deactivate_section")}>
|
||||
<SettingsSubsection
|
||||
heading={_t("Account management")}
|
||||
heading={_t("settings|general|account_management_section")}
|
||||
data-testid="account-management-section"
|
||||
description={_t("Deactivating your account is a permanent action — be careful!")}
|
||||
description={_t("settings|general|deactivate_warning")}
|
||||
>
|
||||
<AccessibleButton onClick={this.onDeactivateClicked} kind="danger">
|
||||
{_t("Deactivate Account")}
|
||||
{_t("settings|general|deactivate_section")}
|
||||
</AccessibleButton>
|
||||
</SettingsSubsection>
|
||||
</SettingsSection>
|
||||
|
@ -549,7 +546,7 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
|
|||
const heading = (
|
||||
<Heading size="2">
|
||||
{discoWarning}
|
||||
{_t("Discovery")}
|
||||
{_t("settings|general|discovery_section")}
|
||||
</Heading>
|
||||
);
|
||||
discoverySection = (
|
||||
|
|
|
@ -143,7 +143,7 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
|
|||
const name = room ? room.name : list.roomId;
|
||||
|
||||
const renderRules = (rules: ListRule[]): JSX.Element => {
|
||||
if (rules.length === 0) return <i>{_t("None")}</i>;
|
||||
if (rules.length === 0) return <i>{_t("labs_mjolnir|rules_empty")}</i>;
|
||||
|
||||
const tiles: JSX.Element[] = [];
|
||||
for (const rule of rules) {
|
||||
|
|
|
@ -63,7 +63,7 @@ export class IgnoredUser extends React.Component<IIgnoredUserProps> {
|
|||
aria-describedby={id}
|
||||
disabled={this.props.inProgress}
|
||||
>
|
||||
{_t("Unignore")}
|
||||
{_t("action|unignore")}
|
||||
</AccessibleButton>
|
||||
<span id={id}>{this.props.userId}</span>
|
||||
</div>
|
||||
|
@ -225,7 +225,7 @@ export default class SecurityUserSettingsTab extends React.Component<IProps, ISt
|
|||
const { waitingUnignored, ignoredUserIds } = this.state;
|
||||
|
||||
const userIds = !ignoredUserIds?.length
|
||||
? _t("You have no ignored users.")
|
||||
? _t("settings|security|ignore_users_empty")
|
||||
: ignoredUserIds.map((u) => {
|
||||
return (
|
||||
<IgnoredUser
|
||||
|
@ -238,7 +238,7 @@ export default class SecurityUserSettingsTab extends React.Component<IProps, ISt
|
|||
});
|
||||
|
||||
return (
|
||||
<SettingsSubsection heading={_t("Ignored users")}>
|
||||
<SettingsSubsection heading={_t("settings|security|ignore_users_section")}>
|
||||
<SettingsSubsectionText>{userIds}</SettingsSubsectionText>
|
||||
</SettingsSubsection>
|
||||
);
|
||||
|
@ -301,9 +301,7 @@ export default class SecurityUserSettingsTab extends React.Component<IProps, ISt
|
|||
if (!privateShouldBeEncrypted(MatrixClientPeg.safeGet())) {
|
||||
warning = (
|
||||
<div className="mx_SecurityUserSettingsTab_warning">
|
||||
{_t(
|
||||
"Your server admin has disabled end-to-end encryption by default in private rooms & Direct Messages.",
|
||||
)}
|
||||
{_t("settings|security|e2ee_default_disabled_warning")}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -320,9 +318,7 @@ export default class SecurityUserSettingsTab extends React.Component<IProps, ISt
|
|||
<SettingsSection heading={_t("common|privacy")}>
|
||||
<SettingsSubsection
|
||||
heading={_t("common|analytics")}
|
||||
description={_t(
|
||||
"Share anonymous data to help us identify issues. Nothing personal. No third parties.",
|
||||
)}
|
||||
description={_t("settings|security|analytics_description")}
|
||||
>
|
||||
<AccessibleButton kind="link" onClick={onClickAnalyticsLearnMore}>
|
||||
{_t("action|learn_more")}
|
||||
|
|
|
@ -302,9 +302,7 @@ const SessionManagerTab: React.FC = () => {
|
|||
disabled={!!signingOutDeviceIds.length}
|
||||
/>
|
||||
}
|
||||
description={_t(
|
||||
"For best security, verify your sessions and sign out from any session that you don't recognize or use anymore.",
|
||||
)}
|
||||
description={_t("settings|sessions|best_security_note")}
|
||||
data-testid="other-sessions-section"
|
||||
stretchContent
|
||||
>
|
||||
|
|
|
@ -67,9 +67,7 @@ const SidebarUserSettingsTab: React.FC = () => {
|
|||
<SettingsSection heading={_t("settings|sidebar|title")}>
|
||||
<SettingsSubsection
|
||||
heading={_t("settings|sidebar|metaspaces_subsection")}
|
||||
description={_t(
|
||||
"Spaces are ways to group rooms and people. Alongside the spaces you're in, you can use some pre-built ones too.",
|
||||
)}
|
||||
description={_t("settings|sidebar|spaces_explainer")}
|
||||
>
|
||||
<StyledCheckbox
|
||||
checked={!!homeEnabled}
|
||||
|
|
|
@ -159,29 +159,30 @@ export default class VoiceUserSettingsTab extends React.Component<{}, IState> {
|
|||
if (!this.state.mediaDevices) {
|
||||
requestButton = (
|
||||
<div>
|
||||
<p>{_t("Missing media permissions, click the button below to request.")}</p>
|
||||
<p>{_t("settings|voip|missing_permissions_prompt")}</p>
|
||||
<AccessibleButton onClick={this.requestMediaPermissions} kind="primary">
|
||||
{_t("Request media permissions")}
|
||||
{_t("settings|voip|request_permissions")}
|
||||
</AccessibleButton>
|
||||
</div>
|
||||
);
|
||||
} else if (this.state.mediaDevices) {
|
||||
speakerDropdown = this.renderDropdown(MediaDeviceKindEnum.AudioOutput, _t("Audio Output")) || (
|
||||
<p>{_t("No Audio Outputs detected")}</p>
|
||||
);
|
||||
speakerDropdown = this.renderDropdown(
|
||||
MediaDeviceKindEnum.AudioOutput,
|
||||
_t("settings|voip|audio_output"),
|
||||
) || <p>{_t("settings|voip|audio_output_empty")}</p>;
|
||||
microphoneDropdown = this.renderDropdown(MediaDeviceKindEnum.AudioInput, _t("common|microphone")) || (
|
||||
<p>{_t("No Microphones detected")}</p>
|
||||
<p>{_t("settings|voip|audio_input_empty")}</p>
|
||||
);
|
||||
webcamDropdown = this.renderDropdown(MediaDeviceKindEnum.VideoInput, _t("common|camera")) || (
|
||||
<p>{_t("No Webcams detected")}</p>
|
||||
<p>{_t("settings|voip|video_input_empty")}</p>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<SettingsTab>
|
||||
<SettingsSection heading={_t("Voice & Video")}>
|
||||
<SettingsSection heading={_t("settings|voip|title")}>
|
||||
{requestButton}
|
||||
<SettingsSubsection heading={_t("Voice settings")} stretchContent>
|
||||
<SettingsSubsection heading={_t("settings|voip|voice_section")} stretchContent>
|
||||
{speakerDropdown}
|
||||
{microphoneDropdown}
|
||||
<LabelledToggleSwitch
|
||||
|
@ -190,18 +191,18 @@ export default class VoiceUserSettingsTab extends React.Component<{}, IState> {
|
|||
await MediaDeviceHandler.setAudioAutoGainControl(v);
|
||||
this.setState({ audioAutoGainControl: MediaDeviceHandler.getAudioAutoGainControl() });
|
||||
}}
|
||||
label={_t("Automatically adjust the microphone volume")}
|
||||
label={_t("settings|voip|voice_agc")}
|
||||
data-testid="voice-auto-gain"
|
||||
/>
|
||||
</SettingsSubsection>
|
||||
<SettingsSubsection heading={_t("Video settings")} stretchContent>
|
||||
<SettingsSubsection heading={_t("settings|voip|video_section")} stretchContent>
|
||||
{webcamDropdown}
|
||||
<SettingsFlag name="VideoView.flipVideoHorizontally" level={SettingLevel.ACCOUNT} />
|
||||
</SettingsSubsection>
|
||||
</SettingsSection>
|
||||
|
||||
<SettingsSection heading={_t("common|advanced")}>
|
||||
<SettingsSubsection heading={_t("Voice processing")}>
|
||||
<SettingsSubsection heading={_t("settings|voip|voice_processing")}>
|
||||
<LabelledToggleSwitch
|
||||
value={this.state.audioNoiseSuppression}
|
||||
onChange={async (v): Promise<void> => {
|
||||
|
@ -221,7 +222,7 @@ export default class VoiceUserSettingsTab extends React.Component<{}, IState> {
|
|||
data-testid="voice-echo-cancellation"
|
||||
/>
|
||||
</SettingsSubsection>
|
||||
<SettingsSubsection heading={_t("Connection")}>
|
||||
<SettingsSubsection heading={_t("settings|voip|connection_section")}>
|
||||
<SettingsFlag
|
||||
name="webRtcAllowPeerToPeer"
|
||||
level={SettingLevel.DEVICE}
|
||||
|
|
|
@ -125,7 +125,7 @@ const SpaceSettingsVisibilityTab: React.FC<IProps> = ({ matrixClient: cli, space
|
|||
let addressesSection: JSX.Element | undefined;
|
||||
if (space.getJoinRule() === JoinRule.Public) {
|
||||
addressesSection = (
|
||||
<SettingsSection heading={_t("Address")}>
|
||||
<SettingsSection heading={_t("room_settings|visibility|alias_section")}>
|
||||
<AliasSettings
|
||||
roomId={space.roomId}
|
||||
canSetCanonicalAlias={canSetCanonical}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue