"apihelp-block-param-reblock": "If the user is already blocked, overwrite the existing block.",
"apihelp-block-param-watchuser": "Watch the user's or IP address's user and talk pages.",
"apihelp-block-param-tags": "Change tags to apply to the entry in the block log.",
+ "apihelp-block-param-partial": "Block user from specific pages or namespaces rather than the entire site.",
+ "apihelp-block-param-pagerestrictions": "List of titles to block the user from editing. Only applies when 'partial' is set to true.",
"apihelp-block-example-ip-simple": "Block IP address <kbd>192.0.2.5</kbd> for three days with reason <kbd>First strike</kbd>.",
"apihelp-block-example-user-complex": "Block user <kbd>Vandal</kbd> indefinitely with reason <kbd>Vandalism</kbd>, and prevent new account creation and email sending.",
"apierror-bad-watchlist-token": "Incorrect watchlist token provided. Please set a correct token in [[Special:Preferences]].",
"apierror-blockedfrommail": "You have been blocked from sending email.",
"apierror-blocked": "You have been blocked from editing.",
+ "apierror-blocked-partial": "You have been blocked from editing this page.",
"apierror-botsnotsupported": "This interface is not supported for bots.",
"apierror-cannot-async-upload-file": "The parameters <var>async</var> and <var>file</var> cannot be combined. If you want asynchronous processing of your uploaded file, first upload it to stash (using the <var>stash</var> parameter) and then publish the stashed file asynchronously (using <var>filekey</var> and <var>async</var>).",
"apierror-cannotreauthenticate": "This action is not available as your identity cannot be verified.",
"apihelp-block-param-reblock": "{{doc-apihelp-param|block|reblock}}",
"apihelp-block-param-watchuser": "{{doc-apihelp-param|block|watchuser}}",
"apihelp-block-param-tags": "{{doc-apihelp-param|block|tags}}",
+ "apihelp-block-param-partial": "{{doc-apihelp-param|block|partial}}",
+ "apihelp-block-param-pagerestrictions": "{{doc-apihelp-param|block|pagerestrictions}}",
"apihelp-block-example-ip-simple": "{{doc-apihelp-example|block}}",
"apihelp-block-example-user-complex": "{{doc-apihelp-example|block}}",
"apihelp-changeauthenticationdata-summary": "{{doc-apihelp-summary|changeauthenticationdata}}",
"apierror-bad-watchlist-token": "{{doc-apierror}}",
"apierror-blockedfrommail": "{{doc-apierror}}",
"apierror-blocked": "{{doc-apierror}}",
+ "apierror-blocked-partial": "{{doc-apierror}}",
"apierror-botsnotsupported": "{{doc-apierror}}",
"apierror-cannot-async-upload-file": "{{doc-apierror}}",
"apierror-cannotreauthenticate": "{{doc-apierror}}",
'Text' => [
'type' => 'textarea',
'rows' => 20,
- 'cols' => 80,
'label-message' => 'emailmessage',
'required' => true,
],
public function execute( $par ) {
$out = $this->getOutput();
+ $request = $this->getRequest();
$out->addModuleStyles( 'mediawiki.special' );
$this->mTarget = is_null( $par )
- ? $this->getRequest()->getVal( 'wpTarget', $this->getRequest()->getVal( 'target', '' ) )
+ ? $request->getVal( 'wpTarget', $request->getVal( 'target', '' ) )
: $par;
+ // Make sure, that HTMLForm uses the correct target.
+ $request->setVal( 'wpTarget', $this->mTarget );
+
// This needs to be below assignment of $this->mTarget because
// getDescription() needs it to determine the correct page title.
$this->setHeaders();
case 'badaccess':
throw new PermissionsError( 'sendemail' );
case 'blockedemailuser':
- throw new UserBlockedError( $this->getUser()->mBlock );
+ throw $this->getBlockedEmailError();
case 'actionthrottledtext':
throw new ThrottledError;
case 'mailnologin':
list( $title, $msg, $params ) = $error;
throw new ErrorPageError( $title, $msg, $params );
}
- // Got a valid target user name? Else ask for one.
- $ret = self::getTarget( $this->mTarget, $this->getUser() );
- if ( !$ret instanceof User ) {
- if ( $this->mTarget != '' ) {
- // Messages used here: notargettext, noemailtext, nowikiemailtext
- $ret = ( $ret == 'notarget' ) ? 'emailnotarget' : ( $ret . 'text' );
- $out->wrapWikiMsg( "<p class='error'>$1</p>", $ret );
- }
- $out->addHTML( $this->userForm( $this->mTarget ) );
-
- return;
- }
-
- $this->mTargetObj = $ret;
-
- // Set the 'relevant user' in the skin, so it displays links like Contributions,
- // User logs, UserRights, etc.
- $this->getSkin()->setRelevantUser( $this->mTargetObj );
+ // Make sure, that a submitted form isn't submitted to a subpage (which could be
+ // a non-existing username)
$context = new DerivativeContext( $this->getContext() );
$context->setTitle( $this->getPageTitle() ); // Remove subpage
- $form = new HTMLForm( $this->getFormFields(), $context );
- // By now we are supposed to be sure that $this->mTarget is a user name
- $form->addPreText( $this->msg( 'emailpagetext', $this->mTarget )->parse() );
- $form->setSubmitTextMsg( 'emailsend' );
- $form->setSubmitCallback( [ __CLASS__, 'uiSubmit' ] );
- $form->setWrapperLegendMsg( 'email-legend' );
- $form->loadData();
-
- if ( !Hooks::run( 'EmailUserForm', [ &$form ] ) ) {
- return;
- }
-
- $result = $form->show();
-
- if ( $result === true || ( $result instanceof Status && $result->isGood() ) ) {
- $out->setPageTitle( $this->msg( 'emailsent' ) );
- $out->addWikiMsg( 'emailsenttext', $this->mTarget );
- $out->returnToMain( false, $this->mTargetObj->getUserPage() );
+ $this->setContext( $context );
+
+ // A little hack: HTMLForm will check $this->mTarget only, if the form was posted, not
+ // if the user opens Special:EmailUser/Florian (e.g.). So check, if the user did that
+ // and show the "Send email to user" form directly, if so. Show the "enter username"
+ // form, otherwise.
+ $this->mTargetObj = self::getTarget( $this->mTarget, $this->getUser() );
+ if ( !$this->mTargetObj instanceof User ) {
+ $this->userForm( $this->mTarget );
+ } else {
+ $this->sendEmailForm();
}
}
* @return string Form asking for user name.
*/
protected function userForm( $name ) {
- $this->getOutput()->addModules( 'mediawiki.userSuggest' );
- $string = Html::openElement(
- 'form',
- [ 'method' => 'get', 'action' => wfScript(), 'id' => 'askusername' ]
- ) .
- Html::hidden( 'title', $this->getPageTitle()->getPrefixedText() ) .
- Html::openElement( 'fieldset' ) .
- Html::rawElement( 'legend', null, $this->msg( 'emailtarget' )->parse() ) .
- Html::label(
- $this->msg( 'emailusername' )->text(),
- 'emailusertarget'
- ) . "\u{00A0}" .
- Html::input(
- 'target',
- $name,
- 'text',
- [
- 'id' => 'emailusertarget',
- 'class' => 'mw-autocomplete-user', // used by mediawiki.userSuggest
- 'autofocus' => true,
- 'size' => 30,
- ]
- ) .
- ' ' .
- Html::submitButton( $this->msg( 'emailusernamesubmit' )->text(), [] ) .
- Html::closeElement( 'fieldset' ) .
- Html::closeElement( 'form' ) . "\n";
-
- return $string;
+ $htmlForm = HTMLForm::factory( 'ooui', [
+ 'Target' => [
+ 'type' => 'user',
+ 'exists' => true,
+ 'label' => $this->msg( 'emailusername' )->text(),
+ 'id' => 'emailusertarget',
+ 'autofocus' => true,
+ 'value' => $name,
+ ]
+ ], $this->getContext() );
+
+ $htmlForm
+ ->setMethod( 'post' )
+ ->setSubmitCallback( [ $this, 'sendEmailForm' ] )
+ ->setFormIdentifier( 'userForm' )
+ ->setId( 'askusername' )
+ ->setWrapperLegendMsg( 'emailtarget' )
+ ->setSubmitTextMsg( 'emailusernamesubmit' )
+ ->show();
}
- /**
- * Submit callback for an HTMLForm object, will simply call submit().
- *
- * @since 1.20
- * @param array $data
- * @param HTMLForm $form
- * @return Status|bool
- */
- public static function uiSubmit( array $data, HTMLForm $form ) {
- return self::submit( $data, $form->getContext() );
+ public function sendEmailForm() {
+ $out = $this->getOutput();
+
+ $ret = $this->mTargetObj;
+ if ( !$ret instanceof User ) {
+ if ( $this->mTarget != '' ) {
+ // Messages used here: notargettext, noemailtext, nowikiemailtext
+ $ret = ( $ret == 'notarget' ) ? 'emailnotarget' : ( $ret . 'text' );
+ return Status::newFatal( $ret );
+ }
+ return false;
+ }
+
+ $htmlForm = HTMLForm::factory( 'ooui', $this->getFormFields(), $this->getContext() );
+ // By now we are supposed to be sure that $this->mTarget is a user name
+ $htmlForm
+ ->addPreText( $this->msg( 'emailpagetext', $this->mTarget )->parse() )
+ ->setSubmitTextMsg( 'emailsend' )
+ ->setSubmitCallback( [ __CLASS__, 'submit' ] )
+ ->setFormIdentifier( 'sendEmailForm' )
+ ->setWrapperLegendMsg( 'email-legend' )
+ ->loadData();
+
+ if ( !Hooks::run( 'EmailUserForm', [ &$htmlForm ] ) ) {
+ return false;
+ }
+
+ $result = $htmlForm->show();
+
+ if ( $result === true || ( $result instanceof Status && $result->isGood() ) ) {
+ $out->setPageTitle( $this->msg( 'emailsent' ) );
+ $out->addWikiMsg( 'emailsenttext', $this->mTarget );
+ $out->returnToMain( false, $ret->getUserPage() );
+ }
+ return true;
}
/**
protected function getGroupName() {
return 'users';
}
+
+ /**
+ * Builds an error message based on the block params
+ *
+ * @return ErrorPageError
+ */
+ private function getBlockedEmailError() {
+ $block = $this->getUser()->mBlock;
+ $params = $block->getBlockErrorParams( $this->getContext() );
+
+ $msg = $block->isSitewide() ? 'blockedtext' : 'blocked-email-user';
+ return new ErrorPageError( 'blockedtitle', $msg, $params );
+ }
}
"subject-preview": "Preview of subject:",
"previewerrortext": "An error occurred while attempting to preview your changes.",
"blockedtitle": "User is blocked",
+ "blocked-email-user": "<strong>Your username has been blocked from sending email. You can still edit other pages on this wiki.</strong> You can view the full block details at [[Special:MyContributions|account contributions]].\n\nThe block was made by $1.\n\nThe reason given is <em>$2</em>.\n\n* Start of block: $8\n* Expiration of block: $6\n* Intended blockee: $7\n* Block ID #$5",
+ "blockedtext-partial": "<strong>Your username or IP address has been blocked from making changes to this page. You can still edit other pages on this wiki.</strong> You can view the full block details at [[Special:MyContributions|account contributions]].\n\nThe block was made by $1.\n\nThe reason given is <em>$2</em>.\n\n* Start of block: $8\n* Expiration of block: $6\n* Intended blockee: $7\n* Block ID #$5",
"blockedtext": "<strong>Your username or IP address has been blocked.</strong>\n\nThe block was made by $1.\nThe reason given is <em>$2</em>.\n\n* Start of block: $8\n* Expiration of block: $6\n* Intended blockee: $7\n\nYou can contact $1 or another [[{{MediaWiki:Grouppage-sysop}}|administrator]] to discuss the block.\nYou cannot use the \"{{int:emailuser}}\" feature unless a valid email address is specified in your [[Special:Preferences|account preferences]] and you have not been blocked from using it.\nYour current IP address is $3, and the block ID is #$5.\nPlease include all above details in any queries you make.",
"autoblockedtext": "Your IP address has been automatically blocked because it was used by another user, who was blocked by $1.\nThe reason given is:\n\n:<em>$2</em>\n\n* Start of block: $8\n* Expiration of block: $6\n* Intended blockee: $7\n\nYou may contact $1 or one of the other [[{{MediaWiki:Grouppage-sysop}}|administrators]] to discuss the block.\n\nNote that you may not use the \"{{int:emailuser}}\" feature unless you have a valid email address registered in your [[Special:Preferences|user preferences]] and you have not been blocked from using it.\n\nYour current IP address is $3, and the block ID is #$5.\nPlease include all above details in any queries you make.",
"systemblockedtext": "Your username or IP address has been automatically blocked by MediaWiki.\nThe reason given is:\n\n:<em>$2</em>\n\n* Start of block: $8\n* Expiration of block: $6\n* Intended blockee: $7\n\nYour current IP address is $3.\nPlease include all above details in any queries you make.",
"ipb-disableusertalk": "Prevent this user from editing their own talk page while blocked",
"ipb-change-block": "Re-block the user with these settings",
"ipb-confirm": "Confirm block",
+ "ipb-sitewide": "Sitewide",
+ "ipb-partial": "Partial",
+ "ipb-type-label": "Type",
+ "ipb-pages-label": "Pages",
"badipaddress": "Invalid IP address",
"blockipsuccesssub": "Block succeeded",
"blockipsuccesstext": "[[Special:Contributions/$1|$1]] has been blocked.<br />\nSee the [[Special:BlockList|block list]] to review blocks.",
"logentry-block-block": "$1 {{GENDER:$2|blocked}} {{GENDER:$4|$3}} with an expiration time of $5 $6",
"logentry-block-unblock": "$1 {{GENDER:$2|unblocked}} {{GENDER:$4|$3}}",
"logentry-block-reblock": "$1 {{GENDER:$2|changed}} block settings for {{GENDER:$4|$3}} with an expiration time of $5 $6",
+ "logentry-partialblock-block": "$1 {{GENDER:$2|blocked}} {{GENDER:$4|$3}} from editing {{PLURAL:$8||the pages}} $7 with an expiration time of $5 $6",
+ "logentry-partialblock-reblock": "$1 {{GENDER:$2|changed}} block settings for {{GENDER:$4|$3}} preventing edits on {{PLURAL:$8||the pages}} $7 with an expiration time of $5 $6",
+ "logentry-non-editing-block-block": "$1 {{GENDER:$2|blocked}} {{GENDER:$4|$3}} from non-editing actions with an expiration time of $5 $6",
+ "logentry-non-editing-block-reblock": "$1 {{GENDER:$2|changed}} block settings for {{GENDER:$4|$3}} for non-editing actions with an expiration time of $5 $6",
"logentry-suppress-block": "$1 {{GENDER:$2|blocked}} {{GENDER:$4|$3}} with an expiration time of $5 $6",
"logentry-suppress-reblock": "$1 {{GENDER:$2|changed}} block settings for {{GENDER:$4|$3}} with an expiration time of $5 $6",
"logentry-import-upload": "$1 {{GENDER:$2|imported}} $3 by file upload",
"mw-widgets-titleinput-description-redirect": "redirect to $1",
"mw-widgets-categoryselector-add-category-placeholder": "Add a category...",
"mw-widgets-usersmultiselect-placeholder": "Add more...",
+ "mw-widgets-titlesmultiselect-placeholder": "Add more...",
"date-range-from": "From date:",
"date-range-to": "To date:",
"sessionmanager-tie": "Cannot combine multiple request authentication types: $1.",
"passwordpolicies-policy-passwordcannotmatchblacklist": "Password cannot match specifically blacklisted passwords",
"passwordpolicies-policy-maximalpasswordlength": "Password must be less than $1 {{PLURAL:$1|character|characters}} long",
"passwordpolicies-policy-passwordcannotbepopular": "Password cannot be {{PLURAL:$1|the popular password|in the list of $1 popular passwords}}",
- "easydeflate-invaliddeflate": "Content provided is not properly deflated"
+ "easydeflate-invaliddeflate": "Content provided is not properly deflated",
+ "unprotected-js": "For security reasons JavaScript cannot be loaded from unprotected pages. Please only create javascript in the MediaWiki: namespace or as a User subpage"
}
"subject-preview": "Used as label for preview of the section title when adding a new section on a talk page.\n\nShould match {{msg-mw|subject}}.\n\nSee also:\n* {{msg-mw|Summary-preview}}\n\n{{Identical|Subject}}",
"previewerrortext": "When a user has the editing preference LivePreview enabled, clicked the Preview or Show Changes button in the edit page and the action did not succeed.",
"blockedtitle": "Used as title displayed for blocked users. The corresponding message body is one of the following messages:\n* {{msg-mw|Blockedtext|notext=1}}\n* {{msg-mw|Autoblockedtext|notext=1}}\n* {{msg-mw|Systemblockedtext}}",
+ "blocked-email-user": "Text displayed to partially blocked users that are blocked from sending email.\n\n\"email this user\" should be consistent with {{msg-mw|Emailuser}}.\n\nParameters:\n* $1 - the blocking sysop (with a link to his/her userpage)\n* $2 - the reason for the block\n* $3 - the current IP address of the blocked user\n* $4 - (Unused) the blocking sysop's username (plain text, without the link)\n* $5 - the unique numeric identifier of the applied autoblock\n* $6 - the expiry of the block\n* $7 - the intended target of the block (what the blocking user specified in the blocking form)\n* $8 - the timestamp when the block started\nSee also:\n* {{msg-mw|Grouppage-sysop}}\n* {{msg-mw|Autoblockedtext}}\n* {{msg-mw|Systemblockedtext}}",
+ "blockedtext-partial": "Text displayed to partially blocked users.\n\n\"email this user\" should be consistent with {{msg-mw|Emailuser}}.\n\nParameters:\n* $1 - the blocking sysop (with a link to his/her userpage)\n* $2 - the reason for the block\n* $3 - the current IP address of the blocked user\n* $4 - (Unused) the blocking sysop's username (plain text, without the link)\n* $5 - the unique numeric identifier of the applied autoblock\n* $6 - the expiry of the block\n* $7 - the intended target of the block (what the blocking user specified in the blocking form)\n* $8 - the timestamp when the block started\nSee also:\n* {{msg-mw|Grouppage-sysop}}\n* {{msg-mw|Autoblockedtext}}\n* {{msg-mw|Systemblockedtext}}",
"blockedtext": "Text displayed to blocked users.\n\n\"email this user\" should be consistent with {{msg-mw|Emailuser}}.\n\nParameters:\n* $1 - the blocking sysop (with a link to his/her userpage)\n* $2 - the reason for the block\n* $3 - the current IP address of the blocked user\n* $4 - (Unused) the blocking sysop's username (plain text, without the link)\n* $5 - the unique numeric identifier of the applied autoblock\n* $6 - the expiry of the block\n* $7 - the intended target of the block (what the blocking user specified in the blocking form)\n* $8 - the timestamp when the block started\nSee also:\n* {{msg-mw|Grouppage-sysop}}\n* {{msg-mw|Autoblockedtext}}\n* {{msg-mw|Systemblockedtext}}",
"autoblockedtext": "Text displayed to automatically blocked users.\n\n\"email this user\" should be consistent with {{msg-mw|Emailuser}}.\n\nParameters:\n* $1 - the blocking sysop (with a link to his/her userpage)\n* $2 - the reason for the block (in case of autoblocks: {{msg-mw|autoblocker}})\n* $3 - the current IP address of the blocked user\n* $4 - (Unused) the blocking sysop's username (plain text, without the link). Use it for GENDER.\n* $5 - the unique numeric identifier of the applied autoblock\n* $6 - the expiry of the block\n* $7 - the intended target of the block (what the blocking user specified in the blocking form)\n* $8 - the timestamp when the block started\nSee also:\n* {{msg-mw|Grouppage-sysop}}\n* {{msg-mw|Blockedtext}}\n* {{msg-mw|Systemblockedtext}}",
"systemblockedtext": "Text displayed to requests blocked by MediaWiki configuration.\n\n\"email this user\" should be consistent with {{msg-mw|Emailuser}}.\n\nParameters:\n* $1 - (Unused) A dummy user attributed as the blocker, possibly as a link to a user page.\n* $2 - the reason for the block\n* $3 - the current IP address of the blocked user\n* $4 - (Unused) the dummy blocking user's username (plain text, without the link).\n* $5 - A short string indicating the type of system block.\n* $6 - the expiry of the block\n* $7 - the intended target of the block\n* $8 - the timestamp when the block started\nSee also:\n* {{msg-mw|Grouppage-sysop}}\n* {{msg-mw|Blockedtext}}\n* {{msg-mw|Autoblockedtext}}",
"ipb-disableusertalk": "{{doc-singularthey}}\nUsed as label for checkbox in [[Special:Block]].\n\nSee also:\n* {{msg-mw|ipbemailban}}\n* {{msg-mw|ipbenableautoblock}}\n* {{msg-mw|ipbhidename}}\n* {{msg-mw|ipbwatchuser}}\n* {{msg-mw|ipb-hardblock}}",
"ipb-change-block": "Confirmation checkbox required for blocks that would override an earlier block. Appears together with {{msg-mw|ipb-needreblock}}.",
"ipb-confirm": "Used as hidden field in the form on [[Special:Block]].",
+ "ipb-sitewide": "A type of block the user can select from on [[Special:Block]].",
+ "ipb-partial": "A type of block the user can select from on [[Special:Block]].",
+ "ipb-type-label": "The label of the type of editing restriction the admin would like to impose on [[Special:Block]].",
+ "ipb-pages-label": "The label for a autocomplete text field to specify pages to block a user from editing on [[Special:Block]].",
"badipaddress": "An error message shown when one entered an invalid IP address in blocking page.",
"blockipsuccesssub": "Used as page title in [[Special:Block]].\n\nThis message is the subject for the following message:\n* {{msg-mw|Blockipsuccesstext}}",
"blockipsuccesstext": "Used in [[Special:Block]].\nThe title (subject) for this message is {{msg-mw|Blockipsuccesssub}}.\n\nParameters:\n* $1 - username, can be used for GENDER",
"logentry-block-block": "{{Logentry|[[Special:Log/block]]}}\n* $4 - user name for gender or empty string for autoblocks\n* $5 - the block duration, localized and formatted with the english tooltip\n* $6 - block detail flags or empty string\n\nCf. {{msg-mw|Blocklogentry}}",
"logentry-block-unblock": "{{Logentry|[[Special:Log/block]]}}\n* $4 - user name for gender or empty string for autoblocks\n\nCf. {{msg-mw|Unblocklogentry}}",
"logentry-block-reblock": "{{Logentry|[[Special:Log/block]]}}\n* $4 - user name for gender or empty string for autoblocks\n* $5 - the block duration, localized and formatted with the english tooltip\n* $6 - block detail flags or empty string\n\nCf. {{msg-mw|Reblock-logentry}}",
+ "logentry-partialblock-block": "{{Logentry|[[Special:Log/block]]}}\n* $4 - user name for gender or empty string for autoblocks\n* $5 - the block duration, localized and formatted with the english tooltip\n* $6 - block detail flags or empty string\n* $7 - list of pages separated by a comma\n* $8 - total number of pages\n\nCf. {{msg-mw|Blocklogentry}}",
+ "logentry-partialblock-reblock": "{{Logentry|[[Special:Log/block]]}}\n* $4 - user name for gender or empty string for autoblocks\n* $5 - the block duration, localized and formatted with the english tooltip\n* $6 - block detail flags or empty string\n* $7 - list of pages separated by a comma\n* $8 - total number of pages\n\nCf. {{msg-mw|Reblock-logentry}}",
+ "logentry-non-editing-block-block": "{{Logentry|[[Special:Log/block]]}}\n* $4 - user name for gender or empty string for autoblocks\n* $5 - the block duration, localized and formatted with the english tooltip\n* $6 - block detail flags or empty string\n\nCf. {{msg-mw|Blocklogentry}}",
+ "logentry-non-editing-block-reblock": "{{Logentry|[[Special:Log/block]]}}\n* $4 - user name for gender or empty string for autoblocks\n* $5 - the block duration, localized and formatted with the english tooltip\n* $6 - block detail flags or empty string\n\nCf. {{msg-mw|Reblock-logentry}}",
"logentry-suppress-block": "{{Logentry}}\n* $4 - user name for gender or empty string for autoblocks\n* $5 - the block duration, localized and formatted with the english tooltip\n* $6 - block detail flags or empty string",
"logentry-suppress-reblock": "{{Logentry}}\n* $4 - user name for gender or empty string for autoblocks\n* $5 - the block duration, localized and formatted with the english tooltip\n* $6 - block detail flags or empty string",
"logentry-import-upload": "{{Logentry|[[Special:Log/import]]}}",
"mw-widgets-titleinput-description-redirect": "Description label for a redirect in the title input widget.",
"mw-widgets-categoryselector-add-category-placeholder": "Placeholder displayed in the category selector widget after the capsules of already added categories.",
"mw-widgets-usersmultiselect-placeholder": "Placeholder displayed in the input field, where new usernames are entered",
+ "mw-widgets-titlesmultiselect-placeholder": "Placeholder displayed in the input field, where new titles are entered",
"date-range-from": "Label for an input field that specifies the start date of a date range filter.",
"date-range-to": "Label for an input field that specifies the end date of a date range filter.",
"sessionmanager-tie": "Used as an error message when multiple session sources are tied in priority.\n\nParameters:\n* $1 - List of dession type descriptions, from messages like {{msg-mw|sessionprovider-mediawiki-session-cookiesessionprovider}}.",
"passwordpolicies-policy-passwordcannotmatchblacklist": "Password policy that enforces that passwords are not on a list of blacklisted passwords (often previously used during MediaWiki automated testing)",
"passwordpolicies-policy-maximalpasswordlength": "Password policy that enforces a maximum number of characters a password must be. $1 - maximum number of characters that a password can be",
"passwordpolicies-policy-passwordcannotbepopular": "Password policy that enforces that a password is not in a list of $1 number of \"popular\" passwords. $1 - number of popular passwords the password will be checked against",
- "easydeflate-invaliddeflate": "Error message if the content passed to easydeflate was not deflated (compressed) properly"
+ "easydeflate-invaliddeflate": "Error message if the content passed to easydeflate was not deflated (compressed) properly",
+ "unprotected-js": "Error message shown when trying to load javascript via action=raw that is not protected"
}