Migrate more strings to translation keys (#11642)
This commit is contained in:
parent
c879882558
commit
faa7b1521f
87 changed files with 6443 additions and 6006 deletions
|
@ -89,7 +89,7 @@ export default class BridgeTile extends React.PureComponent<IProps> {
|
|||
creator = (
|
||||
<li>
|
||||
{_t(
|
||||
"This bridge was provisioned by <user />.",
|
||||
"labs|bridge_state_creator",
|
||||
{},
|
||||
{
|
||||
user: () => (
|
||||
|
@ -109,7 +109,7 @@ export default class BridgeTile extends React.PureComponent<IProps> {
|
|||
const bot = (
|
||||
<li>
|
||||
{_t(
|
||||
"This bridge is managed by <user />.",
|
||||
"labs|bridge_state_manager",
|
||||
{},
|
||||
{
|
||||
user: () => (
|
||||
|
@ -154,7 +154,7 @@ export default class BridgeTile extends React.PureComponent<IProps> {
|
|||
);
|
||||
}
|
||||
networkItem = _t(
|
||||
"Workspace: <networkLink/>",
|
||||
"labs|bridge_state_workspace",
|
||||
{},
|
||||
{
|
||||
networkLink: () => networkLink,
|
||||
|
@ -181,7 +181,7 @@ export default class BridgeTile extends React.PureComponent<IProps> {
|
|||
{networkItem}
|
||||
<span className="mx_RoomSettingsDialog_channel">
|
||||
{_t(
|
||||
"Channel: <channelLink/>",
|
||||
"labs|bridge_state_channel",
|
||||
{},
|
||||
{
|
||||
channelLink: () => channelLink,
|
||||
|
|
|
@ -127,7 +127,7 @@ export default class ChangePassword extends React.Component<IProps, IState> {
|
|||
this.props.onError(err);
|
||||
} else {
|
||||
this.props.onError(
|
||||
new UserFriendlyError("Error while changing password: %(error)s", {
|
||||
new UserFriendlyError("auth|change_password_error", {
|
||||
error: String(err),
|
||||
cause: undefined,
|
||||
}),
|
||||
|
@ -155,16 +155,16 @@ export default class ChangePassword extends React.Component<IProps, IState> {
|
|||
*/
|
||||
private checkPassword(oldPass: string, newPass: string, confirmPass: string): void {
|
||||
if (newPass !== confirmPass) {
|
||||
throw new UserFriendlyError("New passwords don't match");
|
||||
throw new UserFriendlyError("auth|change_password_mismatch");
|
||||
} else if (!newPass || newPass.length === 0) {
|
||||
throw new UserFriendlyError("Passwords can't be empty");
|
||||
throw new UserFriendlyError("auth|change_password_empty");
|
||||
}
|
||||
}
|
||||
|
||||
private optionallySetEmail(): Promise<boolean> {
|
||||
// Ask for an email otherwise the user has no way to reset their password
|
||||
const modal = Modal.createDialog(SetEmailDialog, {
|
||||
title: _t("Do you want to set an email address?"),
|
||||
title: _t("auth|set_email_prompt"),
|
||||
});
|
||||
return modal.finished.then(([confirmed]) => !!confirmed);
|
||||
}
|
||||
|
@ -194,7 +194,7 @@ export default class ChangePassword extends React.Component<IProps, IState> {
|
|||
{
|
||||
key: "required",
|
||||
test: ({ value, allowEmpty }) => allowEmpty || !!value,
|
||||
invalid: () => _t("Passwords can't be empty"),
|
||||
invalid: () => _t("auth|change_password_empty"),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
@ -226,14 +226,14 @@ export default class ChangePassword extends React.Component<IProps, IState> {
|
|||
{
|
||||
key: "required",
|
||||
test: ({ value, allowEmpty }) => allowEmpty || !!value,
|
||||
invalid: () => _t("Confirm password"),
|
||||
invalid: () => _t("auth|change_password_confirm_label"),
|
||||
},
|
||||
{
|
||||
key: "match",
|
||||
test({ value }) {
|
||||
return !value || value === this.state.newPassword;
|
||||
},
|
||||
invalid: () => _t("Passwords don't match"),
|
||||
invalid: () => _t("auth|change_password_confirm_invalid"),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
@ -261,7 +261,7 @@ export default class ChangePassword extends React.Component<IProps, IState> {
|
|||
this.props.onError(err);
|
||||
} else {
|
||||
this.props.onError(
|
||||
new UserFriendlyError("Error while changing password: %(error)s", {
|
||||
new UserFriendlyError("auth|change_password_error", {
|
||||
error: String(err),
|
||||
cause: undefined,
|
||||
}),
|
||||
|
@ -344,7 +344,7 @@ export default class ChangePassword extends React.Component<IProps, IState> {
|
|||
<Field
|
||||
ref={(field) => (this[FIELD_OLD_PASSWORD] = field)}
|
||||
type="password"
|
||||
label={_t("Current password")}
|
||||
label={_t("auth|change_password_current_label")}
|
||||
value={this.state.oldPassword}
|
||||
onChange={this.onChangeOldPassword}
|
||||
onValidate={this.onOldPasswordValidate}
|
||||
|
@ -354,7 +354,7 @@ export default class ChangePassword extends React.Component<IProps, IState> {
|
|||
<PassphraseField
|
||||
fieldRef={(field) => (this[FIELD_NEW_PASSWORD] = field)}
|
||||
type="password"
|
||||
label={_td("New Password")}
|
||||
label={_td("auth|change_password_new_label")}
|
||||
minScore={PASSWORD_MIN_SCORE}
|
||||
value={this.state.newPassword}
|
||||
autoFocus={this.props.autoFocusNewPasswordInput}
|
||||
|
@ -367,7 +367,7 @@ export default class ChangePassword extends React.Component<IProps, IState> {
|
|||
<Field
|
||||
ref={(field) => (this[FIELD_NEW_PASSWORD_CONFIRM] = field)}
|
||||
type="password"
|
||||
label={_t("Confirm password")}
|
||||
label={_t("auth|change_password_confirm_label")}
|
||||
value={this.state.newPasswordConfirm}
|
||||
onChange={this.onChangeNewPasswordConfirm}
|
||||
onValidate={this.onNewPasswordConfirmValidate}
|
||||
|
@ -379,7 +379,7 @@ export default class ChangePassword extends React.Component<IProps, IState> {
|
|||
kind={this.props.buttonKind}
|
||||
onClick={this.onClickChange}
|
||||
>
|
||||
{this.props.buttonLabel || _t("Change Password")}
|
||||
{this.props.buttonLabel || _t("auth|change_password_action")}
|
||||
</AccessibleButton>
|
||||
</form>
|
||||
);
|
||||
|
|
|
@ -263,32 +263,52 @@ export default class CrossSigningPanel extends React.PureComponent<{}, IState> {
|
|||
<summary>{_t("Advanced")}</summary>
|
||||
<table className="mx_CrossSigningPanel_statusList">
|
||||
<tr>
|
||||
<th scope="row">{_t("Cross-signing public keys:")}</th>
|
||||
<td>{crossSigningPublicKeysOnDevice ? _t("in memory") : _t("not found")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{_t("Cross-signing private keys:")}</th>
|
||||
<th scope="row">{_t("settings|security|cross_signing_public_keys")}</th>
|
||||
<td>
|
||||
{crossSigningPrivateKeysInStorage
|
||||
? _t("in secret storage")
|
||||
: _t("not found in storage")}
|
||||
{crossSigningPublicKeysOnDevice
|
||||
? _t("settings|security|cross_signing_in_memory")
|
||||
: _t("settings|security|cross_signing_not_found")}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{_t("Master private key:")}</th>
|
||||
<td>{masterPrivateKeyCached ? _t("cached locally") : _t("not found locally")}</td>
|
||||
<th scope="row">{_t("settings|security|cross_signing_private_keys")}</th>
|
||||
<td>
|
||||
{crossSigningPrivateKeysInStorage
|
||||
? _t("settings|security|cross_signing_in_4s")
|
||||
: _t("settings|security|cross_signing_not_in_4s")}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{_t("Self signing private key:")}</th>
|
||||
<td>{selfSigningPrivateKeyCached ? _t("cached locally") : _t("not found locally")}</td>
|
||||
<th scope="row">{_t("settings|security|cross_signing_master_private_Key")}</th>
|
||||
<td>
|
||||
{masterPrivateKeyCached
|
||||
? _t("settings|security|cross_signing_cached")
|
||||
: _t("settings|security|cross_signing_not_cached")}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{_t("User signing private key:")}</th>
|
||||
<td>{userSigningPrivateKeyCached ? _t("cached locally") : _t("not found locally")}</td>
|
||||
<th scope="row">{_t("settings|security|cross_signing_self_signing_private_key")}</th>
|
||||
<td>
|
||||
{selfSigningPrivateKeyCached
|
||||
? _t("settings|security|cross_signing_cached")
|
||||
: _t("settings|security|cross_signing_not_cached")}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{_t("Homeserver feature support:")}</th>
|
||||
<td>{homeserverSupportsCrossSigning ? _t("exists") : _t("not found")}</td>
|
||||
<th scope="row">{_t("settings|security|cross_signing_user_signing_private_key")}</th>
|
||||
<td>
|
||||
{userSigningPrivateKeyCached
|
||||
? _t("settings|security|cross_signing_cached")
|
||||
: _t("settings|security|cross_signing_not_cached")}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{_t("settings|security|cross_signing_homeserver_support")}</th>
|
||||
<td>
|
||||
{homeserverSupportsCrossSigning
|
||||
? _t("settings|security|cross_signing_homeserver_support_exists")
|
||||
: _t("settings|security|cross_signing_not_found")}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</details>
|
||||
|
|
|
@ -52,10 +52,10 @@ export default class CryptographyPanel extends React.Component<IProps, IState> {
|
|||
importExportButtons = (
|
||||
<div className="mx_CryptographyPanel_importExportButtons">
|
||||
<AccessibleButton kind="primary" onClick={this.onExportE2eKeysClicked}>
|
||||
{_t("Export E2E room keys")}
|
||||
{_t("settings|security|export_megolm_keys")}
|
||||
</AccessibleButton>
|
||||
<AccessibleButton kind="primary" onClick={this.onImportE2eKeysClicked}>
|
||||
{_t("Import E2E room keys")}
|
||||
{_t("settings|security|import_megolm_keys")}
|
||||
</AccessibleButton>
|
||||
</div>
|
||||
);
|
||||
|
@ -73,17 +73,17 @@ export default class CryptographyPanel extends React.Component<IProps, IState> {
|
|||
}
|
||||
|
||||
return (
|
||||
<SettingsSubsection heading={_t("Cryptography")}>
|
||||
<SettingsSubsection heading={_t("settings|security|cryptography_section")}>
|
||||
<SettingsSubsectionText>
|
||||
<table className="mx_CryptographyPanel_sessionInfo">
|
||||
<tr>
|
||||
<th scope="row">{_t("Session ID:")}</th>
|
||||
<th scope="row">{_t("settings|security|session_id")}</th>
|
||||
<td>
|
||||
<code>{deviceId}</code>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{_t("Session key:")}</th>
|
||||
<th scope="row">{_t("settings|security|session_key")}</th>
|
||||
<td>
|
||||
<code>
|
||||
<b>{identityKey}</b>
|
||||
|
|
|
@ -26,7 +26,7 @@ const SETTING_MANUALLY_VERIFY_ALL_SESSIONS = "e2ee.manuallyVerifyAllSessions";
|
|||
|
||||
const E2eAdvancedPanel: React.FC = () => {
|
||||
return (
|
||||
<SettingsSubsection heading={_t("Encryption")}>
|
||||
<SettingsSubsection heading={_t("settings|security|encryption_section")}>
|
||||
<SettingsFlag name={SETTING_MANUALLY_VERIFY_ALL_SESSIONS} level={SettingLevel.DEVICE} />
|
||||
<SettingsSubsectionText>
|
||||
{_t(
|
||||
|
|
|
@ -366,18 +366,28 @@ export default class SecureBackupPanel extends React.PureComponent<{}, IState> {
|
|||
<table className="mx_SecureBackupPanel_statusList">
|
||||
<tr>
|
||||
<th scope="row">{_t("Backup key stored:")}</th>
|
||||
<td>{backupKeyStored === true ? _t("in secret storage") : _t("not stored")}</td>
|
||||
<td>
|
||||
{backupKeyStored === true
|
||||
? _t("settings|security|cross_signing_in_4s")
|
||||
: _t("not stored")}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{_t("Backup key cached:")}</th>
|
||||
<td>
|
||||
{backupKeyCached ? _t("cached locally") : _t("not found locally")}
|
||||
{backupKeyCached
|
||||
? _t("settings|security|cross_signing_cached")
|
||||
: _t("settings|security|cross_signing_not_cached")}
|
||||
{backupKeyWellFormedText}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{_t("Secret storage public key:")}</th>
|
||||
<td>{secretStorageKeyInAccount ? _t("in account data") : _t("not found")}</td>
|
||||
<td>
|
||||
{secretStorageKeyInAccount
|
||||
? _t("in account data")
|
||||
: _t("settings|security|cross_signing_not_found")}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{_t("Secret storage:")}</th>
|
||||
|
|
|
@ -33,16 +33,16 @@ function installUpdate(): void {
|
|||
function getStatusText(status: UpdateCheckStatus, errorDetail?: string): ReactNode {
|
||||
switch (status) {
|
||||
case UpdateCheckStatus.Error:
|
||||
return _t("Error encountered (%(errorDetail)s).", { errorDetail });
|
||||
return _t("update|error_encountered", { errorDetail });
|
||||
case UpdateCheckStatus.Checking:
|
||||
return _t("Checking for an update…");
|
||||
return _t("update|checking");
|
||||
case UpdateCheckStatus.NotAvailable:
|
||||
return _t("No update available.");
|
||||
return _t("update|no_update");
|
||||
case UpdateCheckStatus.Downloading:
|
||||
return _t("Downloading update…");
|
||||
return _t("update|downloading");
|
||||
case UpdateCheckStatus.Ready:
|
||||
return _t(
|
||||
"New version available. <a>Update now.</a>",
|
||||
"update|new_version_available",
|
||||
{},
|
||||
{
|
||||
a: (sub) => (
|
||||
|
@ -86,7 +86,7 @@ const UpdateCheckButton: React.FC = () => {
|
|||
return (
|
||||
<React.Fragment>
|
||||
<AccessibleButton onClick={onCheckForUpdateClick} kind="primary" disabled={busy}>
|
||||
{_t("Check for update")}
|
||||
{_t("update|check_action")}
|
||||
</AccessibleButton>
|
||||
{suffix}
|
||||
</React.Fragment>
|
||||
|
|
|
@ -111,7 +111,7 @@ export default class AdvancedRoomSettingsTab extends React.Component<IProps, ISt
|
|||
|
||||
let unfederatableSection: JSX.Element | undefined;
|
||||
if (room.currentState.getStateEvents(EventType.RoomCreate, "")?.getContent()["m.federate"] === false) {
|
||||
unfederatableSection = <div>{_t("This room is not accessible by remote Matrix servers")}</div>;
|
||||
unfederatableSection = <div>{_t("room_settings|advanced|unfederated")}</div>;
|
||||
}
|
||||
|
||||
let roomUpgradeButton;
|
||||
|
@ -120,7 +120,7 @@ export default class AdvancedRoomSettingsTab extends React.Component<IProps, ISt
|
|||
<div>
|
||||
<p className="mx_SettingsTab_warningText">
|
||||
{_t(
|
||||
"<b>Warning</b>: upgrading a room will <i>not automatically migrate room members to the new version of the room.</i> We'll post a link to the new room in the old version of the room - room members will have to click this link to join the new room.",
|
||||
"room_settings|advanced|room_upgrade_warning",
|
||||
{},
|
||||
{
|
||||
b: (sub) => <b>{sub}</b>,
|
||||
|
@ -130,8 +130,8 @@ export default class AdvancedRoomSettingsTab extends React.Component<IProps, ISt
|
|||
</p>
|
||||
<AccessibleButton onClick={this.upgradeRoom} kind="primary">
|
||||
{isSpace
|
||||
? _t("Upgrade this space to the recommended room version")
|
||||
: _t("Upgrade this room to the recommended room version")}
|
||||
? _t("room_settings|advanced|space_upgrade_button")
|
||||
: _t("room_settings|advanced|room_upgrade_button")}
|
||||
</AccessibleButton>
|
||||
</div>
|
||||
);
|
||||
|
@ -141,9 +141,9 @@ export default class AdvancedRoomSettingsTab extends React.Component<IProps, ISt
|
|||
if (this.state.oldRoomId) {
|
||||
let copy: string;
|
||||
if (isSpace) {
|
||||
copy = _t("View older version of %(spaceName)s.", { spaceName: room.name ?? this.state.oldRoomId });
|
||||
copy = _t("room_settings|advanced|space_predecessor", { spaceName: room.name ?? this.state.oldRoomId });
|
||||
} else {
|
||||
copy = _t("View older messages in %(roomName)s.", { roomName: room.name ?? this.state.oldRoomId });
|
||||
copy = _t("room_settings|advanced|room_predecessor", { roomName: room.name ?? this.state.oldRoomId });
|
||||
}
|
||||
|
||||
oldRoomLink = (
|
||||
|
@ -158,16 +158,16 @@ export default class AdvancedRoomSettingsTab extends React.Component<IProps, ISt
|
|||
<SettingsSection heading={_t("Advanced")}>
|
||||
<SettingsSubsection heading={room.isSpaceRoom() ? _t("Space information") : _t("Room information")}>
|
||||
<div>
|
||||
<span>{_t("Internal room ID")}</span>
|
||||
<span>{_t("room_settings|advanced|room_id")}</span>
|
||||
<CopyableText getTextToCopy={() => this.props.room.roomId}>
|
||||
{this.props.room.roomId}
|
||||
</CopyableText>
|
||||
</div>
|
||||
{unfederatableSection}
|
||||
</SettingsSubsection>
|
||||
<SettingsSubsection heading={_t("Room version")}>
|
||||
<SettingsSubsection heading={_t("room_settings|advanced|room_version_section")}>
|
||||
<div>
|
||||
<span>{_t("Room version:")}</span>
|
||||
<span>{_t("room_settings|advanced|room_version")}</span>
|
||||
{room.getVersion()}
|
||||
</div>
|
||||
{oldRoomLink}
|
||||
|
|
|
@ -444,7 +444,7 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
|
|||
<SettingsTab>
|
||||
<SettingsSection heading={_t("room_settings|security|title")}>
|
||||
<SettingsFieldset
|
||||
legend={_t("Encryption")}
|
||||
legend={_t("settings|security|encryption_section")}
|
||||
description={
|
||||
isEncryptionForceDisabled && !isEncrypted
|
||||
? undefined
|
||||
|
|
|
@ -402,14 +402,18 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
|
|||
href={this.state.externalAccountManagementUrl}
|
||||
data-testid="external-account-management-link"
|
||||
>
|
||||
{_t("Manage account")}
|
||||
{_t("settings|general|oidc_manage_button")}
|
||||
</AccessibleButton>
|
||||
</>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<SettingsSubsection heading={_t("Account")} stretchContent data-testid="accountSection">
|
||||
<SettingsSubsection
|
||||
heading={_t("settings|general|account_section")}
|
||||
stretchContent
|
||||
data-testid="accountSection"
|
||||
>
|
||||
{externalAccountManagement}
|
||||
{passwordChangeSection}
|
||||
</SettingsSubsection>
|
||||
|
@ -421,7 +425,7 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
|
|||
private renderLanguageSection(): JSX.Element {
|
||||
// TODO: Convert to new-styled Field
|
||||
return (
|
||||
<SettingsSubsection heading={_t("Language and region")} stretchContent>
|
||||
<SettingsSubsection heading={_t("settings|general|language_section")} stretchContent>
|
||||
<LanguageDropdown
|
||||
className="mx_GeneralUserSettingsTab_section_languageInput"
|
||||
onOptionChange={this.onLanguageChange}
|
||||
|
@ -433,7 +437,7 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
|
|||
|
||||
private renderSpellCheckSection(): JSX.Element {
|
||||
const heading = (
|
||||
<SettingsSubsectionHeading heading={_t("Spell check")}>
|
||||
<SettingsSubsectionHeading heading={_t("settings|general|spell_check_section")}>
|
||||
<ToggleSwitch checked={!!this.state.spellCheckEnabled} onChange={this.onSpellCheckEnabledChange} />
|
||||
</SettingsSubsectionHeading>
|
||||
);
|
||||
|
|
|
@ -110,21 +110,18 @@ export default class LabsUserSettingsTab extends React.Component<{}> {
|
|||
|
||||
return (
|
||||
<SettingsTab>
|
||||
<SettingsSection heading={_t("Upcoming features")}>
|
||||
<SettingsSection heading={_t("labs|beta_section")}>
|
||||
<SettingsSubsectionText>
|
||||
{_t(
|
||||
"What's next for %(brand)s? Labs are the best way to get things early, test out new features and help shape them before they actually launch.",
|
||||
{ brand: SdkConfig.get("brand") },
|
||||
)}
|
||||
{_t("labs|beta_description", { brand: SdkConfig.get("brand") })}
|
||||
</SettingsSubsectionText>
|
||||
{betaSection}
|
||||
</SettingsSection>
|
||||
|
||||
{labsSections && (
|
||||
<SettingsSection heading={_t("Early previews")}>
|
||||
<SettingsSection heading={_t("labs|experimental_section")}>
|
||||
<SettingsSubsectionText>
|
||||
{_t(
|
||||
"Feeling experimental? Try out our latest ideas in development. These features are not finalised; they may be unstable, may change, or may be dropped altogether. <a>Learn more</a>.",
|
||||
"labs|experimental_description",
|
||||
{},
|
||||
{
|
||||
a: (sub) => {
|
||||
|
|
|
@ -69,14 +69,14 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
|
|||
this.setState({ busy: true });
|
||||
try {
|
||||
const list = await Mjolnir.sharedInstance().getOrCreatePersonalList();
|
||||
await list.banEntity(kind, this.state.newPersonalRule, _t("Ignored/Blocked"));
|
||||
await list.banEntity(kind, this.state.newPersonalRule, _t("labs_mjolnir|ban_reason"));
|
||||
this.setState({ newPersonalRule: "" }); // this will also cause the new rule to be rendered
|
||||
} catch (e) {
|
||||
logger.error(e);
|
||||
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Error adding ignored user/server"),
|
||||
description: _t("Something went wrong. Please try again or view your console for hints."),
|
||||
title: _t("labs_mjolnir|error_adding_ignore"),
|
||||
description: _t("labs_mjolnir|something_went_wrong"),
|
||||
});
|
||||
} finally {
|
||||
this.setState({ busy: false });
|
||||
|
@ -96,8 +96,8 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
|
|||
logger.error(e);
|
||||
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Error subscribing to list"),
|
||||
description: _t("Please verify the room ID or address and try again."),
|
||||
title: _t("labs_mjolnir|error_adding_list_title"),
|
||||
description: _t("labs_mjolnir|error_adding_list_description"),
|
||||
});
|
||||
} finally {
|
||||
this.setState({ busy: false });
|
||||
|
@ -113,8 +113,8 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
|
|||
logger.error(e);
|
||||
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Error removing ignored user/server"),
|
||||
description: _t("Something went wrong. Please try again or view your console for hints."),
|
||||
title: _t("labs_mjolnir|error_removing_ignore"),
|
||||
description: _t("labs_mjolnir|something_went_wrong"),
|
||||
});
|
||||
} finally {
|
||||
this.setState({ busy: false });
|
||||
|
@ -130,8 +130,8 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
|
|||
logger.error(e);
|
||||
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Error unsubscribing from list"),
|
||||
description: _t("Please try again or view your console for hints."),
|
||||
title: _t("labs_mjolnir|error_removing_list_title"),
|
||||
description: _t("labs_mjolnir|error_removing_list_description"),
|
||||
});
|
||||
} finally {
|
||||
this.setState({ busy: false });
|
||||
|
@ -157,12 +157,12 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
|
|||
};
|
||||
|
||||
Modal.createDialog(QuestionDialog, {
|
||||
title: _t("Ban list rules - %(roomName)s", { roomName: name }),
|
||||
title: _t("labs_mjolnir|rules_title", { roomName: name }),
|
||||
description: (
|
||||
<div>
|
||||
<h3>{_t("Server rules")}</h3>
|
||||
<h3>{_t("labs_mjolnir|rules_server")}</h3>
|
||||
{renderRules(list.serverRules)}
|
||||
<h3>{_t("User rules")}</h3>
|
||||
<h3>{_t("labs_mjolnir|rules_user")}</h3>
|
||||
{renderRules(list.userRules)}
|
||||
</div>
|
||||
),
|
||||
|
@ -174,7 +174,7 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
|
|||
private renderPersonalBanListRules(): JSX.Element {
|
||||
const list = Mjolnir.sharedInstance().getPersonalList();
|
||||
const rules = list ? [...list.userRules, ...list.serverRules] : [];
|
||||
if (!list || rules.length <= 0) return <i>{_t("You have not ignored anyone.")}</i>;
|
||||
if (!list || rules.length <= 0) return <i>{_t("labs_mjolnir|personal_empty")}</i>;
|
||||
|
||||
const tiles: JSX.Element[] = [];
|
||||
for (const rule of rules) {
|
||||
|
@ -195,7 +195,7 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
|
|||
|
||||
return (
|
||||
<div>
|
||||
<p>{_t("You are currently ignoring:")}</p>
|
||||
<p>{_t("labs_mjolnir|personal_section")}</p>
|
||||
<ul>{tiles}</ul>
|
||||
</div>
|
||||
);
|
||||
|
@ -206,7 +206,7 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
|
|||
const lists = Mjolnir.sharedInstance().lists.filter((b) => {
|
||||
return personalList ? personalList.roomId !== b.roomId : true;
|
||||
});
|
||||
if (!lists || lists.length <= 0) return <i>{_t("You are not subscribed to any lists")}</i>;
|
||||
if (!lists || lists.length <= 0) return <i>{_t("labs_mjolnir|no_lists")}</i>;
|
||||
|
||||
const tiles: JSX.Element[] = [];
|
||||
for (const list of lists) {
|
||||
|
@ -233,7 +233,7 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
|
|||
onClick={() => this.viewListRules(list)}
|
||||
disabled={this.state.busy}
|
||||
>
|
||||
{_t("View rules")}
|
||||
{_t("labs_mjolnir|view_rules")}
|
||||
</AccessibleButton>
|
||||
|
||||
{name}
|
||||
|
@ -243,7 +243,7 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
|
|||
|
||||
return (
|
||||
<div>
|
||||
<p>{_t("You are currently subscribed to:")}</p>
|
||||
<p>{_t("labs_mjolnir|lists")}</p>
|
||||
<ul>{tiles}</ul>
|
||||
</div>
|
||||
);
|
||||
|
@ -254,37 +254,24 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
|
|||
|
||||
return (
|
||||
<SettingsTab>
|
||||
<SettingsSection heading={_t("Ignored users")}>
|
||||
<SettingsSection heading={_t("labs_mjolnir|title")}>
|
||||
<SettingsSubsectionText>
|
||||
<span className="warning">{_t("⚠ These settings are meant for advanced users.")}</span>
|
||||
<p>
|
||||
{_t(
|
||||
"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.",
|
||||
{ brand },
|
||||
{ code: (s) => <code>{s}</code> },
|
||||
)}
|
||||
</p>
|
||||
<p>
|
||||
{_t(
|
||||
"Ignoring people is done through ban lists which contain rules for who to ban. Subscribing to a ban list means the users/servers blocked by that list will be hidden from you.",
|
||||
)}
|
||||
</p>
|
||||
<span className="warning">{_t("labs_mjolnir|advanced_warning")}</span>
|
||||
<p>{_t("labs_mjolnir|explainer_1", { brand }, { code: (s) => <code>{s}</code> })}</p>
|
||||
<p>{_t("labs_mjolnir|explainer_2")}</p>
|
||||
</SettingsSubsectionText>
|
||||
<SettingsSubsection
|
||||
heading={_t("Personal ban list")}
|
||||
description={_t(
|
||||
"Your personal ban list holds all the users/servers you personally don't want to see messages from. After ignoring your first user/server, a new room will show up in your room list named '%(myBanList)s' - stay in this room to keep the ban list in effect.",
|
||||
{
|
||||
myBanList: _t("labs_mjolnir|room_name"),
|
||||
},
|
||||
)}
|
||||
heading={_t("labs_mjolnir|personal_heading")}
|
||||
description={_t("labs_mjolnir|personal_description", {
|
||||
myBanList: _t("labs_mjolnir|room_name"),
|
||||
})}
|
||||
>
|
||||
{this.renderPersonalBanListRules()}
|
||||
<form onSubmit={this.onAddPersonalRule} autoComplete="off">
|
||||
<Field
|
||||
type="text"
|
||||
label={_t("Server or user ID to ignore")}
|
||||
placeholder={_t("eg: @bot:* or example.org")}
|
||||
label={_t("labs_mjolnir|personal_new_label")}
|
||||
placeholder={_t("labs_mjolnir|personal_new_placeholder")}
|
||||
value={this.state.newPersonalRule}
|
||||
onChange={this.onPersonalRuleChanged}
|
||||
/>
|
||||
|
@ -299,16 +286,12 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
|
|||
</form>
|
||||
</SettingsSubsection>
|
||||
<SettingsSubsection
|
||||
heading={_t("Subscribed lists")}
|
||||
heading={_t("labs_mjolnir|lists_heading")}
|
||||
description={
|
||||
<>
|
||||
<span className="warning">
|
||||
{_t("Subscribing to a ban list will cause you to join it!")}
|
||||
</span>
|
||||
<span className="warning">{_t("labs_mjolnir|lists_description_1")}</span>
|
||||
|
||||
<span>
|
||||
{_t("If this isn't what you want, please use a different tool to ignore users.")}
|
||||
</span>
|
||||
<span>{_t("labs_mjolnir|lists_description_2")}</span>
|
||||
</>
|
||||
}
|
||||
>
|
||||
|
@ -316,7 +299,7 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
|
|||
<form onSubmit={this.onSubscribeList} autoComplete="off">
|
||||
<Field
|
||||
type="text"
|
||||
label={_t("Room ID or address of ban list")}
|
||||
label={_t("labs_mjolnir|lists_new_label")}
|
||||
value={this.state.newList}
|
||||
onChange={this.onNewListChanged}
|
||||
/>
|
||||
|
|
|
@ -358,7 +358,7 @@ export default class SecurityUserSettingsTab extends React.Component<IProps, ISt
|
|||
return (
|
||||
<SettingsTab>
|
||||
{warning}
|
||||
<SettingsSection heading={_t("Encryption")}>
|
||||
<SettingsSection heading={_t("settings|security|encryption_section")}>
|
||||
{secureBackup}
|
||||
{eventIndex}
|
||||
{crossSigning}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue