tables.
* Added $wgEnableParserLimitReporting to control whether the NewPP limit report is
output in a HTML comment.
+* The 'UnwatchArticle' and 'WatchArticle' hooks now support a Status object
+ instead of just a boolean return value to abort the hook.
=== Bug fixes in 1.22 ===
* Disable Special:PasswordReset when $wgEnableEmail is false. Previously one
user blocks.
* (bug 48201) action=parse&text=foo now assumes wikitext if no title is given,
rather than using the content model of the page "API".
-* action=watch may now return errors.
+* action=watch no longer silently ignores hook abort.
* (bug 50785) action=purge with forcelinkupdate=1 no longer queues refreshLinks
jobs in the job queue for link table updates of pages that use the given page
as a template. Instead, forcerecursivelinkupdate=1 is introduced and should
to the Vector skin in core.
* SpecialRecentChanges::addRecentChangesJS() function has been renamed
to addModules() and made protected.
+* Methods WatchAction::doWatch and WatchAction::doUnwatch now return a Status
+ object instead of a boolean.
== Compatibility ==
return $this;
}
+ /**
+ * Add parameters that are durations of time and will be passed through
+ * Language::formatDuration before substitution
+ * @since 1.22
+ * @param Varargs: numeric parameters (or single argument that is array of numeric parameters)
+ * @return Message: $this
+ */
+ public function durationParams( /*...*/ ) {
+ $params = func_get_args();
+ if ( isset( $params[0] ) && is_array( $params[0] ) ) {
+ $params = $params[0];
+ }
+ foreach ( $params as $param ) {
+ $this->parameters[] = self::durationParam( $param );
+ }
+ return $this;
+ }
+
+ /**
+ * Add parameters that are expiration times and will be passed through
+ * Language::formatExpiry before substitution
+ * @since 1.22
+ * @param Varargs: numeric parameters (or single argument that is array of numeric parameters)
+ * @return Message: $this
+ */
+ public function expiryParams( /*...*/ ) {
+ $params = func_get_args();
+ if ( isset( $params[0] ) && is_array( $params[0] ) ) {
+ $params = $params[0];
+ }
+ foreach ( $params as $param ) {
+ $this->parameters[] = self::expiryParam( $param );
+ }
+ return $this;
+ }
+
+ /**
+ * Add parameters that are time periods and will be passed through
+ * Language::formatTimePeriod before substitution
+ * @since 1.22
+ * @param Varargs: numeric parameters (or single argument that is array of numeric parameters)
+ * @return Message: $this
+ */
+ public function timeperiodParams( /*...*/ ) {
+ $params = func_get_args();
+ if ( isset( $params[0] ) && is_array( $params[0] ) ) {
+ $params = $params[0];
+ }
+ foreach ( $params as $param ) {
+ $this->parameters[] = self::timeperiodParam( $param );
+ }
+ return $this;
+ }
+
+ /**
+ * Add parameters that are file sizes and will be passed through
+ * Language::formatSize before substitution
+ * @since 1.22
+ * @param Varargs: numeric parameters (or single argument that is array of numeric parameters)
+ * @return Message: $this
+ */
+ public function sizeParams( /*...*/ ) {
+ $params = func_get_args();
+ if ( isset( $params[0] ) && is_array( $params[0] ) ) {
+ $params = $params[0];
+ }
+ foreach ( $params as $param ) {
+ $this->parameters[] = self::sizeParam( $param );
+ }
+ return $this;
+ }
+
+ /**
+ * Add parameters that are bitrates and will be passed through
+ * Language::formatBitrate before substitution
+ * @since 1.22
+ * @param Varargs: numeric parameters (or single argument that is array of numeric parameters)
+ * @return Message: $this
+ */
+ public function bitrateParams( /*...*/ ) {
+ $params = func_get_args();
+ if ( isset( $params[0] ) && is_array( $params[0] ) ) {
+ $params = $params[0];
+ }
+ foreach ( $params as $param ) {
+ $this->parameters[] = self::bitrateParam( $param );
+ }
+ return $this;
+ }
+
/**
* Set the language and the title from a context object
* @since 1.19
return array( 'num' => $value );
}
+ /**
+ * @since 1.22
+ * @param $value
+ * @return array
+ */
+ public static function durationParam( $value ) {
+ return array( 'duration' => $value );
+ }
+
+ /**
+ * @since 1.22
+ * @param $value
+ * @return array
+ */
+ public static function expiryParam( $value ) {
+ return array( 'expiry' => $value );
+ }
+
+ /**
+ * @since 1.22
+ * @param $value
+ * @return array
+ */
+ public static function timeperiodParam( $value ) {
+ return array( 'period' => $value );
+ }
+
+ /**
+ * @since 1.22
+ * @param $value
+ * @return array
+ */
+ public static function sizeParam( $value ) {
+ return array( 'size' => $value );
+ }
+
+ /**
+ * @since 1.22
+ * @param $value
+ * @return array
+ */
+ public static function bitrateParam( $value ) {
+ return array( 'bitrate' => $value );
+ }
+
/**
* Substitutes any parameters into the message text.
* @since 1.17
* @return Tuple(type, value)
*/
protected function extractParam( $param ) {
- if ( is_array( $param ) && isset( $param['raw'] ) ) {
- return array( 'after', $param['raw'] );
- } elseif ( is_array( $param ) && isset( $param['num'] ) ) {
- // Replace number params always in before step for now.
- // No support for combined raw and num params
- return array( 'before', $this->language->formatNum( $param['num'] ) );
- } elseif ( !is_array( $param ) ) {
- return array( 'before', $param );
+ if ( is_array( $param ) ){
+ if ( isset( $param['raw'] ) ) {
+ return array( 'after', $param['raw'] );
+ } elseif ( isset( $param['num'] ) ) {
+ // Replace number params always in before step for now.
+ // No support for combined raw and num params
+ return array( 'before', $this->language->formatNum( $param['num'] ) );
+ } elseif ( isset( $param['duration'] ) ) {
+ return array( 'before', $this->language->formatDuration( $param['duration'] ) );
+ } elseif ( isset( $param['expiry'] ) ) {
+ return array( 'before', $this->language->formatExpiry( $param['expiry'] ) );
+ } elseif ( isset( $param['period'] ) ) {
+ return array( 'before', $this->language->formatTimePeriod( $param['period'] ) );
+ } elseif ( isset( $param['size'] ) ) {
+ return array( 'before', $this->language->formatSize( $param['size'] ) );
+ } elseif ( isset( $param['bitrate'] ) ) {
+ return array( 'before', $this->language->formatBitrate( $param['bitrate'] ) );
+ } else {
+ trigger_error(
+ "Invalid message parameter: " . htmlspecialchars( serialize( $param ) ),
+ E_USER_WARNING
+ );
+ return array( 'before', '[INVALID]' );
+ }
} else {
- trigger_error(
- "Invalid message parameter: " . htmlspecialchars( serialize( $param ) ),
- E_USER_WARNING
- );
- return array( 'before', '[INVALID]' );
+ return array( 'before', $param );
}
}
* Once the return value goes out scope, the locks will be released and
* the status updated. Unlock fatals will not change the status "OK" value.
*
- * @param array $paths Storage paths
- * @param integer $type LockManager::LOCK_* constant
+ * @see ScopedLock::factory()
+ *
+ * @param array $paths List of storage paths or map of lock types to path lists
+ * @param integer|string $type LockManager::LOCK_* constant or "mixed"
* @param Status $status Status to update on lock/unlock
* @return ScopedLock|null Returns null on failure
*/
$mbe = $this->backends[$this->masterIndex]; // convenience
- // Get the paths to lock from the master backend
- $realOps = $this->substOpBatchPaths( $ops, $mbe );
- $paths = $mbe->getPathsToLockForOpsInternal( $mbe->getOperationsInternal( $realOps ) );
- // Get the paths under the proxy backend's name
- $paths['sh'] = $this->unsubstPaths( $paths['sh'] );
- $paths['ex'] = $this->unsubstPaths( $paths['ex'] );
// Try to lock those files for the scope of this function...
if ( empty( $opts['nonLocking'] ) ) {
// Try to lock those files for the scope of this function...
- $scopeLockS = $this->getScopedFileLocks( $paths['sh'], LockManager::LOCK_UW, $status );
- $scopeLockE = $this->getScopedFileLocks( $paths['ex'], LockManager::LOCK_EX, $status );
+ $scopeLock = $this->getScopedLocksForOps( $ops, $status );
if ( !$status->isOK() ) {
return $status; // abort
}
}
}
// Actually attempt the operation batch on the master backend...
+ $realOps = $this->substOpBatchPaths( $ops, $mbe );
$masterStatus = $mbe->doOperations( $realOps, $opts );
$status->merge( $masterStatus );
// Propagate the operations to the clone backends if there were no unexpected errors
}
public function getScopedLocksForOps( array $ops, Status $status ) {
- $fileOps = $this->backends[$this->masterIndex]->getOperationsInternal( $ops );
+ $realOps = $this->substOpBatchPaths( $ops, $this->backends[$this->masterIndex] );
+ $fileOps = $this->backends[$this->masterIndex]->getOperationsInternal( $realOps );
// Get the paths to lock from the master backend
$paths = $this->backends[$this->masterIndex]->getPathsToLockForOpsInternal( $fileOps );
// Get the paths under the proxy backend's name
- $paths['sh'] = $this->unsubstPaths( $paths['sh'] );
- $paths['ex'] = $this->unsubstPaths( $paths['ex'] );
- return array(
- $this->getScopedFileLocks( $paths['sh'], LockManager::LOCK_UW, $status ),
- $this->getScopedFileLocks( $paths['ex'], LockManager::LOCK_EX, $status )
+ $pbPaths = array(
+ LockManager::LOCK_UW => $this->unsubstPaths( $paths[LockManager::LOCK_UW] ),
+ LockManager::LOCK_EX => $this->unsubstPaths( $paths[LockManager::LOCK_EX] )
);
+ // Actually acquire the locks
+ return array( $this->getScopedFileLocks( $pbPaths, 'mixed', $status ) );
}
}
/**
* Get a list of storage paths to lock for a list of operations
- * Returns an array with 'sh' (shared) and 'ex' (exclusive) keys,
- * each corresponding to a list of storage paths to be locked.
- * All returned paths are normalized.
+ * Returns an array with LockManager::LOCK_UW (shared locks) and
+ * LockManager::LOCK_EX (exclusive locks) keys, each corresponding
+ * to a list of storage paths to be locked. All returned paths are
+ * normalized.
*
* @param array $performOps List of FileOp objects
- * @return Array ('sh' => list of paths, 'ex' => list of paths)
+ * @return Array (LockManager::LOCK_UW => path list, LockManager::LOCK_EX => path list)
*/
final public function getPathsToLockForOpsInternal( array $performOps ) {
// Build up a list of files to lock...
// Get a shared lock on the parent directory of each path changed
$paths['sh'] = array_merge( $paths['sh'], array_map( 'dirname', $paths['ex'] ) );
- return $paths;
+ return array(
+ LockManager::LOCK_UW => $paths['sh'],
+ LockManager::LOCK_EX => $paths['ex']
+ );
}
public function getScopedLocksForOps( array $ops, Status $status ) {
$paths = $this->getPathsToLockForOpsInternal( $this->getOperationsInternal( $ops ) );
- return array(
- $this->getScopedFileLocks( $paths['sh'], LockManager::LOCK_UW, $status ),
- $this->getScopedFileLocks( $paths['ex'], LockManager::LOCK_EX, $status )
- );
+ return array( $this->getScopedFileLocks( $paths, 'mixed', $status ) );
}
final protected function doOperationsInternal( array $ops, array $opts ) {
// Build up a list of files to lock...
$paths = $this->getPathsToLockForOpsInternal( $performOps );
// Try to lock those files for the scope of this function...
- $scopeLockS = $this->getScopedFileLocks( $paths['sh'], LockManager::LOCK_UW, $status );
- $scopeLockE = $this->getScopedFileLocks( $paths['ex'], LockManager::LOCK_EX, $status );
+ $scopeLock = $this->getScopedFileLocks( $paths, 'mixed', $status );
if ( !$status->isOK() ) {
return $status; // abort
}
wfDebugLog( 'imagemove', "Finished moving {$this->name}" );
- $this->purgeEverything();
- foreach ( $archiveNames as $archiveName ) {
- $this->purgeOldThumbnails( $archiveName );
- }
+ // Purge the source and target files...
+ $oldTitleFile = wfLocalFile( $this->title );
+ $newTitleFile = wfLocalFile( $target );
+ // Hack: the lock()/unlock() pair is nested in a transaction so the locking is not
+ // tied to BEGIN/COMMIT. To avoid slow purges in the transaction, move them outside.
+ $this->getRepo()->getMasterDB()->onTransactionIdle(
+ function() use ( $oldTitleFile, $newTitleFile, $archiveNames ) {
+ $oldTitleFile->purgeEverything();
+ foreach ( $archiveNames as $archiveName ) {
+ $oldTitleFile->purgeOldThumbnails( $archiveName );
+ }
+ $newTitleFile->purgeEverything();
+ }
+ );
+
if ( $status->isOK() ) {
// Now switch the object
$this->title = $target;
// Force regeneration of the name and hashpath
unset( $this->name );
unset( $this->hashPath );
- // Purge the new image
- $this->purgeEverything();
}
return $status;
// 1.15
array( 'doUniquePlTlIl' ),
array( 'addTable', 'change_tag', 'patch-change_tag.sql' ),
- /* array( 'addTable', 'tag_summary', 'patch-change_tag.sql' ), */
- /* array( 'addTable', 'valid_tag', 'patch-change_tag.sql' ), */
+ array( 'addTable', 'tag_summary', 'patch-tag_summary.sql' ),
+ array( 'addTable', 'valid_tag', 'patch-valid_tag.sql' ),
// 1.16
array( 'addTable', 'user_properties', 'patch-user_properties.sql' ),
// 1.15
array( 'addTable', 'change_tag', 'patch-change_tag.sql' ),
- array( 'addTable', 'tag_summary', 'patch-change_tag.sql' ),
- array( 'addTable', 'valid_tag', 'patch-change_tag.sql' ),
+ array( 'addTable', 'tag_summary', 'patch-tag_summary.sql' ),
+ array( 'addTable', 'valid_tag', 'patch-valid_tag.sql' ),
// 1.16
array( 'addTable', 'user_properties', 'patch-user_properties.sql' ),
protected $dupCache;
const QOS_ATOMIC = 1; // integer; "all-or-nothing" job insertions
- const QoS_Atomic = 1; // integer; "all-or-nothing" job insertions (b/c)
const ROOTJOB_TTL = 2419200; // integer; seconds to remember root jobs (28 days)
* @since 1.22
*/
class JobQueueFederated extends JobQueue {
- /** @var Array (partition name => weight) */
+ /** @var Array (partition name => weight) reverse sorted by weight */
protected $partitionMap = array();
- /** @var Array (partition name => JobQueue) */
+ /** @var Array (partition name => JobQueue) reverse sorted by weight */
protected $partitionQueues = array();
/** @var HashRing */
protected $partitionPushRing;
if ( !isset( $params['partitionsBySection'][$section] ) ) {
throw new MWException( "No configuration for section '$section'." );
}
+ // Get the full partition map
$this->partitionMap = $params['partitionsBySection'][$section];
+ arsort( $this->partitionMap, SORT_NUMERIC );
+ // Get the partitions jobs can actually be pushed to
$partitionPushMap = $this->partitionMap;
if ( isset( $params['partitionsNoPush'] ) ) {
foreach ( $params['partitionsNoPush'] as $partition ) {
$this->partitionQueues[$partition] = JobQueue::factory(
$baseConfig + $params['configByPartition'][$partition] );
}
- // Get the ring of partitions to push job de-duplication information into
+ // Get the ring of partitions to push jobs into
$this->partitionPushRing = new HashRing( $partitionPushMap );
// Aggregate cache some per-queue values if there are multiple partition queues
$this->cache = count( $this->partitionMap ) > 1 ? wfGetMainCache() : new EmptyBagOStuff();
return false;
}
} catch ( JobQueueError $e ) {
- wfDebugLog( 'exception', $e->getLogMessage() );
+ MWExceptionHandler::logException( $e );
}
}
try {
$count += $queue->$method();
} catch ( JobQueueError $e ) {
- wfDebugLog( 'exception', $e->getLogMessage() );
+ MWExceptionHandler::logException( $e );
}
}
$ok = $queue->doBatchPush( $jobBatch, $flags | self::QOS_ATOMIC );
} catch ( JobQueueError $e ) {
$ok = false;
- wfDebugLog( 'exception', $e->getLogMessage() );
+ MWExceptionHandler::logException( $e );
}
if ( $ok ) {
$key = $this->getCacheKey( 'empty' );
$ok = $queue->doBatchPush( $jobBatch, $flags | self::QOS_ATOMIC );
} catch ( JobQueueError $e ) {
$ok = false;
- wfDebugLog( 'exception', $e->getLogMessage() );
+ MWExceptionHandler::logException( $e );
}
if ( $ok ) {
$key = $this->getCacheKey( 'empty' );
$job = $queue->pop();
} catch ( JobQueueError $e ) {
$job = false;
- wfDebugLog( 'exception', $e->getLogMessage() );
+ MWExceptionHandler::logException( $e );
}
if ( $job ) {
$job->metadata['QueuePartition'] = $partition;
$partitions = $this->partitionPushRing->getLocations( $params['rootJobSignature'], 2 );
try {
return $this->partitionQueues[$partitions[0]]->doIsRootJobOldDuplicate( $job );
- } catch ( MWException $e ) {
+ } catch ( JobQueueError $e ) {
if ( isset( $partitions[1] ) ) { // check fallback partition
return $this->partitionQueues[$partitions[1]]->doIsRootJobOldDuplicate( $job );
}
$partitions = $this->partitionPushRing->getLocations( $params['rootJobSignature'], 2 );
try {
return $this->partitionQueues[$partitions[0]]->doDeduplicateRootJob( $job );
- } catch ( MWException $e ) {
+ } catch ( JobQueueError $e ) {
if ( isset( $partitions[1] ) ) { // check fallback partition
return $this->partitionQueues[$partitions[1]]->doDeduplicateRootJob( $job );
}
try {
$queue->doDelete();
} catch ( JobQueueError $e ) {
- wfDebugLog( 'exception', $e->getLogMessage() );
+ MWExceptionHandler::logException( $e );
}
}
}
try {
$queue->waitForBackups();
} catch ( JobQueueError $e ) {
- wfDebugLog( 'exception', $e->getLogMessage() );
+ MWExceptionHandler::logException( $e );
}
}
}
try {
$nonEmpty = $queue->doGetSiblingQueuesWithJobs( $types );
if ( is_array( $nonEmpty ) ) {
- $result = array_merge( $result, $nonEmpty );
+ $result = array_unique( array_merge( $result, $nonEmpty ) );
} else {
return null; // not supported on all partitions; bail
}
+ if ( count( $result ) == count( $types ) ) {
+ break; // short-circuit
+ }
} catch ( JobQueueError $e ) {
- wfDebugLog( 'exception', $e->getLogMessage() );
+ MWExceptionHandler::logException( $e );
}
}
- return array_values( array_unique( $result ) );
+ return array_values( $result );
}
protected function doGetSiblingQueueSizes( array $types ) {
return null; // not supported on all partitions; bail
}
} catch ( JobQueueError $e ) {
- wfDebugLog( 'exception', $e->getLogMessage() );
+ MWExceptionHandler::logException( $e );
}
}
return $result;
'email-address-validity-invalid' => 'أدخل عنوان بريد إلكتروني صالح',
# User rights
-'userrights' => 'إدارة صÙ\84اØÙ\8aات اÙ\84Ù\85ستخدÙ\85',
+'userrights' => 'صلاحيات المستخدم',
'userrights-lookup-user' => 'أدِر مجموعات المستخدم',
'userrights-user-editname' => 'أدخل اسم مستخدم:',
'editusergroup' => 'عدل مجموعات المستخدم',
'sp-contributions-uploads' => 'مرفوعات',
'sp-contributions-logs' => 'سجلات',
'sp-contributions-talk' => 'نقاش',
-'sp-contributions-userrights' => 'إدارة صÙ\84اØÙ\8aات اÙ\84Ù\85ستخدÙ\85',
+'sp-contributions-userrights' => 'صلاحيات المستخدم',
'sp-contributions-blocked-notice' => 'هذا المستخدم ممنوع حاليا.
إن آخر مدخلة في سجل المنع موجودة أدناه كمرجع:',
'sp-contributions-blocked-notice-anon' => 'عنوان الأيبي هذا ممنوع حاليا.
'tags-tag' => 'اسم الوسم',
'tags-display-header' => 'الظهور في قوائم التغييرات',
'tags-description-header' => 'وصف كامل للمعنى',
+'tags-active-header' => 'نشط؟',
'tags-hitcount-header' => 'تغييرات موسومة',
+'tags-active-yes' => 'نعم',
+'tags-active-no' => 'لا',
'tags-edit' => 'عدل',
'tags-hitcount' => '{{PLURAL:$1|لا تغييرات|تغيير واحد|تغييران|$1 تغييرات|$1 تغييرا|$1 تغيير}}',
'revdelete-uname-unhid' => 'Benutzername freigegeben',
'revdelete-restricted' => 'Einschränkungen gelten auch für Administratoren',
'revdelete-unrestricted' => 'Einschränkungen für Administratoren aufgehoben',
-'logentry-move-move' => '$1 {{GENDER:$2|verschob}} Seite $3 nach $4',
-'logentry-move-move-noredirect' => '$1 {{GENDER:$2|verschob}} Seite $3 nach $4, ohne dabei eine Weiterleitung anzulegen',
-'logentry-move-move_redir' => '$1 {{GENDER:$2|verschob}} Seite $3 nach $4 und überschrieb dabei eine Weiterleitung',
-'logentry-move-move_redir-noredirect' => '$1 {{GENDER:$2|verschob}} Seite $3 nach $4 und überschrieb dabei eine Weiterleitung, ohne selbst eine Weiterleitung anzulegen',
-'logentry-patrol-patrol' => '$1 {{GENDER:$2|markierte}} Version $4 von Seite $3 als kontrolliert',
-'logentry-patrol-patrol-auto' => '$1 {{GENDER:$2|markierte}} automatisch Version $4 von Seite $3 als kontrolliert',
+'logentry-move-move' => '$1 {{GENDER:$2|verschob}} die Seite $3 nach $4',
+'logentry-move-move-noredirect' => '$1 {{GENDER:$2|verschob}} die Seite $3 nach $4, ohne dabei eine Weiterleitung anzulegen',
+'logentry-move-move_redir' => '$1 {{GENDER:$2|verschob}} die Seite $3 nach $4 und überschrieb dabei eine Weiterleitung',
+'logentry-move-move_redir-noredirect' => '$1 {{GENDER:$2|verschob}} die Seite $3 nach $4 und überschrieb dabei eine Weiterleitung, ohne selbst eine Weiterleitung anzulegen',
+'logentry-patrol-patrol' => '$1 {{GENDER:$2|markierte}} die Version $4 von Seite $3 als kontrolliert',
+'logentry-patrol-patrol-auto' => '$1 {{GENDER:$2|markierte}} automatisch die Version $4 von Seite $3 als kontrolliert',
'logentry-newusers-newusers' => 'Benutzerkonto $1 wurde {{GENDER:$2|erstellt}}',
'logentry-newusers-create' => 'Benutzerkonto $1 wurde {{GENDER:$2|erstellt}}',
'logentry-newusers-create2' => 'Benutzerkonto $3 wurde von $1 {{GENDER:$2|erstellt}}',
'articlepage' => 'View content page',
'talk' => 'Discussion',
'views' => 'Views',
-'toolbox' => 'Toolbox',
+'toolbox' => 'Tools',
'userpage' => 'View user page',
'projectpage' => 'View project page',
'imagepage' => 'View file page',
'right-editmyprivateinfo' => 'دادههای خصوصی خود را ویرایش کنید (مانند رایانشانی و نام واقعی)',
'right-editmyoptions' => 'ترجیحات خود را ویرایش',
'right-rollback' => 'واگردانی سریع ویرایشهای آخرین کاربری که یک صفحه را ویرایش کردهاست',
-'right-markbotedits' => 'علامت زدن ویرایشهای واگردانی شده به عنوان ویرایش ربات',
+'right-markbotedits' => 'علامتزدن ویرایشهای واگردانیشده بهعنوان ویرایش ربات',
'right-noratelimit' => 'تاثیر نپذیرفتن از محدودیت سرعت',
'right-import' => 'وارد کردن صفحه از ویکیهای دیگر',
'right-importupload' => 'وارد کردن صفحه از طریق بارگذاری پرونده',
'movenotallowedfile' => 'شما اجازهٔ انتقال پروندهها را ندارید.',
'cant-move-user-page' => 'شما اجازه ندارید صفحههای کاربری سرشاخه را انتقال دهید.',
'cant-move-to-user-page' => 'شما اجازه ندارید که یک صفحه را به یک صفحهٔ کاربر انتقال دهید (به استثنای زیر صفحههای کاربری).',
-'newtitle' => 'به عنوان جدید',
+'newtitle' => 'بهعنوان جدید',
'move-watch' => 'پیگیری صفحههای مبدأ و مقصد',
'movepagebtn' => 'صفحه منتقل شود',
'pagemovedsub' => 'انتقال با موفقیت انجام شد',
'specialpage' => 'विशेष पृष्ठ',
'personaltools' => 'वैयक्तिक औज़ार',
'postcomment' => 'नया अनुभाग',
-'articlepage' => 'लà¥\87à¤\96 देखें',
+'articlepage' => 'सामà¤\97à¥\8dरà¥\80 पà¥\83षà¥\8dठदेखें',
'talk' => 'चर्चा',
'views' => 'दर्शाव',
'toolbox' => 'साधन पेटी',
'aboutsite' => '{{SITENAME}} के बारे में',
'aboutpage' => 'Project:परिचय',
'copyright' => 'उपलब्ध सामग्री $1 के अधीन है जब तक अलग से उल्लेख ना किया गया हो।',
-'copyrightpage' => '{{ns:project}}:सरà¥\8dवाधिà¤\95ार',
+'copyrightpage' => '{{ns:project}}:à¤\95à¥\89पà¥\80राà¤\87à¤\9f',
'currentevents' => 'हाल की घटनाएँ',
'currentevents-url' => 'Project:हाल की घटनाएँ',
'disclaimers' => 'अस्वीकरण',
'hidetoc' => 'छिपाएँ',
'collapsible-collapse' => 'छोटा करें',
'collapsible-expand' => 'विस्तार करें',
-'thisisdeleted' => '$1 दà¥\87à¤\96à¥\87à¤\82 या बदलà¥\87à¤\82?',
+'thisisdeleted' => '$1 दà¥\87à¤\96à¥\87à¤\82 या वापिस लाà¤\8fà¤\81?',
'viewdeleted' => '$1 दिखायें?',
'restorelink' => '{{PLURAL:$1|एक हटाया हुआ|$1 हटाये हुए}} बदलाव',
'feedlinks' => 'फ़ीड:',
'prefs-personal' => 'सदस्य व्यक्तिरेखा',
'prefs-rc' => 'हाल में हुए बदलाव',
'prefs-watchlist' => 'ध्यानसूची',
-'prefs-watchlist-days' => 'ध्यानसूचीमें दिखाने के दिन:',
+'prefs-watchlist-days' => 'ध्यानसूची में दिखाने के दिन:',
'prefs-watchlist-days-max' => 'अधिकतम $1 {{PLURAL:$1|दिन}}',
'prefs-watchlist-edits' => 'बढ़ाई हुई ध्यानसूची में दिखाने हेतु अधिकतम बदलाव:',
-'prefs-watchlist-edits-max' => 'à¤\85धिà¤\95तम सà¤\82à¤\96à¥\8dया: १०००',
+'prefs-watchlist-edits-max' => 'à¤\85धिà¤\95तम सà¤\82à¤\96à¥\8dया: à¤\8fà¤\95 हà¤\9c़ार',
'prefs-watchlist-token' => 'ध्यानसूची टोकन',
'prefs-misc' => 'अन्य',
'prefs-resetpass' => 'कूटशब्द बदलें',
'newuserlogpagetext' => 'यह सदस्य खातों के निर्माण का लॉग है।',
# User rights log
-'rightslog' => 'सदसà¥\8dय à¤\85धिà¤\95ार सà¥\82à¤\9aà¥\80',
+'rightslog' => 'सदसà¥\8dय à¤\85धिà¤\95ार लà¥\89à¤\97',
'rightslogtext' => 'यह सदस्य अधिकारों में हुए बदलावों की सूची है।',
# Associated actions - in the sentence "You do not have permission to X"
'action-block' => 'इस सदस्य को संपादन करने से ब्लॉक करने',
'action-protect' => 'इस पृष्ठ के सुरक्षा स्तर बदलने',
'action-rollback' => 'किसी पृष्ठ का अंतिम सम्पादन करने वाले सदस्य के सम्पादन वापिस लेने',
-'action-import' => 'à¤\95िसà¥\80 à¤\94र विà¤\95ि सà¥\87 यह पà¥\83षà¥\8dठà¤\86यात à¤\95रनà¥\87',
+'action-import' => 'किसी और विकि से पृष्ठ आयात करने',
'action-importupload' => 'फ़ाइल अपलोड द्वारा यह पृष्ठ आयात करे',
'action-patrol' => 'अन्य सदस्यों के सम्पादन परीक्षित करने',
'action-autopatrol' => 'अपने सम्पादन स्वचालित रूप से परीक्षित करने',
'withoutinterwiki' => 'बिना अंतरविकि कड़ियों वाले पृष्ठ',
'withoutinterwiki-summary' => 'निम्न पृष्ठ अन्य भाषाओं के अवतरणों से नहीं जुड़ते हैं।',
-'withoutinterwiki-legend' => 'à¤\89पपद',
+'withoutinterwiki-legend' => 'à¤\89पसरà¥\8dà¤\97',
'withoutinterwiki-submit' => 'दिखायें',
'fewestrevisions' => 'सबसे कम अवतरणों वाले पृष्ठ',
'listusers' => 'सदस्यसूची',
'listusers-editsonly' => 'केवल संपादन कर चुके सदस्य दिखाएँ',
'listusers-creationsort' => 'निर्माण तिथि के आधार पर क्रमांकन करें',
-'usereditcount' => '$1 {{PLURAL:$1|सà¤\82पादन|सà¤\82पादन}}',
+'usereditcount' => '$1 {{PLURAL:$1|समà¥\8dपादन}}',
'usercreated' => '$1 को $2 बजे बनाया गया, सदस्यनाम $3 है',
'newpages' => 'नए पृष्ठ',
'newpages-username' => 'सदस्यनाम:',
# Special:Log
'specialloguserlabel' => 'कर्ता:',
-'speciallogtitlelabel' => 'प्रयोजन (शीर्षक):',
+'speciallogtitlelabel' => 'प्रयोजन (शीर्षक अथवा सदस्यनाम):',
'log' => 'लॉग',
'all-logs-page' => 'सभी सार्वजनिक लॉग',
'alllogstext' => '{{SITENAME}} की सभी उपलब्ध लॉगों की प्रविष्टियों का मिला-जुला प्रदर्शन।
'deleteotherreason' => 'अन्य/अतिरिक्त कारण:',
'deletereasonotherlist' => 'अन्य कारण',
'deletereason-dropdown' => '*हटाने के सामान्य कारण
-** लेखक की बिनती
+** स्पैम
+** बर्बरता
** कॉपीराइट उल्लंघन
-** बर्बरता',
+** लेखक का अनुरोध
+** टूटा अनुप्रेषण',
'delete-edit-reasonlist' => 'हटाने के कारण संपादित करें',
'delete-toobig' => 'इस पृष्ठ का संपादन इतिहास $1 से अधिक {{PLURAL:$1|अवतरण}} होने की वजह से बहुत बड़ा है।
{{SITENAME}} के अनपेक्षित रूप से बंद होने से रोकने के लिये ऐसे पृष्ठों को हटाने की अनुमति नहीं है।',
इस पृष्ठ का अन्तिम संपादन [[User:$3|$3]] ([[User talk:$3|वार्ता]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]) ने किया है।',
'editcomment' => "संपादन सारांश था: \"''\$1''\"।",
'revertpage' => '[[Special:Contributions/$2|$2]] ([[User talk:$2|Talk]]) के संपादनों को हटाकर [[User:$1|$1]] के अन्तिम अवतरण को पूर्ववत किया',
-'revertpage-nouser' => '(सदसà¥\8dय नाम हà¤\9fाया à¤\97या हà¥\88) दà¥\8dवारा à¤\95िà¤\8f à¤\97à¤\8f सà¤\82पादन à¤\95à¥\8b वापिस पà¥\81रानà¥\80 सà¥\8dथिति मà¥\87à¤\82 ला à¤\95र à¤\87सà¤\95à¥\87 पहलà¥\87 à¤\95à¥\87 [[User:$1|$1]] दà¥\8dवारा बनà¥\87 à¤\85वतरण à¤\95à¥\8b फिर सà¥\87 ताà¤\9c़ा à¤\85वतरण बनाया।',
+'revertpage-nouser' => '(सदसà¥\8dय नाम हà¤\9fाया à¤\97या हà¥\88) à¤\95à¥\87 सà¤\82पादनà¥\8bà¤\82 à¤\95à¥\8b हà¤\9fाà¤\95र {{GENDER:$1|[[User:$1|$1]]}} à¤\95à¥\87 à¤\85नà¥\8dतिम à¤\85वतरण à¤\95à¥\8b पà¥\82रà¥\8dववत à¤\95िया।',
'rollback-success' => '$1 के संपादन हटाए;
$2 द्वारा संपादित अन्तिम अवतरण को पुनर्स्थापित किया।',
**अफलदायी सम्पादन युद्ध
**अधिक यातायात वाला पृष्ठ',
'protect-edit-reasonlist' => 'सुरक्षा के कारण बदलें',
-'protect-expiry-options' => '१ à¤\98à¤\82à¤\9fा:1 hour,१ दिन:1 day,१ सपà¥\8dताह:1 week,२ सपà¥\8dताह:2 weeks,१ महà¥\80ना:1 month,३ महà¥\80नà¥\87:3 months,६ महà¥\80नà¥\87:6 months,१ साल:1 year,हमेशा के लिए:infinite',
+'protect-expiry-options' => 'à¤\8fà¤\95 à¤\98à¤\82à¤\9fा:1 hour,à¤\8fà¤\95 दिन:1 day,à¤\8fà¤\95 सपà¥\8dताह:1 week,दà¥\8b सपà¥\8dताह:2 weeks,à¤\8fà¤\95 महà¥\80ना:1 month,तà¥\80न महà¥\80नà¥\87:3 months,à¤\9bà¤\83 महà¥\80नà¥\87:6 months,à¤\8fà¤\95 साल:1 year,हमेशा के लिए:infinite',
'restriction-type' => 'अधिकार:',
'restriction-level' => 'सुरक्षा-स्तर:',
'minimum-size' => 'न्यूनतम आकार',
'restriction-level-all' => 'कोई भी स्तर',
# Undelete
-'undelete' => 'हà¤\9fाया पृष्ठ देखें',
+'undelete' => 'हà¤\9fाà¤\8f पृष्ठ देखें',
'undeletepage' => 'हटाए गए पृष्ठ देखें और पुनर्स्थापित करें',
'undeletepagetitle' => "'''नीचे [[:$1|$1]] के हटाए गए अवतरण दर्शाए गये हैं।'''",
'viewdeletedpage' => 'हटाए गए पृष्ठ देखें',
'undelete-fieldset-title' => 'अवतरण पुरानी स्थिति पर लाएँ',
'undeleteextrahelp' => "पृष्ठ का संपूर्ण इतिहास वापस लाने के लिए सभी बक्सों से सही का निशान हटा दें और '''''{{int:undeletebtn}}''''' पर क्लिक करें।
चुनिंदा इतिहास को वापस लाने के लिए उन अवतरणों के बगल के बक्सों पर सही का निशान लगाएँ और '''''{{int:undeletebtn}}''''' पर क्लिक करें।",
-'undeleterevisions' => '$1 {{PLURAL:$1|अवतरण}} लेखागार में हैं',
+'undeleterevisions' => '$1 अवतरण लेखागार में {{PLURAL:$1|है|हैं}}',
'undeletehistory' => 'यदि आप पृष्ठ को पुनर्स्थापित करते हैं तो सभी अवतरण इतिहास में पुनर्स्थापित हो जायेंगे।
हटाने के बाद यदि एक नया पृष्ठ उसी नाम से बनाया गया है तो पुनर्स्थापित अवतरण पिछले इतिहास में दर्शित होंगे।',
'undeleterevdel' => 'यदि पुनर्स्थापन के फलस्वरूप शीर्ष पृष्ठ या फ़ाइल अवतरण आंशिक रूप से मिट सकता है, तो इसे नहीं किया जायेगा।
ऐसी स्थिति में, आपको नवीनतम मिटाए गए अवतरण को बिना सही के निशान लगाये हुए या बिना छुपाये रखना होगा।',
-'undeletehistorynoadmin' => 'यह पà¥\83षà¥\8dठनिà¤\95ाल दिया गया है।
-निà¤\95ालà¥\87 à¤\9cानà¥\87 à¤\95ा à¤\95ारन नà¥\80à¤\9aà¥\87 साराà¤\82श मà¥\87à¤\82 दिया à¤\97या हà¥\88, à¤\94र साथ हà¥\80 à¤\89न सदसà¥\8dयà¥\8bà¤\82 à¤\95à¥\87 बारà¥\87 मà¥\87à¤\82 विसà¥\8dतार à¤à¥\80 दिया à¤\97या हà¥\88, à¤\9cिनà¥\8dहà¥\8bà¤\82नà¥\87 निà¤\95ालà¥\87 à¤\9cानà¥\87 सà¥\87 पहलà¥\87 à¤\87स पà¥\83षà¥\8dठà¤\95à¥\8b सà¤\82पादित à¤\95िया हà¥\88।
-à¤\87न हà¤\9fायà¥\87 à¤\97à¤\8f à¤\85वतरणà¥\8bà¤\82 à¤\95à¥\87 विदà¥\8dयमान विषय वसà¥\8dतà¥\81 à¤\95à¥\87वल पà¥\8dरशासकों को ही उपलब्ध है।',
+'undeletehistorynoadmin' => 'यह पà¥\83षà¥\8dठहà¤\9fा दिया गया है।
+हà¤\9fाà¤\8f à¤\9cानà¥\87 à¤\95ा à¤\95ारन नà¥\80à¤\9aà¥\87 साराà¤\82श मà¥\87à¤\82 दिया à¤\97या हà¥\88, à¤\94र साथ हà¥\80 à¤\89न सदसà¥\8dयà¥\8bà¤\82 à¤\95à¥\87 बारà¥\87 मà¥\87à¤\82 विसà¥\8dतार à¤à¥\80 दिया à¤\97या हà¥\88, à¤\9cिनà¥\8dहà¥\8bà¤\82नà¥\87 हà¤\9fाà¤\8f à¤\9cानà¥\87 सà¥\87 पहलà¥\87 à¤\87स पà¥\83षà¥\8dठà¤\95à¥\8b सà¤\82पादित à¤\95िया था।
+à¤\87न हà¤\9fायà¥\87 à¤\97à¤\8f à¤\85वतरणà¥\8bà¤\82 à¤\95ा पाठà¤\95à¥\87वल पà¥\8dरबà¤\82धकों को ही उपलब्ध है।',
'undelete-revision' => '$1 ($4 को $5 बजे $3 द्वारा बनाया गया) का मिटाया हुआ संस्करण:',
'undeleterevision-missing' => 'अमान्य अथवा अनुपस्थित अवतरण।
-या तà¥\8b à¤\86प à¤\97़लत समà¥\8dपरà¥\8dà¤\95 पà¥\8dरयà¥\8bà¤\97 à¤\95र रहà¥\87 हà¥\88à¤\82, या यह à¤\85वतरण पà¥\81नरà¥\8dसà¥\8dथापित à¤\95िया à¤\9cा à¤\9aà¥\81à¤\95ा हà¥\88, à¤\85थवा à¤\87सà¥\87 लà¥\87à¤\96ाà¤\97ार सà¥\87 निà¤\95ाल दिया गया है।',
-'undelete-nodiff' => 'पà¥\81रान à¤\85वतरण नहà¥\80à¤\82 हà¥\88à¤\82।',
+या तà¥\8b à¤\86प à¤\97़लत à¤\95ड़à¥\80 पà¥\8dरयà¥\8bà¤\97 à¤\95र रहà¥\87 हà¥\88à¤\82, या यह à¤\85वतरण पà¥\81नरà¥\8dसà¥\8dथापित à¤\95िया à¤\9cा à¤\9aà¥\81à¤\95ा हà¥\88, à¤\85थवा à¤\87सà¥\87 लà¥\87à¤\96ाà¤\97ार सà¥\87 हà¤\9fा दिया गया है।',
+'undelete-nodiff' => 'à¤\95à¥\8bà¤\88 पà¥\81राना à¤\85वतरण नहà¥\80à¤\82 मिला।',
'undeletebtn' => 'वापस ले आयें',
-'undeletelink' => 'दà¥\87à¤\96à¥\87à¤\82/पà¥\81रानà¥\80 सà¥\8dथिति पर लाà¤\8fà¤\81',
+'undeletelink' => 'दà¥\87à¤\96à¥\87à¤\82/पà¥\81नरà¥\8dसà¥\8dथापित à¤\95रà¥\87à¤\82',
'undeleteviewlink' => 'देखें',
'undeletereset' => 'पूर्ववत करें',
'undeleteinvert' => 'चुनाव उलटें',
'undeletecomment' => 'कारण:',
-'undeletedrevisions' => '{{PLURAL:$1|à¤\8fà¤\95 रà¥\82पानà¥\8dतर वापस लाया à¤\97या|$1 रà¥\82पानà¥\8dतर वापस लायà¥\87 à¤\97यà¥\87}} हà¥\88',
-'undeletedrevisions-files' => '{{PLURAL:$1|1 à¤\85वतरण|$1 à¤\85वतरण}} à¤\94र {{PLURAL:$2|1 फ़ाà¤\88ल|$2 फ़ाà¤\87लà¥\87à¤\82}} पà¥\81नरà¥\8dसà¥\8dथापित à¤\95र दियà¥\87ं',
-'undeletedfiles' => '{{PLURAL:$1|1 फ़ाà¤\88ल|$1 फ़ाà¤\88लें}} पुनर्स्थापित',
+'undeletedrevisions' => '{{PLURAL:$1|à¤\8fà¤\95 à¤\85वतरण पà¥\81नरà¥\8dसà¥\8dथापित à¤\95िया|$1 à¤\85वतरण पà¥\81नरà¥\8dसà¥\8dथापित à¤\95ियà¥\87}}',
+'undeletedrevisions-files' => '{{PLURAL:$1|1 à¤\85वतरण|$1 à¤\85वतरण}} à¤\94र {{PLURAL:$2|1 फ़ाà¤\87ल|$2 फ़ाà¤\87लà¥\87à¤\82}} पà¥\81नरà¥\8dसà¥\8dथापित à¤\95र दà¥\80ं',
+'undeletedfiles' => '{{PLURAL:$1|1 फ़ाà¤\87ल|$1 फ़ाà¤\87लें}} पुनर्स्थापित',
'cannotundelete' => 'पुनर्स्थापित नहीं कर सके:
$1',
'undeletedpage' => "'''$1 को पुनर्स्थापित कर दिया गया है'''
हाल में हटाये गये तथा पुनर्स्थापित किये गए पन्नों की जानकारी के लिये [[Special:Log/delete|हटाने की लॉग]] देखें।",
-'undelete-header' => 'हाल में हटाये गये पृष्ठ देखने के लियें [[Special:Log/delete|हटाने की सूची]] देखें।',
+'undelete-header' => 'हाल में हटाये गये पृष्ठ देखने के लिये [[Special:Log/delete|हटाने का लॉग]] देखें।',
'undelete-search-title' => 'हटाये गये पृष्ठ खोजें',
'undelete-search-box' => 'हटाये गये पृष्ठ खोजें',
'undelete-search-prefix' => 'शुरूआती शब्द अनुसार पृष्ठ खोजें:',
'undelete-search-submit' => 'खोजें',
-'undelete-no-results' => 'हà¤\9fायà¥\87à¤\82 à¤\97यà¥\87à¤\82 पनà¥\8dनà¥\8bà¤\82à¤\95à¥\87 à¤\86रà¥\8dà¤\9aिवà¥\8dहमà¥\87à¤\82 मà¥\87ल à¤\96ानà¥\87 वालà¥\87 पà¥\83षà¥\8dठमिलà¥\87 नहà¥\80à¤\82।',
-'undelete-filename-mismatch' => '$1 समयà¤\95à¥\87 फ़ाà¤\87लà¤\95à¥\87 हà¤\9fायà¥\87 à¤\97यà¥\87 à¤\85वतरणà¤\95à¥\8b पà¥\81नरà¥\8dसà¥\8dथापित नहà¥\80à¤\82 à¤\95िया à¤\9cा सà¤\95ता: फ़ाà¤\88ल का नाम मेल नहीं खाता',
-'undelete-bad-store-key' => '$1 समयà¤\95ा फ़ाà¤\88ल à¤\85वतरण पà¥\81नरà¥\8dसà¥\8dथापित नहà¥\80à¤\82 à¤\95र सà¤\95तà¥\87à¤\82 हà¥\88à¤\82: हà¤\9fानà¥\87 सà¥\87 पहलà¥\87 फ़ाà¤\88ल à¤\85सà¥\8dतितà¥\8dवमà¥\87à¤\82 नहीं थी।',
-'undelete-cleanup-error' => 'à¤\87सà¥\8dतà¥\87मालमà¥\87à¤\82 न लाà¤\88 à¤\97à¤\88 "$1" à¤\86रà¥\8dà¤\9aिवà¥\8dह फ़ाà¤\88ल हà¤\9fानà¥\87 मà¥\87à¤\82 समसà¥\8dया हà¥\81à¤\88 हà¥\88à¤\82।',
-'undelete-missing-filearchive' => 'सिà¤\9aिà¤\95ा पà¥\81रालà¥\87à¤\96 à¤\95à¥\8dरमाà¤\82à¤\95 $1 à¤\95à¥\8b पà¥\81नरà¥\8dसà¥\8dथापित à¤\95रनà¥\87 मà¥\87à¤\82 à¤\85सà¤\95à¥\8dषम हà¥\88à¤\82, à¤\95à¥\8dयà¥\8bà¤\82à¤\95ि यह à¤\86à¤\81à¤\95ड़ाà¤\95à¥\8bष में उपलब्ध नहीं है।
+'undelete-no-results' => 'हà¤\9fाà¤\8f à¤\97à¤\8f पà¥\83षà¥\8dठà¥\8bà¤\82 à¤\95à¥\87 लà¥\87à¤\96ाà¤\97ार मà¥\87à¤\82 मà¥\87ल à¤\96ातà¥\87 à¤\95à¥\8bà¤\88 पà¥\83षà¥\8dठनहà¥\80à¤\82 मिलà¥\87।',
+'undelete-filename-mismatch' => '$1 à¤\95à¥\87 फ़ाà¤\87ल à¤\95à¥\87 हà¤\9fायà¥\87 à¤\97यà¥\87 à¤\85वतरण à¤\95à¥\8b पà¥\81नरà¥\8dसà¥\8dथापित नहà¥\80à¤\82 à¤\95िया à¤\9cा सà¤\95ता: फ़ाà¤\87ल का नाम मेल नहीं खाता',
+'undelete-bad-store-key' => '$1 à¤\95ा फ़ाà¤\87ल à¤\85वतरण पà¥\81नरà¥\8dसà¥\8dथापित नहà¥\80à¤\82 à¤\95र सà¤\95तà¥\87 हà¥\88à¤\82: हà¤\9fानà¥\87 सà¥\87 पहलà¥\87 à¤à¥\80 फ़ाà¤\87ल मà¥\8cà¤\9cà¥\82द नहीं थी।',
+'undelete-cleanup-error' => 'पà¥\81रालà¥\87à¤\96 मà¥\87à¤\82 सà¥\87 à¤\85पà¥\8dरयà¥\81à¤\95à¥\8dत फ़ाà¤\87ल "$1" हà¤\9fानà¥\87 मà¥\87à¤\82 तà¥\8dरà¥\81à¤\9fि।',
+'undelete-missing-filearchive' => 'फ़ाà¤\87ल पà¥\81रालà¥\87à¤\96 à¤\86à¤\88॰डà¥\80 $1 à¤\95à¥\8b पà¥\81नरà¥\8dसà¥\8dथापित à¤\95रनà¥\87 मà¥\87à¤\82 à¤\85सà¤\95à¥\8dषम हà¥\88à¤\82, à¤\95à¥\8dयà¥\8bà¤\82à¤\95ि यह डाà¤\9fाबà¥\87स में उपलब्ध नहीं है।
या ऐसा भी हो सकता है कि इसे पहले से ही पुनर्स्थापित किया जा चुका हो।',
-'undelete-error' => 'पà¥\83षà¥\8dठà¤\85विलà¥\8bपन में त्रुटि',
-'undelete-error-short' => 'फ़ाà¤\88ल पà¥\81नरà¥\8dसà¥\8dथापित à¤\95रनà¥\87 मà¥\87à¤\82 समसà¥\8dया: $1',
-'undelete-error-long' => 'फ़ाà¤\88ल पà¥\81नरà¥\8dसà¥\8dथापित à¤\95रनà¥\87 मà¥\87à¤\82 à¤\86à¤\88 हà¥\81à¤\88 समसà¥\8dयाà¤\8fà¤\82:
+'undelete-error' => 'पà¥\83षà¥\8dठपà¥\81नरà¥\8dसà¥\8dथापन में त्रुटि',
+'undelete-error-short' => 'फ़ाà¤\87ल पà¥\81नरà¥\8dसà¥\8dथापन मà¥\87à¤\82 तà¥\8dरà¥\81à¤\9fि: $1',
+'undelete-error-long' => 'फ़ाà¤\87ल पà¥\81नरà¥\8dसà¥\8dथापन मà¥\87à¤\82 à¤\86à¤\88 तà¥\8dरà¥\81à¤\9fियाà¤\81:
$1',
'undelete-show-file-confirm' => 'क्या आप वाकई फ़ाइल "<nowiki>$1</nowiki>" के $2 को $3 बजे बने, हटाए जा चुके अवतरण को देखना चाहते हैं?',
'ipbenableautoblock' => 'इस सदस्यद्वारा इस्तेमाल किया गया आखिरी आईपी एड्रेस और यहां से आगे इस सदस्य द्वारा इस्तेमालमें लाये जाने वाले सभी एड्रेस ब्लॉक करें।',
'ipbsubmit' => 'इस सदस्य को और बदलाव करने से रोकें',
'ipbother' => 'अन्य समय:',
-'ipboptions' => '२ à¤\98à¤\82à¤\9fà¥\87:2 hours,१ दिन:1 day,३ दिन:3 days,१ हफà¥\8dता:1 week,२ हफà¥\8dतà¥\87:2 weeks,१ महिना:1 month,३ महिनà¥\87:3 months,६ महिनà¥\87:6 months,१ साल:1 year,हमेशा के लिये:infinite',
+'ipboptions' => 'दà¥\8b à¤\98à¤\82à¤\9fà¥\87:2 hours,à¤\8fà¤\95 दिन:1 day,तà¥\80न दिन:3 days,à¤\8fà¤\95 सपà¥\8dताह:1 week,दà¥\8b सपà¥\8dताह:2 weeks,à¤\8fà¤\95 महà¥\80ना:1 month,तà¥\80न महà¥\80नà¥\87:3 months,à¤\9bà¤\83 महà¥\80नà¥\87:6 months,à¤\8fà¤\95 साल:1 year,हमेशा के लिये:infinite',
'ipbotheroption' => 'अन्य',
'ipbotherreason' => 'अन्य/दूसरा कारण:',
'ipbhidename' => 'संपादन व सूचियों से सदस्य नाम छिपाएँ',
'tooltip-ca-protect' => 'इस पृष्ठको सुरक्षित किजीयें',
'tooltip-ca-unprotect' => 'इस पृष्ठ की सुरक्षा बदलें ।',
'tooltip-ca-delete' => 'इस पृष्ठ को हटाएं',
-'tooltip-ca-undelete' => 'इस पृष्ठको हटाने से पहले किये गये बदलाव पुनर्स्थापित करें',
+'tooltip-ca-undelete' => 'इस पृष्ठ को हटाने से पहले किये गये बदलाव पुनर्स्थापित करें',
'tooltip-ca-move' => 'यह पृष्ठ स्थानांतरित करें',
'tooltip-ca-watch' => 'इस पृष्ठ को अपनी ध्यानसूची में डालें',
'tooltip-ca-unwatch' => 'यह पृष्ठ अपने ध्यानसूचीसे हटाएं',
'userlogin-noaccount' => '계정이 없나요?',
'userlogin-joinproject' => '{{SITENAME}}에 가입하세요',
'nologin' => '계정이 없나요? $1.',
-'nologinlink' => 'ê³\84ì \95ì\9d\84 ë§\8cë\93\9cì\84¸ì\9a\94',
+'nologinlink' => 'ê³\84ì \95ì\9d\84 ë§\8cë\93¤ê¸°',
'createaccount' => '계정 만들기',
'gotaccount' => '계정이 이미 있다면, $1.',
'gotaccountlink' => '로그인하세요',
'deletereasonotherlist' => '다른 이유',
'deletereason-dropdown' => '* 일반적인 삭제 이유
** 스팸
-** 훼손 행위
+** 문서 훼손 행위
** 저작권 침해
** 작성자의 요청
** 깨진 넘겨주기',
'editingsection' => 'Modìfica ëd $1 (session)',
'editingcomment' => 'Modìfica ëd $1 (neuva session)',
'editconflict' => 'Conflit ëd modìfica: $1',
-'explainconflict' => "Cheidun d'àutr a l'ha salvà soa version dl'artìcol antramentré che chiel (chila) as prontava la soa.
+'explainconflict' => "Cheidun d'àutr a l'ha salvà soa version dl'artìcol antramentre che chiel as prontava la soa.
Ël quàder ëd modìfica dë dzora a mostra ël test ëd l'artìcol coma a resta adess (visadì, lòn che a-i é ant sla Ragnà). Soe modìfiche a stan ant ël quàder dë sota.
Ën volend a peul gionté soe modìfiche ant ël quàder dë dzora.
'''Mach''' ël test ant ël quàder dë dzora a sarà salvà, ën sgnacand ël boton \"{{int:savearticle}}\".",
'yourtext' => 'Sò test',
-'storedversion' => 'Version memorisà',
-'nonunicodebrowser' => "'''A L'EUJ! Sò programa ëd navigassion (browser) a travaja pa giust con lë stàndard unicode. I soma obligà a dovré dij truschin përchè a peula salvesse sò artìcoj sensa problema: ij caràter che a son nen ASCII a jë s-ciairerà ant ël quàder ëd modìfica test coma còdes esadecimaj.'''",
+'storedversion' => 'La version memorisà',
+'nonunicodebrowser' => "'''A L'EUJ! Sò programa ëd navigassion a marcia pa giust con lë stàndard Unicode. I soma obligà a dovré dij truschin përchè a peula salvesse sò artìcoj sensa problema: ij caràter che a son nen ASCII a jë s-ciairerà ant ël quàder ëd modìfica dël test coma còdes esadecimaj.'''",
'editingold' => "'''CHE A FASA MACH ATENSION: che a sta fasend-je dle modìfiche a na version nen agiornà dl'artìcol.<br />
Se a la salva parèj, lòn che a l'era stàit fàit dapress a sta revision-sì as perdrà d'autut.'''",
'yourdiff' => 'Diferense',
* @author Incnis Mrsi
* @author Iniquity
* @author Innv
+ * @author Ivan Shmakov
* @author Jackie
* @author JenVan
* @author Jl
'revdelete-concurrent-change' => 'Ошибка изменения записи от $2, $1: её статус был изменён кем-то другим, пока вы пытались изменить его.
Пожалуйста, проверьте журналы.',
'revdelete-only-restricted' => 'Ошибка сокрытия записи от $2 $1: вы не можете скрыть запись от просмотра администраторами без выбора одной из других настроек сокрытия.',
-'revdelete-reason-dropdown' => 'Стандартные причины удаления
+'revdelete-reason-dropdown' => '* Стандартные причины удаления
** Нарушение авторских прав
** Неуместные личные сведения
+** Неуместное имя участника
** Потенциально клеветнические сведения',
'revdelete-otherreason' => 'Другая/дополнительная причина:',
'revdelete-reasonotherlist' => 'Другая причина',
'tog-newpageshidepatrolled' => 'Göm patrullerade sidor från listan över nya sidor',
'tog-extendwatchlist' => 'Utöka bevakningslistan till att visa alla ändringar, inte bara den senaste',
'tog-usenewrc' => 'Gruppera ändringar efter sida i senaste ändringar och bevakningslistan',
-'tog-numberheadings' => 'Numrerade rubriker',
+'tog-numberheadings' => 'Automatisk numrerade rubriker',
'tog-showtoolbar' => 'Visa redigerings-verktygsraden',
'tog-editondblclick' => 'Redigera sidor med dubbelklick',
'tog-editsection' => 'Aktivera redigering av avsnitt genom [redigera]-länkar',
'userlogin-resetpassword-link' => 'צוריקשטעלן אײַער פאַסווארט',
'helplogin-url' => 'Help:אריינלאגירן',
'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|הילף מיט אריינלאגירן]]',
+'userlogin-loggedin' => 'איר זענט שוין אריינלאגירט ווי {{GENDER:$1|$1}}.
+ניצט די פארעם אונטן כדי אריינלאגירן ווי אן אנדער באניצער.',
'userlogin-createanother' => 'שאפֿן נאך א קאנטע',
'createacct-join' => 'גיט ארײַן אײַער אינפֿארמאציע אונטן.',
'createacct-another-join' => 'ארײַנגעבן דער נײַער קאנטעס אינפארמאציע אונטן.',
CREATE UNIQUE INDEX /*i*/change_tag_rev_tag ON /*_*/change_tag (ct_rev_id,ct_tag);
-- Covering index, so we can pull all the info only out of the index.
CREATE INDEX /*i*/change_tag_tag_id ON /*_*/change_tag (ct_tag,ct_rc_id,ct_rev_id,ct_log_id);
-
--- Rollup table to pull a LIST of tags simply without ugly GROUP_CONCAT that only works on MySQL 4.1+
-CREATE TABLE /*_*/tag_summary (
- ts_rc_id int NULL,
- ts_log_id int NULL,
- ts_rev_id int NULL,
- ts_tags BLOB NOT NULL
-) /*$wgDBTableOptions*/;
-
-CREATE UNIQUE INDEX /*i*/tag_summary_rc_id ON /*_*/tag_summary (ts_rc_id);
-CREATE UNIQUE INDEX /*i*/tag_summary_log_id ON /*_*/tag_summary (ts_log_id);
-CREATE UNIQUE INDEX /*i*/tag_summary_rev_id ON /*_*/tag_summary (ts_rev_id);
-
-
-CREATE TABLE /*_*/valid_tag (
- vt_tag varchar(255) NOT NULL PRIMARY KEY
-) /*$wgDBTableOptions*/;
--- /dev/null
+-- Rollup table to pull a LIST of tags simply without ugly GROUP_CONCAT that only works on MySQL 4.1+
+-- Andrew Garrett, 2009-01
+CREATE TABLE /*_*/tag_summary (
+ ts_rc_id int NULL,
+ ts_log_id int NULL,
+ ts_rev_id int NULL,
+ ts_tags BLOB NOT NULL
+) /*$wgDBTableOptions*/;
+
+CREATE UNIQUE INDEX /*i*/tag_summary_rc_id ON /*_*/tag_summary (ts_rc_id);
+CREATE UNIQUE INDEX /*i*/tag_summary_log_id ON /*_*/tag_summary (ts_log_id);
+CREATE UNIQUE INDEX /*i*/tag_summary_rev_id ON /*_*/tag_summary (ts_rev_id);
--- /dev/null
+-- Andrew Garrett, 2009-01
+CREATE TABLE /*_*/valid_tag (
+ vt_tag varchar(255) NOT NULL PRIMARY KEY
+) /*$wgDBTableOptions*/;
$default = wfMessage( $key )->inLanguage( $langCode )->useDatabase( false )->plain();
$messageInfo['relevantPages']++;
- if ( $actual === $default ) {
+
+ if (
+ // Exclude messages that are empty by default, such as sitenotice, specialpage
+ // summaries and accesskeys.
+ $default !== '' && $default !== '-' &&
+ $actual === $default
+ ) {
$hasTalk = isset( $statuses['talks'][$key] );
$messageInfo['results'][] = array(
'title' => $key . $titleSuffix,
} else {
$props = FSFile::getPropsFromPath( $file );
$flags = 0;
- $options = array();
+ $publishOptions = array();
$handler = MediaHandler::getHandler( $props['mime'] );
if ( $handler ) {
- $options['headers'] = $handler->getStreamHeaders( $props['metadata'] );
+ $publishOptions['headers'] = $handler->getStreamHeaders( $props['metadata'] );
} else {
- $options['headers'] = array();
+ $publishOptions['headers'] = array();
}
- $archive = $image->publish( $file, $flags, $options );
+ $archive = $image->publish( $file, $flags, $publishOptions );
if ( !$archive->isGood() ) {
echo "failed. (" .
$archive->getWikiText() .
}
$commentText = SpecialUpload::getInitialPageText( $commentText, $license );
- if ( !$summary ) {
+ if ( !isset( $options['summary'] ) ) {
$summary = $commentText;
}
* @param {HTMLElement|jQuery|mw.Message|string} message
* @param {Object} options The options to use for the notification.
* See #defaults for details.
+ * @return {Object} Object with a close function to close the notification
*/
notify: function ( message, options ) {
var notif;
} else {
preReadyNotifQueue.push( notif );
}
+ return { close: $.proxy( notif.close, notif ) };
},
/**
/**
* @class mw.plugin.notify
*/
-( function ( mw ) {
+( function ( mw, $ ) {
'use strict';
/**
* @see mw.notification#notify
* @param message
* @param options
+ * @return {jQuery.Promise}
*/
mw.notify = function ( message, options ) {
+ var d = $.Deferred();
// Don't bother loading the whole notification system if we never use it.
mw.loader.using( 'mediawiki.notification', function () {
- // Don't bother calling mw.loader.using a second time after we've already loaded mw.notification.
- mw.notify = mw.notification.notify;
// Call notify with the notification the user requested of us.
- mw.notify( message, options );
- } );
+ d.resolve( mw.notification.notify( message, options ) );
+ }, d.reject );
+ return d.promise();
};
/**
* @mixins mw.plugin.notify
*/
-}( mediaWiki ) );
+}( mediaWiki, jQuery ) );
$this->assertEquals( 'abcdefghijka2', $msg->params( $params )->plain(), 'Params > 9 are replaced correctly' );
}
+ /**
+ * FIXME: This should not need database, but Language#formatExpiry does (bug 55912)
+ * @group Database
+ */
+ function testMessageParamTypes() {
+ $lang = Language::factory( 'en' );
+
+ $msg = new RawMessage( '$1' );
+ $this->assertEquals(
+ $lang->formatNum( 123456.789 ),
+ $msg->inLanguage( $lang )->numParams( 123456.789 )->plain(),
+ 'numParams is handled correctly'
+ );
+
+ $msg = new RawMessage( '$1' );
+ $this->assertEquals(
+ $lang->formatDuration( 1234 ),
+ $msg->inLanguage( $lang )->durationParams( 1234 )->plain(),
+ 'durationParams is handled correctly'
+ );
+
+ $msg = new RawMessage( '$1' );
+ $this->assertEquals(
+ $lang->formatExpiry( wfTimestampNow() ),
+ $msg->inLanguage( $lang )->expiryParams( wfTimestampNow() )->plain(),
+ 'expiryParams is handled correctly'
+ );
+
+ $msg = new RawMessage( '$1' );
+ $this->assertEquals(
+ $lang->formatTimePeriod( 1234 ),
+ $msg->inLanguage( $lang )->timeperiodParams( 1234 )->plain(),
+ 'timeperiodParams is handled correctly'
+ );
+
+ $msg = new RawMessage( '$1' );
+ $this->assertEquals(
+ $lang->formatSize( 123456 ),
+ $msg->inLanguage( $lang )->sizeParams( 123456 )->plain(),
+ 'sizeParams is handled correctly'
+ );
+
+ $msg = new RawMessage( '$1' );
+ $this->assertEquals(
+ $lang->formatBitrate( 123456 ),
+ $msg->inLanguage( $lang )->bitrateParams( 123456 )->plain(),
+ 'bitrateParams is handled correctly'
+ );
+ }
+
function testInContentLanguageDisabled() {
$this->setMwGlobals( 'wgLang', Language::factory( 'fr' ) );
* test usernames
*
* @dataProvider provideUserGenders
+ * @covers GenderCache::getGenderOf
*/
function testUserName( $username, $expectedGender ) {
$genderCache = GenderCache::singleton();
* genderCache should work with user objects, too
*
* @dataProvider provideUserGenders
+ * @covers GenderCache::getGenderOf
*/
function testUserObjects( $username, $expectedGender ) {
$genderCache = GenderCache::singleton();
* against the never existing username
*
* @dataProvider provideStripSubpages
+ * @covers GenderCache::getGenderOf
*/
function testStripSubpages( $pageWithSubpage, $expectedGender ) {
$genderCache = GenderCache::singleton();
/**
* @group Database
* @group Cache
+ * @covers MessageCache
*/
class MessageCacheTest extends MediaWikiLangTestCase {
/**
* @dataProvider dataGetDefaultModelFor
+ * @covers ContentHandler::getDefaultModelFor
*/
public function testGetDefaultModelFor( $title, $expectedModelId ) {
$title = Title::newFromText( $title );
/**
* @dataProvider dataGetDefaultModelFor
+ * @covers ContentHandler::getForTitle
*/
public function testGetForTitle( $title, $expectedContentModel ) {
$title = Title::newFromText( $title );
/**
* @dataProvider dataGetLocalizedName
+ * @covers ContentHandler::getLocalizedName
*/
public function testGetLocalizedName( $id, $expected ) {
$name = ContentHandler::getLocalizedName( $id );
/**
* @dataProvider dataGetPageLanguage
+ * @covers ContentHandler::getPageLanguage
*/
public function testGetPageLanguage( $title, $expected ) {
if ( is_string( $title ) ) {
/**
* @dataProvider dataGetContentText_Null
+ * @covers ContentHandler::getContentText
*/
public function testGetContentText_Null( $contentHandlerTextFallback ) {
$this->setMwGlobals( 'wgContentHandlerTextFallback', $contentHandlerTextFallback );
/**
* @dataProvider dataGetContentText_TextContent
+ * @covers ContentHandler::getContentText
*/
public function testGetContentText_TextContent( $contentHandlerTextFallback ) {
$this->setMwGlobals( 'wgContentHandlerTextFallback', $contentHandlerTextFallback );
/**
* ContentHandler::getContentText should have thrown an exception for non-text Content object
* @expectedException MWException
+ * @covers ContentHandler::getContentText
*/
public function testGetContentText_NonTextContent_fail() {
$this->setMwGlobals( 'wgContentHandlerTextFallback', 'fail' );
ContentHandler::getContentText( $content );
}
+ /**
+ * @covers ContentHandler::getContentText
+ */
public function testGetContentText_NonTextContent_serialize() {
$this->setMwGlobals( 'wgContentHandlerTextFallback', 'serialize' );
$this->assertEquals( $content->serialize(), $text );
}
+ /**
+ * @covers ContentHandler::getContentText
+ */
public function testGetContentText_NonTextContent_ignore() {
$this->setMwGlobals( 'wgContentHandlerTextFallback', 'ignore' );
/**
* @dataProvider dataMakeContent
+ * @covers ContentHandler::makeContent
*/
public function testMakeContent( $data, $title, $modelId, $format, $expectedModelId, $expectedNativeData, $shouldFail ) {
$title = Title::newFromText( $title );
}
*/
+ /**
+ * @covers ContentHandler::runLegacyHooks
+ */
public function testRunLegacyHooks() {
Hooks::register( 'testRunLegacyHooks', __CLASS__ . '::dummyHookHandler' );
);
}
+ /**
+ * @covers CssContent::getModel
+ */
public function testGetModel() {
$content = $this->newContent( 'hello world.' );
$this->assertEquals( CONTENT_MODEL_CSS, $content->getModel() );
}
+ /**
+ * @covers CssContent::getContentHandler
+ */
public function testGetContentHandler() {
$content = $this->newContent( 'hello world.' );
/**
* @dataProvider dataEquals
+ * @covers CssContent::equals
*/
public function testEquals( Content $a, Content $b = null, $equal = false ) {
$this->assertEquals( $equal, $a->equals( $b ) );
);
}
+ /**
+ * @covers JavaScriptContent::addSectionHeader
+ */
public function testAddSectionHeader() {
$content = $this->newContent( 'hello world' );
$c = $content->addSectionHeader( 'test' );
);
}
+ /**
+ * @covers JavaScriptContent::matchMagicWord
+ */
public function testMatchMagicWord() {
$mw = MagicWord::get( "staticredirect" );
$this->assertFalse( $content->matchMagicWord( $mw ), "should not have matched magic word, since it's not wikitext" );
}
+ /**
+ * @covers JavaScriptContent::updateRedirect
+ */
public function testUpdateRedirect() {
$target = Title::newFromText( "testUpdateRedirect_target" );
$this->assertTrue( $content->equals( $newContent ), "content should be unchanged since it's not wikitext" );
}
+ /**
+ * @covers JavaScriptContent::getModel
+ */
public function testGetModel() {
$content = $this->newContent( "hello world." );
$this->assertEquals( CONTENT_MODEL_JAVASCRIPT, $content->getModel() );
}
+ /**
+ * @covers JavaScriptContent::getContentHandler
+ */
public function testGetContentHandler() {
$content = $this->newContent( "hello world." );
/**
* @dataProvider dataGetParserOutput
+ * @covers TextContent::getParserOutput
*/
public function testGetParserOutput( $title, $model, $text, $expectedHtml, $expectedFields = null ) {
$title = Title::newFromText( $title );
/**
* @dataProvider dataPreSaveTransform
+ * @covers TextContent::preSaveTransform
*/
public function testPreSaveTransform( $text, $expected ) {
global $wgContLang;
/**
* @dataProvider dataPreloadTransform
+ * @covers TextContent::preloadTransform
*/
public function testPreloadTransform( $text, $expected ) {
global $wgContLang;
/**
* @dataProvider dataGetRedirectTarget
+ * @covers TextContent::getRedirectTarget
*/
public function testGetRedirectTarget( $text, $expected ) {
$content = $this->newContent( $text );
/**
* @dataProvider dataGetRedirectTarget
+ * @covers TextContent::isRedirect
*/
public function testIsRedirect( $text, $expected ) {
$content = $this->newContent( $text );
/**
* @dataProvider dataIsCountable
* @group Database
+ * @covers TextContent::isCountable
*/
public function testIsCountable( $text, $hasLinks, $mode, $expected ) {
$this->setMwGlobals( 'wgArticleCountMethod', $mode );
/**
* @dataProvider dataGetTextForSummary
+ * @covers TextContent::getTextForSummary
*/
public function testGetTextForSummary( $text, $maxlength, $expected ) {
$content = $this->newContent( $text );
$this->assertEquals( $expected, $content->getTextForSummary( $maxlength ) );
}
+ /**
+ * @covers TextContent::getTextForSearchIndex
+ */
public function testGetTextForSearchIndex() {
$content = $this->newContent( 'hello world.' );
$this->assertEquals( 'hello world.', $content->getTextForSearchIndex() );
}
+ /**
+ * @covers TextContent::copy
+ */
public function testCopy() {
$content = $this->newContent( 'hello world.' );
$copy = $content->copy();
$this->assertEquals( 'hello world.', $copy->getNativeData() );
}
+ /**
+ * @covers TextContent::getSize
+ */
public function testGetSize() {
$content = $this->newContent( 'hello world.' );
$this->assertEquals( 12, $content->getSize() );
}
+ /**
+ * @covers TextContent::getNativeData
+ */
public function testGetNativeData() {
$content = $this->newContent( 'hello world.' );
$this->assertEquals( 'hello world.', $content->getNativeData() );
}
+ /**
+ * @covers TextContent::getWikitextForTransclusion
+ */
public function testGetWikitextForTransclusion() {
$content = $this->newContent( 'hello world.' );
$this->assertEquals( 'hello world.', $content->getWikitextForTransclusion() );
}
+ /**
+ * @covers TextContent::getModel
+ */
public function testGetModel() {
$content = $this->newContent( "hello world." );
$this->assertEquals( CONTENT_MODEL_TEXT, $content->getModel() );
}
+ /**
+ * @covers TextContent::getContentHandler
+ */
public function testGetContentHandler() {
$content = $this->newContent( "hello world." );
/**
* @dataProvider dataIsEmpty
+ * @covers TextContent::isEmpty
*/
public function testIsEmpty( $text, $empty ) {
$content = $this->newContent( $text );
/**
* @dataProvider dataEquals
+ * @covers TextContent::equals
*/
public function testEquals( Content $a, Content $b = null, $equal = false ) {
$this->assertEquals( $equal, $a->equals( $b ) );
/**
* @dataProvider dataGetDeletionUpdates
+ * @covers TextContent::getDeletionUpdates
*/
public function testDeletionUpdates( $title, $model, $text, $expectedStuff ) {
$ns = $this->getDefaultWikitextNS();
/**
* @dataProvider provideConvert
+ * @covers TextContent::convert
*/
public function testConvert( $text, $model, $lossy, $expectedNative ) {
$content = $this->newContent( $text );
$this->handler = ContentHandler::getForModelID( CONTENT_MODEL_WIKITEXT );
}
+ /**
+ * @covers WikitextContentHandler::serializeContent
+ */
public function testSerializeContent() {
$content = new WikitextContent( 'hello world' );
}
}
+ /**
+ * @covers WikitextContentHandler::unserializeContent
+ */
public function testUnserializeContent() {
$content = $this->handler->unserializeContent( 'hello world' );
$this->assertEquals( 'hello world', $content->getNativeData() );
}
}
+ /**
+ * @covers WikitextContentHandler::makeEmptyContent
+ */
public function testMakeEmptyContent() {
$content = $this->handler->makeEmptyContent();
* @dataProvider provideMakeRedirectContent
* @param Title|string $title Title object or string for Title::newFromText()
* @param string $expected Serialized form of the content object built
+ * @covers WikitextContentHandler::makeRedirectContent
*/
public function testMakeRedirectContent( $title, $expected ) {
global $wgContLang;
/**
* @dataProvider dataIsSupportedFormat
+ * @covers WikitextContentHandler::isSupportedFormat
*/
public function testIsSupportedFormat( $format, $supported ) {
$this->assertEquals( $supported, $this->handler->isSupportedFormat( $format ) );
/**
* @dataProvider dataMerge3
+ * @covers WikitextContentHandler::merge3
*/
public function testMerge3( $old, $mine, $yours, $expected ) {
$this->checkHasDiff3();
/**
* @dataProvider dataGetAutosummary
+ * @covers WikitextContentHandler::getAutosummary
*/
public function testGetAutosummary( $old, $new, $flags, $expected ) {
$oldContent = is_null( $old ) ? null : new WikitextContent( $old );
/**
* @dataProvider dataGetSecondaryDataUpdates
* @group Database
+ * @covers WikitextContent::getSecondaryDataUpdates
*/
public function testGetSecondaryDataUpdates( $title, $model, $text, $expectedStuff ) {
$ns = $this->getDefaultWikitextNS();
/**
* @dataProvider dataGetSection
+ * @covers WikitextContent::getSection
*/
public function testGetSection( $text, $sectionId, $expectedText ) {
$content = $this->newContent( $text );
/**
* @dataProvider dataReplaceSection
+ * @covers WikitextContent::replaceSection
*/
public function testReplaceSection( $text, $section, $with, $sectionTitle, $expected ) {
$content = $this->newContent( $text );
$this->assertEquals( $expected, is_null( $c ) ? null : $c->getNativeData() );
}
+ /**
+ * @covers WikitextContent::addSectionHeader
+ */
public function testAddSectionHeader() {
$content = $this->newContent( 'hello world' );
$content = $content->addSectionHeader( 'test' );
);
}
+ /**
+ * @covers WikitextContent::matchMagicWord
+ */
public function testMatchMagicWord() {
$mw = MagicWord::get( "staticredirect" );
$this->assertFalse( $content->matchMagicWord( $mw ), "should not have matched magic word" );
}
+ /**
+ * @covers WikitextContent::updateRedirect
+ */
public function testUpdateRedirect() {
$target = Title::newFromText( "testUpdateRedirect_target" );
$this->assertEquals( $target->getFullText(), $newContent->getRedirectTarget()->getFullText() );
}
+ /**
+ * @covers WikitextContent::getModel
+ */
public function testGetModel() {
$content = $this->newContent( "hello world." );
$this->assertEquals( CONTENT_MODEL_WIKITEXT, $content->getModel() );
}
+ /**
+ * @covers WikitextContent::getContentHandler
+ */
public function testGetContentHandler() {
$content = $this->newContent( "hello world." );
/**
* @dataProvider provideDiapers
+ * @covers DatabaseMysqlBase::addIdentifierQuotes
*/
function testAddIdentifierQuotes( $expected, $in ) {
$db = new FakeDatabaseMysqlBase();
*/
class DatabaseSQLTest extends MediaWikiTestCase {
+ /**
+ * @var DatabaseTestHelper
+ */
private $database;
protected function setUp() {
/**
* @dataProvider provideSelect
+ * @covers DatabaseBase::select
*/
function testSelect( $sql, $sqlText ) {
$this->database->select(
/**
* @dataProvider provideUpdate
+ * @covers DatabaseBase::update
*/
function testUpdate( $sql, $sqlText ) {
$this->database->update(
/**
* @dataProvider provideDelete
+ * @covers DatabaseBase::delete
*/
function testDelete( $sql, $sqlText ) {
$this->database->delete(
/**
* @dataProvider provideUpsert
+ * @covers DatabaseBase::upsert
*/
function testUpsert( $sql, $sqlText ) {
$this->database->upsert(
/**
* @dataProvider provideDeleteJoin
+ * @covers DatabaseBase::deleteJoin
*/
function testDeleteJoin( $sql, $sqlText ) {
$this->database->deleteJoin(
/**
* @dataProvider provideInsert
+ * @covers DatabaseBase::insert
*/
function testInsert( $sql, $sqlText ) {
$this->database->insert(
/**
* @dataProvider provideInsertSelect
+ * @covers DatabaseBase::insertSelect
*/
function testInsertSelect( $sql, $sqlText ) {
$this->database->insertSelect(
/**
* @dataProvider provideReplace
+ * @covers DatabaseBase::replace
*/
function testReplace( $sql, $sqlText ) {
$this->database->replace(
/**
* @dataProvider provideNativeReplace
+ * @covers DatabaseBase::nativeReplace
*/
function testNativeReplace( $sql, $sqlText ) {
$this->database->nativeReplace(
/**
* @dataProvider provideConditional
+ * @covers DatabaseBase::conditional
*/
function testConditional( $sql, $sqlText ) {
$this->assertEquals( trim( $this->database->conditional(
/**
* @dataProvider provideBuildConcat
+ * @covers DatabaseBase::buildConcat
*/
function testBuildConcat( $stringList, $sqlText ) {
$this->assertEquals( trim( $this->database->buildConcat(
/**
* @dataProvider provideBuildLike
+ * @covers DatabaseBase::buildLike
*/
function testBuildLike( $array, $sqlText ) {
$this->assertEquals( trim( $this->database->buildLike(
/**
* @dataProvider provideUnionQueries
+ * @covers DatabaseBase::unionQueries
*/
function testUnionQueries( $sql, $sqlText ) {
$this->assertEquals( trim( $this->database->unionQueries(
);
}
+ /**
+ * @covers DatabaseBase::commit
+ */
function testTransactionCommit() {
$this->database->begin( __METHOD__ );
$this->database->commit( __METHOD__ );
$this->assertLastSql( 'BEGIN; COMMIT' );
}
+ /**
+ * @covers DatabaseBase::rollback
+ */
function testTransactionRollback() {
$this->database->begin( __METHOD__ );
$this->database->rollback( __METHOD__ );
$this->assertLastSql( 'BEGIN; ROLLBACK' );
}
+ /**
+ * @covers DatabaseBase::dropTable
+ */
function testDropTable() {
$this->database->setExistingTables( array( 'table' ) );
$this->database->dropTable( 'table', __METHOD__ );
$this->assertLastSql( 'DROP TABLE table' );
}
+ /**
+ * @covers DatabaseBase::dropTable
+ */
function testDropNonExistingTable() {
$this->assertFalse(
$this->database->dropTable( 'non_existing', __METHOD__ )
* @group medium
*/
class DatabaseSqliteTest extends MediaWikiTestCase {
+
+ /**
+ * @var MockDatabaseSqlite
+ */
var $db;
protected function setUp() {
/**
* @dataProvider provideAddQuotes()
+ * @covers DatabaseSqlite::addQuotes
*/
public function testAddQuotes( $value, $expected ) {
// check quoting
}
}
+ /**
+ * @covers DatabaseSqlite::replaceVars
+ */
public function testReplaceVars() {
$this->assertEquals( 'foo', $this->replaceVars( 'foo' ), "Don't break anything accidentally" );
);
}
+ /**
+ * @covers DatabaseSqlite::tableName
+ */
public function testTableName() {
// @todo Moar!
$db = new DatabaseSqliteStandalone( ':memory:' );
$this->assertEquals( 'foobar', $db->tableName( 'bar' ) );
}
+ /**
+ * @covers DatabaseSqlite::duplicateTableStructure
+ */
public function testDuplicateTableStructure() {
$db = new DatabaseSqliteStandalone( ':memory:' );
$db->query( 'CREATE TABLE foo(foo, barfoo)' );
);
}
+ /**
+ * @covers DatabaseSqlite::duplicateTableStructure
+ */
public function testDuplicateTableStructureVirtual() {
$db = new DatabaseSqliteStandalone( ':memory:' );
if ( $db->getFulltextSearchModule() != 'FTS3' ) {
);
}
+ /**
+ * @covers DatabaseSqlite::deleteJoin
+ */
public function testDeleteJoin() {
$db = new DatabaseSqliteStandalone( ':memory:' );
$db->query( 'CREATE TABLE a (a_1)', __METHOD__ );
}
}
+ /**
+ * @covers DatabaseSqlite::insertId
+ */
public function testInsertIdType() {
$db = new DatabaseSqliteStandalone( ':memory:' );
- $this->assertInstanceOf( 'ResultWrapper',
- $db->query( 'CREATE TABLE a ( a_1 )', __METHOD__ ), "Database creationg" );
- $this->assertTrue( $db->insert( 'a', array( 'a_1' => 10 ), __METHOD__ ),
- "Insertion worked" );
+
+ $databaseCreation = $db->query( 'CREATE TABLE a ( a_1 )', __METHOD__ );
+ $this->assertInstanceOf( 'ResultWrapper', $databaseCreation, "Database creation" );
+
+ $insertion = $db->insert( 'a', array( 'a_1' => 10 ), __METHOD__ );
+ $this->assertTrue( $insertion, "Insertion worked" );
+
$this->assertInternalType( 'integer', $db->insertId(), "Actual typecheck" );
$this->assertTrue( $db->close(), "closing database" );
}
* @group DatabaseBase
*/
class DatabaseTest extends MediaWikiTestCase {
- var $db, $functionTest = false;
+ /**
+ * @var DatabaseBase
+ */
+ var $db;
+ var $functionTest = false;
protected function setUp() {
parent::setUp();
$this->functionTest = false;
}
}
-
+ /**
+ * @covers DatabaseBase::dropTable
+ */
function testAddQuotesNull() {
$check = "NULL";
if ( $this->db->getType() === 'sqlite' || $this->db->getType() === 'oracle' ) {