--- /dev/null
+warmup: true
+runs: 3
+scenarios:
+ # View the Main Page without redirect
+ - url: "{MW_SERVER}{MW_SCRIPT_PATH}/index.php?mainpage"
+ viewport:
+ width: 1100
+ height: 700
+ reports:
+ - navtiming
+ - paint
+ - transfer
+ probes:
+ - screenshot
+ - trace
+ # alerts:
+ # navtiming/loadEventEnd: 10%
node_modules/
/tests/phpunit/phpunit.phar
/tests/selenium/log
+.eslintcache
# Composer
/vendor
grunt.initConfig( {
eslint: {
options: {
- reportUnusedDisableDirectives: true
+ reportUnusedDisableDirectives: true,
+ cache: true
},
all: [
'**/*.js',
deletion will be processed via the job queue.
* action=setnotificationtimestamp will now update the watchlist asynchronously
if entirewatchlist is set, so updates may not be visible immediately
+* Block info will be added to "blocked" errors from more modules.
+* (T216245) Autoblocks will now be spread by action=edit and action=move.
=== Action API internal changes in 1.33 ===
* A number of deprecated methods for API documentation, intended for overriding
hyphen. Methods such as ApiBase::dieWithError() and
ApiMessageTrait::setApiCode() will throw an InvalidArgumentException if
passed a bad code.
+* ApiBase::checkTitleUserPermissions() now takes an options array as its third
+ parameter. Passing a User object or null is deprecated.
=== Languages updated in 1.33 ===
MediaWiki supports over 350 languages. Many localisations are updated regularly.
* Removed deprecated class property WikiRevision::$importer.
* ResourceLoaderFileModule::readStyleFiles() now requires its $context
parameter.
+* The ChangeList::insertArticleLink() method, that was deprecated in 1.27, has
+ been removed.
+* MessageBlobStore::__construct() now requires its $rl parameter.
=== Deprecations in 1.33 ===
* The configuration option $wgUseESI has been deprecated, and is expected
Use require( 'mediawiki.language.specialCharacters' ) instead.
* ChangeTags::purgeTagUsageCache() has been deprecated, and is expected to be
removed in a future release.
+* Passing a User object or null as the third parameter to
+ ApiBase::checkTitleUserPermissions() has been deprecated. Pass an array
+ [ 'user' => $user ] instead.
=== Other changes in 1.33 ===
* (T201747) Html::openElement() warns if given an element name with a space
/** @var int[][][] Cache for self::filterIDs() */
private static $filterIDsCache = [];
+ /** $var array Map of web UI block messages to corresponding API messages and codes */
+ private static $blockMsgMap = [
+ 'blockedtext' => [ 'apierror-blocked', 'blocked' ],
+ 'blockedtext-partial' => [ 'apierror-blocked', 'blocked' ],
+ 'autoblockedtext' => [ 'apierror-autoblocked', 'autoblocked' ],
+ 'systemblockedtext' => [ 'apierror-systemblocked', 'blocked' ],
+ ];
+
/** @var ApiMain */
private $mMainModule;
/** @var string */
$status = Status::newGood();
foreach ( $errors as $error ) {
- if ( is_array( $error ) && $error[0] === 'blockedtext' && $user->getBlock() ) {
- $status->fatal( ApiMessage::create(
- 'apierror-blocked',
- 'blocked',
- [ 'blockinfo' => ApiQueryUserInfo::getBlockInfo( $user->getBlock() ) ]
- ) );
- } elseif ( is_array( $error ) && $error[0] === 'blockedtext-partial' && $user->getBlock() ) {
- $status->fatal( ApiMessage::create(
- 'apierror-blocked-partial',
- 'blocked',
- [ 'blockinfo' => ApiQueryUserInfo::getBlockInfo( $user->getBlock() ) ]
- ) );
- } elseif ( is_array( $error ) && $error[0] === 'autoblockedtext' && $user->getBlock() ) {
- $status->fatal( ApiMessage::create(
- 'apierror-autoblocked',
- 'autoblocked',
- [ 'blockinfo' => ApiQueryUserInfo::getBlockInfo( $user->getBlock() ) ]
- ) );
- } elseif ( is_array( $error ) && $error[0] === 'systemblockedtext' && $user->getBlock() ) {
- $status->fatal( ApiMessage::create(
- 'apierror-systemblocked',
- 'blocked',
+ if ( is_array( $error ) && isset( self::$blockMsgMap[$error[0]] ) && $user->getBlock() ) {
+ list( $msg, $code ) = self::$blockMsgMap[$error[0]];
+ $status->fatal( ApiMessage::create( $msg, $code,
[ 'blockinfo' => ApiQueryUserInfo::getBlockInfo( $user->getBlock() ) ]
) );
} else {
return $status;
}
+ /**
+ * Add block info to block messages in a Status
+ * @since 1.33
+ * @param StatusValue $status
+ * @param User|null $user
+ */
+ public function addBlockInfoToStatus( StatusValue $status, User $user = null ) {
+ if ( $user === null ) {
+ $user = $this->getUser();
+ }
+
+ foreach ( self::$blockMsgMap as $msg => list( $apiMsg, $code ) ) {
+ if ( $status->hasMessage( $msg ) && $user->getBlock() ) {
+ $status->replaceMessage( $msg, ApiMessage::create( $apiMsg, $code,
+ [ 'blockinfo' => ApiQueryUserInfo::getBlockInfo( $user->getBlock() ) ]
+ ) );
+ }
+ }
+ }
+
/**
* Call wfTransactionalTimeLimit() if this request was POSTed
* @since 1.26
$status = $newStatus;
}
+ $this->addBlockInfoToStatus( $status );
throw new ApiUsageException( $this, $status );
}
/**
* Helper function for permission-denied errors
* @since 1.29
+ * @since 1.33 Changed the third parameter from $user to $options.
* @param Title $title
* @param string|string[] $actions
- * @param User|null $user
+ * @param array $options Additional options
+ * - user: (User) User to use rather than $this->getUser()
+ * - autoblock: (bool, default false) Whether to spread autoblocks
+ * For compatibility, passing a User object is treated as the value for the 'user' option.
* @throws ApiUsageException if the user doesn't have all of the rights.
*/
- public function checkTitleUserPermissions( Title $title, $actions, $user = null ) {
- if ( !$user ) {
- $user = $this->getUser();
+ public function checkTitleUserPermissions( Title $title, $actions, $options = [] ) {
+ if ( !is_array( $options ) ) {
+ wfDeprecated( '$user as the third parameter to ' . __METHOD__, '1.33' );
+ $options = [ 'user' => $options ];
}
+ $user = $options['user'] ?? $this->getUser();
$errors = [];
foreach ( (array)$actions as $action ) {
$this->trackBlockNotices( $errors );
}
+ if ( !empty( $options['autoblock'] ) ) {
+ $user->spreadAnyEditBlock();
+ }
+
$this->dieStatus( $this->errorArrayToStatus( $errors, $user ) );
}
}
// Now let's check whether we're even allowed to do this
$this->checkTitleUserPermissions(
$titleObj,
- $titleObj->exists() ? 'edit' : [ 'edit', 'create' ]
+ $titleObj->exists() ? 'edit' : [ 'edit', 'create' ],
+ [ 'autoblock' => true ]
);
$toMD5 = $params['text'];
$status = $this->movePage( $fromTitle, $toTitle, $params['reason'], !$params['noredirect'],
$params['tags'] ?: [] );
if ( !$status->isOK() ) {
+ $user->spreadAnyEditBlock();
$this->dieStatus( $status );
}
*/
class MessageBlobStore implements LoggerAwareInterface {
- /* @var ResourceLoader|null */
+ /* @var ResourceLoader */
private $resourceloader;
/**
protected $wanCache;
/**
- * @param ResourceLoader|null $rl
+ * @param ResourceLoader $rl
* @param LoggerInterface|null $logger
*/
- public function __construct( ResourceLoader $rl = null, LoggerInterface $logger = null ) {
+ public function __construct( ResourceLoader $rl, LoggerInterface $logger = null ) {
$this->resourceloader = $rl;
$this->logger = $logger ?: new NullLogger();
- $this->wanCache = ObjectCache::getMainWANInstance();
+ $this->wanCache = MediaWikiServices::getInstance()->getMainWANObjectCache();
}
/**
* @return ResourceLoader
*/
protected function getResourceLoader() {
- // Back-compat: This class supports instantiation without a ResourceLoader object.
- // Lazy-initialise this property because most callers don't need it.
- if ( $this->resourceloader === null ) {
- $this->logger->warning( __CLASS__ . ' created without a ResourceLoader instance' );
- $this->resourceloader = MediaWikiServices::getInstance()->getResourceLoader();
- }
return $this->resourceloader;
}
# HACK: If using a null (i.e. disabled) storage backend, we
# can't write to the MessageBlobStore either
if ( $purgeBlobs && !$this->store instanceof LCStoreNull ) {
- $blobStore = new MessageBlobStore();
+ $blobStore = new MessageBlobStore(
+ MediaWikiServices::getInstance()->getResourceLoader()
+ );
$blobStore->clear();
}
}
' <span class="mw-changeslist-separator"></span> ';
}
- /**
- * @param string &$s Article link will be appended to this string, in place.
- * @param RecentChange $rc
- * @param bool $unpatrolled
- * @param bool $watched
- * @deprecated since 1.27, use getArticleLink instead.
- */
- public function insertArticleLink( &$s, RecentChange $rc, $unpatrolled, $watched ) {
- $s .= $this->getArticleLink( $rc, $unpatrolled, $watched );
- }
-
/**
* @param RecentChange &$rc
* @param bool $unpatrolled
* @since 1.16.3
*/
class IcuCollation extends Collation {
- const FIRST_LETTER_VERSION = 3;
+ const FIRST_LETTER_VERSION = 4;
/** @var Collator */
private $primaryCollator;
'tl' => [ "Ñ", "Ng" ], // not in libicu
'to' => [ "Ng", "ʻ" ],
'tr' => [ "Ç", "Ğ", "İ", "Ö", "Ş", "Ü" ],
+ '-tr' => [ "ı" ],
'tt' => [ "Ә", "Ө", "Ү", "Җ", "Ң", "Һ" ], // not in libicu
'uk' => [ "Ґ", "Ь" ],
'uz' => [ "Ch", "G'", "Ng", "O'", "Sh" ], // not in libicu
// Try cache
if ( !$this->mRefreshCache ) {
$difftext = $cache->get( $key );
- if ( $difftext ) {
+ if ( is_string( $difftext ) ) {
wfIncrStats( 'diff_cache.hit' );
$difftext = $this->localiseDiff( $difftext );
$difftext .= "\n<!-- diff cache key $key -->\n";
/**
* Perform database upgrades
*
+ * @suppress SecurityCheck-XSS Escaping provided by $this->outputHandler
* @return bool
*/
public function doUpgrade() {
}
// ResourceLoader: Message cache
- $blobStore = new MessageBlobStore();
+ $blobStore = new MessageBlobStore(
+ MediaWikiServices::getInstance()->getResourceLoader()
+ );
$blobStore->clear();
// ResourceLoader: File-dependency cache
/**
* Installs the auto-detected extensions.
*
+ * @suppress SecurityCheck-OTHER It thinks $exts/$IP is user controlled but they are not.
* @return Status
*/
protected function includeExtensions() {
"config-env-hhvm": "HHVM $1 er uppsett.",
"config-apc": "[https://secure.php.net/apc APC] er uppsett",
"config-wincache": "[https://www.iis.net/downloads/microsoft/wincache-extension WinCache] er uppsett",
- "config-diff3-bad": "GNU diff3 fannst ekki.",
+ "config-diff3-bad": "GNU diff3 textasamanburðartólið fannst ekki. Þú getur hunsað þetta núna, en þú gætir lent oftar í breytingaárekstrum.",
"config-using-server": "Nota \"<nowiki>$1</nowiki>\" sem heiti á þjóni.",
"config-using-uri": "Nota \"<nowiki>$1$2</nowiki>\" sem slóð á þjón.",
"config-db-type": "Tegund gagnagrunns:",
"config-db-host": "Netþjónn gagnagrunns:",
- "config-db-name": "Heiti gagnagrunns:",
+ "config-db-name": "Heiti gagnagrunns (engin bandstrik):",
"config-db-name-oracle": "Gagnagrunnsskema:",
"config-db-username": "Notandanafn á gagnagrunni:",
"config-db-password": "Lykilorð gagnagrunns:",
"config-db-port": "Gátt gagnagrunns:",
"config-sqlite-dir": "Gagnamappa SQLite:",
- "config-type-mysql": "MySQL (eða samhæft)",
+ "config-type-mysql": "MariaDB, MySQL, eða samhæft",
"config-type-postgres": "PostgreSQL",
"config-type-sqlite": "SQLite",
"config-type-oracle": "Oracle",
"config-type-mssql": "Microsoft SQL Server",
- "config-header-mysql": "Stillingar MySQL",
+ "config-header-mysql": "Stillingar MariaDB/MySQL",
"config-header-postgres": "Stillingar PostgreSQL",
"config-header-sqlite": "Stillingar SQLite",
"config-header-oracle": "Stillingar Oracle",
"config-show-table-status": "<code>SHOW TABLE STATUS</code> beiðni mistókst!",
"config-db-web-account": "Gagnagrunnsreikningur fyrir vefaðgang",
"config-mysql-engine": "Gagnagrunnshýsing:",
- "config-mysql-innodb": "InnoDB",
+ "config-mysql-innodb": "InnoDB (mælt með)",
"config-mysql-myisam": "MyISAM",
"config-mssql-auth": "Tegund auðkenningar:",
"config-mssql-sqlauth": "SQL Server auðkenning",
/**
* This function should *not* be called outside of JobQueueDB
*
+ * @suppress SecurityCheck-SQLInjection Bug in phan-taint-check handling bulk inserts
* @param IDatabase $dbw
* @param IJobSpecification[] $jobs
* @param int $flags
curl_setopt( $ch, CURLOPT_HEADERFUNCTION,
function ( $ch, $header ) use ( &$req ) {
- if ( !empty( $req['flags']['relayResponseHeaders'] ) ) {
+ if ( !empty( $req['flags']['relayResponseHeaders'] ) && trim( $header ) !== '' ) {
header( $header );
}
$length = strlen( $header );
/** Seconds to keep lock keys around */
const LOCK_TTL = 10;
+ /** Seconds to no-op key set() calls to avoid large blob I/O stampedes */
+ const COOLOFF_TTL = 1;
/** Default remaining TTL at which to consider pre-emptive regeneration */
const LOW_TTL = 30;
/** Tiny negative float to use when CTL comes up >= 0 due to clock skew */
const TINY_NEGATIVE = -0.000001;
+ /** Seconds of delay after get() where set() storms are a consideration with 'lockTSE' */
+ const SET_DELAY_HIGH_SEC = 0.1;
+
/** Cache format version number */
const VERSION = 1;
const INTERIM_KEY_PREFIX = 'WANCache:i:';
const TIME_KEY_PREFIX = 'WANCache:t:';
const MUTEX_KEY_PREFIX = 'WANCache:m:';
+ const COOLOFF_KEY_PREFIX = 'WANCache:c:';
const PURGE_VAL_PREFIX = 'PURGED:';
* is useful if thousands or millions of keys depend on the same entity. The entity can
* simply have its "check" key updated whenever the entity is modified.
* Default: [].
- * - graceTTL: If the key is invalidated (by "checkKeys") less than this many seconds ago,
- * consider reusing the stale value. The odds of a refresh becomes more likely over time,
- * becoming certain once the grace period is reached. This can reduce traffic spikes
- * when millions of keys are compared to the same "check" key and touchCheckKey() or
- * resetCheckKey() is called on that "check" key. This option is not useful for the
- * case of the key simply expiring on account of its TTL (use "lowTTL" instead).
+ * - graceTTL: If the key is invalidated (by "checkKeys"/"touchedCallback") less than this
+ * many seconds ago, consider reusing the stale value. The odds of a refresh becomes
+ * more likely over time, becoming certain once the grace period is reached. This can
+ * reduce traffic spikes when millions of keys are compared to the same "check" key and
+ * touchCheckKey() or resetCheckKey() is called on that "check" key. This option is not
+ * useful for avoiding traffic spikes in the case of the key simply expiring on account
+ * of its TTL (use "lowTTL" instead).
* Default: WANObjectCache::GRACE_TTL_NONE.
- * - lockTSE: If the key is tombstoned or invalidated (by "checkKeys") less than this many
- * seconds ago, try to have a single thread handle cache regeneration at any given time.
- * Other threads will try to use stale values if possible. If, on miss, the time since
- * expiration is low, the assumption is that the key is hot and that a stampede is worth
- * avoiding. Setting this above WANObjectCache::HOLDOFF_TTL makes no difference. The
- * higher this is set, the higher the worst-case staleness can be. This option does not
- * by itself handle the case of the key simply expiring on account of its TTL, so make
- * sure that "lowTTL" is not disabled when using this option.
+ * - lockTSE: If the key is tombstoned or invalidated (by "checkKeys"/"touchedCallback")
+ * less than this many seconds ago, try to have a single thread handle cache regeneration
+ * at any given time. Other threads will use stale values if possible. If, on miss,
+ * the time since expiration is low, the assumption is that the key is hot and that a
+ * stampede is worth avoiding. Note that if the key falls out of cache then concurrent
+ * threads will all run the callback on cache miss until the value is saved in cache.
+ * The only stampede protection in that case is from duplicate cache sets when the
+ * callback takes longer than WANObjectCache::SET_DELAY_HIGH_SEC seconds; consider
+ * using "busyValue" if such stampedes are a problem. Note that the higher "lockTSE" is
+ * set, the higher the worst-case staleness of returned values can be. Also note that
+ * this option does not by itself handle the case of the key simply expiring on account
+ * of its TTL, so make sure that "lowTTL" is not disabled when using this option. Avoid
+ * combining this option with delete() as it can always cause a stampede due to their
+ * being no stale value available until after a thread completes the callback.
* Use WANObjectCache::TSE_NONE to disable this logic.
* Default: WANObjectCache::TSE_NONE.
* - busyValue: If no value exists and another thread is currently regenerating it, use this
// This avoids stampedes on eviction or preemptive regeneration taking too long.
( $busyValue !== null && $value === false );
- $lockAcquired = false;
+ $hasLock = false;
if ( $useMutex ) {
// Acquire a datacenter-local non-blocking lock
if ( $this->cache->add( self::MUTEX_KEY_PREFIX . $key, 1, self::LOCK_TTL ) ) {
// Lock acquired; this thread will recompute the value and update cache
- $lockAcquired = true;
+ $hasLock = true;
} elseif ( $this->isValid( $value, $versioned, $asOf, $minTime ) ) {
// Lock not acquired and a stale value exists; use the stale value
$this->stats->increment( "wanobjectcache.$kClass.hit.stale" );
$valueIsCacheable = ( $value !== false && $ttl >= 0 );
if ( $valueIsCacheable ) {
+ $ago = max( $this->getCurrentTime() - $preCallbackTime, 0.0 );
if ( $isKeyTombstoned ) {
- // When delete() is called, writes are write-holed by the tombstone,
- // so use a special INTERIM key to pass the new value among threads.
- $tempTTL = max( self::INTERIM_KEY_TTL, (int)$lockTSE ); // set() expects seconds
- $newAsOf = $this->getCurrentTime();
- $wrapped = $this->wrap( $value, $tempTTL, $newAsOf );
- // Avoid using set() to avoid pointless mcrouter broadcasting
- $this->setInterimValue( $key, $wrapped, $tempTTL );
- } elseif ( !$useMutex || $lockAcquired ) {
- // Save the value unless a lock-winning thread is already expected to do that
- $setOpts['lockTSE'] = $lockTSE;
- $setOpts['staleTTL'] = $staleTTL;
- // Use best known "since" timestamp if not provided
- $setOpts += [ 'since' => $preCallbackTime ];
- // Update the cache; this will fail if the key is tombstoned
- $this->set( $key, $value, $ttl, $setOpts );
+ if ( $this->checkAndSetCooloff( $key, $kClass, $ago, $lockTSE, $hasLock ) ) {
+ // When delete() is called, writes are write-holed by the tombstone,
+ // so use a special INTERIM key to pass the new value among threads.
+ $tempTTL = max( self::INTERIM_KEY_TTL, (int)$lockTSE ); // set() expects seconds
+ $newAsOf = $this->getCurrentTime();
+ $wrapped = $this->wrap( $value, $tempTTL, $newAsOf );
+ // Avoid using set() to avoid pointless mcrouter broadcasting
+ $this->setInterimValue( $key, $wrapped, $tempTTL );
+ }
+ } elseif ( !$useMutex || $hasLock ) {
+ if ( $this->checkAndSetCooloff( $key, $kClass, $ago, $lockTSE, $hasLock ) ) {
+ // Save the value unless a lock-winning thread is already expected to do that
+ $setOpts['lockTSE'] = $lockTSE;
+ $setOpts['staleTTL'] = $staleTTL;
+ // Use best known "since" timestamp if not provided
+ $setOpts += [ 'since' => $preCallbackTime ];
+ // Update the cache; this will fail if the key is tombstoned
+ $this->set( $key, $value, $ttl, $setOpts );
+ }
}
}
- if ( $lockAcquired ) {
+ if ( $hasLock ) {
// Avoid using delete() to avoid pointless mcrouter broadcasting
$this->cache->changeTTL( self::MUTEX_KEY_PREFIX . $key, (int)$preCallbackTime - 60 );
}
return $value;
}
+ /**
+ * @param string $key
+ * @param string $kClass
+ * @param float $elapsed Seconds spent regenerating the value
+ * @param float $lockTSE
+ * @param $hasLock bool
+ * @return bool Whether it is OK to proceed with a key set operation
+ */
+ private function checkAndSetCooloff( $key, $kClass, $elapsed, $lockTSE, $hasLock ) {
+ // If $lockTSE is set, the lock was bypassed because there was no stale/interim value,
+ // and $elapsed indicates that regeration is slow, then there is a risk of set()
+ // stampedes with large blobs. With a typical scale-out infrastructure, CPU and query
+ // load from $callback invocations is distributed among appservers and replica DBs,
+ // but cache operations for a given key route to a single cache server (e.g. striped
+ // consistent hashing).
+ if ( $lockTSE < 0 || $hasLock ) {
+ return true; // either not a priori hot or thread has the lock
+ } elseif ( $elapsed <= self::SET_DELAY_HIGH_SEC ) {
+ return true; // not enough time for threads to pile up
+ }
+
+ $this->cache->clearLastError();
+ if (
+ !$this->cache->add( self::COOLOFF_KEY_PREFIX . $key, 1, self::COOLOFF_TTL ) &&
+ // Don't treat failures due to I/O errors as the key being in cooloff
+ $this->cache->getLastError() === BagOStuff::ERR_NONE
+ ) {
+ $this->stats->increment( "wanobjectcache.$kClass.cooloff_bounce" );
+
+ return false;
+ }
+
+ return true;
+ }
+
/**
* @param mixed $value
* @param float $asOf
/**
* Replace internal links
+ * @suppress SecurityCheck-XSS Gets confused with $entry['pdbk']
* @param string &$text
*/
protected function replaceInternal( &$text ) {
/**
* Replace interwiki links
* @param string &$text
+ * @suppress SecurityCheck-XSS Gets confused with $this->interwikis['pdbk']
*/
protected function replaceInterwiki( &$text ) {
if ( empty( $this->interwikis ) ) {
// Add the QUnit testrunner as implicit dependency to extension test suites.
foreach ( $testModules['qunit'] as &$module ) {
+ // Shuck any single-module dependency as an array
+ if ( is_string( $module['dependencies'] ) ) {
+ $module['dependencies'] = [ $module['dependencies'] ];
+ }
+
$module['dependencies'][] = 'test.mediawiki.qunit.testrunner';
}
$explicitlyDefinedTags = array_fill_keys( ChangeTags::listExplicitlyDefinedTags(), 0 );
$softwareActivatedTags = array_fill_keys( ChangeTags::listSoftwareActivatedTags(), 0 );
- // Hit counts disabled for perf reasons, see T169997
- /*
$tagStats = ChangeTags::tagUsageStatistics();
$tagHitCounts = array_merge( $explicitlyDefinedTags, $softwareActivatedTags, $tagStats );
- // Sort by hits
- arsort( $tagHitCounts );
- */
- $tagHitCounts = array_merge( $explicitlyDefinedTags, $softwareActivatedTags );
+ // Sort by hits (disabled for now)
+ //arsort( $tagHitCounts );
// Build the list and data
$result = [];
foreach ( $tagHitCounts as $tagName => $hits ) {
if (
- // Only get active tags
- isset( $explicitlyDefinedTags[ $tagName ] ) ||
- isset( $softwareActivatedTags[ $tagName ] )
+ (
+ // Only get active tags
+ isset( $explicitlyDefinedTags[ $tagName ] ) ||
+ isset( $softwareActivatedTags[ $tagName ] )
+ ) &&
+ // Only get tags with more than 0 hits
+ $hits > 0
) {
$result[] = [
'name' => $tagName,
}
$this->opts = ContribsPager::processDateFilter( $this->opts );
+ if ( $this->opts['namespace'] < NS_MAIN ) {
+ $this->getOutput()->wrapWikiMsg(
+ "<div class=\"mw-negative-namespace-not-supported error\">\n\$1\n</div>",
+ [ 'negative-namespace-not-supported' ]
+ );
+ $out->addHTML( $this->getForm() );
+ return;
+ }
+
$feedType = $request->getVal( 'feed' );
$feedParams = [
];
$options = [];
if ( $data !== null ) {
- $options['ORDER BY'] = 'qcc_title ' . $data['dir'];
+ $options['ORDER BY'] = 'qcc_title ' . $data['order'];
$options['LIMIT'] = $data['limit'];
$conds = array_merge( $conds, $data['conds'] );
}
class BlockListPager extends TablePager {
protected $conds;
- protected $page;
/**
* Array of restrictions.
* @param array $conds
*/
public function __construct( $page, $conds ) {
- $this->page = $page;
$this->conds = $conds;
$this->mDefaultDirection = IndexPager::DIR_DESCENDING;
parent::__construct( $page->getContext() );
*/
class NewPagesPager extends ReverseChronologicalPager {
- // Stored opts
+ /**
+ * @var FormOptions
+ */
protected $opts;
/**
- * @var HTMLForm
+ * @var SpecialNewpages
*/
protected $mForm;
+ /**
+ * @param SpecialNewpages $form
+ * @param FormOptions $opts
+ */
public function __construct( $form, FormOptions $opts ) {
parent::__construct( $form->getContext() );
$this->mForm = $form;
class ProtectedPagesPager extends TablePager {
- public $mForm, $mConds;
+ public $mConds;
private $type, $level, $namespace, $sizetype, $size, $indefonly, $cascadeonly, $noredirect;
/**
private $linkRenderer;
/**
- * @param SpecialProtectedpages $form
+ * @param SpecialPage $form
* @param array $conds
* @param string $type
* @param string $level
$sizetype, $size, $indefonly, $cascadeonly, $noredirect,
LinkRenderer $linkRenderer
) {
- $this->mForm = $form;
$this->mConds = $conds;
$this->type = ( $type ) ? $type : 'edit';
$this->level = $level;
'gan' => '贛語', # Gan (multiple scripts - defaults to Traditional)
'gan-hans' => "赣语(简体)\u{200E}", # Gan (Simplified Han)
'gan-hant' => "贛語(繁體)\u{200E}", # Gan (Traditional Han)
- 'gcr' => 'kréyòl gwiyanè', # Guianan Creole
+ 'gcr' => 'kriyòl gwiyannen', # Guianan Creole
'gd' => 'Gàidhlig', # Scots Gaelic
'gl' => 'galego', # Galician
'glk' => 'گیلکی', # Gilaki
"mergehistory-list": "ڤیرگار آلشدکاریٱل سٱریٱک بیڌنی",
"mergehistory-go": "دیاری کردن آلشدکاریٱل سٱریٱک بیڌنی",
"mergehistory-submit": "سر یٱک کردن ڤانیاریٱل",
+ "mergehistory-fail-invalid-source": "سرچشمٱ بٱلگاْ نادیاراْ.",
+ "mergehistory-fail-invalid-dest": "بٱلگاْ مٱقسٱڌ نادیاراْ.",
"mergehistory-reason": "دلیل:",
"mergelog": "سیائاْ ؤریٱک",
"revertmerge": "سٱڤا کردن",
"history-title": "دوڤارتاْ دیڌن ڤیرگار $1",
"difference-title": "فٱرخ میٛنجقا ڤاناٛیریا \"$1\"",
- "difference-multipage": "(فٱخ میٛنجقا بٱلگاْیٱل)",
+ "difference-title-multipage": "فٱرخ میٛنجقا بٱلگاْیٱل \"$1\" و \"$2\"",
+ "difference-multipage": "(فٱرخ میٛنجقا بٱلگاْیٱل)",
"lineno": "خٱت $1:",
"compareselectedversions": "کنار یٱک ناهاڌن ڤانیٱریٱل گولاْڤورچین ڤابیڌاْ",
"editundo": "ٱنجومشیڤ کردن",
"diff-empty": "(یٱ جۊر)",
"diff-multi-sameuser": "({{PLURAL:$1|یٱ دۊناٛ نوسقاٛ مؽنجخایی|$1 نوسقاٛیٱل مؽنجخایی}} ب دٱسد{{PLURAL:$2|کاریاری ديٱ|$2 کاريارا}} نشۊن دیاری نٱکرداْ)",
"diff-multi-otherusers": "({{PLURAL:$1|یٱ نوسقاْ میٛنجقایی|$1 نوسقاْیٱل میٛنجایی}} ڤا دٱسد {{PLURAL:$2|کاریاری دیٱ|$2 کاریارٱل}} نشۊن داڌاْ نٱڤابیڌاْ)",
+ "diff-paragraph-moved-tonew": "پاراگراف جا ب جا ڤابی، یٱ کاْرٱت بپۊرنین تا رۉین یٱ جا دیٱر.",
+ "diff-paragraph-moved-toold": "پاراگراف جا ب جا ڤابی، یٱ کاْرٱت بپۊرنین تا رۉین ب جا نیایی.",
"searchresults": "نتيجاْیٱل پاٛی جۊری",
"search-filter-title-prefix-reset": "پاٛی جۊری میٛن تٱموم بٱلگاْیٱل",
"searchresults-title": "نتيجاْیٱل پاٛی جۊری سی \"$1\"",
"search-redirect": "(ڤاگٱردونی ز $1)",
"search-section": "(بٱرجا $1)",
"search-category": "(دٱسداْ $1)",
- "search-file-match": "(Û\8cÚ©Û\8c کردÙ\86 Ù\85Û\8cÙ\86Û\8aناْ جانیا)",
+ "search-file-match": "(Û\8cÚ©Û\8c کردÙ\86 Ù\85Û\8cÙ\9bÙ\86Ù\88ناْ جانیا)",
"search-suggest": "مٱنزۊرت یو بی:$1",
"search-interwiki-default": "نتیجاْیٱل $1:",
"search-interwiki-more": "(بيشتر)",
"right-upload_by_url": "سوڤار کرد جانیایٱل ز یٱ یۊ آر اْل",
"right-writeapi": "سي نڤشدن اْی پی آی ڤٱنين ڤاکار",
"right-delete": "پاکسا کردن بٱلگاْیٱل",
+ "right-bigdelete": "بٱلگاْیٱلی ناْ کاْ ڤیرگار گٱپ دارن پاکسا کونین.",
+ "right-browsearchive": "پاٛی جۊری میٛن بٱلگاْیٱل پاکسا ڤابیڌاْ.",
+ "right-undelete": "بٱلگاْ ناْ پاکسا نٱکونین",
"right-block": "نیا کاریارٱل دیٱر ناْ ز آلشدکاری بگرین.",
"right-blockemail": "نیا کاریار ناْ سی بیٛسی کردن ٱنجوماناماْ بگرین",
"right-hideuser": "نیاگری یٱ نوم کاریاری، قام کردنس ز ڤٱر تی خٱلک",
"rcfilters-activefilters-hide": "قام کردن",
"rcfilters-activefilters-show": "دیاری کردن",
"rcfilters-advancedfilters": "فیلترٱل پیشکرداْ",
+ "rcfilters-limit-title": "نتیجاْیٱل سی دیاری کردن",
+ "rcfilters-limit-and-date-label": "$1 {{PLURAL:$1|آلشدکاری|آلشدکاریٱل}}, $2",
"rcfilters-days-title": "رۊزٱل ایسنی",
"rcfilters-days-show-days": "$1 {{PLURAL:$1|رۊز|رۊزٱل}}",
"rcfilters-highlighted-filters-list": "پورٱنڳ ڤابیڌاْ:$1",
"rcfilters-invalid-filter": "فیلتر نادیار",
"rcfilters-filterlist-title": "فیلترٱل",
"rcfilters-filterlist-whatsthis": "یونو چ جۊر کار اْکونن؟",
+ "rcfilters-highlightmenu-title": "یٱ رٱنڳ گولاْڤورچین کونین",
+ "rcfilters-filterlist-noresults": "هیچ فیلتری دیاری نکرد.",
"rcfilters-filter-editsbyself-label": "ایسا آلشدس کردین",
"rcfilters-filter-editsbyother-label": "آلشدکاریٱل دیٱرون",
"rcfilters-filter-user-experience-level-registered-label": "سٱڤت نام ڤابیڌاْ",
"rcfilters-filtergroup-lastRevision": "آخری ڤانیٱریٱل",
"rcfilters-filter-lastrevision-label": "آخری ڤانیٱری",
"rcfilters-tag-prefix-namespace-inverted": "<strong>:نیڌ</strong> $1",
+ "rcfilters-target-page-placeholder": "نوم یٱ بٱلگاْ(یا دٱسداْ) ناْ بزنین",
"rcnotefrom": "ڤازیر {{PLURAL:$5|آلشدکاری|آلشدکاریٱل}}ز ڤیرگار strong>$3, $4</strong> تا ڤیرگار <strong>$1</strong> دیاری اْکونن .",
"rclistfrom": "دیار کردن آلشدکاریٱل ز $3 $2",
"rcshowhideminor": "آلشدکاری کۊچیر $1",
"sourcefilename": "سرچشماْ نوم جانیا:",
"sourceurl": "سرچشماْ يۊ آر ال:",
"destfilename": "نوم جانیا مٱقسٱڌ:",
+ "upload-description": "تۉزی جانیا",
"watchthisupload": "ساٛیل ای جانیا کونین",
"upload-proto-error": "پورتوکول نادوروسد",
"upload-file-error": "خٱتا میٛنجقایی",
"upload-form-label-own-work": "یو کار موناْ.",
"upload-form-label-infoform-categories": "دٱسداْیٱل",
"upload-form-label-infoform-date": "ڤیرگار",
+ "http-invalid-url": "یۊ آر اْل لیش:$1",
"http-read-error": "خٱتا خوندن اْچ تی تی پی.",
"http-internal-error": "خٱتا میٛنجقایی اْچ تی تی پی",
"license": "میٛن هال و بال لیسانس دار ڤابیڌن",
"uploadnewversion-linktext": "یٱ نوسقاْ تازاْ زی جانیا سوڤار کونین",
"shared-repo-from": "ز $1",
"upload-disallowed-here": "ايسا ناْترین ای جانیا نٱ ز نۉ سوڤار کونین",
+ "filerevert": "ز سرگرهڌن سی $1",
+ "filerevert-legend": "ز سرگرهڌن جانیا",
"filerevert-comment": "دلیل:",
+ "filerevert-submit": "لرنیڌن",
"filedelete": "$1 ناْ پاکسا کو",
"filedelete-legend": "پاکسا کردن جانیا",
"filedelete-comment": "دلیل:",
"filedelete-submit": "پاکسا کردن",
+ "filedelete-success": "<strong>$1</strong> پاکسا ڤابیڌاْ.",
+ "filedelete-otherreason": "دیٱری/دلیل اْزافی:",
"filedelete-reason-otherlist": "دلیل هیٛنی",
+ "filedelete-reason-dropdown": "*دلیل جاڤٱسداْ سی پاکسا کردن\n*تی پۊشنیڌن ز کوپی رایت\n*جانیا تکراری",
+ "filedelete-edit-reasonlist": "دلیل پاکسا کردن ناْ آلشد کونین",
+ "filedelete-maintenance-title": "نیبۊ جانیا ناْ پاکسا کونین",
"mimesearch": "MIME جستجو رو پایه",
+ "mimetype": "جۊر MIME:",
"download": "گرهڌن",
"listredirects": "نومگاْ ڤاگٱردونیٱل",
"unusedtemplates": "چۊئاْیٱل ڤا کار نٱڤٱسداْ",
+ "unusedtemplateswlh": "هومپاٛیڤٱندٱل هیٛنی",
"randompage": "بٱلگاْ شامسٱکی",
"randomincategory-category": "دٱسداْ:",
"randomincategory-submit": "رۉ",
"statistics-header-pages": "آمار بٱلگاْ",
"statistics-header-edits": "آمار آلشدکاریٱل",
"statistics-header-users": "آمار کاریارٱل",
+ "statistics-articles": "بٱلگاْیٱل مینۊناْ دار",
"statistics-pages": "بٱگاْیٱل",
"statistics-files": "جانیایٱل سوڤار ڤابیڌاْ",
"statistics-users": "کاریارٱل سٱڤت نام کرداْ",
"statistics-users-active": "کاریارٱل کونشتکار",
+ "pageswithprop-prop": "نوم خاسیٱت:",
"pageswithprop-submit": "رۉ",
"doubleredirects": "ڤاگٱردونی دۊبلاْ",
"double-redirect-fixer": "ساموݩکار آلشڌتورٱل",
"mostrevisions": "بٱلگاْیٱلی کاْ بیشترین ڤانیٱری ناْ دارن",
"prefixindex": "نماواٛ نهاڤٱنڌ",
"prefixindex-submit": "دیاری کردن",
+ "prefixindex-strip": "دیندادیس ناْ میٛن نتیچاْیٱل قام کو",
"shortpages": "بٱلگاْیٱل کۊچیر",
"longpages": "بٱلگاْیٱل بولوند",
"deadendpages": "بٱلگاْیٱل بون بٱست",
"protectedpages-performer": "کاریار پٱر و پیم ڤابیڌاْ.",
"protectedpages-params": "پینیارٱل پٱر و پیم کاری",
"protectedpages-reason": "دلیل",
+ "protectedpages-submit": "نشوݩ داڌن بٱلگاْیٱل",
"protectedpages-unknown-timestamp": "نادیار",
"protectedpages-unknown-performer": "کاریار نادیار",
"listusers": "نومگاْ کاریار",
+ "listusers-creationsort": "میزونکاری ز ری گات راست ڤابیڌن",
+ "listusers-desc": "میزونکاری ز ری گٱپ کۊچیری",
"usereditcount": "$1 {{PLURAL:$1|آلشدکاری|آلشدکاریٱل}}",
"usercreated": "{{GENDER:$3|راسد ڤابیڌاْ}} سی $1 تا $2",
"newpages": "بٱلگاْیٱل نۏ",
"apisandbox-submit": "خاستن",
"apisandbox-reset": "پاکسا کردن",
"apisandbox-retry": "ز نۉ تلاش کردن",
+ "apisandbox-helpurls": "هومپاٛیڤٱند هومیاری",
"apisandbox-examples": "نموناْیٱل",
"apisandbox-dynamic-parameters": "پینیارٱل اْزافی",
"apisandbox-dynamic-parameters-add-label": "اْزاف کردن پینیار:",
"apisandbox-dynamic-parameters-add-placeholder": "نوم پینیار.",
"apisandbox-add-multi": "اْزاف کردن",
"apisandbox-results": "نتیجاْیٱل",
+ "apisandbox-request-url-label": "درخاست یۊ آر اْل:",
+ "apisandbox-request-json-label": "درخاست JSON:",
"apisandbox-continue": "ديندا گرهڌن",
"apisandbox-continue-clear": "پاکسا کردن",
+ "apisandbox-multivalue-all-values": "$1 (تٱموم ٱرزایشتٱل)",
"booksources": "سرچشماْیٱل کتاو",
"booksources-search-legend": "پاٛ جۊری سی سٱرچٱشمٱیٱل کتاو",
"booksources-search": "پاٛی جۊری",
"specialloguserlabel": "مؽنتور:",
"speciallogtitlelabel": "دال(داسۊن یا {{ns:user}}:نوم کاریاری سی کاریار):",
"log": "پاْرستنوماْیٱل",
+ "logeventslist-submit": "نشوݩ دائن",
"all-logs-page": "گشڌنمائیٱل",
"alllogstext": "نمایشت یٱ جا کاْ تٱموم پهرستنۊماْیٱل میٛن {{SITENAME}}.\nایسا تاْرین ڤا گولاْڤورچین کردن جۊر پهرستنۊماْ ، نوم کاریاری(هساس ب کۊچیری و گٱپی هٱرفا) و بٱلگاْیٱل آلشت کرداْ(هساس ب گٱپی و کۊچیری هٱرفا) نمایشت نٱ دیر ز ڤیر کونین.",
"logempty": "چونو چی کاْ ایسا خاسدین میٛن پهرستنۊماْ نیڌس",
+ "checkbox-select": "گولاْڤورچین کردن: $1",
"checkbox-all": "هٱماْ",
"checkbox-none": "هيش کوم",
"allpages": "تٱموم بٱلگاْیٱل",
"allpages-hide-redirects": "بؽ دیارنیڌن آلشڌتورٱل",
"categories": "دٱسداْیٱل",
"categories-submit": "دیاری کردن",
+ "sp-deletedcontributions-contribs": "هومياریٱل",
+ "linksearch": "هومپاٛیڤٱند پاٛی جۊری خارجی",
+ "linksearch-pat": "سازاْیار پاٛی جۊری:",
+ "linksearch-ns": "نوم جا:",
"linksearch-ok": "پاٛی جۊری",
"listusers-submit": "نشوݩ دائن",
+ "listusers-noresult": "چونو کاریاری ڤوجۊڌ ناراْ.",
+ "listusers-blocked": "(نیاگری ڤابیڌاْ)",
+ "activeusers": "نومگٱ کاریارٱل کونشتکار",
+ "activeusers-noresult": "چونو کاریارٱلی ڤوجۊڌ نارن.",
+ "activeusers-submit": "دیاری کردن کاریارٱل کونتشکار",
"listgrouprights-group": "جٱرغاْ",
+ "listgrouprights-rights": "هوقۊق",
+ "listgrouprights-helppage": "هومیاری:هوقۊق جٱرغاْ",
"listgrouprights-members": "(نومگاْ ٱندومٱل)",
+ "listgrouprights-addgroup": "{{PLURAL:$2|جٱرغاْ|جٱرغاْیٱل}} ناْ اْزاف کونین: $1",
+ "listgrouprights-removegroup": "{{PLURAL:$2|جٱرغاْ|جٱرغاْیٱل}} ناْ ڤوردارین: $1",
+ "listgrouprights-addgroup-all": "اْزاف کردن تٱموم جٱرغاْیٱل",
+ "listgrouprights-removegroup-all": "ڤورداشتن تٱموم جٱرغاْیٱل",
+ "listgrants-rights": "هوقۊق",
+ "trackingcategories-name": "نوم پاٛیغوم",
"emailuser": "ٱنجوماناماْ کاریار",
+ "emailuser-title-notarget": "ٱنجوماناماْ کاریار",
+ "defemailsubject": "{{SITENAME}} ٱنجوماناماْ ز کاریار \"$1\"",
+ "emailusername": "نوم کاریاری:",
+ "emailusernamesubmit": "داڌن",
+ "email-legend": "یٱ ٱنجومانٱماْ سی کاریار دیٱری {{SITENAME}} بیٛسی کو",
"emailfrom": "ز:",
"emailto": "سی:",
"emailsubject": "داسوݩ:",
"emailccme": "یٱ کوپی ز پاٛیغوموم سیم بیٛسی کو",
"emailsent": "ٱنجوماناماْ بیٛسی ڤابیڌاْ",
"emailsenttext": "پاٛیغومتوݩ ٱنجوماناماْیی بیٛسی ڤابیڌاْ.",
- "usermessage-editor": "پاٛیغوم فرشن سامۊناْیی",
+ "usermessage-summary": "لاهاڌن پاٛیغوم سیستمی.",
+ "usermessage-editor": "پاٛیغوم فرشن ساموناْیی",
"watchlist": "لیسڌ دیناگریٱل مو",
- "mywatchlist": "سئیل بٱرگ",
+ "mywatchlist": "ساÙ\9bیل بٱرگ",
"watchlistfor2": "سی $1 $2",
"watchnologin": "هٱنی نٱڤۊڌیناْ ڤامیٛن",
"addwatch": "اْزاف کردن ب ساٛیل بٱرگ",
"addedwatchtext": "\"[[:$1]]\" و بٱلگاْ چٱک چناْس اْزاف ڤابی ب [[Special:ساٛیل بٱرگ|ساٛیل بٱرگ]]توݩ .",
- "removedwatchtext": "آن صفحه\"[[:$1]]\" جابجا وابیده زه[[Special:لیست پیگیری|لیست پیگیری ایسا]].",
+ "removewatch": "ڤورداشتن ز ساٛیل بٱرگ",
+ "removedwatchtext": "\"[[:$1]]\" و بٱلگاْ چٱک چناْس ز [[Special:نومگاْ ساٛیل بٱرگ|نومگٱ ساٛیل بٱرگ]]ایسا ڤورداشتاْ ڤابی.",
+ "removedwatchtext-talk": "\"[[:$1]]\" و بٱلگاْ هومیاریس ز [[Special:نومگاْ ساٛیل بٱرگ|نومگٱ ساٛیل بٱرگ]]ایسا ڤورداشتاْ ڤابی.",
"watch": "پاٛیگری",
"watchthispage": "پاٛگری ای بٱلگاْ",
"unwatch": "پاٛیگری نٱڤابیڌاْ",
"enotif_impersonal_salutation": "{{SITENAME}} کاریار",
"enotif_minoredit": "یو یٱ هیرداْ ڤیرایشداْ",
"deletepage": "پاکسا کردن بٱلگاْ",
+ "confirm": "پوشت راست کاری کردن",
+ "excontent": "میٛنوناْ: \"$1\" بی",
+ "delete-confirm": "پاکسا کردن \"$1\"",
+ "delete-legend": "پاکسا کردن",
"historywarning": "ب ڤیرتوݩ بۊ:بٱلگاْیی کاْ ایسا خاین پاکساس کونین یٱ ڤیرگار $1 ڤا{{PLURAL:$1|ڤانیٱری|ڤانیٱریٱل}} داراْ:",
"historyaction-submit": "نشوݩ دائن",
"confirmdeletetext": "ایسا اْخاین یٱ بٱلگاْ بولوند ناْ ڤا تٱموم ڤیرگارس پاکسا کونن.\nلوتف کونین پوشت راستکاری کونین کاْ چونو کاری ناْ اْخاین ٱنجوم بڌین، ایسا دونین کاْ نتیجاْ و آریٛنگ کاری کاْ خاین ٱنجوم بڌین ڤا زی ری [[{{MediaWiki:Policy-url}}|سیاستٱل]] بۊ.",
"actionfailed": "کار کاْ ناخوش سرٱنجوم بی",
"deletedtext": "\"$1\" پاکسا ڤابیڌاْ.\nبیٛنیٱر ب $2 سی سٱڤت آخری پاکسا کاریٱل.",
"dellogpage": "پهرستنۊماْ پاکسا کردن",
+ "deletionlog": "پهرستنۊماْ پاکسا کردن",
"deletecomment": "دلیل:",
"deleteotherreason": "دیٱر/دلیل اْزافی:",
"deletereasonotherlist": "دلیل دیٱر",
"rollbacklink": "ڤورگٱشتن",
"rollbacklinkcount": "چٱڤاساْ کردن $1 {{PLURAL:$1|آلشدکاری|آلشدکاریٱل}}",
"changecontentmodel-title-label": "داسوݩ بٱلگاْ",
+ "changecontentmodel-model-label": "مودل میٛنوناْ تازاْ",
"changecontentmodel-reason-label": "دلیل:",
"changecontentmodel-submit": "آلشد کردن",
"protectlogpage": "پهرستنۊماْ پٱر و پیم کاری",
"protect_expiry_old": "گات تٱموم ڤابیڌن ز دینداتراْ.",
"protect-text": "گاشا ایسا ریتراز پٱر و پیم کاری بٱلگاْ ناْ بیٛنیٱرین و آلشدس کونین سی '''$1'''.",
"protect-locked-access": "هساو کاریاری ایسا سلا آلشدکاری ریتراز پٱر و پیم کاری ناْ ناراْ.\nمیزونکاری ایسنی سی بلگاْ ایچوناْ '''$1''':",
- "protect-cascadeon": "ای صفحه در حال حاضر حفاظت وحمایت وابیده چون که در {{PLURAL:$1|صفحه|صفحات}}\nزیر که گزینه حفاظت وحمایت موجی {{PLURAL:$1|آن|آنها}} فعال هده ،\nایسا ترین سطح حفاظت ای صفحه را تغییر بدین اما ای کارنتره تاثیری رو\nحفاظت وحمایت موجی صفحه داشته بوه.",
+ "protect-cascadeon": "This page is currently protected because it is transcluded in the following {{PLURAL:$1|page, which has|pages, which have}} cascading protection turned on.\nChanges to this page's protection level will not affect the cascading protection.",
"protect-default": "هٱماْ کاریارٱل سلادارن",
- "protect-fallback": "درخواست\"$1\" اجازه",
- "protect-level-autoconfirmed": "بستن کاربران ثبت نام نوابیده",
- "protect-level-sysop": "Sysops فقط",
- "protect-summary-cascade": "موجی کردن",
- "protect-expiring": "سپری وابیده $1 (UTC)",
+ "protect-fallback": "فٱقٱت کاریارٱلی کاْ ب «$1» دٱسرسی دارن، سلادار ای کارن.",
+ "protect-level-autoconfirmed": "فٱقٱت کاریارٱلی کاْ خودپوشت راست کاری ڤابیڌناْ سلا چونو کاری دارن",
+ "protect-level-sysop": "فٱقٱت سردیڤونکارٱل",
+ "protect-summary-cascade": "مۉجی کردن",
+ "protect-expiring": "گات تٱمو ڤابیڌاْ $1 (UTC)",
+ "protect-expiry-indefinite": "بی گات",
"protect-cascade": "حمایت صفحات دربرگیرنده در ای صفحه (cascading protection)",
"protect-cantedit": "ایسا نترین تغییر بدین سطوح حمایتی ای صفحه را, زیرا ایسا اجازه اصلاح آن را ندارین.",
+ "protect-othertime": "گات هیٛنی:",
+ "protect-othertime-op": "گات هیٛنی:",
+ "protect-otherreason-op": "دلیل هیٛنی",
"protect-expiry-options": "۱ ساعت:1 hour,۱ روز:1 day,۱ هفته:1 week,۲ هفته:2 weeks,۱ ماه:1 month,۳ ماه:3 months,۶ ماه:6 months,۱ سال:1 year,بینهایت:infinite",
"restriction-type": "اجازه:",
"restriction-level": "سطح محدودیت:",
- "restriction-edit": "ڤيرایشت کردن",
+ "pagesize": "(بایتٱل)",
+ "restriction-edit": "آلشدکاری کردن",
"restriction-move": "جا ڤا جا کردن",
+ "restriction-create": "راس كردن",
+ "restriction-upload": "سوڤارکرد",
"undeletebtn": "بازیافت",
+ "undeleteviewlink": "ديڌن",
+ "undeletecomment": "دلیل:",
+ "undelete-search-submit": "پاٛی جۊری",
+ "undelete-show-file-submit": "هٱراْ",
"namespace": "نوم جا:",
"invert": "گولڤورچین کردن بٱرٱسگ بۊ",
"tooltip-invert": "ز ری ای جٱڤاْ بپۊرنین و آلشدٱلی ناْ کاْ ماٛنجقا نوم ڤٱرگٱ گولاْڤورچین ڤابیڌن و ٱنجوم داڌاْ ڤابیڌناْ قام کونین.",
"sp-contributions-blocklog": "پهرستنوماْ قولف ڤابیڌاْ",
"sp-contributions-uploads": "سوڤارکردٱل",
"sp-contributions-logs": "پاْرستنۊماْیٱل",
- "sp-contributions-talk": "Ú\86Ù±Ú© Ú\86Ù\86اÙ\9b",
+ "sp-contributions-talk": "Ú\86Ù±Ú© Ú\86Ù\86اÙ\92",
"sp-contributions-search": "سی هومیاریٱل پاٛی جۊری ڤابۊ",
"sp-contributions-username": "نوم ناٛشۊن آی پی یا نوم کاریاری",
"sp-contributions-toponly": "فقٱت آلشدکاریٱلی کاْ جۏزڤاْ آخریݩ دۉران دیاری کو",
"whatlinkshere-hidelinks": "هومپاٛیڤٱند سی $1",
"whatlinkshere-hideimages": "جانیا هومپاٛیڤٱندٱل $1",
"whatlinkshere-filters": "فيلترٱل",
- "blockip": "بستن کاربر",
+ "whatlinkshere-submit": "رۉ",
+ "autoblockid": "خود نیاگری #$1",
+ "block": "قولف کردن کاریار",
+ "unblock": "قولف نکردن کاریار",
+ "blockip": "قولف کردن {{GENDER:$1|کاریار}}",
+ "ipaddressorusername": "نوم نشوݩ آی پی یا نوم کاریاری",
+ "ipbreason": "دلیل:",
"ipbcreateaccount": "راسد کردن هساو کاریاری",
+ "ipbsubmit": "ای کاریار ناْ نیاگری کو",
+ "ipbother": "گات هیٛنی:",
"ipboptions": "۲ سات:2 hours,۱ رۊز:1 day,۳ رۊز:3 days,۱ هٱفتاْ:1 week,۲ هٱفتاْ:2 weeks,۱ ما:1 month,۳ ما:3 months,۶ ما:6 months,۱ سال:1 year,بی ڤیرگار:infinite",
+ "ipb-pages-label": "بٱگاْیٱل",
+ "ipb-namespaces-label": "نوم ڤارگٱیٱل",
+ "autoblocklist-submit": "پاٛی جۊری",
"ipblocklist": "آدرسهای آی پی وکاربران بسته وابیدند",
"blocklist-userblocks": "قام کردن هساو نیاگری ڤابیڌاْ.",
"infiniteblock": "بؽ تٱ",
"delete": "Bestere",
"undelete_short": "{{PLURAL:$1|Yew vırnayışi|$1 Vırnayışan}} mestere",
"viewdeleted_short": "{{PLURAL:$1|Jew vurnayış esternayi|$1 Vurnayışanê esternayan}} bımotne",
- "protect": "Bısıtarne",
+ "protect": "Bışevekne",
"protect_change": "bıvırne",
"unprotect": "Starnayışi bıvurne",
"newpage": "Perra newi",
"templatesused": "{{PLURAL:$1|Şablon|Şabloni}} ke ena perrer de karneyayê:",
"templatesusedpreview": "{{PLURAL:$1|Sablon|Sabloni}} ke na verqayt de xebetnayê:",
"templatesusedsection": "{{PLURAL:$1|Template|Templateyan}} ke na qısım de xebetniyenê:",
- "template-protected": "(sıtarna)",
+ "template-protected": "(şeveknaye)",
"template-semiprotected": "(nime staryayış)",
"hiddencategories": "Ena per de {{PLURAL:$1|1 kategoriyo nımıte|$1 kategoriyê nımıtey}} muhtewa benê:",
"edittools": "<div id=\"specialcharss\" class=\"toccolours specialchars\" style=\"margin-top:.5em; padding: .3em .5em; font-size: 100%; color:#aaa; text-align:left;\" title=\"{{int:bw-edittools-tooltip}}\">\n<p class=\"specialbasic\" id=\"Standard\">\n'''{{int:bw-edittools-lead-in}}''' \n<charinsert>Á á É é Í í Ó ó Ú ú Ý ý</charinsert> –\n<charinsert>À à È è Ì ì Ò ò Ù ù </charinsert> –\n<charinsert> â Ê ê Î î Ô ô Û û </charinsert> –\n<charinsert>Ä ä Ë ë Ï ï Ö ö Ü ü Ÿ ÿ</charinsert> –\n<charinsert>Æ æ Ø ø Œ œ ẞ ß </charinsert> –\n<charinsert>Å å Ů ů </charinsert> –\n<charinsert>à ã Ẽ ẽ ɛ̃ Ĩ ĩ Ñ ñ Õ õ ɔ̃ Ũ ũ </charinsert> –\n<charinsert>Ð ð Þ þ </charinsert> –\n<charinsert>Ç ç Ģ ģ Ķ ķ Ļ ļ Ņ ņ Ŗ ŗ Ş ş Ţ ţ </charinsert> –\n<charinsert>Ć ć Ĺ ĺ Ń ń Ŕ ŕ Ś ś Ý ý Ź ź </charinsert> –\n<charinsert>Č č Ď ď Ľ ľ Ň ň Ř ř Š š Ť ť Ž ž </charinsert> –\n<charinsert>Ǎ ǎ Ě ě Ǐ ǐ Ǒ ǒ Ǔ ǔ </charinsert> –\n<charinsert>Ā ā Ē ē Ī ī Ō ō Ū ū </charinsert> –\n<charinsert>ǖ ǘ ǚ ǜ </charinsert> –\n<charinsert>Ĉ ĉ Ĝ ĝ Ĥ ĥ Ĵ ĵ Ŝ ŝ Ŵ ŵ Ŷ ŷ </charinsert> –\n<charinsert>Ă ă Ğ ğ Ŭ ŭ </charinsert> –\n<charinsert>Ċ ċ Ė ė Ġ ġ Għ għ İ ı Ż ż </charinsert> –\n<charinsert>Ą ą Ę ę Į į Ų ų </charinsert> –\n<charinsert>Ő ő Ű ű </charinsert> –\n<charinsert>Đ đ Ħ ħ Ł ł Ŀ ŀ </charinsert> –\n<charinsert>Ɖ ɖ Ɛ ɛ Ƒ ƒ Ɣ ɣ Ŋ ŋ Ɔ ɔ Ʋ ʋ </charinsert> -\n<charinsert>Ə ə </charinsert> –\n<charinsert>– — ’</charinsert> –\n<charinsert>~ | ° ¹ ² ³ ⅛ ¼ ⅓ ⅜ ½ ⅝ ¾ ⅔ ⅞ € $ ¥ £ † × ← → ↔ ↑ ± ≠ © ® ™ ‰ «+» ‹+› „+“ „+” ‚+‘ ¡ ¿ …</charinsert> –\n<charinsert>&nbsp; [[Category:+]] #REDIRECT[[+]] {{msg-mw|+|notext=1}} !!FUZZY!! ~~~~ <nowiki>+</nowiki></charinsert>\n<charinsert>ڈ ڑ ٹ </charinsert>\n<charinsert>ټ څ ځ ډ ړ ږ ښ ڼ ؤ ي ې ۍ ئ </charinsert>\n<charinsert>{{{+}}} {{+}} {{subst:+}} <noinclude>+</noinclude></charinsert>\n<charinsert><!-- + --> <br /></charinsert>\n</p></div>",
"group": "Grube:",
"group-user": "Karberi",
"group-autoconfirmed": "Karberê ke otomatikmen biyê araşt",
- "group-bot": "Roboti",
+ "group-bot": "Boti",
"group-sysop": "İdarekari",
"group-interface-admin": "İdarekarê namnişani",
"group-bureaucrat": "Buroqrati",
"right-upload_by_url": "Yew URL ra dosyeyan bar ke",
"right-purge": "Virê sita seba yew pele bêdestur bestere.",
"right-autoconfirmed": "Perê ke nême kılit biyê, inan bıvurne",
- "right-bot": "Zey yew kardê otomotiki kar bıvin",
+ "right-bot": "Zey yew karê otomatiki kar bıvêne",
"right-nominornewtalk": "Pelanê werênayışan rê vurnayışê qıckeki çıniyê, qutiya mesacanê newiyan bıgurene",
"right-apihighlimits": "Persanê API de sinoranê berzêran bıgurene",
"right-writeapi": "Xebtnayışê API nusnayışi",
"rcshowhideminor": "Vırnayışê werdiy $1",
"rcshowhideminor-show": "Bımocne",
"rcshowhideminor-hide": "Bınımne",
- "rcshowhidebots": "botan $1",
+ "rcshowhidebots": "boti $1",
"rcshowhidebots-show": "Bımocne",
"rcshowhidebots-hide": "Bınımne",
"rcshowhideliu": "karberê qeydbiyay $1",
"logentry-newusers-create2": "Hesabê karberi $1 terefê $3 ra {{GENDER:$2|vıraziya}}",
"logentry-newusers-byemail": "Karber $1 hesabe $3 {{GENDER:$2|virast}} u parola rist epostadaci",
"logentry-newusers-autocreate": "Hesabê karberi $1 otomatikmen {{GENDER:$2|vıraşt}}",
- "logentry-protect-protect": "$1, pela $3 gırewte {{GENDER:$2|sıtare}} $4",
- "logentry-protect-protect-cascade": "$1, pela $3 gırewte {{GENDER:$2|sıtare}} $4 [qademeyın]",
+ "logentry-protect-protect": "$1, pela $3 {{GENDER:$2|şeveknê}} $4",
+ "logentry-protect-protect-cascade": "$1, pela $3 {{GENDER:$2|şeveknê}} $4 [qademeyın]",
"logentry-rights-rights": "$1 qandê {{GENDER:$6|$3}} rê ezayiya grube $4 ra $5 {{GENDER:$2|vuriye}}",
"logentry-rights-rights-legacy": "$1 qandê $3 rê ezayiya grube {{GENDER:$2|vuriye}}",
"logentry-rights-autopromote": "$1 otomatikmen $4 ra $5 {{GENDER:$2|terfi bi}}",
"anoncontribs": "Contributions",
"contribsub2": "For {{GENDER:$3|$1}} ($2)",
"contributions-userdoesnotexist": "User account \"$1\" is not registered.",
+ "negative-namespace-not-supported": "Namespaces with negative values are not supported.",
"nocontribs": "No changes were found matching these criteria.",
"uctop": "current",
"month": "From month (and earlier):",
"Metsavend",
"Cumbril",
"Ilmarine",
- "Fitoschido"
+ "Fitoschido",
+ "Mardus"
]
},
"tog-underline": "Linkide allakriipsutus:",
"pagecategories": "{{PLURAL:$1|Kategooria|Kategooriad}}",
"category_header": "Leheküljed kategoorias \"$1\"",
"subcategories": "Alamkategooriad",
- "category-media-header": "Meediumifailid kategoorias \"$1\"",
- "category-empty": "<em>Selles kategoorias pole praegu ühtegi lehekülge ega meediumifaili.</em>",
+ "category-media-header": "Meediafaile kategoorias \"$1\"",
+ "category-empty": "<em>Selles kategoorias pole praegu ühtegi lehekülge ega meediafaili.</em>",
"hidden-categories": "{{PLURAL:$1|Peidetud kategooria|Peidetud kategooriad}}",
"hidden-category-category": "Peidetud kategooriad",
"category-subcat-count": "{{PLURAL:$2|Selles kategoorias on ainult järgmine alamkategooria.|{{PLURAL:$1|Järgmine alamkategooria|Järgmised $1 alamkategooriat}} on selles kategoorias (kokku $2).}}",
"sort-ascending": "Järjesta tõusvalt",
"nstab-main": "Artikkel",
"nstab-user": "Kasutaja leht",
- "nstab-media": "Meediumileht",
+ "nstab-media": "Meedialeht",
"nstab-special": "Eri",
"nstab-project": "Projektileht",
"nstab-image": "Fail",
"right-deletechangetags": "Kustutada andmebaasist [[Special:Tags|märgiseid]]",
"grant-generic": "Volituse \"$1\" õiguste komplekt",
"grant-group-page-interaction": "Interaktsioon lehekülgedega",
- "grant-group-file-interaction": "Interaktsioon meediumifailidega",
+ "grant-group-file-interaction": "Käsitle meediafaile",
"grant-group-watchlist-interaction": "Interaktsioon sinu jälgimisloendiga",
"grant-group-email": "E-kirja saatmine",
"grant-group-high-volume": "Suuremahuline tegevus",
"tooltip-t-permalink": "Püsilink lehekülje sellele redaktsioonile",
"tooltip-ca-nstab-main": "Vaata sisulehekülge",
"tooltip-ca-nstab-user": "Näita kasutaja lehte",
- "tooltip-ca-nstab-media": "Vaata meediumifaili lehekülge",
+ "tooltip-ca-nstab-media": "Vaata meedialehte",
"tooltip-ca-nstab-special": "See on erilehekülg ja seda ei saa redigeerida.",
"tooltip-ca-nstab-project": "Näita projekti lehte",
"tooltip-ca-nstab-image": "Vaata faili lehekülge",
"version-editors": "Toimetid",
"version-antispam": "Rämpsposti tõkestus",
"version-other": "Muu",
- "version-mediahandlers": "Meediumitöötlejad",
+ "version-mediahandlers": "Meedia käsitlejad",
"version-hooks": "Haagid",
"version-parser-extensiontags": "Parseri lisasildid",
"version-parser-function-hooks": "Parserifunktsioonid",
"default-skin-not-found-no-skins": "Oih! Sinu viki vaikekujundus, milleks muutuja <code dir=\"ltr\">$wgDefaultSkin</code> järgi on <code>$1</code>, pole saadaval.\n\nÜhtegi kujundust pole paigaldatud.\n\n; Kui oled MediaWiki just paigaldanud või täiendasid seda:\n: Paigaldasid tarkvara ilmselt Giti kaudu või otse lähtekoodist või mõnel muul viisil. See on ootuspärane. MediaWiki 1.24 ja uuemad versioonid ei sisalda peahoidlas ühtegi kujundust. Proovi [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org-i kujunduste kataloogist] mõni kujundus paigaldada. Selleks saad:\n:* laadida alla [https://www.mediawiki.org/wiki/Download lintarhiivi paigaldaja], mis sisaldab mitut kujundust ja tarkvaralisa. Saad sealt kleepimiseks kopeerida kausta <code dir=\"ltr\">skins/</code>;\n:* [https://www.mediawiki.org/wiki/Special:SkinDistributor mediawiki.org-ist] kindla kujunduse lintarhiivi alla laadida;\n:* [https://www.mediawiki.org/wiki/Download_from_Git#Using_Git_to_download_MediaWiki_skins kasutada Giti, et kujundusi alla laadida].\n: Selle tegemine ei tohiks häirida Giti hoidlat, kui oled MediaWiki arendaja. Vaata [https://www.mediawiki.org/wiki/Manual:Skin_configuration kujunduste häälestusjuhendist], kuidas kujundusi lubada ja kuidas valida vaikekujundus.",
"default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (lubatud)",
"default-skin-not-found-row-disabled": "* <code>$1</code> / $2 (<strong>keelatud</strong>)",
- "mediastatistics": "Meediumifailide arvandmestik",
+ "mediastatistics": "Meediastatistika",
"mediastatistics-summary": "Arvandmed üles laaditud failitüüpide kohta. See käib ainult failide viimaste versioonide kohta. Vanu ja kustutatud versioone pole arvesse võetud.",
"mediastatistics-nbytes": "{{PLURAL:$1|$1 bait|$1 baiti}} ($2; $3%)",
"mediastatistics-bytespertype": "Failide kogusuurus selles alaosas: $1 {{PLURAL:$1|bait|baiti}} ($2; $3%).",
"mw-widgets-dateinput-no-date": "Kuupäev valimata",
"mw-widgets-dateinput-placeholder-day": "AAAA-KK-PP",
"mw-widgets-dateinput-placeholder-month": "AAAA-KK",
- "mw-widgets-mediasearch-input-placeholder": "Otsi meediumifaile",
+ "mw-widgets-mediasearch-input-placeholder": "Otsi meediat",
"mw-widgets-mediasearch-noresults": "Tulemusi ei leitud.",
"mw-widgets-titleinput-description-new-page": "lehekülge pole veel",
"mw-widgets-titleinput-description-redirect": "ümbersuunamine leheküljele \"$1\"",
"signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|uloi]])",
"duplicate-defaultsort": "'''Chotrai:''' Default arin manddunk chavi ''$2'' rodd korta adhlem default arin manddunk chavi ''$1'', haka.",
"redirect": "Fayl, vaporpi, pan, uzollnni vo sotr ank vorvim punornirdexon kor",
- "redirect-summary": "Hem vixex pan punornirdexit korta eka faylik (faylichem nanv dilear), eke panak (uziollnecho ank vo panacho ank dilear), ek vaporpeachem panak (eke vaporpeache ank dilear), vo ek sotr provishtt (sotrachem ank dilear). Vapor: [[{{#Special:Redirect}}/file/Dekhik.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], [[{{#Special:Redirect}}/user/101]], vo [[{{#Special:Redirect}}/logid/186]].",
+ "redirect-summary": "Hem vixex pan punornirdexit korta eka faylik (faylichem nanv dilear), eke panak (uziollnecho ank vo panacho ank dilear), ek vaporpeachem panak (eke vaporpeache ank dilear), vo ek sotr nond (sotrachem ank dilear). Vapor: [[{{#Special:Redirect}}/file/Dekhik.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], [[{{#Special:Redirect}}/user/101]], vo [[{{#Special:Redirect}}/logid/186]].",
"redirect-submit": "Voch",
"redirect-lookup": "Suchien polloi:",
"redirect-value": "Mol:",
"anoncontribs": "תרומות",
"contribsub2": "עבור {{GENDER:$3|$1}} ($2)",
"contributions-userdoesnotexist": "חשבון המשתמש \"$1\" אינו רשום.",
+ "negative-namespace-not-supported": "אין תמיכה במרחבי שם בעלי ערך שלילי.",
"nocontribs": "לא נמצאו שינויים המתאימים לקריטריונים אלו.",
"uctop": "נוכחי",
"month": "עד החודש:",
"grant-delete": "Eyða síðum, yfirferðum og annálsfærslum",
"grant-editinterface": "Breyta nafnrými MediaWiki og JSON notanda/vefsvæðis",
"grant-editmycssjs": "Breyta þínum eigin CSS/JSON/JavaScript",
- "grant-editmyoptions": "Breyta notandastillingunum þínum",
+ "grant-editmyoptions": "Breyta notandastillingunum þínum og JSON-uppsetningu",
"grant-editmywatchlist": "Breyta vaktlistanum þínum",
"grant-editpage": "Breyta fyrirliggjandi síðum",
"grant-editprotected": "Breyta vernduðum síðum",
"uploadstash-zero-length": "Lengd skráar er núll.",
"invalid-chunk-offset": "Ógild raðbreyting bunka",
"img-auth-accessdenied": "Aðgangur óheimill",
- "img-auth-nopathinfo": "PATH_INFO vantar.\nBiðlarinn þínn er ekki stilltur til að gefa upp þessar upplýsingar.\nÞær mega vera CGI-byggðar og mega ekki styðja img_auth.\nhttps://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization",
+ "img-auth-nopathinfo": "Vantar upplýsingar um slóð.\nÞjónninn þinn er ekki stilltur til að senda REQUEST_URI og/eða PATH_INFO breyturnar.\nEf svo er, prófaðu að virkja $wgUsePathInfo.\nSkoðaðu https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization.",
"img-auth-notindir": "Umbeðin slóð var ekki í stilltri innhleðslumöppu.",
"img-auth-badtitle": "Mistókst að búa til gildan titil útfrá „$1”.",
"img-auth-nologinnWL": "Þú ert ekki skráð(ur) inn og „$1“ er ekki á hvítlista.",
"ipbreason": "Ástæða:",
"ipbreason-dropdown": "* Algengar bannástæður\n** Setur inn rangar upplýsingar\n** Fjarlægir efni af síðum\n** Setur inn rusltengla á utanaðkomandi síður\n** Setur inn vitleysu/þvaður á síður\n** Yfirþyrmandi framkoma/áreitni\n** Misnotkun á fjölda notandanafna\n** Óásættanlegt notandanafn",
"ipb-hardblock": "Banna innskráðum notendum að breyta frá þessu IP-vistfangi.",
- "ipbcreateaccount": "Banna nýskráningu notandanafns",
- "ipbemailban": "Banna notanda að senda tölvupóst",
+ "ipbcreateaccount": "Gerð notandaaðgangs",
+ "ipbemailban": "Senda tölvupóst",
"ipbenableautoblock": "Banna síðasta vistfang notanda sjálfkrafa; og þau vistföng sem viðkomandi notar til að breyta síðum",
"ipbsubmit": "Banna notanda",
"ipbother": "Annar tími:",
"ipboptions": "2 tíma:2 hours,1 dag:1 day,3 daga:3 days,1 viku:1 week,2 vikur:2 weeks,1 mánuð:1 month,3 mánuði:3 months,6 mánuði:6 months,1 ár:1 year,aldrei:infinite",
"ipbhidename": "Fela notandanafn úr breytingaskrá og listum",
"ipbwatchuser": "Vakta notanda- og spjallsíður þessa notanda",
- "ipb-disableusertalk": "Banna þessum notanda að breyta eigin spjallsíðu",
+ "ipb-disableusertalk": "Breyta eigin spjallsíðu",
"ipb-change-block": "Endurbanna notanda með þessum stillingum",
"ipb-confirm": "Staðfesta bann",
"ipb-sitewide": "Á öllum vefnum",
"anoncontribs": "Same as {{msg-mw|mycontris}} but used for non-logged-in users.\n\nSee also:\n* {{msg-mw|Accesskey-pt-anoncontribs}}\n* {{msg-mw|Tooltip-pt-anoncontribs}}\n{{Identical|Contribution}}",
"contribsub2": "Contributions for \"user\" (links). Parameters:\n* $1 is an IP address or a username, with a link which points to the user page (if registered user).\n* $2 is list of tool links. The list contains a link which has text {{msg-mw|Sp-contributions-talk}}.\n* $3 is a plain text username used for GENDER.\n{{Identical|For $1}}",
"contributions-userdoesnotexist": "This message is used in [[Special:Contributions]]. It is used to tell the user that the name he searched for doesn't exist.\n\nParameters:\n* $1 - a username\n{{Identical|Userdoesnotexist}}",
+ "negative-namespace-not-supported": "This message is used in [[Special:Contributions]] to tell users that use namespaces with negative value. It not supported as associated namespace(s) doesn't exist.",
"nocontribs": "Used in [[Special:Contributions]] and [[Special:DeletedContributions]].\n\nSee examples: [[Special:Contributions/x]] and [[Special:DeletedContributions/x]].\n\nParameters:\n* $1 - (Unused) the user name",
"uctop": "This message is used in [[Special:Contributions]]. It is used to show that a particular edit was the last made to a page. Example: 09:57, 11 February 2008 (hist) (diff) Pagename (edit summary) (current)\n{{Identical|Current}}",
"month": "Used in [[Special:Contributions]] and history pages ([{{fullurl:Sandbox|action=history}} example]), as label for a dropdown box to select a specific month to view the edits made in that month, and the earlier months. See also {{msg-mw|year}}.",
"nospecialpagetext": "<strong>您請求的特定頁面無效。</strong>\n\n欲取得有效的特定頁面清單可至 [[Special:SpecialPages|{{int:specialpages}}]]。",
"error": "錯誤",
"databaseerror": "資料庫錯誤",
- "databaseerror-text": "出現資料庫查詢錯誤。\n這可能表示系統有問題存在。",
+ "databaseerror-text": "出現資料庫查詢錯誤。\n這表示系統可能有問題存在。",
"databaseerror-textcl": "資料庫查詢錯誤。",
"databaseerror-query": "查詢:$1",
"databaseerror-function": "功能:$1",
<?php
-/** Guianan Creole (kréyòl gwiyanè)
+/** Guianan Creole (Kriyòl Gwiyannen)
*
* To improve a translation please visit https://translatewiki.net
*
use MediaWiki\MediaWikiServices;
use Wikimedia\Rdbms\IDatabase;
+use Wikimedia\Rdbms\IMaintainableDatabase;
require_once __DIR__ . '/../Maintenance.php';
/* This style adds a toggle button with internationalized message for the TOC. */
-/* When the browser supports :checked then overwrite the style="display:none" and make the /*
+/* When the browser supports :checked then overwrite the style="display:none" and make the */
/* checkbox invisible on another way to allow to focus the checkbox with keyboard. */
:not( :checked ) > .toctogglecheckbox {
+ // Make the checkbox visible to allow it to focus with keyboard.
display: inline !important; /* stylelint-disable-line declaration-no-important */
+ // Remove any size of the checkbox.
position: absolute;
+ // Make the checkbox invisible.
opacity: 0;
+ // Prevent that the checkbox is clickable and changes the cursor.
+ z-index: -1;
}
.toctogglespan {
<?php
use MediaWiki\MediaWikiServices;
+use Wikimedia\Rdbms\IMaintainableDatabase;
use Wikimedia\ScopedCallback;
use Wikimedia\TestingAccessWrapper;
$nonce->setAccessible( true );
$nonce->setValue( $out, 'secret' );
$rl = $out->getResourceLoader();
- $rl->setMessageBlobStore( new NullMessageBlobStore() );
+ $rl->setMessageBlobStore( $this->createMock( MessageBlobStore::class ) );
$rl->register( [
'test.foo' => new ResourceLoaderTestModule( [
'script' => 'mw.test.foo( { a: true } );',
->method( 'buildCssLinksArray' )
->willReturn( [] );
$rl = $op->getResourceLoader();
- $rl->setMessageBlobStore( new NullMessageBlobStore() );
+ $rl->setMessageBlobStore( $this->createMock( MessageBlobStore::class ) );
// Register custom modules
$rl->register( [
return new OutputPage( $context );
}
}
-
-/**
- * MessageBlobStore that doesn't do anything
- */
-class NullMessageBlobStore extends MessageBlobStore {
- public function get( ResourceLoader $resourceLoader, $modules, $lang ) {
- return [];
- }
-
- public function updateModule( $name, ResourceLoaderModule $module, $lang ) {
- }
-
- public function updateMessage( $key ) {
- }
-
- public function clear() {
- }
-}
], $user ) );
}
+ public function testAddBlockInfoToStatus() {
+ $mock = new MockApi();
+
+ // Sanity check empty array
+ $expect = Status::newGood();
+ $test = Status::newGood();
+ $mock->addBlockInfoToStatus( $test );
+ $this->assertEquals( $expect, $test );
+
+ // No blocked $user, so no special block handling
+ $expect = Status::newGood();
+ $expect->fatal( 'blockedtext' );
+ $expect->fatal( 'autoblockedtext' );
+ $expect->fatal( 'systemblockedtext' );
+ $expect->fatal( 'mainpage' );
+ $expect->fatal( 'parentheses', 'foobar' );
+ $test = clone $expect;
+ $mock->addBlockInfoToStatus( $test );
+ $this->assertEquals( $expect, $test );
+
+ // Has a blocked $user, so special block handling
+ $user = $this->getMutableTestUser()->getUser();
+ $block = new \Block( [
+ 'address' => $user->getName(),
+ 'user' => $user->getID(),
+ 'by' => $this->getTestSysop()->getUser()->getId(),
+ 'reason' => __METHOD__,
+ 'expiry' => time() + 100500,
+ ] );
+ $block->insert();
+ $blockinfo = [ 'blockinfo' => ApiQueryUserInfo::getBlockInfo( $block ) ];
+
+ $expect = Status::newGood();
+ $expect->fatal( ApiMessage::create( 'apierror-blocked', 'blocked', $blockinfo ) );
+ $expect->fatal( ApiMessage::create( 'apierror-autoblocked', 'autoblocked', $blockinfo ) );
+ $expect->fatal( ApiMessage::create( 'apierror-systemblocked', 'blocked', $blockinfo ) );
+ $expect->fatal( 'mainpage' );
+ $expect->fatal( 'parentheses', 'foobar' );
+ $test = Status::newGood();
+ $test->fatal( 'blockedtext' );
+ $test->fatal( 'autoblockedtext' );
+ $test->fatal( 'systemblockedtext' );
+ $test->fatal( 'mainpage' );
+ $test->fatal( 'parentheses', 'foobar' );
+ $mock->addBlockInfoToStatus( $test, $user );
+ $this->assertEquals( $expect, $test );
+ }
+
public function testDieStatus() {
$mock = new MockApi();
public function testEditWhileBlocked() {
$name = 'Help:' . ucfirst( __FUNCTION__ );
- $this->setExpectedException( ApiUsageException::class,
- 'You have been blocked from editing.' );
+ $this->assertNull( Block::newFromTarget( '127.0.0.1' ), 'Sanity check' );
$block = new Block( [
'address' => self::$users['sysop']->getUser()->getName(),
'reason' => 'Capriciousness',
'timestamp' => '19370101000000',
'expiry' => 'infinity',
+ 'enableAutoblock' => true,
] );
$block->insert();
'title' => $name,
'text' => 'Some text',
] );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( ApiUsageException $ex ) {
+ $this->assertSame( 'You have been blocked from editing.', $ex->getMessage() );
+ $this->assertNotNull( Block::newFromTarget( '127.0.0.1' ), 'Autoblock spread' );
} finally {
$block->delete();
self::$users['sysop']->getUser()->clearInstanceCache();
}
}
+ public function testMoveWhileBlocked() {
+ $this->assertNull( Block::newFromTarget( '127.0.0.1' ), 'Sanity check' );
+
+ $block = new Block( [
+ 'address' => self::$users['sysop']->getUser()->getName(),
+ 'by' => self::$users['sysop']->getUser()->getId(),
+ 'reason' => 'Capriciousness',
+ 'timestamp' => '19370101000000',
+ 'expiry' => 'infinity',
+ 'enableAutoblock' => true,
+ ] );
+ $block->insert();
+
+ $name = ucfirst( __FUNCTION__ );
+ $id = $this->createPage( $name );
+
+ try {
+ $this->doApiRequestWithToken( [
+ 'action' => 'move',
+ 'from' => $name,
+ 'to' => "$name 2",
+ ] );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( ApiUsageException $ex ) {
+ $this->assertSame( 'You have been blocked from editing.', $ex->getMessage() );
+ $this->assertNotNull( Block::newFromTarget( '127.0.0.1' ), 'Autoblock spread' );
+ } finally {
+ $block->delete();
+ self::$users['sysop']->getUser()->clearInstanceCache();
+ $this->assertSame( $id, Title::newFromText( $name )->getArticleID() );
+ }
+ }
+
// @todo File moving
public function testPingLimiter() {
class MessageBlobStoreTest extends PHPUnit\Framework\TestCase {
use MediaWikiCoversValidator;
+ use PHPUnit4And6Compat;
protected function setUp() {
parent::setUp();
protected function makeBlobStore( $methods = null, $rl = null ) {
$blobStore = $this->getMockBuilder( MessageBlobStore::class )
- ->setConstructorArgs( [ $rl ] )
+ ->setConstructorArgs( [ $rl ?? $this->createMock( ResourceLoader::class ) ] )
->setMethods( $methods )
->getMock();