Migrate more strings to translation keys (#11642)

This commit is contained in:
Michael Telatynski 2023-09-21 18:16:04 +01:00 committed by GitHub
parent c879882558
commit faa7b1521f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
87 changed files with 6443 additions and 6006 deletions

View file

@ -1607,8 +1607,8 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
}
Modal.createDialog(ErrorDialog, {
title: _t("Signed Out"),
description: _t("For security, this session has been signed out. Please sign in again."),
title: _t("auth|session_logged_out_title"),
description: _t("auth|session_logged_out_description"),
});
dis.dispatch({
@ -1619,19 +1619,13 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
Modal.createDialog(
QuestionDialog,
{
title: _t("Terms and Conditions"),
title: _t("terms|tac_title"),
description: (
<div>
<p>
{" "}
{_t(
"To continue using the %(homeserverDomain)s homeserver you must review and agree to our terms and conditions.",
{ homeserverDomain: cli.getDomain() },
)}
</p>
<p> {_t("terms|tac_description", { homeserverDomain: cli.getDomain() })}</p>
</div>
),
button: _t("Review terms and conditions"),
button: _t("terms|tac_button"),
cancelButton: _t("action|dismiss"),
onFinished: (confirmed) => {
if (confirmed) {
@ -1672,11 +1666,10 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
switch (type) {
case "CRYPTO_WARNING_OLD_VERSION_DETECTED":
Modal.createDialog(ErrorDialog, {
title: _t("Old cryptography data detected"),
description: _t(
"Data from an older version of %(brand)s has been detected. This will have caused end-to-end cryptography to malfunction in the older version. End-to-end encrypted messages exchanged recently whilst using the older version may not be decryptable in this version. This may also cause messages exchanged with this version to fail. If you experience problems, log out and back in again. To retain message history, export and re-import your keys.",
{ brand: SdkConfig.get().brand },
),
title: _t("encryption|old_version_detected_title"),
description: _t("encryption|old_version_detected_description", {
brand: SdkConfig.get().brand,
}),
});
break;
}
@ -1732,7 +1725,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
} else if (request.pending) {
ToastStore.sharedInstance().addOrReplaceToast({
key: "verifreq_" + request.transactionId,
title: _t("Verification requested"),
title: _t("encryption|verification_requested_toast_title"),
icon: "verification",
props: { request },
component: VerificationRequestToast,

View file

@ -2335,7 +2335,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
className="mx_RoomView_auxPanel_hiddenHighlights"
onClick={this.onHiddenHighlightsClick}
>
{_t("You have %(count)s unread notifications in a prior version of this room.", {
{_t("room|unread_notifications_predecessor", {
count: hiddenHighlightCount,
})}
</AccessibleButton>

View file

@ -487,7 +487,7 @@ const validateEmailRules = withValidation({
{
key: "email",
test: ({ value }) => !value || Email.looksValid(value),
invalid: () => _t("Doesn't look like a valid email address"),
invalid: () => _t("auth|email_field_label_invalid"),
},
],
});
@ -509,7 +509,7 @@ const SpaceSetupPrivateInvite: React.FC<{
name={name}
type="text"
label={_t("Email address")}
placeholder={_t("Email")}
placeholder={_t("auth|email_field_label")}
value={emailAddresses[i]}
onChange={(ev: React.ChangeEvent<HTMLInputElement>) => setEmailAddress(i, ev.target.value)}
ref={fieldRefs[i]}

View file

@ -93,7 +93,7 @@ export default class ViewSource extends React.Component<IProps, IState> {
</details>
<details className="mx_ViewSource_details">
<summary>
<span className="mx_ViewSource_heading">{_t("Original event source")}</span>
<span className="mx_ViewSource_heading">{_t("devtools|original_event_source")}</span>
</summary>
<CopyableText getTextToCopy={copyOriginalFunc}>
<SyntaxHighlight language="json">{stringify(originalEventSource)}</SyntaxHighlight>
@ -104,7 +104,7 @@ export default class ViewSource extends React.Component<IProps, IState> {
} else {
return (
<>
<div className="mx_ViewSource_heading">{_t("Original event source")}</div>
<div className="mx_ViewSource_heading">{_t("devtools|original_event_source")}</div>
<CopyableText getTextToCopy={copyOriginalFunc}>
<SyntaxHighlight language="json">{stringify(originalEventSource)}</SyntaxHighlight>
</CopyableText>

View file

@ -396,7 +396,7 @@ export default class ForgotPassword extends React.Component<Props, State> {
<PassphraseField
name="reset_password"
type="password"
label={_td("New Password")}
label={_td("auth|change_password_new_label")}
value={this.state.password}
minScore={PASSWORD_MIN_SCORE}
fieldRef={(field) => (this.fieldPassword = field)}

View file

@ -53,7 +53,7 @@ export const CheckEmail: React.FC<CheckEmailProps> = ({
return (
<>
<EMailPromptIcon className="mx_AuthBody_emailPromptIcon--shifted" />
<h1>{_t("Check your email to continue")}</h1>
<h1>{_t("auth|uia|email_auth_header")}</h1>
<div className="mx_AuthBody_text">
<p>{_t("auth|check_email_explainer", { email: email }, { b: (t) => <b>{t}</b> })}</p>
<div className="mx_AuthBody_did-not-receive">

View file

@ -40,9 +40,9 @@ interface IProps extends Omit<IInputProps, "onValidate" | "element"> {
class EmailField extends PureComponent<IProps> {
public static defaultProps = {
label: _td("Email"),
labelRequired: _td("Enter email address"),
labelInvalid: _td("Doesn't look like a valid email address"),
label: _td("auth|email_field_label"),
labelRequired: _td("auth|email_field_label_required"),
labelInvalid: _td("auth|email_field_label_invalid"),
};
public readonly validate = withValidation({

View file

@ -169,7 +169,7 @@ export class PasswordAuthEntry extends React.Component<IAuthEntryProps, IPasswor
return (
<div>
<p>{_t("Confirm your identity by entering your account password below.")}</p>
<p>{_t("auth|uia|password_prompt")}</p>
<form onSubmit={this.onSubmit} className="mx_InteractiveAuthEntryComponents_passwordSection">
<Field
className={passwordBoxClass}
@ -219,9 +219,7 @@ export class RecaptchaAuthEntry extends React.Component<IRecaptchaAuthEntryProps
let sitePublicKey: string | undefined;
if (!this.props.stageParams || !this.props.stageParams.public_key) {
errorText = _t(
"Missing captcha public key in homeserver configuration. Please report this to your homeserver administrator.",
);
errorText = _t("auth|uia|recaptcha_missing_params");
} else {
sitePublicKey = this.props.stageParams.public_key;
}
@ -352,7 +350,7 @@ export class TermsAuthEntry extends React.Component<ITermsAuthEntryProps, ITerms
if (allChecked) {
this.props.submitAuthDict({ type: AuthType.Terms });
} else {
this.setState({ errorText: _t("Please review and accept all of the homeserver's policies") });
this.setState({ errorText: _t("auth|uia|terms_invalid") });
}
};
@ -403,7 +401,7 @@ export class TermsAuthEntry extends React.Component<ITermsAuthEntryProps, ITerms
return (
<div className="mx_InteractiveAuthEntryComponents">
<p>{_t("Please review and accept the policies of this homeserver:")}</p>
<p>{_t("auth|uia|terms")}</p>
{checkboxes}
{errorSection}
{submitButton}
@ -474,19 +472,19 @@ export class EmailIdentityAuthEntry extends React.Component<
return (
<div className="mx_InteractiveAuthEntryComponents_emailWrapper">
<AuthHeaderModifier
title={_t("Check your email to continue")}
icon={<img src={EmailPromptIcon} alt={_t("Unread email icon")} width={16} />}
title={_t("auth|uia|email_auth_header")}
icon={<img src={EmailPromptIcon} role="presentation" alt="" width={16} />}
hideServerPicker={true}
/>
<p>
{_t("To create your account, open the link in the email we just sent to %(emailAddress)s.", {
{_t("auth|uia|email", {
emailAddress: <b>{this.props.inputs.emailAddress}</b>,
})}
</p>
{this.state.requesting ? (
<p className="secondary">
{_t(
"Did not receive it? <a>Resend it</a>",
"auth|uia|email_resend_prompt",
{},
{
a: (text: string) => (
@ -502,13 +500,15 @@ export class EmailIdentityAuthEntry extends React.Component<
) : (
<p className="secondary">
{_t(
"Did not receive it? <a>Resend it</a>",
"auth|uia|email_resend_prompt",
{},
{
a: (text: string) => (
<AccessibleTooltipButton
kind="link_inline"
title={this.state.requested ? _t("Resent!") : _t("action|resend")}
title={
this.state.requested ? _t("auth|uia|email_resent") : _t("action|resend")
}
alignment={Alignment.Right}
onHideTooltip={
this.state.requested
@ -642,7 +642,7 @@ export class MsisdnAuthEntry extends React.Component<IMsisdnAuthEntryProps, IMsi
});
} else {
this.setState({
errorText: _t("Token incorrect"),
errorText: _t("auth|uia|msisdn_token_incorrect"),
});
}
} catch (e) {
@ -670,8 +670,8 @@ export class MsisdnAuthEntry extends React.Component<IMsisdnAuthEntryProps, IMsi
}
return (
<div>
<p>{_t("A text message has been sent to %(msisdn)s", { msisdn: <i>{this.msisdn}</i> })}</p>
<p>{_t("Please enter the code it contains:")}</p>
<p>{_t("auth|uia|msisdn", { msisdn: <i>{this.msisdn}</i> })}</p>
<p>{_t("auth|uia|msisdn_token_prompt")}</p>
<div className="mx_InteractiveAuthEntryComponents_msisdnWrapper">
<form onSubmit={this.onFormSubmit}>
<input
@ -761,13 +761,13 @@ export class RegistrationTokenAuthEntry extends React.Component<IAuthEntryProps,
return (
<div>
<p>{_t("Enter a registration token provided by the homeserver administrator.")}</p>
<p>{_t("auth|uia|registration_token_prompt")}</p>
<form onSubmit={this.onSubmit} className="mx_InteractiveAuthEntryComponents_registrationTokenSection">
<Field
className={registrationTokenBoxClass}
type="text"
name="registrationTokenField"
label={_t("Registration token")}
label={_t("auth|uia|registration_token_label")}
autoFocus={true}
value={this.state.registrationToken}
onChange={this.onRegistrationTokenFieldChange}
@ -895,7 +895,7 @@ export class SSOAuthEntry extends React.Component<ISSOAuthEntryProps, ISSOAuthEn
} else if (this.state.attemptFailed) {
errorSection = (
<div className="error" role="alert">
{_t("Something went wrong in confirming your identity. Cancel and try again.")}
{_t("auth|uia|sso_failed")}
</div>
);
}
@ -972,7 +972,7 @@ export class FallbackAuthEntry extends React.Component<IAuthEntryProps> {
return (
<div>
<AccessibleButton kind="link" inputRef={this.fallbackButton} onClick={this.onShowFallbackClick}>
{_t("Start authentication")}
{_t("auth|uia|fallback_button")}
</AccessibleButton>
{errorSection}
</div>

View file

@ -37,9 +37,9 @@ interface IProps extends Omit<IInputProps, "onValidate" | "label" | "element"> {
class PassphraseConfirmField extends PureComponent<IProps> {
public static defaultProps = {
label: _td("Confirm password"),
labelRequired: _td("Confirm password"),
labelInvalid: _td("Passwords don't match"),
label: _td("auth|change_password_confirm_label"),
labelRequired: _td("auth|change_password_confirm_label"),
labelInvalid: _td("auth|change_password_confirm_invalid"),
};
private validate = withValidation({

View file

@ -46,9 +46,9 @@ interface IProps extends Omit<IInputProps, "onValidate" | "element"> {
class PassphraseField extends PureComponent<IProps> {
public static defaultProps = {
label: _td("common|password"),
labelEnterPassword: _td("Enter password"),
labelStrongPassword: _td("Nice, strong password!"),
labelAllowedButUnsafe: _td("Password is allowed, but unsafe"),
labelEnterPassword: _td("auth|password_field_label"),
labelStrongPassword: _td("auth|password_field_strong_label"),
labelAllowedButUnsafe: _td("auth|password_field_weak_label"),
};
public readonly validate = withValidation<this, ZxcvbnResult | null>({
@ -91,7 +91,7 @@ class PassphraseField extends PureComponent<IProps> {
return null;
}
const { feedback } = complexity;
return feedback.warning || feedback.suggestions[0] || _t("Keep going…");
return feedback.warning || feedback.suggestions[0] || _t("auth|password_field_keep_going_prompt");
},
},
],

View file

@ -214,7 +214,7 @@ export default class PasswordLogin extends React.PureComponent<IProps, IState> {
test({ value, allowEmpty }) {
return allowEmpty || !!value;
},
invalid: () => _t("Enter username"),
invalid: () => _t("auth|username_field_required_invalid"),
},
],
});
@ -236,12 +236,12 @@ export default class PasswordLogin extends React.PureComponent<IProps, IState> {
test({ value, allowEmpty }): boolean {
return allowEmpty || !!value;
},
invalid: (): string => _t("Enter phone number"),
invalid: (): string => _t("auth|msisdn_field_required_invalid"),
},
{
key: "number",
test: ({ value }): boolean => !value || PHONE_NUMBER_REGEX.test(value),
invalid: (): string => _t("That phone number doesn't look quite right, please check and try again"),
invalid: (): string => _t("auth|msisdn_field_number_invalid"),
},
],
});
@ -259,7 +259,7 @@ export default class PasswordLogin extends React.PureComponent<IProps, IState> {
test({ value, allowEmpty }): boolean {
return allowEmpty || !!value;
},
invalid: (): string => _t("Enter password"),
invalid: (): string => _t("auth|password_field_label"),
},
],
});
@ -341,7 +341,7 @@ export default class PasswordLogin extends React.PureComponent<IProps, IState> {
autoComplete="tel-national"
key="phone_input"
type="text"
label={_t("Phone")}
label={_t("auth|msisdn_field_label")}
value={this.props.phoneNumber}
prefixComponent={phoneCountry}
onChange={this.onPhoneNumberChanged}
@ -378,7 +378,7 @@ export default class PasswordLogin extends React.PureComponent<IProps, IState> {
kind="link"
onClick={this.onForgotPasswordClick}
>
{_t("Forgot password?")}
{_t("auth|reset_password_button")}
</AccessibleButton>
);
}
@ -396,7 +396,7 @@ export default class PasswordLogin extends React.PureComponent<IProps, IState> {
if (!SdkConfig.get().disable_3pid_login) {
loginType = (
<div className="mx_Login_type_container">
<label className="mx_Login_type_label">{_t("Sign in with")}</label>
<label className="mx_Login_type_label">{_t("auth|identifier_label")}</label>
<Field
element="select"
value={this.state.loginType}
@ -410,7 +410,7 @@ export default class PasswordLogin extends React.PureComponent<IProps, IState> {
{_t("Email address")}
</option>
<option key={LoginField.Password} value={LoginField.Password}>
{_t("Phone")}
{_t("auth|msisdn_field_label")}
</option>
</Field>
</div>

View file

@ -267,7 +267,7 @@ export default class RegistrationForm extends React.PureComponent<IProps, IState
};
private validateEmailRules = withValidation({
description: () => _t("Use an email address to recover your account"),
description: () => _t("auth|reset_password_email_field_description"),
hideDescriptionIfValid: true,
rules: [
{
@ -275,12 +275,12 @@ export default class RegistrationForm extends React.PureComponent<IProps, IState
test(this: RegistrationForm, { value, allowEmpty }) {
return allowEmpty || !this.authStepIsRequired("m.login.email.identity") || !!value;
},
invalid: () => _t("Enter email address (required on this homeserver)"),
invalid: () => _t("auth|reset_password_email_field_required_invalid"),
},
{
key: "email",
test: ({ value }) => !value || Email.looksValid(value),
invalid: () => _t("Doesn't look like a valid email address"),
invalid: () => _t("auth|email_field_label_invalid"),
},
],
});
@ -324,7 +324,7 @@ export default class RegistrationForm extends React.PureComponent<IProps, IState
};
private validatePhoneNumberRules = withValidation({
description: () => _t("Other users can invite you to rooms using your contact details"),
description: () => _t("auth|msisdn_field_description"),
hideDescriptionIfValid: true,
rules: [
{
@ -332,12 +332,12 @@ export default class RegistrationForm extends React.PureComponent<IProps, IState
test(this: RegistrationForm, { value, allowEmpty }) {
return allowEmpty || !this.authStepIsRequired("m.login.msisdn") || !!value;
},
invalid: () => _t("Enter phone number (required on this homeserver)"),
invalid: () => _t("auth|registration_msisdn_field_required_invalid"),
},
{
key: "email",
test: ({ value }) => !value || phoneNumberLooksValid(value),
invalid: () => _t("That phone number doesn't look quite right, please check and try again"),
invalid: () => _t("auth|msisdn_field_number_invalid"),
},
],
});
@ -380,7 +380,7 @@ export default class RegistrationForm extends React.PureComponent<IProps, IState
{
key: "required",
test: ({ value, allowEmpty }) => allowEmpty || !!value,
invalid: () => _t("Enter username"),
invalid: () => _t("auth|username_field_required_invalid"),
},
{
key: "safeLocalpart",
@ -451,7 +451,9 @@ export default class RegistrationForm extends React.PureComponent<IProps, IState
if (!this.showEmail()) {
return null;
}
const emailLabel = this.authStepIsRequired("m.login.email.identity") ? _td("Email") : _td("Email (optional)");
const emailLabel = this.authStepIsRequired("m.login.email.identity")
? _td("auth|email_field_label")
: _td("Email (optional)");
return (
<EmailField
fieldRef={(field) => (this[RegistrationField.Email] = field)}

View file

@ -179,7 +179,7 @@ export default class UserSettingsDialog extends React.Component<IProps, IState>
tabs.push(
new Tab(
UserTab.Mjolnir,
_td("Ignored users"),
_td("labs_mjolnir|title"),
"mx_UserSettingsDialog_mjolnirIcon",
<MjolnirUserSettingsTab />,
"UserSettingMjolnir",

View file

@ -63,8 +63,8 @@ const MAX_OPTION_LENGTH = 340;
function creatingInitialState(): IState {
return {
title: _t("Create poll"),
actionLabel: _t("Create Poll"),
title: _t("poll|create_poll_title"),
actionLabel: _t("poll|create_poll_action"),
canSubmit: false, // need to add a question and at least one option first
question: "",
options: arraySeed("", DEFAULT_NUM_OPTIONS),
@ -79,7 +79,7 @@ function editingInitialState(editingMxEvent: MatrixEvent): IState {
if (!poll?.isEquivalentTo(M_POLL_START)) return creatingInitialState();
return {
title: _t("Edit poll"),
title: _t("poll|edit_poll_title"),
actionLabel: _t("action|done"),
canSubmit: true,
question: poll.question.text,
@ -175,8 +175,8 @@ export default class PollCreateDialog extends ScrollableBaseModal<IProps, IState
.catch((e) => {
console.error("Failed to post poll:", e);
Modal.createDialog(QuestionDialog, {
title: _t("Failed to post poll"),
description: _t("Sorry, the poll you tried to create was not posted."),
title: _t("poll|failed_send_poll_title"),
description: _t("poll|failed_send_poll_description"),
button: _t("action|try_again"),
cancelButton: _t("action|cancel"),
onFinished: (tryAgain: boolean) => {
@ -197,37 +197,37 @@ export default class PollCreateDialog extends ScrollableBaseModal<IProps, IState
protected renderContent(): React.ReactNode {
return (
<div className="mx_PollCreateDialog">
<h2>{_t("Poll type")}</h2>
<h2>{_t("poll|type_heading")}</h2>
<Field element="select" value={this.state.kind.name} onChange={this.onPollTypeChange}>
<option key={M_POLL_KIND_DISCLOSED.name} value={M_POLL_KIND_DISCLOSED.name}>
{_t("Open poll")}
{_t("poll|type_open")}
</option>
<option key={M_POLL_KIND_UNDISCLOSED.name} value={M_POLL_KIND_UNDISCLOSED.name}>
{_t("Closed poll")}
{_t("poll|type_closed")}
</option>
</Field>
<p>{pollTypeNotes(this.state.kind)}</p>
<h2>{_t("What is your poll question or topic?")}</h2>
<h2>{_t("poll|topic_heading")}</h2>
<Field
id="poll-topic-input"
value={this.state.question}
maxLength={MAX_QUESTION_LENGTH}
label={_t("Question or topic")}
placeholder={_t("Write something…")}
label={_t("poll|topic_label")}
placeholder={_t("poll|topic_placeholder")}
onChange={this.onQuestionChange}
usePlaceholderAsHint={true}
disabled={this.state.busy}
autoFocus={this.state.autoFocusTarget === FocusTarget.Topic}
/>
<h2>{_t("Create options")}</h2>
<h2>{_t("poll|options_heading")}</h2>
{this.state.options.map((op, i) => (
<div key={`option_${i}`} className="mx_PollCreateDialog_option">
<Field
id={`pollcreate_option_${i}`}
value={op}
maxLength={MAX_OPTION_LENGTH}
label={_t("Option %(number)s", { number: i + 1 })}
placeholder={_t("Write an option")}
label={_t("poll|options_label", { number: i + 1 })}
placeholder={_t("poll|options_placeholder")}
onChange={(e: ChangeEvent<HTMLInputElement>) => this.onOptionChange(i, e)}
usePlaceholderAsHint={true}
disabled={this.state.busy}
@ -250,7 +250,7 @@ export default class PollCreateDialog extends ScrollableBaseModal<IProps, IState
className="mx_PollCreateDialog_addOption"
inputRef={this.addOptionRef}
>
{_t("Add option")}
{_t("poll|options_add_button")}
</AccessibleButton>
{this.state.busy && (
<div className="mx_PollCreateDialog_busy">
@ -270,8 +270,8 @@ export default class PollCreateDialog extends ScrollableBaseModal<IProps, IState
function pollTypeNotes(kind: KnownPollKind): string {
if (M_POLL_KIND_DISCLOSED.matches(kind.name)) {
return _t("Voters see results as soon as they have voted");
return _t("poll|disclosed_notes");
} else {
return _t("Results are only revealed when you end the poll");
return _t("poll|notes");
}
}

View file

@ -99,7 +99,7 @@ export default function RoomTopic({ room, ...props }: IProps): JSX.Element {
dis.dispatch({ action: "open_room_settings" });
}}
>
{_t("Edit topic")}
{_t("room|edit_topic")}
</AccessibleButton>
)}
</div>
@ -119,7 +119,7 @@ export default function RoomTopic({ room, ...props }: IProps): JSX.Element {
onClick={onClick}
dir="auto"
tooltipTargetClassName={className}
label={_t("Click to read topic")}
label={_t("room|read_topic")}
alignment={Alignment.Bottom}
ignoreHover={ignoreHover}
>

View file

@ -106,7 +106,7 @@ const EncryptionInfo: React.FC<IProps> = ({
return (
<React.Fragment>
<div data-testid="encryption-info-description" className="mx_UserInfo_container">
<h3>{_t("Encryption")}</h3>
<h3>{_t("settings|security|encryption_section")}</h3>
{description}
</div>
<div className="mx_UserInfo_container">

View file

@ -78,7 +78,7 @@ export default class RoomUpgradeWarningBar extends React.PureComponent<IProps, I
</p>
<p>
{_t(
"<b>Warning</b>: upgrading a room will <i>not automatically migrate room members to the new version of the room.</i> We'll post a link to the new room in the old version of the room - room members will have to click this link to join the new room.",
"room_settings|advanced|room_upgrade_warning",
{},
{
b: (sub) => <b>{sub}</b>,
@ -89,7 +89,7 @@ export default class RoomUpgradeWarningBar extends React.PureComponent<IProps, I
</div>
<p className="mx_RoomUpgradeWarningBar_upgradelink">
<AccessibleButton onClick={this.onUpgradeClick}>
{_t("Upgrade this room to the recommended room version")}
{_t("room_settings|advanced|room_upgrade_button")}
</AccessibleButton>
</p>
</div>

View file

@ -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,

View file

@ -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>
);

View file

@ -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>

View file

@ -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>

View file

@ -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(

View file

@ -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>

View file

@ -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>

View file

@ -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>&nbsp;
<span>{_t("room_settings|advanced|room_version")}</span>&nbsp;
{room.getVersion()}
</div>
{oldRoomLink}

View file

@ -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

View file

@ -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>
);

View file

@ -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) => {

View file

@ -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>
&nbsp;
{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>
&nbsp;
<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}
/>

View file

@ -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}

View file

@ -29,14 +29,10 @@ export default class VerificationComplete extends React.Component<IProps> {
<div>
<h2>{_t("encryption|verification|complete_title")}</h2>
<p>{_t("encryption|verification|complete_description")}</p>
<p>
{_t(
"Secure messages with this user are end-to-end encrypted and not able to be read by third parties.",
)}
</p>
<p>{_t("encryption|verification|explainer")}</p>
<DialogButtons
onPrimaryButtonClick={this.props.onDone}
primaryButton={_t("Got It")}
primaryButton={_t("encryption|verification|complete_action")}
hasCancel={false}
/>
</div>

View file

@ -133,18 +133,18 @@ export default class VerificationShowSas extends React.Component<IProps, IState>
</div>
);
sasCaption = this.props.isSelf
? _t("Confirm the emoji below are displayed on both devices, in the same order:")
: _t("Verify this user by confirming the following emoji appear on their screen.");
? _t("encryption|verification|sas_emoji_caption_self")
: _t("encryption|verification|sas_emoji_caption_user");
} else if (this.props.sas.decimal) {
const numberBlocks = this.props.sas.decimal.map((num, i) => <span key={i}>{num}</span>);
sasDisplay = <div className="mx_VerificationShowSas_decimalSas">{numberBlocks}</div>;
sasCaption = this.props.isSelf
? _t("Verify this device by confirming the following number appears on its screen.")
: _t("Verify this user by confirming the following number appears on their screen.");
? _t("encryption|verification|sas_caption_self")
: _t("encryption|verification|sas_caption_user");
} else {
return (
<div>
{_t("Unable to find a supported verification method.")}
{_t("encryption|verification|unsupported_method")}
<AccessibleButton kind="primary" onClick={this.props.onCancel}>
{_t("action|cancel")}
</AccessibleButton>
@ -159,21 +159,21 @@ export default class VerificationShowSas extends React.Component<IProps, IState>
// logged out during verification
const otherDevice = this.props.otherDeviceDetails;
if (otherDevice) {
text = _t("Waiting for you to verify on your other device, %(deviceName)s (%(deviceId)s)…", {
text = _t("encryption|verification|waiting_other_device_details", {
deviceName: otherDevice.displayName,
deviceId: otherDevice.deviceId,
});
} else {
text = _t("Waiting for you to verify on your other device…");
text = _t("encryption|verification|waiting_other_device");
}
confirm = <p>{text}</p>;
} else if (this.state.pending || this.state.cancelling) {
let text;
if (this.state.pending) {
const { displayName } = this.props;
text = _t("Waiting for %(displayName)s to verify…", { displayName });
text = _t("encryption|verification|waiting_other_user", { displayName });
} else {
text = _t("Cancelling…");
text = _t("encryption|verification|cancelling");
}
confirm = <PendingActionSpinner text={text} />;
} else {