Merge "API: Expose wfIsBadImage() in prop=imageinfo"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Wed, 14 Dec 2016 16:07:53 +0000 (16:07 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Wed, 14 Dec 2016 16:07:53 +0000 (16:07 +0000)
1  2 
includes/api/ApiQueryImageInfo.php
includes/api/i18n/en.json
includes/api/i18n/qqq.json

@@@ -58,6 -58,15 +58,15 @@@ class ApiQueryImageInfo extends ApiQuer
                        'revdelUser' => $this->getUser(),
                ];
  
+               if ( isset( $params['badfilecontexttitle'] ) ) {
+                       $badFileContextTitle = Title::newFromText( $params['badfilecontexttitle'] );
+                       if ( !$badFileContextTitle ) {
+                               $this->dieUsage( 'Invalid title in badfilecontexttitle parameter', 'invalid-title' );
+                       }
+               } else {
+                       $badFileContextTitle = false;
+               }
                $pageIds = $this->getPageSet()->getGoodAndMissingTitlesByNamespace();
                if ( !empty( $pageIds[NS_FILE] ) ) {
                        $titles = array_keys( $pageIds[NS_FILE] );
  
                        $result = $this->getResult();
                        foreach ( $titles as $title ) {
+                               $info = [];
                                $pageId = $pageIds[NS_FILE][$title];
                                $start = $title === $fromTitle ? $fromTimestamp : $params['start'];
  
                                if ( !isset( $images[$title] ) ) {
-                                       if ( isset( $prop['uploadwarning'] ) ) {
-                                               // Uploadwarning needs info about non-existing files
+                                       if ( isset( $prop['uploadwarning'] ) || isset( $prop['badfile'] ) ) {
+                                               // uploadwarning and badfile need info about non-existing files
                                                $images[$title] = wfLocalFile( $title );
+                                               // Doesn't exist, so set an empty image repository
+                                               $info['imagerepository'] = '';
                                        } else {
                                                $result->addValue(
                                                        [ 'query', 'pages', intval( $pageId ) ],
                                        break;
                                }
  
-                               $fit = $result->addValue(
-                                       [ 'query', 'pages', intval( $pageId ) ],
-                                       'imagerepository', $img->getRepoName()
-                               );
+                               if ( !isset( $info['imagerepository'] ) ) {
+                                       $info['imagerepository'] = $img->getRepoName();
+                               }
+                               if ( isset( $prop['badfile'] ) ) {
+                                       $info['badfile'] = (bool)wfIsBadImage( $title, $badFileContextTitle );
+                               }
+                               $fit = $result->addValue( [ 'query', 'pages' ], intval( $pageId ), $info );
                                if ( !$fit ) {
                                        if ( count( $pageIds[NS_FILE] ) == 1 ) {
                                                // The user is screwed. imageinfo can't be solely
  
                $h = $image->getHandler();
                if ( !$h ) {
 -                      $this->setWarning( 'Could not create thumbnail because ' .
 -                              $image->getName() . ' does not have an associated image handler' );
 +                      $this->addWarning( [ 'apiwarn-nothumb-noimagehandler', wfEscapeWikiText( $image->getName() ) ] );
  
                        return $thumbParams;
                }
                        // we could still render the image using width and height parameters,
                        // and this type of thing could happen between different versions of
                        // handlers.
 -                      $this->setWarning( "Could not parse {$p}urlparam for " . $image->getName()
 -                              . '. Using only width and height' );
 +                      $this->addWarning( [ 'apiwarn-badurlparam', $p, wfEscapeWikiText( $image->getName() ) ] );
                        $this->checkParameterNormalise( $image, $thumbParams );
                        return $thumbParams;
                }
  
                if ( isset( $paramList['width'] ) && isset( $thumbParams['width'] ) ) {
                        if ( intval( $paramList['width'] ) != intval( $thumbParams['width'] ) ) {
 -                              $this->setWarning( "Ignoring width value set in {$p}urlparam ({$paramList['width']}) "
 -                                      . "in favor of width value derived from {$p}urlwidth/{$p}urlheight "
 -                                      . "({$thumbParams['width']})" );
 +                              $this->addWarning(
 +                                      [ 'apiwarn-urlparamwidth', $p, $paramList['width'], $thumbParams['width'] ]
 +                              );
                        }
                }
  
                foreach ( $paramList as $name => $value ) {
                        if ( !$h->validateParam( $name, $value ) ) {
 -                              $this->dieUsage( "Invalid value for {$p}urlparam ($name=$value)", 'urlparam' );
 +                              $this->dieWithError(
 +                                      [ 'apierror-invalidurlparam', $p, wfEscapeWikiText( $name ), wfEscapeWikiText( $value ) ]
 +                              );
                        }
                }
  
                // in the actual normalised version, only if we can actually normalise them,
                // so we use the functions scope to throw away the normalisations.
                if ( !$h->normaliseParams( $image, $finalParams ) ) {
 -                      $this->dieUsage( 'Could not normalise image parameters for ' .
 -                              $image->getName(), 'urlparamnormal' );
 +                      $this->dieWithError( [ 'apierror-urlparamnormal', wfEscapeWikiText( $image->getName() ) ] );
                }
        }
  
                                ApiBase::PARAM_DFLT => '',
                                ApiBase::PARAM_TYPE => 'string',
                        ],
+                       'badfilecontexttitle' => [
+                               ApiBase::PARAM_TYPE => 'string',
+                       ],
                        'continue' => [
                                ApiBase::PARAM_HELP_MSG => 'api-help-param-continue',
                        ],
                                'archivename' => 'apihelp-query+imageinfo-paramvalue-prop-archivename',
                                'bitdepth' => 'apihelp-query+imageinfo-paramvalue-prop-bitdepth',
                                'uploadwarning' => 'apihelp-query+imageinfo-paramvalue-prop-uploadwarning',
+                               'badfile' => 'apihelp-query+imageinfo-paramvalue-prop-badfile',
                        ],
                        array_flip( $filter )
                );
        "apihelp-main-param-requestid": "Any value given here will be included in the response. May be used to distinguish requests.",
        "apihelp-main-param-servedby": "Include the hostname that served the request in the results.",
        "apihelp-main-param-curtimestamp": "Include the current timestamp in the result.",
 +      "apihelp-main-param-responselanginfo": "Include the languages used for <var>uselang</var> and <var>errorlang</var> in the result.",
        "apihelp-main-param-origin": "When accessing the API using a cross-domain AJAX request (CORS), set this to the originating domain. This must be included in any pre-flight request, and therefore must be part of the request URI (not the POST body).\n\nFor authenticated requests, this must match one of the origins in the <code>Origin</code> header exactly, so it has to be set to something like <kbd>https://en.wikipedia.org</kbd> or <kbd>https://meta.wikimedia.org</kbd>. If this parameter does not match the <code>Origin</code> header, a 403 response will be returned. If this parameter matches the <code>Origin</code> header and the origin is whitelisted, the <code>Access-Control-Allow-Origin</code> and <code>Access-Control-Allow-Credentials</code> headers will be set.\n\nFor non-authenticated requests, specify the value <kbd>*</kbd>. This will cause the <code>Access-Control-Allow-Origin</code> header to be set, but <code>Access-Control-Allow-Credentials</code> will be <code>false</code> and all user-specific data will be restricted.",
        "apihelp-main-param-uselang": "Language to use for message translations. <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd> with <kbd>siprop=languages</kbd> returns a list of language codes, or specify <kbd>user</kbd> to use the current user's language preference, or specify <kbd>content</kbd> to use this wiki's content language.",
 +      "apihelp-main-param-errorformat": "Format to use for warning and error text output.\n; plaintext: Wikitext with HTML tags removed and entities replaced.\n; wikitext: Unparsed wikitext.\n; html: HTML.\n; raw: Message key and parameters.\n; none: No text output, only the error codes.\n; bc: Format used prior to MediaWiki 1.29. <var>errorlang</var> and <var>errorsuselocal</var> are ignored.",
 +      "apihelp-main-param-errorlang": "Language to use for warnings and errors. <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd> with <kbd>siprop=languages</kbd> returns a list of language codes, or specify <kbd>content</kbd> to use this wiki's content language, or specify <kbd>uselang</kbd> to use the same value as the <var>uselang</var> parameter.",
 +      "apihelp-main-param-errorsuselocal": "If given, error texts will use locally-customized messages from the {{ns:MediaWiki}} namespace.",
  
        "apihelp-block-description": "Block a user.",
 -      "apihelp-block-param-user": "Username, IP address, or IP address range to block.",
 +      "apihelp-block-param-user": "Username, IP address, or IP address range to block. Cannot be used together with <var>$1userid</var>",
 +      "apihelp-block-param-userid": "User ID to block. Cannot be used together with <var>$1user</var>.",
        "apihelp-block-param-expiry": "Expiry time. May be relative (e.g. <kbd>5 months</kbd> or <kbd>2 weeks</kbd>) or absolute (e.g. <kbd>2014-09-18T12:34:56Z</kbd>). If set to <kbd>infinite</kbd>, <kbd>indefinite</kbd>, or <kbd>never</kbd>, the block will never expire.",
        "apihelp-block-param-reason": "Reason for block.",
        "apihelp-block-param-anononly": "Block anonymous users only (i.e. disable anonymous edits for this IP address).",
        "apihelp-query+allmessages-param-prop": "Which properties to get.",
        "apihelp-query+allmessages-param-enableparser": "Set to enable parser, will preprocess the wikitext of message (substitute magic words, handle templates, etc.).",
        "apihelp-query+allmessages-param-nocontent": "If set, do not include the content of the messages in the output.",
 -      "apihelp-query+allmessages-param-includelocal": "Also include local messages, i.e. messages that don't exist in the software but do exist as a MediaWiki: page.\nThis lists all MediaWiki: pages, so it will also list those that aren't really messages such as [[MediaWiki:Common.js|Common.js]].",
 +      "apihelp-query+allmessages-param-includelocal": "Also include local messages, i.e. messages that don't exist in the software but do exist as in the {{ns:MediaWiki}} namespace.\nThis lists all {{ns:MediaWiki}}-namespace pages, so it will also list those that aren't really messages such as [[MediaWiki:Common.js|Common.js]].",
        "apihelp-query+allmessages-param-args": "Arguments to be substituted into message.",
        "apihelp-query+allmessages-param-filter": "Return only messages with names that contain this string.",
        "apihelp-query+allmessages-param-customised": "Return only messages in this customisation state.",
        "apihelp-query+imageinfo-paramvalue-prop-archivename": "Adds the filename of the archive version for non-latest versions.",
        "apihelp-query+imageinfo-paramvalue-prop-bitdepth": "Adds the bit depth of the version.",
        "apihelp-query+imageinfo-paramvalue-prop-uploadwarning": "Used by the Special:Upload page to get information about an existing file. Not intended for use outside MediaWiki core.",
+       "apihelp-query+imageinfo-paramvalue-prop-badfile": "Adds whether the file is on the [[MediaWiki:Bad image list]]",
        "apihelp-query+imageinfo-param-limit": "How many file revisions to return per file.",
        "apihelp-query+imageinfo-param-start": "Timestamp to start listing from.",
        "apihelp-query+imageinfo-param-end": "Timestamp to stop listing at.",
        "apihelp-query+imageinfo-param-extmetadatamultilang": "If translations for extmetadata property are available, fetch all of them.",
        "apihelp-query+imageinfo-param-extmetadatafilter": "If specified and non-empty, only these keys will be returned for $1prop=extmetadata.",
        "apihelp-query+imageinfo-param-urlparam": "A handler specific parameter string. For example, PDFs might use <kbd>page15-100px</kbd>. <var>$1urlwidth</var> must be used and be consistent with <var>$1urlparam</var>.",
+       "apihelp-query+imageinfo-param-badfilecontexttitle": "If <kbd>$2prop=badfile</kbd> is set, this is the page title used when evaluting the [[MediaWiki:Bad image list]]",
        "apihelp-query+imageinfo-param-localonly": "Look only for files in the local repository.",
        "apihelp-query+imageinfo-example-simple": "Fetch information about the current version of [[:File:Albert Einstein Head.jpg]].",
        "apihelp-query+imageinfo-example-dated": "Fetch information about versions of [[:File:Test.jpg]] from 2008 and later.",
        "apihelp-query+users-paramvalue-prop-cancreate": "Indicates whether an account for valid but unregistered usernames can be created.",
        "apihelp-query+users-param-attachedwiki": "With <kbd>$1prop=centralids</kbd>, indicate whether the user is attached with the wiki identified by this ID.",
        "apihelp-query+users-param-users": "A list of users to obtain information for.",
 +      "apihelp-query+users-param-userids": "A list of user IDs to obtain information for.",
        "apihelp-query+users-param-token": "Use <kbd>[[Special:ApiHelp/query+tokens|action=query&meta=tokens]]</kbd> instead.",
        "apihelp-query+users-example-simple": "Return information for user <kbd>Example</kbd>.",
  
        "apihelp-tokens-example-emailmove": "Retrieve an email token and a move token.",
  
        "apihelp-unblock-description": "Unblock a user.",
 -      "apihelp-unblock-param-id": "ID of the block to unblock (obtained through <kbd>list=blocks</kbd>). Cannot be used together with <var>$1user</var>.",
 -      "apihelp-unblock-param-user": "Username, IP address or IP address range to unblock. Cannot be used together with <var>$1id</var>.",
 +      "apihelp-unblock-param-id": "ID of the block to unblock (obtained through <kbd>list=blocks</kbd>). Cannot be used together with <var>$1user</var> or <var>$luserid</var>.",
 +      "apihelp-unblock-param-user": "Username, IP address or IP address range to unblock. Cannot be used together with <var>$1id</var> or <var>$luserid</var>.",
 +      "apihelp-unblock-param-userid": "User ID to unblock. Cannot be used together with <var>$1id</var> or <var>$1user</var>.",
        "apihelp-unblock-param-reason": "Reason for unblock.",
        "apihelp-unblock-param-tags": "Change tags to apply to the entry in the block log.",
        "apihelp-unblock-example-id": "Unblock block ID #<kbd>105</kbd>.",
        "apihelp-phpfm-description": "Output data in serialized PHP format (pretty-print in HTML).",
        "apihelp-rawfm-description": "Output data, including debugging elements, in JSON format (pretty-print in HTML).",
        "apihelp-xml-description": "Output data in XML format.",
 -      "apihelp-xml-param-xslt": "If specified, adds the named page as an XSL stylesheet. The value must be a title in the {{ns:mediawiki}} namespace ending in <code>.xsl</code>.",
 +      "apihelp-xml-param-xslt": "If specified, adds the named page as an XSL stylesheet. The value must be a title in the {{ns:MediaWiki}} namespace ending in <code>.xsl</code>.",
        "apihelp-xml-param-includexmlnamespace": "If specified, adds an XML namespace.",
        "apihelp-xmlfm-description": "Output data in XML format (pretty-print in HTML).",
  
        "api-help-authmanagerhelper-continue": "This request is a continuation after an earlier <samp>UI</samp> or <samp>REDIRECT</samp> response. Either this or <var>$1returnurl</var> is required.",
        "api-help-authmanagerhelper-additional-params": "This module accepts additional parameters depending on the available authentication requests. Use <kbd>[[Special:ApiHelp/query+authmanagerinfo|action=query&meta=authmanagerinfo]]</kbd> with <kbd>amirequestsfor=$1</kbd> (or a previous response from this module, if applicable) to determine the requests available and the fields that they use.",
  
 +      "apierror-allimages-redirect": "Use <kbd>gaifilterredir=nonredirects</kbd> instead of <var>redirects</var> when using <kbd>allimages</kbd> as a generator.",
 +      "apierror-allpages-generator-redirects": "Use <kbd>gapfilterredir=nonredirects</kbd> instead of <var>redirects</var> when using <kbd>allpages</kbd> as a generator.",
 +      "apierror-appendnotsupported": "Can't append to pages using content model $1.",
 +      "apierror-articleexists": "The article you tried to create has been created already.",
 +      "apierror-assertbotfailed": "Assertion that the user has the <code>bot</code> right failed.",
 +      "apierror-assertnameduserfailed": "Assertion that the user is \"$1\" failed.",
 +      "apierror-assertuserfailed": "Assertion that the user is logged in failed.",
 +      "apierror-autoblocked": "Your IP address has been blocked automatically, because it was used by a blocked user.",
 +      "apierror-badconfig-resulttoosmall": "The value of <code>$wgAPIMaxResultSize</code> on this wiki is too small to hold basic result information.",
 +      "apierror-badcontinue": "Invalid continue param. You should pass the original value returned by the previous query.",
 +      "apierror-baddiff": "The diff cannot be retrieved, one or both revisions do not exist or you do not have permission to view them.",
 +      "apierror-baddiffto": "<var>$1diffto</var> must be set to a non-negative number, <kbd>prev</kbd>, <kbd>next</kbd> or <kbd>cur</kbd>.",
 +      "apierror-badformat-generic": "The requested format $1 is not supported for content model $2.",
 +      "apierror-badformat": "The requested format $1 is not supported for content model $2 used by $3.",
 +      "apierror-badgenerator-notgenerator": "Module <kbd>$1</kbd> cannot be used as a generator.",
 +      "apierror-badgenerator-unknown": "Unknown <kbd>generator=$1</kbd>.",
 +      "apierror-badip": "IP parameter is not valid.",
 +      "apierror-badmd5": "The supplied MD5 hash was incorrect.",
 +      "apierror-badmodule-badsubmodule": "The module <kbd>$1</kbd> does not have a submodule \"$2\".",
 +      "apierror-badmodule-nosubmodules": "The module <kbd>$1</kbd> has no submodules.",
 +      "apierror-badparameter": "Invalid value for parameter <var>$1</var>.",
 +      "apierror-badquery": "Invalid query.",
 +      "apierror-badtimestamp": "Invalid value \"$2\" for timestamp parameter <var>$1</var>.",
 +      "apierror-badtoken": "Invalid CSRF token.",
 +      "apierror-badupload": "File upload parameter <var>$1</var> is not a file upload; be sure to use <code>multipart/form-data</code> for your POST and include a filename in the <code>Content-Disposition</code> header.",
 +      "apierror-badurl": "Invalid value \"$2\" for URL parameter <var>$1</var>.",
 +      "apierror-baduser": "Invalid value \"$2\" for user parameter <var>$1</var>.",
 +      "apierror-badvalue-notmultivalue": "U+001F multi-value separation may only be used for multi-valued parameters.",
 +      "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-botsnotsupported": "This interface is not supported for bots.",
 +      "apierror-cannotreauthenticate": "This action is not available as your identity cannot be verified.",
 +      "apierror-cannotviewtitle": "You are not allowed to view $1.",
 +      "apierror-cantblock-email": "You don't have permission to block users from sending email through the wiki.",
 +      "apierror-cantblock": "You don't have permission to block users.",
 +      "apierror-cantchangecontentmodel": "You don't have permission to change the content model of a page.",
 +      "apierror-canthide": "You don't have permission to hide user names from the block log.",
 +      "apierror-cantimport-upload": "You don't have permission to import uploaded pages.",
 +      "apierror-cantimport": "You don't have permission to import pages.",
 +      "apierror-cantoverwrite-sharedfile": "The target file exists on a shared repository and you do not have permission to override it.",
 +      "apierror-cantsend": "You are not logged in, you do not have a confirmed email address, or you are not allowed to send email to other users, so you cannot send email.",
 +      "apierror-cantundelete": "Couldn't undelete: the requested revisions may not exist, or may have been undeleted already.",
 +      "apierror-changeauth-norequest": "Failed to create change request.",
 +      "apierror-chunk-too-small": "Minimum chunk size is $1 {{PLURAL:$1|byte|bytes}} for non-final chunks.",
 +      "apierror-cidrtoobroad": "$1 CIDR ranges broader than /$2 are not accepted.",
 +      "apierror-compare-inputneeded": "A title, a page ID, or a revision number is needed for both the <var>from</var> and the <var>to</var> parameters.",
 +      "apierror-contentserializationexception": "Content serialization failed: $1",
 +      "apierror-contenttoobig": "The content you supplied exceeds the article size limit of $1 {{PLURAL:$1|kilobyte|kilobytes}}.",
 +      "apierror-copyuploadbaddomain": "Uploads by URL are not allowed from this domain.",
 +      "apierror-copyuploadbadurl": "Upload not allowed from this URL.",
 +      "apierror-create-titleexists": "Existing titles can't be protected with <kbd>create</kbd>.",
 +      "apierror-csp-report": "Error processing CSP report: $1.",
 +      "apierror-databaseerror": "[$1] Database query error.",
 +      "apierror-deletedrevs-param-not-1-2": "The <var>$1</var> parameter cannot be used in modes 1 or 2.",
 +      "apierror-deletedrevs-param-not-3": "The <var>$1</var> parameter cannot be used in mode 3.",
 +      "apierror-emptynewsection": "Creating empty new sections is not possible.",
 +      "apierror-emptypage": "Creating new, empty pages is not allowed.",
 +      "apierror-exceptioncaught": "[$1] Exception caught: $2",
 +      "apierror-filedoesnotexist": "File does not exist.",
 +      "apierror-fileexists-sharedrepo-perm": "The target file exists on a shared repository. Use the <var>ignorewarnings</var> parameter to override it.",
 +      "apierror-filenopath": "Cannot get local file path.",
 +      "apierror-filetypecannotberotated": "File type cannot be rotated.",
 +      "apierror-formatphp": "This response cannot be represented using <kbd>format=php</kbd>. See https://phabricator.wikimedia.org/T68776.",
 +      "apierror-imageusage-badtitle": "The title for <kbd>$1</kbd> must be a file.",
 +      "apierror-import-unknownerror": "Unknown error on import: $1.",
 +      "apierror-integeroutofrange-abovebotmax": "<var>$1</var> may not be over $2 (set to $3) for bots or sysops.",
 +      "apierror-integeroutofrange-abovemax": "<var>$1</var> may not be over $2 (set to $3) for users.",
 +      "apierror-integeroutofrange-belowminimum": "<var>$1</var> may not be less than $2 (set to $3).",
 +      "apierror-invalidcategory": "The category name you entered is not valid.",
 +      "apierror-invalid-chunk": "Offset plus current chunk is greater than claimed file size.",
 +      "apierror-invalidexpiry": "Invalid expiry time \"$1\".",
 +      "apierror-invalid-file-key": "Not a valid file key.",
 +      "apierror-invalidlang": "Invalid language code for parameter <var>$1</var>.",
 +      "apierror-invalidoldimage": "The oldimage parameter has invalid format.",
 +      "apierror-invalidparammix-cannotusewith": "The <kbd>$1</kbd> parameter cannot be used with <kbd>$2</kbd>.",
 +      "apierror-invalidparammix-mustusewith": "The <kbd>$1</kbd> parameter may only be used with <kbd>$2</kbd>.",
 +      "apierror-invalidparammix-parse-new-section": "<kbd>section=new</kbd> cannot be combined with the <var>oldid</var>, <var>pageid</var> or <var>page</var> parameters. Please use <var>title</var> and <var>text</var>.",
 +      "apierror-invalidparammix": "The {{PLURAL:$2|parameters}} $1 can not be used together.",
 +      "apierror-invalidsection": "The section parameter must be a valid section ID or <kbd>new</kbd>.",
 +      "apierror-invalidsha1base36hash": "The SHA1Base36 hash provided is not valid.",
 +      "apierror-invalidsha1hash": "The SHA1 hash provided is not valid.",
 +      "apierror-invalidtitle": "Bad title \"$1\".",
 +      "apierror-invalidurlparam": "Invalid value for <var>$1urlparam</var> (<kbd>$2=$3</kbd>).",
 +      "apierror-invaliduser": "Invalid username \"$1\".",
 +      "apierror-maxlag-generic": "Waiting for a database server: $1 {{PLURAL:$1|second|seconds}} lagged.",
 +      "apierror-maxlag": "Waiting for $2: $1 {{PLURAL:$1|second|seconds}} lagged.",
 +      "apierror-mimesearchdisabled": "MIME search is disabled in Miser Mode.",
 +      "apierror-missingcontent-pageid": "Missing content for page ID $1.",
 +      "apierror-missingparam-at-least-one-of": "{{PLURAL:$2|The parameter|At least one of the parameters}} $1 is required.",
 +      "apierror-missingparam-one-of": "{{PLURAL:$2|The parameter|One of the parameters}} $1 is required.",
 +      "apierror-missingparam": "The <var>$1</var> parameter must be set.",
 +      "apierror-missingrev-pageid": "No current revision of page ID $1.",
 +      "apierror-missingtitle-createonly": "Missing titles can only be protected with <kbd>create</kbd>.",
 +      "apierror-missingtitle": "The page you specified doesn't exist.",
 +      "apierror-missingtitle-byname": "The page $1 doesn't exist.",
 +      "apierror-moduledisabled": "The <kbd>$1</kbd> module has been disabled.",
 +      "apierror-multival-only-one-of": "{{PLURAL:$3|Only|Only one of}} $2 is allowed for parameter <var>$1</var>.",
 +      "apierror-multival-only-one": "Only one value is allowed for parameter <var>$1</var>.",
 +      "apierror-multpages": "<var>$1</var> may only be used with a single page.",
 +      "apierror-mustbeloggedin-changeauth": "You must be logged in to change authentication data.",
 +      "apierror-mustbeloggedin-generic": "You must be logged in.",
 +      "apierror-mustbeloggedin-linkaccounts": "You must be logged in to link accounts.",
 +      "apierror-mustbeloggedin-removeauth": "You must be logged in to remove authentication data.",
 +      "apierror-mustbeloggedin-uploadstash": "The upload stash is only available to logged-in users.",
 +      "apierror-mustbeloggedin": "You must be logged in to $1.",
 +      "apierror-mustbeposted": "The <kbd>$1</kbd> module requires a POST request.",
 +      "apierror-mustpostparams": "The following {{PLURAL:$2|parameter was|parameters were}} found in the query string, but must be in the POST body: $1.",
 +      "apierror-noapiwrite": "Editing of this wiki through the API is disabled. Make sure the <code>$wgEnableWriteAPI=true;</code> statement is included in the wiki's <code>LocalSettings.php</code> file.",
 +      "apierror-nochanges": "No changes were requested.",
 +      "apierror-nodeleteablefile": "No such old version of the file.",
 +      "apierror-no-direct-editing": "Direct editing via API is not supported for content model $1 used by $2.",
 +      "apierror-noedit-anon": "Anonymous users can't edit pages.",
 +      "apierror-noedit": "You don't have permission to edit pages.",
 +      "apierror-noimageredirect-anon": "Anonymous users can't create image redirects.",
 +      "apierror-noimageredirect": "You don't have permission to create image redirects.",
 +      "apierror-nosuchlogid": "There is no log entry with ID $1.",
 +      "apierror-nosuchpageid": "There is no page with ID $1.",
 +      "apierror-nosuchrcid": "There is no recent change with ID $1.",
 +      "apierror-nosuchrevid": "There is no revision with ID $1.",
 +      "apierror-nosuchsection": "There is no section $1.",
 +      "apierror-nosuchsection-what": "There is no section $1 in $2.",
 +      "apierror-nosuchuserid": "There is no user with ID $1.",
 +      "apierror-notarget": "You have not specified a valid target for this action.",
 +      "apierror-notpatrollable": "The revision r$1 can't be patrolled as it's too old.",
 +      "apierror-nouploadmodule": "No upload module set.",
 +      "apierror-opensearch-json-warnings": "Warnings cannot be represented in OpenSearch JSON format.",
 +      "apierror-pagecannotexist": "Namespace doesn't allow actual pages.",
 +      "apierror-pagedeleted": "The page has been deleted since you fetched its timestamp.",
 +      "apierror-paramempty": "The parameter <var>$1</var> may not be empty.",
 +      "apierror-parsetree-notwikitext": "<kbd>prop=parsetree</kbd> is only supported for wikitext content.",
 +      "apierror-parsetree-notwikitext-title": "<kbd>prop=parsetree</kbd> is only supported for wikitext content. $1 uses content model $2.",
 +      "apierror-pastexpiry": "Expiry time \"$1\" is in the past.",
 +      "apierror-permissiondenied": "You don't have permission to $1.",
 +      "apierror-permissiondenied-generic": "Permission denied.",
 +      "apierror-permissiondenied-patrolflag": "You need the <code>patrol</code> or <code>patrolmarks</code> right to request the patrolled flag.",
 +      "apierror-permissiondenied-unblock": "You don't have permission to unblock users.",
 +      "apierror-prefixsearchdisabled": "Prefix search is disabled in Miser Mode.",
 +      "apierror-promised-nonwrite-api": "The <code>Promise-Non-Write-API-Action</code> HTTP header cannot be sent to write-mode API modules.",
 +      "apierror-protect-invalidaction": "Invalid protection type \"$1\".",
 +      "apierror-protect-invalidlevel": "Invalid protection level \"$1\".",
 +      "apierror-ratelimited": "You've exceeded your rate limit. Please wait some time and try again.",
 +      "apierror-readapidenied": "You need read permission to use this module.",
 +      "apierror-readonly": "The wiki is currently in read-only mode.",
 +      "apierror-reauthenticate": "You have not authenticated recently in this session, please reauthenticate.",
 +      "apierror-redirect-appendonly": "You have attempted to edit using the redirect-following mode, which must be used in conjuction with <kbd>section=new</kbd>, <var>prependtext</var>, or <var>appendtext</var>.",
 +      "apierror-revdel-mutuallyexclusive": "The same field cannot be used in both <var>hide</var> and <var>show</var>.",
 +      "apierror-revdel-needtarget": "A target title is required for this RevDel type.",
 +      "apierror-revdel-paramneeded": "At least one value is required for <var>hide</var> and/or <var>show</var>.",
 +      "apierror-revisions-norevids": "The <var>revids</var> parameter may not be used with the list options (<var>$1limit</var>, <var>$1startid</var>, <var>$1endid</var>, <kbd>$1dir=newer</kbd>, <var>$1user</var>, <var>$1excludeuser</var>, <var>$1start</var>, and <var>$1end</var>).",
 +      "apierror-revisions-singlepage": "<var>titles</var>, <var>pageids</var> or a generator was used to supply multiple pages, but the <var>$1limit</var>, <var>$1startid</var>, <var>$1endid</var>, <kbd>$1dir=newer</kbd>, <var>$1user</var>, <var>$1excludeuser</var>, <var>$1start</var>, and <var>$1end</var> parameters may only be used on a single page.",
 +      "apierror-revwrongpage": "r$1 is not a revision of $2.",
 +      "apierror-searchdisabled": "<var>$1</var> search is disabled.",
 +      "apierror-sectionreplacefailed": "Could not merge updated section.",
 +      "apierror-sectionsnotsupported": "Sections are not supported for content model $1.",
 +      "apierror-sectionsnotsupported-what": "Sections are not supported by $1.",
 +      "apierror-show": "Incorrect parameter - mutually exclusive values may not be supplied.",
 +      "apierror-siteinfo-includealldenied": "Cannot view all servers' info unless <var>$wgShowHostNames</var> is true.",
 +      "apierror-sizediffdisabled": "Size difference is disabled in Miser Mode.",
 +      "apierror-spamdetected": "Your edit was refused because it contained a spam fragment: <code>$1</code>.",
 +      "apierror-specialpage-cantexecute": "You don't have permission to view the results of this special page.",
 +      "apierror-stashedfilenotfound": "Could not find the file in the stash: $1.",
 +      "apierror-stashedit-missingtext": "No stashed text found with the given hash.",
 +      "apierror-stashfailed-complete": "Chunked upload is already completed, check status for details.",
 +      "apierror-stashfailed-nosession": "No chunked upload session with this key.",
 +      "apierror-stashfilestorage": "Could not store upload in the stash: $1",
 +      "apierror-stashnosuchfilekey": "No such filekey: $1.",
 +      "apierror-stashpathinvalid": "File key of improper format or otherwise invalid: $1.",
 +      "apierror-stashwrongowner": "Wrong owner: $1",
 +      "apierror-stashzerolength": "File is of zero length, and could not be stored in the stash: $1.",
 +      "apierror-templateexpansion-notwikitext": "Template expansion is only supported for wikitext content. $1 uses content model $2.",
 +      "apierror-toofewexpiries": "$1 expiry {{PLURAL:$1|timestamp was|timestamps were}} provided where $2 {{PLURAL:$2|was|were}} needed.",
 +      "apierror-unknownaction": "The action specified, <kbd>$1</kbd>, is not recognized.",
 +      "apierror-unknownerror-editpage": "Unknown EditPage error: $1.",
 +      "apierror-unknownerror-nocode": "Unknown error.",
 +      "apierror-unknownerror": "Unknown error: \"$1\".",
 +      "apierror-unknownformat": "Unrecognized format \"$1\".",
 +      "apierror-unrecognizedparams": "Unrecognized {{PLURAL:$2|parameter|parameters}}: $1.",
 +      "apierror-unrecognizedvalue": "Unrecognized value for parameter <var>$1</var>: $2.",
 +      "apierror-unsupportedrepo": "Local file repository does not support querying all images.",
 +      "apierror-upload-filekeyneeded": "Must supply a <var>filekey</var> when <var>offset</var> is non-zero.",
 +      "apierror-upload-filekeynotallowed": "Cannot supply a <var>filekey</var> when <var>offset</var> is 0.",
 +      "apierror-upload-inprogress": "Upload from stash already in progress.",
 +      "apierror-upload-missingresult": "No result in status data.",
 +      "apierror-urlparamnormal": "Could not normalize image parameters for $1.",
 +      "apierror-writeapidenied": "You're not allowed to edit this wiki through the API.",
 +
 +      "apiwarn-alldeletedrevisions-performance": "For better performance when generating titles, set <kbd>$1dir=newer</kbd>.",
 +      "apiwarn-badurlparam": "Could not parse <var>$1urlparam</var> for $2. Using only width and height.",
 +      "apiwarn-badutf8": "The value passed for <var>$1</var> contains invalid or non-normalized data. Textual data should be valid, NFC-normalized Unicode without C0 control characters other than HT (\\t), LF (\\n), and CR (\\r).",
 +      "apiwarn-checktoken-percentencoding": "Check that symbols such as \"+\" in the token are properly percent-encoded in the URL.",
 +      "apiwarn-deprecation-deletedrevs": "<kbd>list=deletedrevs</kbd> has been deprecated. Please use <kbd>prop=deletedrevisions</kbd> or <kbd>list=alldeletedrevisions</kbd> instead.",
 +      "apiwarn-deprecation-expandtemplates-prop": "Because no values have been specified for the <var>prop</var> parameter, a legacy format has been used for the output. This format is deprecated, and in the future, a default value will be set for the <var>prop</var> parameter, causing the new format to always be used.",
 +      "apiwarn-deprecation-httpsexpected": "HTTP used when HTTPS was expected.",
 +      "apiwarn-deprecation-login-botpw": "Main-account login via <kbd>action=login</kbd> is deprecated and may stop working without warning. To continue login with <kbd>action=login</kbd>, see [[Special:BotPasswords]]. To safely continue using main-account login, see <kbd>action=clientlogin</kbd>.",
 +      "apiwarn-deprecation-login-nobotpw": "Main-account login via <kbd>action=login</kbd> is deprecated and may stop working without warning. To safely log in, see <kbd>action=clientlogin</kbd>.",
 +      "apiwarn-deprecation-login-token": "Fetching a token via <kbd>action=login</kbd> is deprecated. Use <kbd>action=query&meta=tokens&type=login</kbd> instead.",
 +      "apiwarn-deprecation-parameter": "The parameter <var>$1</var> has been deprecated.",
 +      "apiwarn-deprecation-parse-headitems": "<kbd>prop=headitems</kbd> is deprecated since MediaWiki 1.28. Use <kbd>prop=headhtml</kbd> when creating new HTML documents, or <kbd>prop=modules|jsconfigvars</kbd> when updating a document client-side.",
 +      "apiwarn-deprecation-purge-get": "Use of <kbd>action=purge</kbd> via GET is deprecated. Use POST instead.",
 +      "apiwarn-deprecation-withreplacement": "<kbd>$1</kbd> has been deprecated. Please use <kbd>$2</kbd> instead.",
 +      "apiwarn-difftohidden": "Couldn't diff to r$1: content is hidden.",
 +      "apiwarn-errorprinterfailed": "Error printer failed. Will retry without params.",
 +      "apiwarn-errorprinterfailed-ex": "Error printer failed (will retry without params): $1",
 +      "apiwarn-invalidcategory": "\"$1\" is not a category.",
 +      "apiwarn-invalidtitle": "\"$1\" is not a valid title.",
 +      "apiwarn-invalidxmlstylesheetext": "Stylesheet should have <code>.xsl</code> extension.",
 +      "apiwarn-invalidxmlstylesheet": "Invalid or non-existent stylesheet specified.",
 +      "apiwarn-invalidxmlstylesheetns": "Stylesheet should be in the {{ns:MediaWiki}} namespace.",
 +      "apiwarn-moduleswithoutvars": "Property <kbd>modules</kbd> was set but not <kbd>jsconfigvars</kbd> or <kbd>encodedjsconfigvars</kbd>. Configuration variables are necessary for proper module usage.",
 +      "apiwarn-notfile": "\"$1\" is not a file.",
 +      "apiwarn-nothumb-noimagehandler": "Could not create thumbnail because $1 does not have an associated image handler.",
 +      "apiwarn-parse-nocontentmodel": "No <var>title</var> or <var>contentmodel</var> was given, assuming $1.",
 +      "apiwarn-parse-titlewithouttext": "<var>title</var> used without <var>text</var>, and parsed page properties were requested. Did you mean to use <var>page</var> instead of <var>title</var>?",
 +      "apiwarn-redirectsandrevids": "Redirect resolution cannot be used together with the <var>revids</var> parameter. Any redirects the <var>revids</var> point to have not been resolved.",
 +      "apiwarn-tokennotallowed": "Action \"$1\" is not allowed for the current user.",
 +      "apiwarn-tokens-origin": "Tokens may not be obtained when the same-origin policy is not applied.",
 +      "apiwarn-toomanyvalues": "Too many values supplied for parameter <var>$1</var>: the limit is $2.",
 +      "apiwarn-truncatedresult": "This result was truncated because it would otherwise be larger than the limit of $1 bytes.",
 +      "apiwarn-unclearnowtimestamp": "Passing \"$2\" for timestamp parameter <var>$1</var> has been deprecated. If for some reason you need to explicitly specify the current time without calculating it client-side, use <kbd>now<kbd>.",
 +      "apiwarn-unrecognizedvalues": "Unrecognized {{PLURAL:$3|value|values}} for parameter <var>$1</var>: $2.",
 +      "apiwarn-unsupportedarray": "Parameter <var>$1</var> uses unsupported PHP array syntax.",
 +      "apiwarn-urlparamwidth": "Ignoring width value set in <var>$1urlparam</var> ($2) in favor of width value derived from <var>$1urlwidth</var>/<var>$1urlheight</var> ($3).",
 +      "apiwarn-validationfailed-badchars": "invalid characters in key (only <code>a-z</code>, <code>A-Z</code>, <code>0-9</code>, <code>_</code>, and <code>-</code> are allowed).",
 +      "apiwarn-validationfailed-badpref": "not a valid preference.",
 +      "apiwarn-validationfailed-cannotset": "cannot be set by this module.",
 +      "apiwarn-validationfailed-keytoolong": "key too long (no more than $1 bytes allowed).",
 +      "apiwarn-validationfailed": "Validation error for <kbd>$1</kbd>: $2",
 +      "apiwarn-wgDebugAPI": "<strong>Security Warning</strong>: <var>$wgDebugAPI</var> is enabled.",
 +
 +      "api-feed-error-title": "Error ($1)",
 +      "api-usage-docref": "See $1 for API usage.",
 +      "api-exception-trace": "$1 at $2($3)\n$4",
        "api-credits-header": "Credits",
        "api-credits": "API developers:\n* Yuri Astrakhan (creator, lead developer Sep 2006–Sep 2007)\n* Roan Kattouw (lead developer Sep 2007–2009)\n* Victor Vasiliev\n* Bryan Tong Minh\n* Sam Reed\n* Brad Jorsch (lead developer 2013–present)\n\nPlease send your comments, suggestions and questions to mediawiki-api@lists.wikimedia.org\nor file a bug report at https://phabricator.wikimedia.org/."
  }
        "apihelp-main-param-requestid": "{{doc-apihelp-param|main|requestid}}",
        "apihelp-main-param-servedby": "{{doc-apihelp-param|main|servedby}}",
        "apihelp-main-param-curtimestamp": "{{doc-apihelp-param|main|curtimestamp}}",
 +      "apihelp-main-param-responselanginfo": "{{doc-apihelp-param|main|responselanginfo}}",
        "apihelp-main-param-origin": "{{doc-apihelp-param|main|origin}}",
        "apihelp-main-param-uselang": "{{doc-apihelp-param|main|uselang}}",
 +      "apihelp-main-param-errorformat": "{{doc-apihelp-param|main|errorformat}}",
 +      "apihelp-main-param-errorlang": "{{doc-apihelp-param|main|errorlang}}",
 +      "apihelp-main-param-errorsuselocal": "{{doc-apihelp-param|main|errorsuselocal}}",
        "apihelp-block-description": "{{doc-apihelp-description|block}}",
        "apihelp-block-param-user": "{{doc-apihelp-param|block|user}}",
 +      "apihelp-block-param-userid": "{{doc-apihelp-param|block|userid}}",
        "apihelp-block-param-expiry": "{{doc-apihelp-param|block|expiry}}\n{{doc-important|Do not translate \"5 months\", \"2 weeks\", \"infinite\", \"indefinite\" or \"never\"!}}",
        "apihelp-block-param-reason": "{{doc-apihelp-param|block|reason}}",
        "apihelp-block-param-anononly": "{{doc-apihelp-param|block|anononly}}\n* See also {{msg-mw|ipb-hardblock}}",
        "apihelp-query+imageinfo-paramvalue-prop-archivename": "{{doc-apihelp-paramvalue|query+imageinfo|prop|archivename}}",
        "apihelp-query+imageinfo-paramvalue-prop-bitdepth": "{{doc-apihelp-paramvalue|query+imageinfo|prop|bitdepth}}",
        "apihelp-query+imageinfo-paramvalue-prop-uploadwarning": "{{doc-apihelp-paramvalue|query+imageinfo|prop|uploadwarning}}",
+       "apihelp-query+imageinfo-paramvalue-prop-badfile": "{{doc-apihelp-paramvalue|query+imageinfo|prop|badfile}}",
        "apihelp-query+imageinfo-param-limit": "{{doc-apihelp-param|query+imageinfo|limit}}",
        "apihelp-query+imageinfo-param-start": "{{doc-apihelp-param|query+imageinfo|start}}",
        "apihelp-query+imageinfo-param-end": "{{doc-apihelp-param|query+imageinfo|end}}",
        "apihelp-query+imageinfo-param-extmetadatamultilang": "{{doc-apihelp-param|query+imageinfo|extmetadatamultilang}}",
        "apihelp-query+imageinfo-param-extmetadatafilter": "{{doc-apihelp-param|query+imageinfo|extmetadatafilter}}",
        "apihelp-query+imageinfo-param-urlparam": "{{doc-apihelp-param|query+imageinfo|urlparam}}",
+       "apihelp-query+imageinfo-param-badfilecontexttitle": "{{doc-apihelp-param|query+imageinfo|badfilecontexttitle}}",
        "apihelp-query+imageinfo-param-localonly": "{{doc-apihelp-param|query+imageinfo|localonly}}",
        "apihelp-query+imageinfo-example-simple": "{{doc-apihelp-example|query+imageinfo}}",
        "apihelp-query+imageinfo-example-dated": "{{doc-apihelp-example|query+imageinfo}}",
        "apihelp-query+users-paramvalue-prop-cancreate": "{{doc-apihelp-paramvalue|query+users|prop|cancreate}}",
        "apihelp-query+users-param-attachedwiki": "{{doc-apihelp-param|query+users|attachedwiki}}",
        "apihelp-query+users-param-users": "{{doc-apihelp-param|query+users|users}}",
 +      "apihelp-query+users-param-userids": "{{doc-apihelp-param|query+users|userids}}",
        "apihelp-query+users-param-token": "{{doc-apihelp-param|query+users|token}}",
        "apihelp-query+users-example-simple": "{{doc-apihelp-example|query+users}}",
        "apihelp-query+watchlist-description": "{{doc-apihelp-description|query+watchlist}}",
        "apihelp-unblock-description": "{{doc-apihelp-description|unblock}}",
        "apihelp-unblock-param-id": "{{doc-apihelp-param|unblock|id}}",
        "apihelp-unblock-param-user": "{{doc-apihelp-param|unblock|user}}",
 +      "apihelp-unblock-param-userid": "{{doc-apihelp-param|unblock|userid}}",
        "apihelp-unblock-param-reason": "{{doc-apihelp-param|unblock|reason}}",
        "apihelp-unblock-param-tags": "{{doc-apihelp-param|unblock|tags}}",
        "apihelp-unblock-example-id": "{{doc-apihelp-example|unblock}}",
        "api-help-authmanagerhelper-returnurl": "{{doc-apihelp-param|description=the \"returnurl\" parameter for AuthManager-using API modules|noseealso=1}}",
        "api-help-authmanagerhelper-continue": "{{doc-apihelp-param|description=the \"continue\" parameter for AuthManager-using API modules|noseealso=1}}",
        "api-help-authmanagerhelper-additional-params": "Message to display for AuthManager modules that take additional parameters to populate AuthenticationRequests. Parameters:\n* $1 - AuthManager action used by this module\n* $2 - Module parameter prefix, e.g. \"login\"\n* $3 - Module name, e.g. \"clientlogin\"\n* $4 - Module path, e.g. \"clientlogin\"",
 +      "apierror-allimages-redirect": "{{doc-apierror}}",
 +      "apierror-allpages-generator-redirects": "{{doc-apierror}}",
 +      "apierror-appendnotsupported": "{{doc-apierror}}\n\nParameters:\n* $1 - Content model",
 +      "apierror-articleexists": "{{doc-apierror}}",
 +      "apierror-assertbotfailed": "{{doc-apierror}}",
 +      "apierror-assertnameduserfailed": "{{doc-apierror}}\n\nParameters:\n* $1 - User name passed in.",
 +      "apierror-assertuserfailed": "{{doc-apierror}}",
 +      "apierror-autoblocked": "{{doc-apierror}}",
 +      "apierror-badconfig-resulttoosmall": "{{doc-apierror}}",
 +      "apierror-badcontinue": "{{doc-apierror}}",
 +      "apierror-baddiff": "{{doc-apierror}}",
 +      "apierror-baddiffto": "{{doc-apierror}}\n\nParameters:\n* $1 - Module parameter prefix, e.g. \"bl\".",
 +      "apierror-badformat-generic": "{{doc-apierror}}\n\nParameters:\n* $1 - Content format.\n* $2 - Content model.",
 +      "apierror-badformat": "{{doc-apierror}}\n\nParameters:\n* $1 - Content format.\n* $2 - Content model.\n* $3 - Title using the model.",
 +      "apierror-badgenerator-notgenerator": "{{doc-apierror}}\n\nParameters:\n* $1 - Generator module name.",
 +      "apierror-badgenerator-unknown": "{{doc-apierror}}\n\nParameters:\n* $1 - Generator module name.",
 +      "apierror-badip": "{{doc-apierror}}",
 +      "apierror-badmd5": "{{doc-apierror}}",
 +      "apierror-badmodule-badsubmodule": "{{doc-apierror}}\n\nParameters:\n* $1 - Module path.\n* $2 - Submodule name.",
 +      "apierror-badmodule-nosubmodules": "{{doc-apierror}}\n\nParameters:\n* $1 - Module path.",
 +      "apierror-badparameter": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.",
 +      "apierror-badquery": "{{doc-apierror}}",
 +      "apierror-badtimestamp": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.\n* $2 - Value of the parameter.",
 +      "apierror-badtoken": "{{doc-apierror}}",
 +      "apierror-badupload": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.",
 +      "apierror-badurl": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.\n* $2 - Value of the parameter.",
 +      "apierror-baduser": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.\n* $2 - Value of the parameter.",
 +      "apierror-badvalue-notmultivalue": "{{doc-apierror}}",
 +      "apierror-bad-watchlist-token": "{{doc-apierror}}",
 +      "apierror-blockedfrommail": "{{doc-apierror}}",
 +      "apierror-blocked": "{{doc-apierror}}",
 +      "apierror-botsnotsupported": "{{doc-apierror}}",
 +      "apierror-cannotreauthenticate": "{{doc-apierror}}",
 +      "apierror-cannotviewtitle": "{{doc-apierror}}\n\nParameters:\n* $1 - Title.",
 +      "apierror-cantblock-email": "{{doc-apierror}}",
 +      "apierror-cantblock": "{{doc-apierror}}",
 +      "apierror-cantchangecontentmodel": "{{doc-apierror}}",
 +      "apierror-canthide": "{{doc-apierror}}",
 +      "apierror-cantimport-upload": "{{doc-apierror}}",
 +      "apierror-cantimport": "{{doc-apierror}}",
 +      "apierror-cantoverwrite-sharedfile": "{{doc-apierror}}",
 +      "apierror-cantsend": "{{doc-apierror}}",
 +      "apierror-cantundelete": "{{doc-apierror}}",
 +      "apierror-changeauth-norequest": "{{doc-apierror}}",
 +      "apierror-chunk-too-small": "{{doc-apierror}}\n\nParameters:\n* $1 - Minimum size in bytes.",
 +      "apierror-cidrtoobroad": "{{doc-apierror}}\n\nParameters:\n* $1 - \"IPv4\" or \"IPv6\"\n* $2 - Minimum CIDR mask length.",
 +      "apierror-compare-inputneeded": "{{doc-apierror}}",
 +      "apierror-contentserializationexception": "{{doc-apierror}}\n\nParameters:\n* $1 - Exception text, may end with punctuation. Currently this is probably English, hopefully we'll fix that in the future.",
 +      "apierror-contenttoobig": "{{doc-apierror}}\n\nParameters:\n* $1 - Maximum article size in kilobytes.",
 +      "apierror-copyuploadbaddomain": "{{doc-apierror}}",
 +      "apierror-copyuploadbadurl": "{{doc-apierror}}",
 +      "apierror-create-titleexists": "{{doc-apierror}}",
 +      "apierror-csp-report": "{{doc-apierror}}\n\nParameters:\n* $1 - Error code, e.g. \"toobig\".",
 +      "apierror-databaseerror": "{{doc-apierror}}\n\nParameters:\n* $1 - Exception log ID code. This is meaningless to the end user, but can be used by people with access to the logs to easily find the logged error.",
 +      "apierror-deletedrevs-param-not-1-2": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.\n\nSee also:\n* {{msg-mw|apihelp-query+deletedrevs-description}}",
 +      "apierror-deletedrevs-param-not-3": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.\n\nSee also:\n* {{msg-mw|apihelp-query+deletedrevs-description}}",
 +      "apierror-emptynewsection": "{{doc-apierror}}",
 +      "apierror-emptypage": "{{doc-apierror}}",
 +      "apierror-exceptioncaught": "{{doc-apierror}}\n\nParameters:\n* $1 - Exception log ID code. This is meaningless to the end user, but can be used by people with access to the logs to easily find the logged error.\n* $2 - Exception message, which may end with punctuation. Probably in English.",
 +      "apierror-filedoesnotexist": "{{doc-apierror}}",
 +      "apierror-fileexists-sharedrepo-perm": "{{doc-apierror}}",
 +      "apierror-filenopath": "{{doc-apierror}}",
 +      "apierror-filetypecannotberotated": "{{doc-apierror}}",
 +      "apierror-formatphp": "{{doc-apierror}}",
 +      "apierror-imageusage-badtitle": "{{doc-apierror}}\n\nParameters:\n* $1 - Module name.",
 +      "apierror-import-unknownerror": "{{doc-apierror}}\n\nParameters:\n* $1 - Error message returned by the import, probably in English.",
 +      "apierror-integeroutofrange-abovebotmax": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name\n* $2 - Maximum allowed value\n* $3 - Supplied value",
 +      "apierror-integeroutofrange-abovemax": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name\n* $2 - Maximum allowed value\n* $3 - Supplied value",
 +      "apierror-integeroutofrange-belowminimum": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name\n* $2 - Minimum allowed value\n* $3 - Supplied value",
 +      "apierror-invalidcategory": "{{doc-apierror}}",
 +      "apierror-invalid-chunk": "{{doc-apierror}}",
 +      "apierror-invalidexpiry": "{{doc-apierror}}\n\nParameters:\n* $1 - Value provided.",
 +      "apierror-invalid-file-key": "{{doc-apierror}}",
 +      "apierror-invalidlang": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.",
 +      "apierror-invalidoldimage": "{{doc-apierror}}",
 +      "apierror-invalidparammix-cannotusewith": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name or \"parameter=value\" text.\n* $2 - Parameter name or \"parameter=value\" text.",
 +      "apierror-invalidparammix-mustusewith": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name or \"parameter=value\" text.\n* $2 - Parameter name or \"parameter=value\" text.",
 +      "apierror-invalidparammix-parse-new-section": "{{doc-apierror}}",
 +      "apierror-invalidparammix": "{{doc-apierror}}\n\nParameters:\n* $1 - List of parameter names or \"parameter=value\" text.\n* $2 - Number of parameters.",
 +      "apierror-invalidsection": "{{doc-apierror}}",
 +      "apierror-invalidsha1base36hash": "{{doc-apierror}}",
 +      "apierror-invalidsha1hash": "{{doc-apierror}}",
 +      "apierror-invalidtitle": "{{doc-apierror}}\n\nParameters:\n* $1 - Title that is invalid",
 +      "apierror-invalidurlparam": "{{doc-apierror}}\n\nParameters:\n* $1 - Module parameter prefix, e.g. \"bl\".\n* $2 - Key\n* $3 - Value.",
 +      "apierror-invaliduser": "{{doc-apierror}}\n\nParameters:\n* $1 - User name that is invalid.",
 +      "apierror-maxlag-generic": "{{doc-apierror}}\n\nParameters:\n* $1 - Database is lag in seconds.",
 +      "apierror-maxlag": "{{doc-apierror}}\n\nParameters:\n* $1 - Database lag in seconds.\n* $2 - Database server that is lagged.",
 +      "apierror-mimesearchdisabled": "{{doc-apierror}}",
 +      "apierror-missingcontent-pageid": "{{doc-apierror}}\n\nParameters:\n* $1 - Page ID number.",
 +      "apierror-missingparam-at-least-one-of": "{{doc-apierror}}\n\nParameters:\n* $1 - List of parameter names.\n* $2 - Number of parameters.",
 +      "apierror-missingparam-one-of": "{{doc-apierror}}\n\nParameters:\n* $1 - List of parameter names.\n* $2 - Number of parameters.",
 +      "apierror-missingparam": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.",
 +      "apierror-missingrev-pageid": "{{doc-apierror}}\n\nParameters:\n* $1 - Page ID number.",
 +      "apierror-missingtitle-createonly": "{{doc-apierror}}",
 +      "apierror-missingtitle": "{{doc-apierror}}",
 +      "apierror-missingtitle-byname": "{{doc-apierror}}",
 +      "apierror-moduledisabled": "{{doc-apierror}}\n\nParameters:\n* $1 - Name of the module.",
 +      "apierror-multival-only-one-of": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.\n* $2 - Possible values for the parameter.\n* $3 - Number of values.",
 +      "apierror-multival-only-one": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.",
 +      "apierror-multpages": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name",
 +      "apierror-mustbeloggedin-changeauth": "{{doc-apierror}}",
 +      "apierror-mustbeloggedin-generic": "{{doc-apierror}}",
 +      "apierror-mustbeloggedin-linkaccounts": "{{doc-apierror}}",
 +      "apierror-mustbeloggedin-removeauth": "{{doc-apierror}}",
 +      "apierror-mustbeloggedin-uploadstash": "{{doc-apierror}}",
 +      "apierror-mustbeloggedin": "{{doc-apierror}}\n\nParameters:\n* $1 - One of the action-* messages (for example {{msg-mw|action-edit}}) or other such messages tagged with {{tl|doc-action}} in their documentation\n\nPlease report at [[Support]] if you are unable to properly translate this message. Also see [[phab:T16246]] (now closed) for background.\n\nSee also:\n* {{msg-mw|apierror-permissiondenied}}\n* {{msg-mw|permissionserrorstext-withaction}}",
 +      "apierror-mustbeposted": "{{doc-apierror}}\n\nParameters:\n* $1 - Module name.",
 +      "apierror-mustpostparams": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter names.\n* $2 - Number of parameters.",
 +      "apierror-noapiwrite": "{{doc-apierror}}",
 +      "apierror-nochanges": "{{doc-apierror}}",
 +      "apierror-nodeleteablefile": "{{doc-apierror}}",
 +      "apierror-no-direct-editing": "{{doc-apierror}}\n\nParameters:\n* $1 - Content model.\n* $2 - Title using the model.",
 +      "apierror-noedit-anon": "{{doc-apierror}}",
 +      "apierror-noedit": "{{doc-apierror}}",
 +      "apierror-noimageredirect-anon": "{{doc-apierror}}",
 +      "apierror-noimageredirect": "{{doc-apierror}}",
 +      "apierror-nosuchlogid": "{{doc-apierror}}\n\nParameters:\n* $1 - Log ID number.",
 +      "apierror-nosuchpageid": "{{doc-apierror}}\n\nParameters:\n* $1 - Page ID number.",
 +      "apierror-nosuchrcid": "{{doc-apierror}}\n\nParameters:\n* $1 - RecentChanges ID number.",
 +      "apierror-nosuchrevid": "{{doc-apierror}}\n\nParameters:\n* $1 - Revision ID number.",
 +      "apierror-nosuchsection": "{{doc-apierror}}\n\nParameters:\n* $1 - Section identifier. Probably a number or \"T-\" followed by a number.",
 +      "apierror-nosuchsection-what": "{{doc-apierror}}\n\nParameters:\n* $1 - Section identifier. Probably a number or \"T-\" followed by a number.\n* $2 - Page title, revision ID formatted with {{msg-mw|revid}}, or page ID formatted with {{msg-mw|pageid}}.",
 +      "apierror-nosuchuserid": "{{doc-apierror}}",
 +      "apierror-notarget": "{{doc-apierror}}",
 +      "apierror-notpatrollable": "{{doc-apierror}}\n\nParameters:\n* $1 - Revision ID number.",
 +      "apierror-nouploadmodule": "{{doc-apierror}}",
 +      "apierror-opensearch-json-warnings": "{{doc-apierror}}",
 +      "apierror-pagecannotexist": "{{doc-apierror}}",
 +      "apierror-pagedeleted": "{{doc-apierror}}",
 +      "apierror-paramempty": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.",
 +      "apierror-parsetree-notwikitext": "{{doc-apierror}}",
 +      "apierror-parsetree-notwikitext-title": "{{doc-apierror}}\n\nParameters:\n* $1 - Page title.\n* $2 - Content model.",
 +      "apierror-pastexpiry": "{{doc-apierror}}\n\nParameters:\n* $1 - Supplied expiry time.",
 +      "apierror-permissiondenied": "{{doc-apierror}}\n\nParameters:\n* $1 - One of the action-* messages (for example {{msg-mw|action-edit}}) or other such messages tagged with {{tl|doc-action}} in their documentation\n\nPlease report at [[Support]] if you are unable to properly translate this message. Also see [[phab:T16246]] (now closed) for background.\n\nSee also:\n* {{msg-mw|permissionserrorstext-withaction}}",
 +      "apierror-permissiondenied-generic": "{{doc-apierror}}",
 +      "apierror-permissiondenied-patrolflag": "{{doc-apierror}}\n\nSee also:\n* {{msg-mw|apierror-permissiondenied}}",
 +      "apierror-permissiondenied-unblock": "{{doc-apierror}}\n\nSee also:\n* {{msg-mw|apierror-permissiondenied}}",
 +      "apierror-prefixsearchdisabled": "{{doc-apierror}}",
 +      "apierror-promised-nonwrite-api": "{{doc-apierror}}",
 +      "apierror-protect-invalidaction": "{{doc-apierror}}\n\nParameters:\n* $1 - Supplied protection type.",
 +      "apierror-protect-invalidlevel": "{{doc-apierror}}\n\nParameters:\n* $1 - Supplied protection level.",
 +      "apierror-ratelimited": "{{doc-apierror}}",
 +      "apierror-readapidenied": "{{doc-apierror}}",
 +      "apierror-readonly": "{{doc-apierror}}",
 +      "apierror-reauthenticate": "{{doc-apierror}}",
 +      "apierror-redirect-appendonly": "{{doc-apierror}}",
 +      "apierror-revdel-mutuallyexclusive": "{{doc-apierror}}",
 +      "apierror-revdel-needtarget": "{{doc-apierror}}",
 +      "apierror-revdel-paramneeded": "{{doc-apierror}}",
 +      "apierror-revisions-norevids": "{{doc-apierror}}\n\nParameters:\n* $1 - Module parameter prefix, e.g. \"bl\".",
 +      "apierror-revisions-singlepage": "{{doc-apierror}}\n\nParameters:\n* $1 - Module parameter prefix, e.g. \"bl\".",
 +      "apierror-revwrongpage": "{{doc-apierror}}\n\nParameters:\n* $1 - Revision ID number.\n* $2 - Page title.",
 +      "apierror-searchdisabled": "{{doc-apierror}}\n\nParameters:\n* $1 - Search parameter that is disabled.",
 +      "apierror-sectionreplacefailed": "{{doc-apierror}}",
 +      "apierror-sectionsnotsupported": "{{doc-apierror}}\n\nParameters:\n* $1 - Content model that doesn't support sections.",
 +      "apierror-sectionsnotsupported-what": "{{doc-apierror}}\n\nParameters:\n* $1 - Page title, revision ID formatted with {{msg-mw|revid}}, or page ID formatted with {{msg-mw|pageid}}.",
 +      "apierror-show": "{{doc-apierror}}",
 +      "apierror-siteinfo-includealldenied": "{{doc-apierror}}",
 +      "apierror-sizediffdisabled": "{{doc-apierror}}",
 +      "apierror-spamdetected": "{{doc-apierror}}\n\nParameters:\n* $1 - Matching \"spam filter\".\n\nSee also:\n* {{msg-mw|spamprotectionmatch}}",
 +      "apierror-specialpage-cantexecute": "{{doc-apierror}}",
 +      "apierror-stashedfilenotfound": "{{doc-apierror}}\n\nParameters:\n* $1 - Exception text. Currently this is probably English, hopefully we'll fix that in the future.",
 +      "apierror-stashedit-missingtext": "{{doc-apierror}}",
 +      "apierror-stashfailed-complete": "{{doc-apierror}}",
 +      "apierror-stashfailed-nosession": "{{doc-apierror}}",
 +      "apierror-stashfilestorage": "{{doc-apierror}}\n\nParameters:\n* $1 - Exception text, which may already end with punctuation. Currently this is probably English, hopefully we'll fix that in the future.",
 +      "apierror-stashnosuchfilekey": "{{doc-apierror}}\n\nParameters:\n* $1 - Exception text. Currently this is probably English, hopefully we'll fix that in the future.",
 +      "apierror-stashpathinvalid": "{{doc-apierror}}\n\nParameters:\n* $1 - Exception text. Currently this is probably English, hopefully we'll fix that in the future.",
 +      "apierror-stashwrongowner": "{{doc-apierror}}\n\nParameters:\n* $1 - Exception text, which should already end with punctuation. Currently this is probably English, hopefully we'll fix that in the future.",
 +      "apierror-stashzerolength": "{{doc-apierror}}\n\nParameters:\n* $1 - Exception text. Currently this is probably English, hopefully we'll fix that in the future.",
 +      "apierror-templateexpansion-notwikitext": "{{doc-apierror}}\n\nParameters:\n* $1 - Page title.\n* $2 - Content model.",
 +      "apierror-toofewexpiries": "{{doc-apierror}}\n\nParameters:\n* $1 - Number provided.\n* $2 - Number needed.",
 +      "apierror-unknownaction": "{{doc-apierror}}\n\nParameters:\n* $1 - Action provided.",
 +      "apierror-unknownerror-editpage": "{{doc-apierror}}\n\nParameters:\n* $1 - Error code (an integer).",
 +      "apierror-unknownerror-nocode": "{{doc-apierror}}",
 +      "apierror-unknownerror": "{{doc-apierror}}\n\nParameters:\n* $1 - Error code (possibly a message key) not handled by ApiBase::parseMsg().",
 +      "apierror-unknownformat": "{{doc-apierror}}\n\nParameters:\n* $1 - Format provided.",
 +      "apierror-unrecognizedparams": "{{doc-apierror}}\n\nParameters:\n* $1 - List of parameters.\n* $2 - Number of parameters.",
 +      "apierror-unrecognizedvalue": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.\n* $2 - Parameter value.",
 +      "apierror-unsupportedrepo": "{{doc-apierror}}",
 +      "apierror-upload-filekeyneeded": "{{doc-apierror}}",
 +      "apierror-upload-filekeynotallowed": "{{doc-apierror}}",
 +      "apierror-upload-inprogress": "{{doc-apierror}}",
 +      "apierror-upload-missingresult": "{{doc-apierror}}",
 +      "apierror-urlparamnormal": "{{doc-apierror}}\n\nParameters:\n* $1 - Image title.",
 +      "apierror-writeapidenied": "{{doc-apierror}}",
 +      "apiwarn-alldeletedrevisions-performance": "{{doc-apierror}}\n\nParameters:\n* $1 - Module parameter prefix, e.g. \"bl\".",
 +      "apiwarn-badurlparam": "{{doc-apierror}}\n\nParameters:\n* $1 - Module parameter prefix, e.g. \"bl\".\n* $2 - Image title.",
 +      "apiwarn-badutf8": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.",
 +      "apiwarn-checktoken-percentencoding": "{{doc-apierror}}",
 +      "apiwarn-deprecation-deletedrevs": "{{doc-apierror}}",
 +      "apiwarn-deprecation-expandtemplates-prop": "{{doc-apierror}}",
 +      "apiwarn-deprecation-httpsexpected": "{{doc-apierror}}",
 +      "apiwarn-deprecation-login-botpw": "{{doc-apierror}}",
 +      "apiwarn-deprecation-login-nobotpw": "{{doc-apierror}}",
 +      "apiwarn-deprecation-login-token": "{{doc-apierror}}",
 +      "apiwarn-deprecation-parameter": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.",
 +      "apiwarn-deprecation-parse-headitems": "{{doc-apierror}}",
 +      "apiwarn-deprecation-purge-get": "{{doc-apierror}}",
 +      "apiwarn-deprecation-withreplacement": "{{doc-apierror}}\n\nParameters:\n* $1 - Query string fragment that is deprecated, e.g. \"action=tokens\".\n* $2 - Query string fragment to use instead, e.g. \"action=tokens\".",
 +      "apiwarn-difftohidden": "{{doc-apierror}}\n\nParameters:\n* $1 - Revision ID number.",
 +      "apiwarn-errorprinterfailed": "{{doc-apierror}}",
 +      "apiwarn-errorprinterfailed-ex": "{{doc-apierror}}\n\nParameters:\n* $1 - Exception message, which may already end in punctuation. Probably in English.",
 +      "apiwarn-invalidcategory": "{{doc-apierror}}\n\nParameters:\n* $1 - Supplied category name.",
 +      "apiwarn-invalidtitle": "{{doc-apierror}}\n\nParameters:\n* $1 - Supplied title.",
 +      "apiwarn-invalidxmlstylesheetext": "{{doc-apierror}}",
 +      "apiwarn-invalidxmlstylesheet": "{{doc-apierror}}",
 +      "apiwarn-invalidxmlstylesheetns": "{{doc-apierror}}",
 +      "apiwarn-moduleswithoutvars": "{{doc-apierror}}",
 +      "apiwarn-notfile": "{{doc-apierror}}\n\nParameters:\n* $1 - Supplied file name.",
 +      "apiwarn-nothumb-noimagehandler": "{{doc-apierror}}\n\nParameters:\n* $1 - File name.",
 +      "apiwarn-parse-nocontentmodel": "{{doc-apierror}}\n\nParameters:\n* $1 - Content model being assumed.",
 +      "apiwarn-parse-titlewithouttext": "{{doc-apierror}}",
 +      "apiwarn-redirectsandrevids": "{{doc-apierror}}",
 +      "apiwarn-tokennotallowed": "{{doc-apierror}}\n\nParameters:\n* $1 - Token type being requested, typically named after the action requiring the token.",
 +      "apiwarn-tokens-origin": "{{doc-apierror}}",
 +      "apiwarn-toomanyvalues": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.\n* $2 - Maximum number of values allowed.",
 +      "apiwarn-truncatedresult": "{{doc-apierror}}\n\nParameters:\n* $1 - Size limit in bytes.",
 +      "apiwarn-unclearnowtimestamp": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.\n* $2 - Supplied value.",
 +      "apiwarn-unrecognizedvalues": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.\n* $2 - List of unknown values supplied.\n* $3 - Number of unknown values.",
 +      "apiwarn-unsupportedarray": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.",
 +      "apiwarn-urlparamwidth": "{{doc-apierror}}\n\nParameters:\n* $1 - Module parameter prefix, e.g. \"bl\".\n* $2 - Width being ignored.\n* $3 - Width being used.",
 +      "apiwarn-validationfailed-badchars": "{{doc-apierror}}\n\nUsed with {{msg-mw|apiwarn-validationfailed}}.",
 +      "apiwarn-validationfailed-badpref": "{{doc-apierror}}\n\nUsed with {{msg-mw|apiwarn-validationfailed}}.",
 +      "apiwarn-validationfailed-cannotset": "{{doc-apierror}}\n\nUsed with {{msg-mw|apiwarn-validationfailed}}.",
 +      "apiwarn-validationfailed-keytoolong": "{{doc-apierror}}\n\nUsed with {{msg-mw|apiwarn-validationfailed}}.\n\nParameters:\n* $1 - Maximum allowed key length in bytes.",
 +      "apiwarn-validationfailed": "{{doc-apierror}}\n\nParameters:\n* $1 - User preference name.\n* $2 - Failure message, such as {{msg-mw|apiwarn-validationfailed-badpref}}. Probably already ends with punctuation",
 +      "apiwarn-wgDebugAPI": "{{doc-apierror}}",
 +      "api-feed-error-title": "Used as a feed item title when an error occurs in <kbd>action=feedwatchlist</kbd>.\n\nParameters:\n* $1 - API error code\n{{Identical|Error}}",
 +      "api-usage-docref": "\n\nParameters:\n* $1 - URL of the API auto-generated documentation.",
 +      "api-exception-trace": "\n\nParameters:\n* $1 - Exception class.\n* $2 - File from which the exception was thrown.\n* $3 - Line number from which the exception was thrown.\n* $4 - Exception backtrace.",
        "api-credits-header": "Header for the API credits section in the API help output\n{{Identical|Credit}}",
        "api-credits": "API credits text, displayed in the API help output"
  }