Jackmcbarn <jackmcbarn@gmail.com>
Jackmcbarn <jackmcbarn@gmail.com> <jackmcbarn@users.noreply.github.com>
jagori <jagori79@gmail.com>
-James Forrester <jforrester@wikimedia.org>
+James D. Forrester <jforrester@wikimedia.org>
Jaime Crespo <jcrespo@wikimedia.org>
Jan Gerber <j@thing.net> <j@users.mediawiki.org>
Jan Luca Naumann <jan@jans-seite.de>
* Jaime Crespo
* Jakub Vrana
* James Earl Douglas
-* James Forrester
+* James D. Forrester
* Jan Berkel
* Jan Drewniak
* Jan Gerber
==== Upgraded external libraries ====
* Updated jquery.chosen from v0.9.14 to v1.8.2.
* Updated composer/spdx-licenses from 1.1.4 to
- 1.2.0 (development dependency).
+ 1.3.0 (development dependency).
* Updated nikic/php-parser from 2.1.0 to 3.1.3
(development dependency).
* Updated wikimedia/ip-set from 1.1.0 to 1.2.0.
* PreparedEdit->newText
* PreparedEdit->oldText
* PreparedEdit->pst
+* QuickTemplate::setRef() was deprecated in favour of QuickTemplate::set().
+ Setting template variables by reference allowed violating the principle of data being
+ immutable once added to the skin template. In practice, this method was not being
+ used for that. Rather, setRef() existed as memory optimisation for PHP 4.
+* Passing false to ParserOptions::setWrapOutputClass() is deprecated. Use the
+ 'unwrap' transform to ParserOutput::getText() instead.
+* ParserOutput objects generated using a non-default value for
+ ParserOptions::setWrapOutputClass() can no longer be added to the parser
+ cache.
== Compatibility ==
MediaWiki 1.31 requires PHP 5.5.9 or later. Although HHVM 3.18.5 or later is supported,
"zordius/lightncandy": "0.23"
},
"require-dev": {
- "composer/spdx-licenses": "1.2.0",
+ "composer/spdx-licenses": "1.3.0",
"hamcrest/hamcrest-php": "^2.0",
"jakub-onderka/php-parallel-lint": "0.9.2",
"jetbrains/phpstorm-stubs": "dev-master#1b9906084d6635456fcf3f3a01f0d7d5b99a578a",
},
"SkinOOUIThemes": {
"type": "object",
- "description": "Map of skin names to OOjs UI themes to use. Same format as ResourceLoaderOOUIModule::$builtinSkinThemeMap."
+ "description": "Map of skin names to OOUI themes to use. Same format as ResourceLoaderOOUIModule::$builtinSkinThemeMap."
},
"PasswordPolicy": {
"type": "object",
*/
$wgContentHandlers = [
// the usual case
- CONTENT_MODEL_WIKITEXT => 'WikitextContentHandler',
+ CONTENT_MODEL_WIKITEXT => WikitextContentHandler::class,
// dumb version, no syntax highlighting
- CONTENT_MODEL_JAVASCRIPT => 'JavaScriptContentHandler',
+ CONTENT_MODEL_JAVASCRIPT => JavaScriptContentHandler::class,
// simple implementation, for use by extensions, etc.
- CONTENT_MODEL_JSON => 'JsonContentHandler',
+ CONTENT_MODEL_JSON => JsonContentHandler::class,
// dumb version, no syntax highlighting
- CONTENT_MODEL_CSS => 'CssContentHandler',
+ CONTENT_MODEL_CSS => CssContentHandler::class,
// plain text, for use by extensions, etc.
- CONTENT_MODEL_TEXT => 'TextContentHandler',
+ CONTENT_MODEL_TEXT => TextContentHandler::class,
];
/**
* Whether to use SSL in DB connection.
*
* This setting is only used if $wgLBFactoryConf['class'] is set to
- * 'LBFactorySimple' and $wgDBservers is an empty array; otherwise
+ * '\Wikimedia\Rdbms\LBFactorySimple' and $wgDBservers is an empty array; otherwise
* the DBO_SSL flag must be set in the 'flags' option of the database
* connection to achieve the same functionality.
*/
* Whether to use compression in DB connection.
*
* This setting is only used $wgLBFactoryConf['class'] is set to
- * 'LBFactorySimple' and $wgDBservers is an empty array; otherwise
+ * '\Wikimedia\Rdbms\LBFactorySimple' and $wgDBservers is an empty array; otherwise
* the DBO_COMPRESS flag must be set in the 'flags' option of the database
* connection to achieve the same functionality.
*/
* The LBFactoryMulti class is provided for this purpose, please see
* includes/db/LBFactoryMulti.php for configuration information.
*/
-$wgLBFactoryConf = [ 'class' => 'LBFactorySimple' ];
+$wgLBFactoryConf = [ 'class' => \Wikimedia\Rdbms\LBFactorySimple::class ];
/**
* After a state-changing request is done by a client, this determines
* ];
* @endcode
*
- * Used by LBFactorySimple, may be ignored if $wgLBFactoryConf is set to
+ * Used by \Wikimedia\Rdbms\LBFactorySimple, may be ignored if $wgLBFactoryConf is set to
* another class.
*/
$wgExternalServers = [];
* given, giving a callable function which will generate a suitable cache object.
*/
$wgObjectCaches = [
- CACHE_NONE => [ 'class' => 'EmptyBagOStuff', 'reportDupes' => false ],
- CACHE_DB => [ 'class' => 'SqlBagOStuff', 'loggroup' => 'SQLBagOStuff' ],
+ CACHE_NONE => [ 'class' => EmptyBagOStuff::class, 'reportDupes' => false ],
+ CACHE_DB => [ 'class' => SqlBagOStuff::class, 'loggroup' => 'SQLBagOStuff' ],
CACHE_ANYTHING => [ 'factory' => 'ObjectCache::newAnything' ],
CACHE_ACCEL => [ 'factory' => 'ObjectCache::getLocalServerInstance' ],
- CACHE_MEMCACHED => [ 'class' => 'MemcachedPhpBagOStuff', 'loggroup' => 'memcached' ],
+ CACHE_MEMCACHED => [ 'class' => MemcachedPhpBagOStuff::class, 'loggroup' => 'memcached' ],
'db-replicated' => [
- 'class' => 'ReplicatedBagOStuff',
+ 'class' => ReplicatedBagOStuff::class,
'readFactory' => [
- 'class' => 'SqlBagOStuff',
+ 'class' => SqlBagOStuff::class,
'args' => [ [ 'slaveOnly' => true ] ]
],
'writeFactory' => [
- 'class' => 'SqlBagOStuff',
+ 'class' => SqlBagOStuff::class,
'args' => [ [ 'slaveOnly' => false ] ]
],
'loggroup' => 'SQLBagOStuff',
'reportDupes' => false
],
- 'apc' => [ 'class' => 'APCBagOStuff', 'reportDupes' => false ],
- 'apcu' => [ 'class' => 'APCUBagOStuff', 'reportDupes' => false ],
- 'xcache' => [ 'class' => 'XCacheBagOStuff', 'reportDupes' => false ],
- 'wincache' => [ 'class' => 'WinCacheBagOStuff', 'reportDupes' => false ],
- 'memcached-php' => [ 'class' => 'MemcachedPhpBagOStuff', 'loggroup' => 'memcached' ],
- 'memcached-pecl' => [ 'class' => 'MemcachedPeclBagOStuff', 'loggroup' => 'memcached' ],
- 'hash' => [ 'class' => 'HashBagOStuff', 'reportDupes' => false ],
+ 'apc' => [ 'class' => APCBagOStuff::class, 'reportDupes' => false ],
+ 'apcu' => [ 'class' => APCUBagOStuff::class, 'reportDupes' => false ],
+ 'xcache' => [ 'class' => XCacheBagOStuff::class, 'reportDupes' => false ],
+ 'wincache' => [ 'class' => WinCacheBagOStuff::class, 'reportDupes' => false ],
+ 'memcached-php' => [ 'class' => MemcachedPhpBagOStuff::class, 'loggroup' => 'memcached' ],
+ 'memcached-pecl' => [ 'class' => MemcachedPeclBagOStuff::class, 'loggroup' => 'memcached' ],
+ 'hash' => [ 'class' => HashBagOStuff::class, 'reportDupes' => false ],
];
/**
*/
$wgWANObjectCaches = [
CACHE_NONE => [
- 'class' => 'WANObjectCache',
+ 'class' => WANObjectCache::class,
'cacheId' => CACHE_NONE,
'channels' => []
]
/* Example of a simple single data-center cache:
'memcached-php' => [
- 'class' => 'WANObjectCache',
+ 'class' => WANObjectCache::class,
'cacheId' => 'memcached-php',
'channels' => [ 'purge' => 'wancache-main-memcached-purge' ]
]
* Use maintenance/rebuildLocalisationCache.php instead.
*/
$wgLocalisationCacheConf = [
- 'class' => 'LocalisationCache',
+ 'class' => LocalisationCache::class,
'store' => 'detect',
'storeClass' => false,
'storeDirectory' => false,
*/
$wgResourceLoaderLESSVars = [
/**
- * Minimum available screen width at which a device can be considered a tablet/desktop
+ * Minimum available screen width at which a device can be considered a tablet
* The number is currently based on the device width of a Samsung Galaxy S5 mini and is low
* enough to cover iPad (768px). Number is prone to change with new information.
* @since 1.27
+ * @deprecated 1.31 Use mediawiki.ui/variables instead
*/
'deviceWidthTablet' => '720px',
];
* an extension setup function.
*/
$wgParserConf = [
- 'class' => 'Parser',
- # 'preprocessorClass' => 'Preprocessor_Hash',
+ 'class' => Parser::class,
+ # 'preprocessorClass' => Preprocessor_Hash::class,
];
/**
* @since 1.27
*/
$wgCentralIdLookupProviders = [
- 'local' => [ 'class' => 'LocalIdLookup' ],
+ 'local' => [ 'class' => LocalIdLookup::class ],
];
/**
* An advanced example:
* @code
* $wgPasswordConfig['bcrypt-peppered'] = [
- * 'class' => 'EncryptedPassword',
+ * 'class' => EncryptedPassword::class,
* 'underlying' => 'bcrypt',
* 'secrets' => [],
* 'cipher' => MCRYPT_RIJNDAEL_256,
*/
$wgPasswordConfig = [
'A' => [
- 'class' => 'MWOldPassword',
+ 'class' => MWOldPassword::class,
],
'B' => [
- 'class' => 'MWSaltedPassword',
+ 'class' => MWSaltedPassword::class,
],
'pbkdf2-legacyA' => [
- 'class' => 'LayeredParameterizedPassword',
+ 'class' => LayeredParameterizedPassword::class,
'types' => [
'A',
'pbkdf2',
],
],
'pbkdf2-legacyB' => [
- 'class' => 'LayeredParameterizedPassword',
+ 'class' => LayeredParameterizedPassword::class,
'types' => [
'B',
'pbkdf2',
],
],
'bcrypt' => [
- 'class' => 'BcryptPassword',
+ 'class' => BcryptPassword::class,
'cost' => 9,
],
'pbkdf2' => [
- 'class' => 'Pbkdf2Password',
+ 'class' => Pbkdf2Password::class,
'algo' => 'sha512',
'cost' => '30000',
'length' => '64',
* Write SQL queries to the debug log.
*
* This setting is only used $wgLBFactoryConf['class'] is set to
- * 'LBFactorySimple' and $wgDBservers is an empty array; otherwise
+ * '\Wikimedia\Rdbms\LBFactorySimple' and $wgDBservers is an empty array; otherwise
* the DBO_DEBUG flag must be set in the 'flags' option of the database
* connection to achieve the same functionality.
*/
*
* @par To completely disable logging:
* @code
- * $wgMWLoggerDefaultSpi = [ 'class' => '\\MediaWiki\\Logger\\NullSpi' ];
+ * $wgMWLoggerDefaultSpi = [ 'class' => \MediaWiki\Logger\NullSpi::class ];
* @endcode
*
* @since 1.25
* @see MwLogger
*/
$wgMWLoggerDefaultSpi = [
- 'class' => '\\MediaWiki\\Logger\\LegacySpi',
+ 'class' => \MediaWiki\Logger\LegacySpi::class,
];
/**
* 'omit_bots' => true,
* ];
* @example $wgRCFeeds['example'] = [
- * 'class' => 'ExampleRCFeed',
+ * 'class' => ExampleRCFeed::class,
* ];
* @since 1.22
*/
* @since 1.22
*/
$wgRCEngines = [
- 'redis' => 'RedisPubSubFeedEngine',
- 'udp' => 'UDPRCFeedEngine',
+ 'redis' => RedisPubSubFeedEngine::class,
+ 'udp' => UDPRCFeedEngine::class,
];
/**
* $wgOut->isSyndicated() is true.
*/
$wgFeedClasses = [
- 'rss' => 'RSSFeed',
- 'atom' => 'AtomFeed',
+ 'rss' => RSSFeed::class,
+ 'atom' => AtomFeed::class,
];
/**
* or (since 1.30) a callback to use for creating the job object.
*/
$wgJobClasses = [
- 'refreshLinks' => 'RefreshLinksJob',
- 'deleteLinks' => 'DeleteLinksJob',
- 'htmlCacheUpdate' => 'HTMLCacheUpdateJob',
- 'sendMail' => 'EmaillingJob',
- 'enotifNotify' => 'EnotifNotifyJob',
- 'fixDoubleRedirect' => 'DoubleRedirectJob',
- 'AssembleUploadChunks' => 'AssembleUploadChunksJob',
- 'PublishStashedFile' => 'PublishStashedFileJob',
- 'ThumbnailRender' => 'ThumbnailRenderJob',
- 'recentChangesUpdate' => 'RecentChangesUpdateJob',
- 'refreshLinksPrioritized' => 'RefreshLinksJob',
- 'refreshLinksDynamic' => 'RefreshLinksJob',
- 'activityUpdateJob' => 'ActivityUpdateJob',
- 'categoryMembershipChange' => 'CategoryMembershipChangeJob',
- 'clearUserWatchlist' => 'ClearUserWatchlistJob',
- 'cdnPurge' => 'CdnPurgeJob',
- 'enqueue' => 'EnqueueJob', // local queue for multi-DC setups
- 'null' => 'NullJob'
+ 'refreshLinks' => RefreshLinksJob::class,
+ 'deleteLinks' => DeleteLinksJob::class,
+ 'htmlCacheUpdate' => HTMLCacheUpdateJob::class,
+ 'sendMail' => EmaillingJob::class,
+ 'enotifNotify' => EnotifNotifyJob::class,
+ 'fixDoubleRedirect' => DoubleRedirectJob::class,
+ 'AssembleUploadChunks' => AssembleUploadChunksJob::class,
+ 'PublishStashedFile' => PublishStashedFileJob::class,
+ 'ThumbnailRender' => ThumbnailRenderJob::class,
+ 'recentChangesUpdate' => RecentChangesUpdateJob::class,
+ 'refreshLinksPrioritized' => RefreshLinksJob::class,
+ 'refreshLinksDynamic' => RefreshLinksJob::class,
+ 'activityUpdateJob' => ActivityUpdateJob::class,
+ 'categoryMembershipChange' => CategoryMembershipChangeJob::class,
+ 'clearUserWatchlist' => ClearUserWatchlistJob::class,
+ 'cdnPurge' => CdnPurgeJob::class,
+ 'enqueue' => EnqueueJob::class, // local queue for multi-DC setups
+ 'null' => NullJob::class,
];
/**
* These settings should be global to all wikis.
*/
$wgJobTypeConf = [
- 'default' => [ 'class' => 'JobQueueDB', 'order' => 'random', 'claimTTL' => 3600 ],
+ 'default' => [ 'class' => JobQueueDB::class, 'order' => 'random', 'claimTTL' => 3600 ],
];
/**
* These settings should be global to all wikis.
*/
$wgJobQueueAggregator = [
- 'class' => 'JobQueueAggregatorNull'
+ 'class' => JobQueueAggregatorNull::class
];
/**
* Expensive Querypages are already updated.
*/
$wgSpecialPageCacheUpdates = [
- 'Statistics' => [ 'SiteStatsUpdate', 'cacheUpdate' ]
+ 'Statistics' => [ SiteStatsUpdate::class, 'cacheUpdate' ]
];
/**
* @see LogFormatter
*/
$wgLogActionsHandlers = [
- 'block/block' => 'BlockLogFormatter',
- 'block/reblock' => 'BlockLogFormatter',
- 'block/unblock' => 'BlockLogFormatter',
- 'contentmodel/change' => 'ContentModelLogFormatter',
- 'contentmodel/new' => 'ContentModelLogFormatter',
- 'delete/delete' => 'DeleteLogFormatter',
- 'delete/delete_redir' => 'DeleteLogFormatter',
- 'delete/event' => 'DeleteLogFormatter',
- 'delete/restore' => 'DeleteLogFormatter',
- 'delete/revision' => 'DeleteLogFormatter',
- 'import/interwiki' => 'ImportLogFormatter',
- 'import/upload' => 'ImportLogFormatter',
- 'managetags/activate' => 'LogFormatter',
- 'managetags/create' => 'LogFormatter',
- 'managetags/deactivate' => 'LogFormatter',
- 'managetags/delete' => 'LogFormatter',
- 'merge/merge' => 'MergeLogFormatter',
- 'move/move' => 'MoveLogFormatter',
- 'move/move_redir' => 'MoveLogFormatter',
- 'patrol/patrol' => 'PatrolLogFormatter',
- 'patrol/autopatrol' => 'PatrolLogFormatter',
- 'protect/modify' => 'ProtectLogFormatter',
- 'protect/move_prot' => 'ProtectLogFormatter',
- 'protect/protect' => 'ProtectLogFormatter',
- 'protect/unprotect' => 'ProtectLogFormatter',
- 'rights/autopromote' => 'RightsLogFormatter',
- 'rights/rights' => 'RightsLogFormatter',
- 'suppress/block' => 'BlockLogFormatter',
- 'suppress/delete' => 'DeleteLogFormatter',
- 'suppress/event' => 'DeleteLogFormatter',
- 'suppress/reblock' => 'BlockLogFormatter',
- 'suppress/revision' => 'DeleteLogFormatter',
- 'tag/update' => 'TagLogFormatter',
- 'upload/overwrite' => 'UploadLogFormatter',
- 'upload/revert' => 'UploadLogFormatter',
- 'upload/upload' => 'UploadLogFormatter',
+ 'block/block' => BlockLogFormatter::class,
+ 'block/reblock' => BlockLogFormatter::class,
+ 'block/unblock' => BlockLogFormatter::class,
+ 'contentmodel/change' => ContentModelLogFormatter::class,
+ 'contentmodel/new' => ContentModelLogFormatter::class,
+ 'delete/delete' => DeleteLogFormatter::class,
+ 'delete/delete_redir' => DeleteLogFormatter::class,
+ 'delete/event' => DeleteLogFormatter::class,
+ 'delete/restore' => DeleteLogFormatter::class,
+ 'delete/revision' => DeleteLogFormatter::class,
+ 'import/interwiki' => ImportLogFormatter::class,
+ 'import/upload' => ImportLogFormatter::class,
+ 'managetags/activate' => LogFormatter::class,
+ 'managetags/create' => LogFormatter::class,
+ 'managetags/deactivate' => LogFormatter::class,
+ 'managetags/delete' => LogFormatter::class,
+ 'merge/merge' => MergeLogFormatter::class,
+ 'move/move' => MoveLogFormatter::class,
+ 'move/move_redir' => MoveLogFormatter::class,
+ 'patrol/patrol' => PatrolLogFormatter::class,
+ 'patrol/autopatrol' => PatrolLogFormatter::class,
+ 'protect/modify' => ProtectLogFormatter::class,
+ 'protect/move_prot' => ProtectLogFormatter::class,
+ 'protect/protect' => ProtectLogFormatter::class,
+ 'protect/unprotect' => ProtectLogFormatter::class,
+ 'rights/autopromote' => RightsLogFormatter::class,
+ 'rights/rights' => RightsLogFormatter::class,
+ 'suppress/block' => BlockLogFormatter::class,
+ 'suppress/delete' => DeleteLogFormatter::class,
+ 'suppress/event' => DeleteLogFormatter::class,
+ 'suppress/reblock' => BlockLogFormatter::class,
+ 'suppress/revision' => DeleteLogFormatter::class,
+ 'tag/update' => TagLogFormatter::class,
+ 'upload/overwrite' => UploadLogFormatter::class,
+ 'upload/revert' => UploadLogFormatter::class,
+ 'upload/upload' => UploadLogFormatter::class,
];
/**
'credits' => true,
'delete' => true,
'edit' => true,
- 'editchangetags' => 'SpecialPageAction',
+ 'editchangetags' => SpecialPageAction::class,
'history' => true,
'info' => true,
'markpatrolled' => true,
'raw' => true,
'render' => true,
'revert' => true,
- 'revisiondelete' => 'SpecialPageAction',
+ 'revisiondelete' => SpecialPageAction::class,
'rollback' => true,
'submit' => true,
'unprotect' => true,
* @code
* $wgAPIModules['foo'] = 'ApiFoo';
* $wgAPIModules['bar'] = [
- * 'class' => 'ApiBar',
+ * 'class' => ApiBar::class,
* 'factory' => function( $main, $name ) { ... }
* ];
* $wgAPIModules['xyzzy'] = [
- * 'class' => 'ApiXyzzy',
- * 'factory' => [ 'XyzzyFactory', 'newApiModule' ]
+ * 'class' => ApiXyzzy::class,
+ * 'factory' => [ XyzzyFactory::class, 'newApiModule' ]
* ];
* @endcode
*
* @par Example using local redis instance:
* @code
* $wgPoolCounterConf = [ 'ArticleView' => [
- * 'class' => 'PoolCounterRedis',
+ * 'class' => PoolCounterRedis::class,
* 'timeout' => 15, // wait timeout in seconds
* 'workers' => 1, // maximum number of active threads in each pool
* 'maxqueue' => 5, // maximum number of total threads in each pool
* @par Example using C daemon from https://www.mediawiki.org/wiki/Extension:PoolCounter:
* @code
* $wgPoolCounterConf = [ 'ArticleView' => [
- * 'class' => 'PoolCounter_Client',
+ * 'class' => PoolCounter_Client::class,
* 'timeout' => 15, // wait timeout in seconds
* 'workers' => 5, // maximum number of active threads in each pool
* 'maxqueue' => 50, // maximum number of total threads in each pool
* @since 1.20
*/
$wgSiteTypes = [
- 'mediawiki' => 'MediaWikiSite',
+ 'mediawiki' => MediaWikiSite::class,
];
/**
* Auto-mounting example for Parsoid:
*
* $wgVirtualRestConfig['paths']['/parsoid/'] = [
- * 'class' => 'ParsoidVirtualRESTService',
+ * 'class' => ParsoidVirtualRESTService::class,
* 'options' => [
* 'url' => 'http://localhost:8000',
* 'prefix' => 'enwiki',
*/
$wgEventRelayerConfig = [
'default' => [
- 'class' => 'EventRelayerNull',
+ 'class' => EventRelayerNull::class,
]
];
$displayTitle = $contextTitle->getPrefixedText();
}
$out->setPageTitle( $this->context->msg( $msg, $displayTitle ) );
+
+ $config = $this->context->getConfig();
+
# Transmit the name of the message to JavaScript for live preview
# Keep Resources.php/mediawiki.action.edit.preview in sync with the possible keys
$out->addJsConfigVars( [
'wgEditMessage' => $msg,
- 'wgAjaxEditStash' => $this->context->getConfig()->get( 'AjaxEditStash' ),
+ 'wgAjaxEditStash' => $config->get( 'AjaxEditStash' ),
] );
+
+ // Add whether to use 'save' or 'publish' messages to JavaScript for post-edit, other
+ // editors, etc.
+ $out->addJsConfigVars(
+ 'wgEditSubmitButtonLabelPublish',
+ $config->get( 'EditSubmitButtonLabelPublish' )
+ );
}
/**
// autoload entries for the lowercase variants of these classes (T166759).
// The code below is never executed, but it is picked up by the AutoloadGenerator
// parser, which scans for class_alias() calls.
- class_alias( 'ConcatenatedGzipHistoryBlob', 'concatenatedgziphistoryblob' );
- class_alias( 'HistoryBlobCurStub', 'historyblobcurstub' );
- class_alias( 'HistoryBlobStub', 'historyblobstub' );
+ class_alias( ConcatenatedGzipHistoryBlob::class, 'concatenatedgziphistoryblob' );
+ class_alias( HistoryBlobCurStub::class, 'historyblobcurstub' );
+ class_alias( HistoryBlobStub::class, 'historyblobstub' );
}
);
return $out instanceof ParserOutput
- ? $out->getText( [ 'enableSectionEditLinks' => false ] )
+ ? $out->getText( [
+ 'enableSectionEditLinks' => false,
+ // Wrapping messages in an extra <div> is probably not expected. If
+ // they're outside the content area they probably shouldn't be
+ // targeted by CSS that's targeting the parser output, and if
+ // they're inside they already are from the outer div.
+ 'unwrap' => true,
+ ] )
: $out;
}
public static function getFormObject(
$user,
IContextSource $context,
- $formClass = 'PreferencesForm',
+ $formClass = PreferencesForm::class,
array $remove = []
) {
$preferencesFactory = self::getDefaultPreferencesFactory();
*/
$wgLockManagers[] = [
'name' => 'fsLockManager',
- 'class' => 'FSLockManager',
+ 'class' => FSLockManager::class,
'lockDirectory' => "{$wgUploadDirectory}/lockdir",
];
$wgLockManagers[] = [
'name' => 'nullLockManager',
- 'class' => 'NullLockManager',
+ 'class' => NullLockManager::class,
];
/**
*/
if ( !$wgLocalFileRepo ) {
$wgLocalFileRepo = [
- 'class' => 'LocalRepo',
+ 'class' => LocalRepo::class,
'name' => 'local',
'directory' => $wgUploadDirectory,
'scriptDirUrl' => $wgScriptPath,
if ( $wgUseSharedUploads ) {
if ( $wgSharedUploadDBname ) {
$wgForeignFileRepos[] = [
- 'class' => 'ForeignDBRepo',
+ 'class' => ForeignDBRepo::class,
'name' => 'shared',
'directory' => $wgSharedUploadDirectory,
'url' => $wgSharedUploadPath,
];
} else {
$wgForeignFileRepos[] = [
- 'class' => 'FileRepo',
+ 'class' => FileRepo::class,
'name' => 'shared',
'directory' => $wgSharedUploadDirectory,
'url' => $wgSharedUploadPath,
}
if ( $wgUseInstantCommons ) {
$wgForeignFileRepos[] = [
- 'class' => 'ForeignAPIRepo',
+ 'class' => ForeignAPIRepo::class,
'name' => 'wikimediacommons',
'apibase' => 'https://commons.wikimedia.org/w/api.php',
'url' => 'https://upload.wikimedia.org/wikipedia/commons',
$wgLocalFileRepo['backend'] = $wgLocalFileRepo['name'] . '-backend';
}
foreach ( $wgForeignFileRepos as &$repo ) {
- if ( !isset( $repo['directory'] ) && $repo['class'] === 'ForeignAPIRepo' ) {
+ if ( !isset( $repo['directory'] ) && $repo['class'] === ForeignAPIRepo::class ) {
$repo['directory'] = $wgUploadDirectory; // b/c
}
if ( !isset( $repo['backend'] ) ) {
$wgLogTypes[] = 'newusers';
$wgLogNames['newusers'] = 'newuserlogpage';
$wgLogHeaders['newusers'] = 'newuserlogpagetext';
- $wgLogActionsHandlers['newusers/newusers'] = 'NewUsersLogFormatter';
- $wgLogActionsHandlers['newusers/create'] = 'NewUsersLogFormatter';
- $wgLogActionsHandlers['newusers/create2'] = 'NewUsersLogFormatter';
- $wgLogActionsHandlers['newusers/byemail'] = 'NewUsersLogFormatter';
- $wgLogActionsHandlers['newusers/autocreate'] = 'NewUsersLogFormatter';
+ $wgLogActionsHandlers['newusers/newusers'] = NewUsersLogFormatter::class;
+ $wgLogActionsHandlers['newusers/create'] = NewUsersLogFormatter::class;
+ $wgLogActionsHandlers['newusers/create2'] = NewUsersLogFormatter::class;
+ $wgLogActionsHandlers['newusers/byemail'] = NewUsersLogFormatter::class;
+ $wgLogActionsHandlers['newusers/autocreate'] = NewUsersLogFormatter::class;
}
if ( $wgPageLanguageUseDB ) {
$wgLogTypes[] = 'pagelang';
- $wgLogActionsHandlers['pagelang/pagelang'] = 'PageLangLogFormatter';
+ $wgLogActionsHandlers['pagelang/pagelang'] = PageLangLogFormatter::class;
}
if ( $wgCookieSecure === 'detect' ) {
// Sites using multiple datacenters can configure a relayer.
$wgMainWANCache = 'mediawiki-main-default';
$wgWANObjectCaches[$wgMainWANCache] = [
- 'class' => 'WANObjectCache',
+ 'class' => WANObjectCache::class,
'cacheId' => $wgMainCacheType,
'channels' => [ 'purge' => 'wancache-main-default-purge' ]
];
// Initialize the request object in $wgRequest
$wgRequest = RequestContext::getMain()->getRequest(); // BackCompat
-// Set user IP/agent information for causal consistency purposes.
-// The cpPosIndex cookie has no prefix and is set by MediaWiki::preOutputCommit().
-$cpPosIndex = $wgRequest->getInt( 'cpPosIndex', (int)$wgRequest->getCookie( 'cpPosIndex', '' ) );
+// Set user IP/agent information for agent session consistency purposes
MediaWikiServices::getInstance()->getDBLoadBalancerFactory()->setRequestInfo( [
'IPAddress' => $wgRequest->getIP(),
'UserAgent' => $wgRequest->getHeader( 'User-Agent' ),
'ChronologyProtection' => $wgRequest->getHeader( 'ChronologyProtection' ),
- 'ChronologyPositionIndex' => $cpPosIndex
+ // The cpPosIndex cookie has no prefix and is set by MediaWiki::preOutputCommit()
+ 'ChronologyPositionIndex' =>
+ $wgRequest->getInt( 'cpPosIndex', (int)$wgRequest->getCookie( 'cpPosIndex', '' ) )
] );
-// Make sure that caching does not compromise the consistency improvements
-if ( $cpPosIndex ) {
+// Make sure that object caching does not undermine the ChronologyProtector improvements
+if ( $wgRequest->getCookie( 'UseDC', '' ) === 'master' ) {
+ // The user is pinned to the primary DC, meaning that they made recent changes which should
+ // be reflected in their subsequent web requests. Avoid the use of interim cache keys because
+ // they use a blind TTL and could be stale if an object changes twice in a short time span.
MediaWikiServices::getInstance()->getMainWANObjectCache()->useInterimHoldOffCaching( false );
}
-unset( $cpPosIndex );
// Useful debug output
if ( $wgCommandLineMode ) {
/** @var bool */
private static $loaded = false;
-
/** @var int[] */
private static $pageCount = [];
self::$row = self::loadAndLazyInit();
- # This code is somewhat schema-agnostic, because I'm changing it in a minor release -- TS
- if ( !isset( self::$row->ss_total_pages ) && self::$row->ss_total_pages == -1 ) {
- # Update schema
- $u = new SiteStatsUpdate( 0, 0, 0 );
- $u->doUpdate();
- self::$row = self::doLoad( wfGetDB( DB_REPLICA ) );
- }
-
self::$loaded = true;
}
}
}
- if ( !$wgMiserMode && !self::isSane( $row ) ) {
- // Normally the site_stats table is initialized at install time.
- // Some manual construction scenarios may leave the table empty or
- // broken, however, for instance when importing from a dump into a
- // clean schema with mwdumper.
- wfDebug( __METHOD__ . ": initializing damaged or missing site_stats\n" );
-
- SiteStatsInit::doAllAndCommit( wfGetDB( DB_REPLICA ) );
+ if ( !self::isSane( $row ) ) {
+ if ( $wgMiserMode ) {
+ // Start off with all zeroes, assuming that this is a new wiki or any
+ // repopulations where done manually via script.
+ SiteStatsInit::doPlaceholderInit();
+ } else {
+ // Normally the site_stats table is initialized at install time.
+ // Some manual construction scenarios may leave the table empty or
+ // broken, however, for instance when importing from a dump into a
+ // clean schema with mwdumper.
+ wfDebug( __METHOD__ . ": initializing damaged or missing site_stats\n" );
+ SiteStatsInit::doAllAndCommit( wfGetDB( DB_REPLICA ) );
+ }
$row = self::doLoad( wfGetDB( DB_MASTER ) );
}
if ( !self::isSane( $row ) ) {
wfDebug( __METHOD__ . ": site_stats persistently nonsensical o_O\n" );
+
+ $row = (object)array_fill_keys( self::selectFields(), 0 );
}
return $row;
* @return bool|stdClass
*/
static function doLoad( $db ) {
- return $db->selectRow( 'site_stats', [
- 'ss_row_id',
- 'ss_total_edits',
- 'ss_good_articles',
- 'ss_total_pages',
- 'ss_users',
- 'ss_active_users',
- 'ss_images',
- ], [], __METHOD__ );
+ return $db->selectRow( 'site_stats', self::selectFields(), [], __METHOD__ );
}
/**
return self::$pageCount[$ns];
}
+ /**
+ * @return array
+ */
+ public static function selectFields() {
+ return [
+ 'ss_row_id',
+ 'ss_total_edits',
+ 'ss_good_articles',
+ 'ss_total_pages',
+ 'ss_users',
+ 'ss_active_users',
+ 'ss_images',
+ ];
+ }
+
/**
* Is the provided row of site stats sane, or should it be regenerated?
*
}
}
+ /**
+ * Insert a dummy row with all zeroes if no row is present
+ */
+ public static function doPlaceholderInit() {
+ $dbw = wfGetDB( DB_MASTER );
+ if ( $dbw->selectRow( 'site_stats', '1', [], __METHOD__ ) === false ) {
+ $dbw->insert(
+ 'site_stats',
+ array_fill_keys( SiteStats::selectFields(), 0 ),
+ __METHOD__,
+ [ 'IGNORE' ]
+ );
+ }
+ }
+
/**
* Refresh site_stats
*/
public function response() {
/* Lazy initialization of response object for this request */
if ( !is_object( $this->response ) ) {
- $class = ( $this instanceof FauxRequest ) ? 'FauxResponse' : 'WebResponse';
+ $class = ( $this instanceof FauxRequest ) ? FauxResponse::class : WebResponse::class;
$this->response = new $class();
}
return $this->response;
* List of available modules: action name => module class
*/
private static $Modules = [
- 'login' => 'ApiLogin',
- 'clientlogin' => 'ApiClientLogin',
- 'logout' => 'ApiLogout',
- 'createaccount' => 'ApiAMCreateAccount',
- 'linkaccount' => 'ApiLinkAccount',
- 'unlinkaccount' => 'ApiRemoveAuthenticationData',
- 'changeauthenticationdata' => 'ApiChangeAuthenticationData',
- 'removeauthenticationdata' => 'ApiRemoveAuthenticationData',
- 'resetpassword' => 'ApiResetPassword',
- 'query' => 'ApiQuery',
- 'expandtemplates' => 'ApiExpandTemplates',
- 'parse' => 'ApiParse',
- 'stashedit' => 'ApiStashEdit',
- 'opensearch' => 'ApiOpenSearch',
- 'feedcontributions' => 'ApiFeedContributions',
- 'feedrecentchanges' => 'ApiFeedRecentChanges',
- 'feedwatchlist' => 'ApiFeedWatchlist',
- 'help' => 'ApiHelp',
- 'paraminfo' => 'ApiParamInfo',
- 'rsd' => 'ApiRsd',
- 'compare' => 'ApiComparePages',
- 'tokens' => 'ApiTokens',
- 'checktoken' => 'ApiCheckToken',
- 'cspreport' => 'ApiCSPReport',
- 'validatepassword' => 'ApiValidatePassword',
+ 'login' => ApiLogin::class,
+ 'clientlogin' => ApiClientLogin::class,
+ 'logout' => ApiLogout::class,
+ 'createaccount' => ApiAMCreateAccount::class,
+ 'linkaccount' => ApiLinkAccount::class,
+ 'unlinkaccount' => ApiRemoveAuthenticationData::class,
+ 'changeauthenticationdata' => ApiChangeAuthenticationData::class,
+ 'removeauthenticationdata' => ApiRemoveAuthenticationData::class,
+ 'resetpassword' => ApiResetPassword::class,
+ 'query' => ApiQuery::class,
+ 'expandtemplates' => ApiExpandTemplates::class,
+ 'parse' => ApiParse::class,
+ 'stashedit' => ApiStashEdit::class,
+ 'opensearch' => ApiOpenSearch::class,
+ 'feedcontributions' => ApiFeedContributions::class,
+ 'feedrecentchanges' => ApiFeedRecentChanges::class,
+ 'feedwatchlist' => ApiFeedWatchlist::class,
+ 'help' => ApiHelp::class,
+ 'paraminfo' => ApiParamInfo::class,
+ 'rsd' => ApiRsd::class,
+ 'compare' => ApiComparePages::class,
+ 'tokens' => ApiTokens::class,
+ 'checktoken' => ApiCheckToken::class,
+ 'cspreport' => ApiCSPReport::class,
+ 'validatepassword' => ApiValidatePassword::class,
// Write modules
- 'purge' => 'ApiPurge',
- 'setnotificationtimestamp' => 'ApiSetNotificationTimestamp',
- 'rollback' => 'ApiRollback',
- 'delete' => 'ApiDelete',
- 'undelete' => 'ApiUndelete',
- 'protect' => 'ApiProtect',
- 'block' => 'ApiBlock',
- 'unblock' => 'ApiUnblock',
- 'move' => 'ApiMove',
- 'edit' => 'ApiEditPage',
- 'upload' => 'ApiUpload',
- 'filerevert' => 'ApiFileRevert',
- 'emailuser' => 'ApiEmailUser',
- 'watch' => 'ApiWatch',
- 'patrol' => 'ApiPatrol',
- 'import' => 'ApiImport',
- 'clearhasmsg' => 'ApiClearHasMsg',
- 'userrights' => 'ApiUserrights',
- 'options' => 'ApiOptions',
- 'imagerotate' => 'ApiImageRotate',
- 'revisiondelete' => 'ApiRevisionDelete',
- 'managetags' => 'ApiManageTags',
- 'tag' => 'ApiTag',
- 'mergehistory' => 'ApiMergeHistory',
- 'setpagelanguage' => 'ApiSetPageLanguage',
+ 'purge' => ApiPurge::class,
+ 'setnotificationtimestamp' => ApiSetNotificationTimestamp::class,
+ 'rollback' => ApiRollback::class,
+ 'delete' => ApiDelete::class,
+ 'undelete' => ApiUndelete::class,
+ 'protect' => ApiProtect::class,
+ 'block' => ApiBlock::class,
+ 'unblock' => ApiUnblock::class,
+ 'move' => ApiMove::class,
+ 'edit' => ApiEditPage::class,
+ 'upload' => ApiUpload::class,
+ 'filerevert' => ApiFileRevert::class,
+ 'emailuser' => ApiEmailUser::class,
+ 'watch' => ApiWatch::class,
+ 'patrol' => ApiPatrol::class,
+ 'import' => ApiImport::class,
+ 'clearhasmsg' => ApiClearHasMsg::class,
+ 'userrights' => ApiUserrights::class,
+ 'options' => ApiOptions::class,
+ 'imagerotate' => ApiImageRotate::class,
+ 'revisiondelete' => ApiRevisionDelete::class,
+ 'managetags' => ApiManageTags::class,
+ 'tag' => ApiTag::class,
+ 'mergehistory' => ApiMergeHistory::class,
+ 'setpagelanguage' => ApiSetPageLanguage::class,
];
/**
* List of available formats: format name => format class
*/
private static $Formats = [
- 'json' => 'ApiFormatJson',
- 'jsonfm' => 'ApiFormatJson',
- 'php' => 'ApiFormatPhp',
- 'phpfm' => 'ApiFormatPhp',
- 'xml' => 'ApiFormatXml',
- 'xmlfm' => 'ApiFormatXml',
- 'rawfm' => 'ApiFormatJson',
- 'none' => 'ApiFormatNone',
+ 'json' => ApiFormatJson::class,
+ 'jsonfm' => ApiFormatJson::class,
+ 'php' => ApiFormatPhp::class,
+ 'phpfm' => ApiFormatPhp::class,
+ 'xml' => ApiFormatXml::class,
+ 'xmlfm' => ApiFormatXml::class,
+ 'rawfm' => ApiFormatJson::class,
+ 'none' => ApiFormatNone::class,
];
/**
* @code
* $modules['foo'] = 'ApiFoo';
* $modules['bar'] = [
- * 'class' => 'ApiBar',
+ * 'class' => ApiBar::class,
* 'factory' => function( $main, $name ) { ... }
* ];
* $modules['xyzzy'] = [
- * 'class' => 'ApiXyzzy',
- * 'factory' => [ 'XyzzyFactory', 'newApiModule' ]
+ * 'class' => ApiXyzzy::class,
+ * 'factory' => [ XyzzyFactory::class, 'newApiModule' ]
* ];
* @endcode
*
$prefix = $query->getModulePath() . '+';
$mgr = $query->getModuleManager();
foreach ( $mgr->getNamesWithClasses() as $name => $class ) {
- if ( is_subclass_of( $class, 'ApiQueryGeneratorBase' ) ) {
+ if ( is_subclass_of( $class, ApiQueryGeneratorBase::class ) ) {
$gens[$name] = $prefix . $name;
}
}
$result_array['text'] = $p_result->getText( [
'allowTOC' => !$params['disabletoc'],
'enableSectionEditLinks' => !$params['disableeditsection'],
+ 'unwrap' => $params['wrapoutputclass'] === '',
] );
$result_array[ApiResult::META_BC_SUBELEMENTS][] = 'text';
}
if ( $params['disabletidy'] ) {
$popts->setTidy( false );
}
- $popts->setWrapOutputClass(
- $params['wrapoutputclass'] === '' ? false : $params['wrapoutputclass']
- );
+ if ( $params['wrapoutputclass'] !== '' ) {
+ $popts->setWrapOutputClass( $params['wrapoutputclass'] );
+ }
$reset = null;
$suppressCache = false;
* @var array
*/
private static $QueryPropModules = [
- 'categories' => 'ApiQueryCategories',
- 'categoryinfo' => 'ApiQueryCategoryInfo',
- 'contributors' => 'ApiQueryContributors',
- 'deletedrevisions' => 'ApiQueryDeletedRevisions',
- 'duplicatefiles' => 'ApiQueryDuplicateFiles',
- 'extlinks' => 'ApiQueryExternalLinks',
- 'fileusage' => 'ApiQueryBacklinksprop',
- 'images' => 'ApiQueryImages',
- 'imageinfo' => 'ApiQueryImageInfo',
- 'info' => 'ApiQueryInfo',
- 'links' => 'ApiQueryLinks',
- 'linkshere' => 'ApiQueryBacklinksprop',
- 'iwlinks' => 'ApiQueryIWLinks',
- 'langlinks' => 'ApiQueryLangLinks',
- 'pageprops' => 'ApiQueryPageProps',
- 'redirects' => 'ApiQueryBacklinksprop',
- 'revisions' => 'ApiQueryRevisions',
- 'stashimageinfo' => 'ApiQueryStashImageInfo',
- 'templates' => 'ApiQueryLinks',
- 'transcludedin' => 'ApiQueryBacklinksprop',
+ 'categories' => ApiQueryCategories::class,
+ 'categoryinfo' => ApiQueryCategoryInfo::class,
+ 'contributors' => ApiQueryContributors::class,
+ 'deletedrevisions' => ApiQueryDeletedRevisions::class,
+ 'duplicatefiles' => ApiQueryDuplicateFiles::class,
+ 'extlinks' => ApiQueryExternalLinks::class,
+ 'fileusage' => ApiQueryBacklinksprop::class,
+ 'images' => ApiQueryImages::class,
+ 'imageinfo' => ApiQueryImageInfo::class,
+ 'info' => ApiQueryInfo::class,
+ 'links' => ApiQueryLinks::class,
+ 'linkshere' => ApiQueryBacklinksprop::class,
+ 'iwlinks' => ApiQueryIWLinks::class,
+ 'langlinks' => ApiQueryLangLinks::class,
+ 'pageprops' => ApiQueryPageProps::class,
+ 'redirects' => ApiQueryBacklinksprop::class,
+ 'revisions' => ApiQueryRevisions::class,
+ 'stashimageinfo' => ApiQueryStashImageInfo::class,
+ 'templates' => ApiQueryLinks::class,
+ 'transcludedin' => ApiQueryBacklinksprop::class,
];
/**
* @var array
*/
private static $QueryListModules = [
- 'allcategories' => 'ApiQueryAllCategories',
- 'alldeletedrevisions' => 'ApiQueryAllDeletedRevisions',
- 'allfileusages' => 'ApiQueryAllLinks',
- 'allimages' => 'ApiQueryAllImages',
- 'alllinks' => 'ApiQueryAllLinks',
- 'allpages' => 'ApiQueryAllPages',
- 'allredirects' => 'ApiQueryAllLinks',
- 'allrevisions' => 'ApiQueryAllRevisions',
- 'mystashedfiles' => 'ApiQueryMyStashedFiles',
- 'alltransclusions' => 'ApiQueryAllLinks',
- 'allusers' => 'ApiQueryAllUsers',
- 'backlinks' => 'ApiQueryBacklinks',
- 'blocks' => 'ApiQueryBlocks',
- 'categorymembers' => 'ApiQueryCategoryMembers',
- 'deletedrevs' => 'ApiQueryDeletedrevs',
- 'embeddedin' => 'ApiQueryBacklinks',
- 'exturlusage' => 'ApiQueryExtLinksUsage',
- 'filearchive' => 'ApiQueryFilearchive',
- 'imageusage' => 'ApiQueryBacklinks',
- 'iwbacklinks' => 'ApiQueryIWBacklinks',
- 'langbacklinks' => 'ApiQueryLangBacklinks',
- 'logevents' => 'ApiQueryLogEvents',
- 'pageswithprop' => 'ApiQueryPagesWithProp',
- 'pagepropnames' => 'ApiQueryPagePropNames',
- 'prefixsearch' => 'ApiQueryPrefixSearch',
- 'protectedtitles' => 'ApiQueryProtectedTitles',
- 'querypage' => 'ApiQueryQueryPage',
- 'random' => 'ApiQueryRandom',
- 'recentchanges' => 'ApiQueryRecentChanges',
- 'search' => 'ApiQuerySearch',
- 'tags' => 'ApiQueryTags',
- 'usercontribs' => 'ApiQueryContributions',
- 'users' => 'ApiQueryUsers',
- 'watchlist' => 'ApiQueryWatchlist',
- 'watchlistraw' => 'ApiQueryWatchlistRaw',
+ 'allcategories' => ApiQueryAllCategories::class,
+ 'alldeletedrevisions' => ApiQueryAllDeletedRevisions::class,
+ 'allfileusages' => ApiQueryAllLinks::class,
+ 'allimages' => ApiQueryAllImages::class,
+ 'alllinks' => ApiQueryAllLinks::class,
+ 'allpages' => ApiQueryAllPages::class,
+ 'allredirects' => ApiQueryAllLinks::class,
+ 'allrevisions' => ApiQueryAllRevisions::class,
+ 'mystashedfiles' => ApiQueryMyStashedFiles::class,
+ 'alltransclusions' => ApiQueryAllLinks::class,
+ 'allusers' => ApiQueryAllUsers::class,
+ 'backlinks' => ApiQueryBacklinks::class,
+ 'blocks' => ApiQueryBlocks::class,
+ 'categorymembers' => ApiQueryCategoryMembers::class,
+ 'deletedrevs' => ApiQueryDeletedrevs::class,
+ 'embeddedin' => ApiQueryBacklinks::class,
+ 'exturlusage' => ApiQueryExtLinksUsage::class,
+ 'filearchive' => ApiQueryFilearchive::class,
+ 'imageusage' => ApiQueryBacklinks::class,
+ 'iwbacklinks' => ApiQueryIWBacklinks::class,
+ 'langbacklinks' => ApiQueryLangBacklinks::class,
+ 'logevents' => ApiQueryLogEvents::class,
+ 'pageswithprop' => ApiQueryPagesWithProp::class,
+ 'pagepropnames' => ApiQueryPagePropNames::class,
+ 'prefixsearch' => ApiQueryPrefixSearch::class,
+ 'protectedtitles' => ApiQueryProtectedTitles::class,
+ 'querypage' => ApiQueryQueryPage::class,
+ 'random' => ApiQueryRandom::class,
+ 'recentchanges' => ApiQueryRecentChanges::class,
+ 'search' => ApiQuerySearch::class,
+ 'tags' => ApiQueryTags::class,
+ 'usercontribs' => ApiQueryContributions::class,
+ 'users' => ApiQueryUsers::class,
+ 'watchlist' => ApiQueryWatchlist::class,
+ 'watchlistraw' => ApiQueryWatchlistRaw::class,
];
/**
* @var array
*/
private static $QueryMetaModules = [
- 'allmessages' => 'ApiQueryAllMessages',
- 'authmanagerinfo' => 'ApiQueryAuthManagerInfo',
- 'siteinfo' => 'ApiQuerySiteinfo',
- 'userinfo' => 'ApiQueryUserInfo',
- 'filerepoinfo' => 'ApiQueryFileRepoInfo',
- 'tokens' => 'ApiQueryTokens',
+ 'allmessages' => ApiQueryAllMessages::class,
+ 'authmanagerinfo' => ApiQueryAuthManagerInfo::class,
+ 'siteinfo' => ApiQuerySiteinfo::class,
+ 'userinfo' => ApiQueryUserInfo::class,
+ 'filerepoinfo' => ApiQueryFileRepoInfo::class,
+ 'tokens' => ApiQueryTokens::class,
];
/**
}
$this->tokenFunctions = [
- 'edit' => [ 'ApiQueryInfo', 'getEditToken' ],
- 'delete' => [ 'ApiQueryInfo', 'getDeleteToken' ],
- 'protect' => [ 'ApiQueryInfo', 'getProtectToken' ],
- 'move' => [ 'ApiQueryInfo', 'getMoveToken' ],
- 'block' => [ 'ApiQueryInfo', 'getBlockToken' ],
- 'unblock' => [ 'ApiQueryInfo', 'getUnblockToken' ],
- 'email' => [ 'ApiQueryInfo', 'getEmailToken' ],
- 'import' => [ 'ApiQueryInfo', 'getImportToken' ],
- 'watch' => [ 'ApiQueryInfo', 'getWatchToken' ],
+ 'edit' => [ self::class, 'getEditToken' ],
+ 'delete' => [ self::class, 'getDeleteToken' ],
+ 'protect' => [ self::class, 'getProtectToken' ],
+ 'move' => [ self::class, 'getMoveToken' ],
+ 'block' => [ self::class, 'getBlockToken' ],
+ 'unblock' => [ self::class, 'getUnblockToken' ],
+ 'email' => [ self::class, 'getEmailToken' ],
+ 'import' => [ self::class, 'getImportToken' ],
+ 'watch' => [ self::class, 'getWatchToken' ],
];
Hooks::run( 'APIQueryInfoTokens', [ &$this->tokenFunctions ] );
$this->everything = $this->titles + $this->missing;
$result = $this->getResult();
- uasort( $this->everything, [ 'Title', 'compare' ] );
+ uasort( $this->everything, [ Title::class, 'compare' ] );
if ( !is_null( $this->params['continue'] ) ) {
// Throw away any titles we're gonna skip so they don't
// clutter queries
}
$this->tokenFunctions = [
- 'patrol' => [ 'ApiQueryRecentChanges', 'getPatrolToken' ]
+ 'patrol' => [ self::class, 'getPatrolToken' ]
];
Hooks::run( 'APIQueryRecentChangesTokens', [ &$this->tokenFunctions ] );
}
$this->tokenFunctions = [
- 'rollback' => [ 'ApiQueryRevisions', 'getRollbackToken' ]
+ 'rollback' => [ self::class, 'getRollbackToken' ]
];
Hooks::run( 'APIQueryRevisionsTokens', [ &$this->tokenFunctions ] );
foreach ( $myWgHooks as $name => $subscribers ) {
$arr = [
'name' => $name,
- 'subscribers' => array_map( [ 'SpecialVersion', 'arrayToString' ], $subscribers ),
+ 'subscribers' => array_map( [ SpecialVersion::class, 'arrayToString' ], $subscribers ),
];
ApiResult::setArrayType( $arr['subscribers'], 'array' );
}
$this->tokenFunctions = [
- 'userrights' => [ 'ApiQueryUsers', 'getUserrightsToken' ],
+ 'userrights' => [ self::class, 'getUserrightsToken' ],
];
Hooks::run( 'APIQueryUsersTokens', [ &$this->tokenFunctions ] );
if ( $types ) {
return $types;
}
- $types = [ 'patrol' => [ 'ApiQueryRecentChanges', 'getPatrolToken' ] ];
+ $types = [ 'patrol' => [ ApiQueryRecentChanges::class, 'getPatrolToken' ] ];
$names = [ 'edit', 'delete', 'protect', 'move', 'block', 'unblock',
'email', 'import', 'watch', 'options' ];
foreach ( $names as $name ) {
- $types[$name] = [ 'ApiQueryInfo', 'get' . ucfirst( $name ) . 'Token' ];
+ $types[$name] = [ ApiQueryInfo::class, 'get' . ucfirst( $name ) . 'Token' ];
}
Hooks::run( 'ApiTokensGetTokenTypes', [ &$types ] );
*/
protected function handleStashException( $e ) {
switch ( get_class( $e ) ) {
- case 'UploadStashFileNotFoundException':
+ case UploadStashFileNotFoundException::class:
$wrap = 'apierror-stashedfilenotfound';
break;
- case 'UploadStashBadPathException':
+ case UploadStashBadPathException::class:
$wrap = 'apierror-stashpathinvalid';
break;
- case 'UploadStashFileException':
+ case UploadStashFileException::class:
$wrap = 'apierror-stashfilestorage';
break;
- case 'UploadStashZeroLengthFileException':
+ case UploadStashZeroLengthFileException::class:
$wrap = 'apierror-stashzerolength';
break;
- case 'UploadStashNotLoggedInException':
+ case UploadStashNotLoggedInException::class:
return StatusValue::newFatal( ApiMessage::create(
[ 'apierror-mustbeloggedin', $this->msg( 'action-upload' ) ], 'stashnotloggedin'
) );
- case 'UploadStashWrongOwnerException':
+ case UploadStashWrongOwnerException::class:
$wrap = 'apierror-stashwrongowner';
break;
- case 'UploadStashNoSuchKeyException':
+ case UploadStashNoSuchKeyException::class:
$wrap = 'apierror-stashnosuchfilekey';
break;
default:
"Tacsipacsi"
]
},
- "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Dokumentation]]\n* [[mw:Special:MyLanguage/API:FAQ|Häufig gestellte Fragen]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Mailingliste]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce API-Ankündigungen]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Fehlerberichte und Anfragen]\n</div>\n<strong>Status:</strong> Alle auf dieser Seite gezeigten Funktionen sollten funktionieren, allerdings ist die API in aktiver Entwicklung und kann sich zu jeder Zeit ändern. Abonniere die [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ MediaWiki-API-Ankündigungs-Mailingliste], um über Aktualisierungen informiert zu werden.\n\n<strong>Fehlerhafte Anfragen:</strong> Wenn fehlerhafte Anfragen an die API gesendet werden, wird ein HTTP-Header mit dem Schlüssel „MediaWiki-API-Error“ gesendet. Der Wert des Headers und der Fehlercode werden auf den gleichen Wert gesetzt. Für weitere Informationen siehe [[mw:Special:MyLanguage/API:Errors_and_warnings|API: Fehler und Warnungen]].\n\n<strong>Testen:</strong> Zum einfachen Testen von API-Anfragen, siehe [[Special:ApiSandbox]].",
+ "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Dokumentation]]\n* [[mw:Special:MyLanguage/API:FAQ|Häufig gestellte Fragen]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Mailingliste]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce API-Ankündigungen]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Fehlerberichte und Anfragen]\n</div>\n<strong>Status:</strong> Alle auf dieser Seite gezeigten Funktionen sollten funktionieren, allerdings ist die API in aktiver Entwicklung und kann sich zu jeder Zeit ändern. Abonniere die [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ MediaWiki-API-Ankündigungs-Mailingliste], um über Aktualisierungen informiert zu werden.\n\n<strong>Fehlerhafte Anfragen:</strong> Wenn fehlerhafte Anfragen an die API gesendet werden, wird ein HTTP-Header mit dem Schlüssel „MediaWiki-API-Error“ gesendet. Der Wert des Headers und der Fehlercode werden auf den gleichen Wert gesetzt. Für weitere Informationen siehe [[mw:Special:MyLanguage/API:Errors_and_warnings|API: Fehler und Warnungen]].\n\n<p class=\"mw-apisandbox-link\"><strong>Testen:</strong> Zum einfachen Testen von API-Anfragen, siehe [[Special:ApiSandbox]].</p>",
"apihelp-main-param-action": "Auszuführende Aktion.",
"apihelp-main-param-format": "Format der Ausgabe.",
"apihelp-main-param-maxlag": "maxlag kann verwendet werden, wenn MediaWiki auf einem datenbankreplizierten Cluster installiert ist. Um weitere Replikationsrückstände zu verhindern, lässt dieser Parameter den Client warten, bis der Replikationsrückstand kleiner als der angegebene Wert (in Sekunden) ist. Bei einem größerem Rückstand wird der Fehlercode <samp>maxlag</samp> zurückgegeben mit einer Nachricht wie <samp>Waiting for $host: $lag seconds lagged</samp>.<br />Siehe [[mw:Special:MyLanguage/Manual:Maxlag_parameter|Handbuch: Maxlag parameter]] für weitere Informationen.",
},
"apihelp-main-summary": "",
- "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Documentation]]\n* [[mw:Special:MyLanguage/API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Mailing list]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce API Announcements]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Bugs & requests]\n</div>\n<strong>Status:</strong> All features shown on this page should be working, but the API is still in active development, and may change at any time. Subscribe to [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ the mediawiki-api-announce mailing list] for notice of updates.\n\n<strong>Erroneous requests:</strong> When erroneous requests are sent to the API, an HTTP header will be sent with the key \"MediaWiki-API-Error\" and then both the value of the header and the error code sent back will be set to the same value. For more information see [[mw:Special:MyLanguage/API:Errors_and_warnings|API: Errors and warnings]].\n\n<strong>Testing:</strong> For ease of testing API requests, see [[Special:ApiSandbox]].",
+ "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Documentation]]\n* [[mw:Special:MyLanguage/API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Mailing list]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce API Announcements]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Bugs & requests]\n</div>\n<strong>Status:</strong> All features shown on this page should be working, but the API is still in active development, and may change at any time. Subscribe to [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ the mediawiki-api-announce mailing list] for notice of updates.\n\n<strong>Erroneous requests:</strong> When erroneous requests are sent to the API, an HTTP header will be sent with the key \"MediaWiki-API-Error\" and then both the value of the header and the error code sent back will be set to the same value. For more information see [[mw:Special:MyLanguage/API:Errors_and_warnings|API: Errors and warnings]].\n\n<p class=\"mw-apisandbox-link\"><strong>Testing:</strong> For ease of testing API requests, see [[Special:ApiSandbox]].</p>",
"apihelp-main-param-action": "Which action to perform.",
"apihelp-main-param-format": "The format of the output.",
"apihelp-main-param-maxlag": "Maximum lag can be used when MediaWiki is installed on a database replicated cluster. To save actions causing any more site replication lag, this parameter can make the client wait until the replication lag is less than the specified value. In case of excessive lag, error code <samp>maxlag</samp> is returned with a message like <samp>Waiting for $host: $lag seconds lagged</samp>.<br />See [[mw:Special:MyLanguage/Manual:Maxlag_parameter|Manual: Maxlag parameter]] for more information.",
"Kenjiraw"
]
},
- "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Documentation]]\n* [[mw:Special:MyLanguage/API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Liste de diffusion]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Annonces de l’API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Bogues et demandes]\n</div>\n<strong>État :</strong> Toutes les fonctionnalités affichées sur cette page devraient fonctionner, mais l’API est encore en cours de développement et peut changer à tout moment. Inscrivez-vous à [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ la liste de diffusion mediawiki-api-announce] pour être informé des mises à jour.\n\n<strong>Requêtes erronées :</strong> Si des requêtes erronées sont envoyées à l’API, un entête HTTP sera renvoyé avec la clé « MediaWiki-API-Error ». La valeur de cet entête et le code d’erreur renvoyé prendront la même valeur. Pour plus d’information, voyez [[mw:Special:MyLanguage/API:Errors_and_warnings|API: Errors and warnings]].\n\n<strong>Test :</strong> Pour faciliter le test des requêtes de l’API, voyez [[Special:ApiSandbox]].",
+ "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Documentation]]\n* [[mw:Special:MyLanguage/API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Liste de diffusion]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Annonces de l’API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Bogues et demandes]\n</div>\n<strong>État :</strong> Toutes les fonctionnalités affichées sur cette page devraient fonctionner, mais l’API est encore en cours de développement et peut changer à tout moment. Inscrivez-vous à [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ la liste de diffusion mediawiki-api-announce] pour être informé des mises à jour.\n\n<strong>Requêtes erronées :</strong> Si des requêtes erronées sont envoyées à l’API, un entête HTTP sera renvoyé avec la clé « MediaWiki-API-Error ». La valeur de cet entête et le code d’erreur renvoyé prendront la même valeur. Pour plus d’information, voyez [[mw:Special:MyLanguage/API:Errors_and_warnings|API: Errors and warnings]].\n\n<p class=\"mw-apisandbox-link\"><strong>Test :</strong> Pour faciliter le test des requêtes de l’API, voyez [[Special:ApiSandbox]].</p>",
"apihelp-main-param-action": "Quelle action effectuer.",
"apihelp-main-param-format": "Le format de sortie.",
"apihelp-main-param-maxlag": "La latence maximale peut être utilisée quand MédiaWiki est installé sur un cluster de base de données répliqué. Pour éviter des actions provoquant un supplément de latence de réplication de site, ce paramètre peut faire attendre le client jusqu’à ce que la latence de réplication soit inférieure à une valeur spécifiée. En cas de latence excessive, le code d’erreur <samp>maxlag</samp> est renvoyé avec un message tel que <samp>Attente de $host : $lag secondes de délai</samp>.<br />Voyez [[mw:Special:MyLanguage/Manual:Maxlag_parameter|Manuel: Maxlag parameter]] pour plus d’information.",
"Dj"
]
},
- "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Dokumentáció]]\n* [[mw:Special:MyLanguage/API:FAQ|GYIK]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Levelezőlista]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce API-bejelentések]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Hibabejelentések és kérések]\n</div>\n<strong>Státusz:</strong> Minden ezen a lapon látható funkciónak működnie kell, de az API jelenleg is aktív fejlesztés alatt áll, és bármikor változhat. Iratkozz fel a [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ mediawiki-api-announce levelezőlistára] a frissítések követéséhez.\n\n<strong>Hibás kérések:</strong> Ha az API hibás kérést kap, egy HTTP-fejlécet küld vissza „MediaWiki-API-Error” kulccsal, és a fejléc értéke és a visszaküldött hibakód ugyanarra az értékre lesz állítva. További információért lásd: [[mw:Special:MyLanguage/API:Errors_and_warnings|API: Hibák és figyelmeztetések]].\n\n<strong>Tesztelés:</strong> Az API-kérések könnyebb teszteléséhez használható az [[Special:ApiSandbox|API-homokozó]].",
+ "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Dokumentáció]]\n* [[mw:Special:MyLanguage/API:FAQ|GYIK]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Levelezőlista]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce API-bejelentések]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Hibabejelentések és kérések]\n</div>\n<strong>Státusz:</strong> Minden ezen a lapon látható funkciónak működnie kell, de az API jelenleg is aktív fejlesztés alatt áll, és bármikor változhat. Iratkozz fel a [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ mediawiki-api-announce levelezőlistára] a frissítések követéséhez.\n\n<strong>Hibás kérések:</strong> Ha az API hibás kérést kap, egy HTTP-fejlécet küld vissza „MediaWiki-API-Error” kulccsal, és a fejléc értéke és a visszaküldött hibakód ugyanarra az értékre lesz állítva. További információért lásd: [[mw:Special:MyLanguage/API:Errors_and_warnings|API: Hibák és figyelmeztetések]].\n\n<p class=\"mw-apisandbox-link\"><strong>Tesztelés:</strong> Az API-kérések könnyebb teszteléséhez használható az [[Special:ApiSandbox|API-homokozó]].</p>",
"apihelp-main-param-action": "Milyen műveletet hajtson végre.",
"apihelp-main-param-format": "A kimenet formátuma.",
"apihelp-main-param-smaxage": "Az <code>s-maxage</code> gyorsítótár-vezérlő HTTP-fejléc beállítása ennyi másodpercre. A hibák soha nincsenek gyorsítótárazva.",
"Margherita.mignanelli"
]
},
- "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Documentazione]] (in inglese)\n* [[mw:Special:MyLanguage/API:FAQ|FAQ]] (in inglese)\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Mailing list]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Annunci sull'API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Bug & richieste]\n</div>\n<strong>Stato:</strong> tutte le funzioni e caratteristiche mostrate su questa pagina dovrebbero funzionare, ma le API sono ancora in fase attiva di sviluppo, e potrebbero cambiare in qualsiasi momento. Iscriviti alla [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ la mailing list sugli annunci delle API MediaWiki] per essere informato sugli aggiornamenti.\n\n<strong>Istruzioni sbagliate:</strong> quando vengono impartite alle API delle istruzioni sbagliate, un'intestazione HTTP verrà inviata col messaggio \"MediaWiki-API-Error\" e, sia il valore dell'intestazione, sia il codice d'errore, verranno impostati con lo stesso valore. Per maggiori informazioni leggi [[mw:Special:MyLanguage/API:Errors_and_warnings|API:Errori ed avvertimenti]] (in inglese).\n\n<strong>Test:</strong> per testare facilmente le richieste API, vedi [[Special:ApiSandbox]].",
+ "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Documentazione]] (in inglese)\n* [[mw:Special:MyLanguage/API:FAQ|FAQ]] (in inglese)\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Mailing list]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Annunci sull'API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Bug & richieste]\n</div>\n<strong>Stato:</strong> tutte le funzioni e caratteristiche mostrate su questa pagina dovrebbero funzionare, ma le API sono ancora in fase attiva di sviluppo, e potrebbero cambiare in qualsiasi momento. Iscriviti alla [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ la mailing list sugli annunci delle API MediaWiki] per essere informato sugli aggiornamenti.\n\n<strong>Istruzioni sbagliate:</strong> quando vengono impartite alle API delle istruzioni sbagliate, un'intestazione HTTP verrà inviata col messaggio \"MediaWiki-API-Error\" e, sia il valore dell'intestazione, sia il codice d'errore, verranno impostati con lo stesso valore. Per maggiori informazioni leggi [[mw:Special:MyLanguage/API:Errors_and_warnings|API:Errori ed avvertimenti]] (in inglese).\n\n<p class=\"mw-apisandbox-link\"><strong>Test:</strong> per testare facilmente le richieste API, vedi [[Special:ApiSandbox]].</p>",
"apihelp-main-param-action": "Azione da compiere.",
"apihelp-main-param-format": "Formato dell'output.",
"apihelp-main-param-assert": "Verifica che l'utente abbia effettuato l'accesso se si è impostato <kbd>user</kbd>, o che abbia i permessi di bot se si è impostato <kbd>bot</kbd>.",
"Omotecho"
]
},
- "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|説明文書]]\n* [[mw:Special:MyLanguage/API:FAQ|よくある質問]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api メーリングリスト]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce API 告知]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R バグの報告とリクエスト]\n</div>\n<strong>状態:</strong> このページに表示されている機能は全て動作するはずですが、この API は未だ活発に開発されており、変更される可能性があります。アップデートの通知を受け取るには、[https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ the mediawiki-api-announce メーリングリスト]に参加してください。\n\n<strong>誤ったリクエスト:</strong> 誤ったリクエストが API に送られた場合、\"MediaWiki-API-Error\" HTTP ヘッダーが送信され、そのヘッダーの値と送り返されるエラーコードは同じ値にセットされます。より詳しい情報は [[mw:Special:MyLanguage/API:Errors_and_warnings|API: Errors and warnings]] を参照してください。\n\n<strong>テスト:</strong> API のリクエストのテストは、[[Special:ApiSandbox]]で簡単に行えます。",
+ "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|説明文書]]\n* [[mw:Special:MyLanguage/API:FAQ|よくある質問]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api メーリングリスト]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce API 告知]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R バグの報告とリクエスト]\n</div>\n<strong>状態:</strong> このページに表示されている機能は全て動作するはずですが、この API は未だ活発に開発されており、変更される可能性があります。アップデートの通知を受け取るには、[https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ the mediawiki-api-announce メーリングリスト]に参加してください。\n\n<strong>誤ったリクエスト:</strong> 誤ったリクエストが API に送られた場合、\"MediaWiki-API-Error\" HTTP ヘッダーが送信され、そのヘッダーの値と送り返されるエラーコードは同じ値にセットされます。より詳しい情報は [[mw:Special:MyLanguage/API:Errors_and_warnings|API: Errors and warnings]] を参照してください。\n\n<p class=\"mw-apisandbox-link\"><strong>テスト:</strong> API のリクエストのテストは、[[Special:ApiSandbox]]で簡単に行えます。</p>",
"apihelp-main-param-action": "実行する操作です。",
"apihelp-main-param-format": "出力する形式です。",
"apihelp-main-param-smaxage": "<code>s-maxage</code> HTTP キャッシュ コントロール ヘッダー に、この秒数を設定します。エラーがキャッシュされることはありません。",
"Hamilton Abreu",
"Mansil",
"Felipe L. Ewald",
- "Athena in Wonderland"
+ "Athena in Wonderland",
+ "Waldir"
]
},
- "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Documentação]]\n* [[mw:Special:MyLanguage/API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Lista de discussão]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Anúncios da API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Erros e pedidos]\n</div>\n<strong>Estado:</strong> Todas as funcionalidades mostradas nesta página devem ter o comportamento documentado, mas a API ainda está em desenvolvimento ativo e pode ser alterada a qualquer momento. Inscreva-se na [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ lista de discussão mediawiki-api-announce] para ser informado acerca das atualizações.\n\n<strong>Pedidos incorretos:</strong> Quando são enviados pedidos incorretos à API, será devolvido um cabeçalho HTTP com a chave \"MediaWiki-API-Error\" e depois tanto o valor desse cabeçalho como o código de erro devolvido serão definidos com o mesmo valor. Para mais informação, consulte [[mw:Special:MyLanguage/API:Errors_and_warnings|API:Erros e avisos]].\n\n<strong>Testes:</strong> Para testar facilmente pedidos à API, visite [[Special:ApiSandbox|Testes da API]].",
+ "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Documentação]]\n* [[mw:Special:MyLanguage/API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Lista de discussão]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Anúncios da API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Erros e pedidos]\n</div>\n<strong>Estado:</strong> Todas as funcionalidades mostradas nesta página devem ter o comportamento documentado, mas a API ainda está em desenvolvimento ativo e pode ser alterada a qualquer momento. Inscreva-se na [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ lista de discussão mediawiki-api-announce] para ser informado acerca das atualizações.\n\n<strong>Pedidos incorretos:</strong> Quando são enviados pedidos incorretos à API, será devolvido um cabeçalho HTTP com a chave \"MediaWiki-API-Error\" e depois tanto o valor desse cabeçalho como o código de erro devolvido serão definidos com o mesmo valor. Para mais informação, consulte [[mw:Special:MyLanguage/API:Errors_and_warnings|API:Erros e avisos]].\n\n<p class=\"mw-apisandbox-link\">\n<strong>Testes:</strong> Para testar facilmente pedidos à API, visite [[Special:ApiSandbox|Testes da API]].\n</p>",
"apihelp-main-param-action": "A operação a ser realizada.",
"apihelp-main-param-format": "O formato do resultado.",
- "apihelp-main-param-maxlag": "O atraso máximo pode ser usado quando o MediaWiki é instalado num ''cluster'' de bases de dados replicadas. Para impedir que as operações causem ainda mais atrasos de replicação do ''site'', este parâmetro pode fazer o cliente aguardar até que o atraso de replicação seja inferior ao valor especificado. Caso o atraso atual exceda esse valor, o código de erro <samp>maxlag</samp> é devolvido com uma mensagem como <samp>À espera do servidor $host: $lag segundos de atraso</samp>.<br />Consulte [[mw:Special:MyLanguage/Manual:Maxlag_parameter|Manual: Parâmetro maxlag]] para mais informações.",
+ "apihelp-main-param-maxlag": "O atraso máximo pode ser usado quando o MediaWiki é instalado num ''cluster'' de bases de dados replicadas. Para impedir que as operações causem ainda mais atrasos de replicação do sítio, este parâmetro pode fazer o cliente aguardar até que o atraso de replicação seja inferior ao valor especificado. Caso o atraso atual exceda esse valor, o código de erro <samp>maxlag</samp> é devolvido com uma mensagem como <samp>À espera do servidor $host: $lag segundos de atraso</samp>.<br />Consulte [[mw:Special:MyLanguage/Manual:Maxlag_parameter|Manual: Parâmetro maxlag]] para mais informações.",
"apihelp-main-param-smaxage": "Definir no cabeçalho HTTP <code>s-maxage</code> de controlo da cache este número de segundos. Os erros nunca são armazenados na cache.",
"apihelp-main-param-maxage": "Definir no cabeçalho HTTP <code>max-age</code> de controlo da cache este número de segundos. Os erros nunca são armazenados na cache.",
"apihelp-main-param-assert": "Se definido com o valor <kbd>user</kbd>, verificar que o utilizador está autenticado. Se definido com o valor <kbd>bot</kbd>, verificar que o utilizador tem o privilégio de conta robô.",
"apihelp-opensearch-example-te": "Encontrar as páginas que começam por <kbd>Te</kbd>.",
"apihelp-options-summary": "Alterar as preferências do utilizador atual.",
"apihelp-options-extended-description": "Só podem ser definidas as opções que estão registadas no núcleo do MediaWiki ou numa das extensões instaladas, ou opções cuja chave tem o prefixo <code>userjs-</code> (que são supostas ser usadas por ''scripts'' de utilizador).",
- "apihelp-options-param-reset": "Reiniciar preferências para os valores por omissão do ''site''.",
+ "apihelp-options-param-reset": "Reiniciar preferências para os valores por omissão do sítio.",
"apihelp-options-param-resetkinds": "Lista dos tipos de opções a reiniciar quando a opção <var>$1reset</var> está definida.",
"apihelp-options-param-change": "Listas das alterações, na forma nome=valor (isto é, skin=vector). Se não for fornecido nenhum valor (nem sequer um sinal de igualdade), por exemplo, nomedaopção|outraopção|..., a opção será reiniciada para o seu valor por omissão. Se qualquer dos valores passados contém uma barra vertical (<kbd>|</kbd>), use um [[Special:ApiHelp/main#main/datatypes|separador alternativo para valores múltiplos]] de forma a obter o comportamento correto.",
"apihelp-options-param-optionname": "O nome da opção que deve ser configurada com o valor dado por <var>$1optionvalue</var>.",
"apihelp-purge-example-simple": "Purgar as páginas <kbd>Main Page</kbd> e <kbd>API</kbd>.",
"apihelp-purge-example-generator": "Purgar as primeiras 10 páginas no espaço nominal principal.",
"apihelp-query-summary": "Obter dados de, e sobre, o MediaWiki.",
- "apihelp-query-extended-description": "Todas as modificações de dados terão primeiro que usar uma consulta para adquirir uma chave, o que visa impedir abusos de sites maliciosos.",
+ "apihelp-query-extended-description": "Todas as modificações de dados terão primeiro que usar uma consulta para adquirir uma chave, o que visa impedir abusos de sítios maliciosos.",
"apihelp-query-param-prop": "As propriedades a serem obtidas para as páginas consultadas.",
"apihelp-query-param-list": "As listas a serem obtidas.",
"apihelp-query-param-meta": "Os metadados a serem obtidos.",
"apihelp-query-param-exportnowrap": "Devolver o XML de exportação sem envolvê-lo num resultado XML (o mesmo formato que [[Special:Export]]). Só pode ser usado com $1export.",
"apihelp-query-param-iwurl": "Indica se deve ser obtido o URL completo quando o título é uma hiperligação interwikis.",
"apihelp-query-param-rawcontinue": "Devolver os dados em bruto de <samp>query-continue</samp> para continuar.",
- "apihelp-query-example-revisions": "Obter [[Special:ApiHelp/query+siteinfo|informação do ''site'']] e as [[Special:ApiHelp/query+revisions|revisões]] da página <kbd>Main Page</kbd>.",
+ "apihelp-query-example-revisions": "Obter [[Special:ApiHelp/query+siteinfo|informação do sítio]] e as [[Special:ApiHelp/query+revisions|revisões]] da página <kbd>Main Page</kbd>.",
"apihelp-query-example-allpages": "Obter as revisões das páginas que começam por <kbd>API/</kbd>.",
"apihelp-query+allcategories-summary": "Enumerar todas as categorias.",
"apihelp-query+allcategories-param-from": "A categoria a partir da qual será começada a enumeração.",
"apihelp-query+alllinks-example-unique": "Listar os títulos únicos para os quais existem hiperligações.",
"apihelp-query+alllinks-example-unique-generator": "Obtém todos os títulos para os quais existem hiperligações, marcando aqueles em falta.",
"apihelp-query+alllinks-example-generator": "Obtém as páginas que contêm as ligações.",
- "apihelp-query+allmessages-summary": "Devolver as mensagens deste ''site''.",
+ "apihelp-query+allmessages-summary": "Devolver as mensagens deste sítio.",
"apihelp-query+allmessages-param-messages": "Mensagens a serem produzidas no resultado. <kbd>*</kbd> (o valor por omissão) significa todas as mensagens.",
"apihelp-query+allmessages-param-prop": "As propriedades a serem obtidas:",
"apihelp-query+allmessages-param-enableparser": "Definir para ativar o analisador sintático; irá pré-processar o texto wiki da mensagem (substituir palavras mágicas, processar predefinições, etc.).",
"apihelp-query+embeddedin-example-simple": "Mostrar as páginas que transcluem <kbd>Template:Stub</kbd>.",
"apihelp-query+embeddedin-example-generator": "Obter informação sobre as páginas que transcluem <kbd>Template:Stub</kbd>.",
"apihelp-query+extlinks-summary": "Devolve todos os URL externos (que não sejam interwikis) das páginas especificadas.",
- "apihelp-query+extlinks-param-limit": "O número de ''links'' a serem devolvidos.",
+ "apihelp-query+extlinks-param-limit": "O número de hiperligações a serem devolvidas.",
"apihelp-query+extlinks-param-protocol": "Protocolo do URL. Se vazio e <var>$1query</var> está definido, o protocolo é <kbd>http</kbd>. Deixe este parâmetro e <var>$1query</var> vazios para listar todas as hiperligações externas.",
"apihelp-query+extlinks-param-query": "Texto de pesquisa sem protocolo. Útil para verificar se uma determinada página contém um determinado URL externo.",
"apihelp-query+extlinks-param-expandurl": "Expandir os URL relativos a protocolo com o protocolo canónico.",
"apihelp-query+info-param-token": "Em substituição, usar [[Special:ApiHelp/query+tokens|action=query&meta=tokens]].",
"apihelp-query+info-example-simple": "Obter informações sobre a página <kbd>Main Page</kbd>.",
"apihelp-query+info-example-protection": "Obter informação geral e de proteção sobre a página <kbd>Main Page</kbd>.",
- "apihelp-query+iwbacklinks-summary": "Encontrar todas as páginas que contêm ''links'' para as páginas indicadas.",
+ "apihelp-query+iwbacklinks-summary": "Encontrar todas as páginas que contêm hiperligações para as páginas indicadas.",
"apihelp-query+iwbacklinks-extended-description": "Pode ser usado para encontrar todas as hiperligações com um prefixo, ou todas as hiperligações para um título (com um prefixo especificado). Se nenhum dos parâmetros for usado, isso efetivamente significa \"todas as hiperligações interwikis\".",
"apihelp-query+iwbacklinks-param-prefix": "O prefixo interwikis.",
"apihelp-query+iwbacklinks-param-title": "A hiperligação interwikis a ser procurada. Tem de ser usado em conjunto com <var>$1blprefix</var>.",
"apihelp-query+langlinks-example-simple": "Obter as hiperligações interlínguas da página <kbd>Main Page</kbd>.",
"apihelp-query+links-summary": "Devolve todas as hiperligações das páginas indicadas.",
"apihelp-query+links-param-namespace": "Mostrar apenas as hiperligações destes espaços nominais.",
- "apihelp-query+links-param-limit": "O número de ''links'' a serem devolvidos.",
+ "apihelp-query+links-param-limit": "O número de hiperligações a serem devolvidas.",
"apihelp-query+links-param-titles": "Listar só as hiperligações para estes títulos. Útil para verificar se uma determinada página contém hiperligações para um determinado título.",
"apihelp-query+links-param-dir": "A direção de listagem.",
- "apihelp-query+links-example-simple": "Obter os ''links'' da página <kbd>Main Page</kbd>.",
+ "apihelp-query+links-example-simple": "Obter as hiperligações da página <kbd>Main Page</kbd>.",
"apihelp-query+links-example-generator": "Obter informação sobre as páginas ligadas na página <kbd>Main Page</kbd>.",
"apihelp-query+links-example-namespaces": "Obter as hiperligações da página <kbd>Main Page</kbd> nos espaços nominais {{ns:user}} e {{ns:template}}.",
"apihelp-query+linkshere-summary": "Encontrar todas as páginas que contêm hiperligações para as páginas indicadas.",
"apihelp-query+search-example-simple": "Pesquisar <kbd>meaning</kbd>.",
"apihelp-query+search-example-text": "Pesquisar <kbd>meaning</kbd> nos textos.",
"apihelp-query+search-example-generator": "Obter informação sobre as páginas devolvidas por uma pesquisa do termo <kbd>meaning</kbd>.",
- "apihelp-query+siteinfo-summary": "Devolver informação geral sobre o ''site''.",
+ "apihelp-query+siteinfo-summary": "Devolver informação geral sobre o sítio.",
"apihelp-query+siteinfo-param-prop": "A informação a ser obtida:",
"apihelp-query+siteinfo-paramvalue-prop-general": "Informação global do sistema.",
"apihelp-query+siteinfo-paramvalue-prop-namespaces": "Uma lista dos espaços nominais registados e dos seus nomes canónicos.",
"apihelp-query+siteinfo-paramvalue-prop-namespacealiases": "Uma lista dos nomes alternativos dos espaços nominais registados.",
"apihelp-query+siteinfo-paramvalue-prop-specialpagealiases": "Uma lista dos nomes alternativos das páginas especiais.",
"apihelp-query+siteinfo-paramvalue-prop-magicwords": "Uma lista das palavras mágicas e dos seus nomes alternativos.",
- "apihelp-query+siteinfo-paramvalue-prop-statistics": "Devolve as estatísticas do ''site''.",
+ "apihelp-query+siteinfo-paramvalue-prop-statistics": "Devolve as estatísticas do sítio.",
"apihelp-query+siteinfo-paramvalue-prop-interwikimap": "Devolve o mapa de interwikis (opcionalmente filtrado, opcionalmente localizado usando <var>$1inlanguagecode</var>).",
"apihelp-query+siteinfo-paramvalue-prop-dbrepllag": "Devolve o servidor da base de dados com o maior atraso de replicação.",
"apihelp-query+siteinfo-paramvalue-prop-usergroups": "Devolve os grupos de utilizadores e as permissões associadas.",
"apihelp-query+siteinfo-paramvalue-prop-functionhooks": "Devolve uma lista dos ''hooks'' de funções do analisador sintático.",
"apihelp-query+siteinfo-paramvalue-prop-showhooks": "Devolve uma lista de todos os ''hooks'' subscritos (conteúdo de <var>[[mw:Special:MyLanguage/Manual:$wgHooks|$wgHooks]]</var>).",
"apihelp-query+siteinfo-paramvalue-prop-variables": "Devolve uma lista de identificadores de variáveis.",
- "apihelp-query+siteinfo-paramvalue-prop-protocols": "Devolve uma lista dos protocolos permitidos nos ''links'' externos.",
+ "apihelp-query+siteinfo-paramvalue-prop-protocols": "Devolve uma lista dos protocolos permitidos nas hiperligações externas.",
"apihelp-query+siteinfo-paramvalue-prop-defaultoptions": "Devolve os valores padrão para as preferências dos utilizadores.",
"apihelp-query+siteinfo-paramvalue-prop-uploaddialog": "Devolve a configuração do diálogo de carregamento.",
"apihelp-query+siteinfo-param-filteriw": "Devolver só as entradas locais, ou só as não locais, do mapa de interwikis.",
"apihelp-query+siteinfo-param-showalldb": "Listar todos os servidores da base de dados, não só aquele que tem maior atraso.",
"apihelp-query+siteinfo-param-numberingroup": "Lista o número de utilizadores nos grupos de utilizadores.",
"apihelp-query+siteinfo-param-inlanguagecode": "O código de língua dos nomes localizados (o melhor possível) das línguas e dos temas.",
- "apihelp-query+siteinfo-example-simple": "Obter as informações do ''site''.",
+ "apihelp-query+siteinfo-example-simple": "Obter as informações do sítio.",
"apihelp-query+siteinfo-example-interwiki": "Obter uma lista dos prefixos interwikis locais.",
"apihelp-query+siteinfo-example-replag": "Verificar o atraso de replicação atual.",
"apihelp-query+stashimageinfo-summary": "Devolve informações dos ficheiros escondidos.",
"NeverBehave"
]
},
- "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|文档]]\n* [[mw:Special:MyLanguage/API:FAQ|常见问题]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api 邮件列表]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce API公告]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R 程序错误与功能请求]\n</div>\n<strong>状态信息:</strong>本页所展示的所有特性都应正常工作,但是API仍在开发当中,将会随时变化。请订阅[https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ mediawiki-api-announce 邮件列表]以便获得更新通知。\n\n<strong>错误请求:</strong>当API收到错误请求时,HTTP header将会返回一个包含\"MediaWiki-API-Error\"的值,随后header的值与error code将会送回并设置为相同的值。详细信息请参阅[[mw:Special:MyLanguage/API:Errors_and_warnings|API:错误与警告]]。\n\n<strong>测试中:</strong>测试API请求的易用性,请参见[[Special:ApiSandbox]]。",
+ "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|文档]]\n* [[mw:Special:MyLanguage/API:FAQ|常见问题]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api 邮件列表]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce API公告]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R 程序错误与功能请求]\n</div>\n<strong>状态信息:</strong>本页所展示的所有特性都应正常工作,但是API仍在开发当中,将会随时变化。请订阅[https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ mediawiki-api-announce 邮件列表]以便获得更新通知。\n\n<strong>错误请求:</strong>当API收到错误请求时,HTTP header将会返回一个包含\"MediaWiki-API-Error\"的值,随后header的值与error code将会送回并设置为相同的值。详细信息请参阅[[mw:Special:MyLanguage/API:Errors_and_warnings|API:错误与警告]]。\n\n<p class=\"mw-apisandbox-link\"><strong>测试中:</strong>测试API请求的易用性,请参见[[Special:ApiSandbox]]。</p>",
"apihelp-main-param-action": "要执行的操作。",
"apihelp-main-param-format": "输出的格式。",
"apihelp-main-param-maxlag": "最大延迟可被用于MediaWiki安装于数据库复制集中。要保存导致更多网站复制延迟的操作,此参数可使客户端等待直到复制延迟少于指定值时。万一发生过多延迟,错误代码<samp>maxlag</samp>会返回消息,例如<samp>等待$host中:延迟$lag秒</samp>。<br />参见[[mw:Special:MyLanguage/Manual:Maxlag_parameter|手册:Maxlag参数]]以获取更多信息。",
$po = ParserOptions::newFromAnon();
$po->setEditSection( false );
$po->setAllowUnsafeRawHtml( false );
- $po->setWrapOutputClass( false );
return $po;
}
// from malicious sources. As a precaution, disable
// the <html> parser tag when parsing messages.
$this->mParserOptions->setAllowUnsafeRawHtml( false );
- // Wrapping messages in an extra <div> is probably not expected. If
- // they're outside the content area they probably shouldn't be
- // targeted by CSS that's targeting the parser output, and if
- // they're inside they already are from the outer div.
- $this->mParserOptions->setWrapOutputClass( false );
}
return $this->mParserOptions;
$wgParser->firstCallInit();
# Clone it and store it
$class = $wgParserConf['class'];
- if ( $class == 'ParserDiffTest' ) {
+ if ( $class == ParserDiffTest::class ) {
# Uncloneable
$this->mParser = new $class( $wgParserConf );
} else {
switch ( $conf['store'] ) {
case 'files':
case 'file':
- $storeClass = 'LCStoreCDB';
+ $storeClass = LCStoreCDB::class;
break;
case 'db':
- $storeClass = 'LCStoreDB';
+ $storeClass = LCStoreDB::class;
break;
case 'array':
- $storeClass = 'LCStoreStaticArray';
+ $storeClass = LCStoreStaticArray::class;
break;
case 'detect':
if ( !empty( $conf['storeDirectory'] ) ) {
- $storeClass = 'LCStoreCDB';
+ $storeClass = LCStoreCDB::class;
} elseif ( $wgCacheDirectory ) {
$storeConf['directory'] = $wgCacheDirectory;
- $storeClass = 'LCStoreCDB';
+ $storeClass = LCStoreCDB::class;
} else {
- $storeClass = 'LCStoreDB';
+ $storeClass = LCStoreDB::class;
}
break;
default:
$this->timestamp = $revision->getTimestamp();
}
$this->revision = $revision;
- $this->newForCategorizationCallback = [ 'RecentChange', 'newForCategorization' ];
+ $this->newForCategorizationCallback = [ RecentChange::class, 'newForCategorization' ];
}
/**
sort( $prevTags );
sort( $newTags );
if ( $prevTags == $newTags ) {
- // No change.
return false;
}
if ( !$newTags ) {
- // no tags left, so delete the row altogether
+ // No tags left, so delete the row altogether
$dbw->delete( 'tag_summary', $tsConds, __METHOD__ );
} else {
- $dbw->replace( 'tag_summary',
- [ 'ts_rev_id', 'ts_rc_id', 'ts_log_id' ],
- array_filter( array_merge( $tsConds, [ 'ts_tags' => implode( ',', $newTags ) ] ) ),
- __METHOD__
- );
+ // Specify the non-DEFAULT value columns in the INSERT/REPLACE clause
+ $row = array_filter( [ 'ts_tags' => implode( ',', $newTags ) ] + $tsConds );
+ // Check the unique keys for conflicts, ignoring any NULL *_id values
+ $uniqueKeys = [];
+ foreach ( [ 'ts_rev_id', 'ts_rc_id', 'ts_log_id' ] as $uniqueColumn ) {
+ if ( isset( $row[$uniqueColumn] ) ) {
+ $uniqueKeys[] = [ $uniqueColumn ];
+ }
+ }
+
+ $dbw->replace( 'tag_summary', $uniqueKeys, $row, __METHOD__ );
}
return true;
) {
switch ( $typeName ) {
case 'revision':
- $className = 'ChangeTagsRevisionList';
+ $className = ChangeTagsRevisionList::class;
break;
case 'logentry':
- $className = 'ChangeTagsLogList';
+ $className = ChangeTagsLogList::class;
break;
default:
throw new Exception( "Class $typeName requested, but does not exist" );
return $e['code'];
}
- function affectedRows() {
+ protected function fetchAffectedRowCount() {
return $this->mAffectedRows;
}
$lbConf += [
'localDomain' => new DatabaseDomain(
$mainConfig->get( 'DBname' ),
- null,
+ $mainConfig->get( 'DBmwschema' ),
$mainConfig->get( 'DBprefix' )
),
'profiler' => Profiler::instance(),
// When making changes here, remember to also specify MediaWiki-specific options
// for Database classes in the relevant Installer subclass.
// Such as MysqlInstaller::openConnection and PostgresInstaller::openConnectionWithParams.
- if ( $lbConf['class'] === 'LBFactorySimple' ) {
+ if ( $lbConf['class'] === Wikimedia\Rdbms\LBFactorySimple::class ) {
if ( isset( $lbConf['servers'] ) ) {
// Server array is already explicitly configured; leave alone
} elseif ( is_array( $mainConfig->get( 'DBservers' ) ) ) {
if ( !isset( $lbConf['externalClusters'] ) ) {
$lbConf['externalClusters'] = $mainConfig->get( 'ExternalServers' );
}
- } elseif ( $lbConf['class'] === 'LBFactoryMulti' ) {
+ } elseif ( $lbConf['class'] === Wikimedia\Rdbms\LBFactoryMulti::class ) {
if ( isset( $lbConf['serverTemplate'] ) ) {
if ( in_array( $lbConf['serverTemplate']['type'], $typesWithSchema, true ) ) {
$lbConf['serverTemplate']['schema'] = $mainConfig->get( 'DBmwschema' );
* Usage:
* @code
* $wgMWLoggerDefaultSpi = [
- * 'class' => '\\MediaWiki\\Logger\\LegacySpi',
+ * 'class' => \MediaWiki\Logger\LegacySpi::class,
* ];
* @endcode
*
* default SPI provider:
* @code
* $wgMWLoggerDefaultSpi = [
- * 'class' => '\\MediaWiki\\Logger\\MonologSpi',
+ * 'class' => \MediaWiki\Logger\MonologSpi::class,
* 'args' => [ [
* 'loggers' => [
* '@default' => [
* ],
* 'processors' => [
* 'wiki' => [
- * 'class' => '\\MediaWiki\\Logger\\Monolog\\WikiProcessor',
+ * 'class' => \MediaWiki\Logger\Monolog\WikiProcessor::class,
* ],
* 'psr' => [
- * 'class' => '\\Monolog\\Processor\\PsrLogMessageProcessor',
+ * 'class' => \Monolog\Processor\PsrLogMessageProcessor::class,
* ],
* 'pid' => [
- * 'class' => '\\Monolog\\Processor\\ProcessIdProcessor',
+ * 'class' => \Monolog\Processor\ProcessIdProcessor::class,
* ],
* 'uid' => [
- * 'class' => '\\Monolog\\Processor\\UidProcessor',
+ * 'class' => \Monolog\Processor\UidProcessor::class,
* ],
* 'web' => [
- * 'class' => '\\Monolog\\Processor\\WebProcessor',
+ * 'class' => \Monolog\Processor\WebProcessor::class,
* ],
* ],
* 'handlers' => [
* 'stream' => [
- * 'class' => '\\Monolog\\Handler\\StreamHandler',
+ * 'class' => \Monolog\Handler\StreamHandler::class,
* 'args' => [ 'path/to/your.log' ],
* 'formatter' => 'line',
* ],
* 'redis' => [
- * 'class' => '\\Monolog\\Handler\\RedisHandler',
+ * 'class' => \Monolog\Handler\RedisHandler::class,
* 'args' => [ function() {
* $redis = new Redis();
* $redis->connect( '127.0.0.1', 6379 );
* 'buffer' => true,
* ],
* 'udp2log' => [
- * 'class' => '\\MediaWiki\\Logger\\Monolog\\LegacyHandler',
+ * 'class' => \MediaWiki\Logger\Monolog\LegacyHandler::class,
* 'args' => [
* 'udp://127.0.0.1:8420/mediawiki
* ],
* ],
* 'formatters' => [
* 'line' => [
- * 'class' => '\\Monolog\\Formatter\\LineFormatter',
+ * 'class' => \Monolog\Formatter\LineFormatter::class,
* ],
* 'logstash' => [
- * 'class' => '\\Monolog\\Formatter\\LogstashFormatter',
+ * 'class' => \Monolog\Formatter\LogstashFormatter::class,
* 'args' => [ 'mediawiki', php_uname( 'n' ), null, '', 1 ],
* ],
* ],
* Usage:
*
* $wgMWLoggerDefaultSpi = [
- * 'class' => '\\MediaWiki\\Logger\\NullSpi',
+ * 'class' => \MediaWiki\Logger\NullSpi::class,
* ];
*
* @see \MediaWiki\Logger\LoggerFactory
/**
* @param callable $callback
* @param string $fname Calling method
- * @param IDatabase|null $dbw Abort if this DB is rolled back [optional] (since 1.28)
+ * @param IDatabase|IDatabase[]|null $dbws Abort if any of the specified DB handles have
+ * a currently pending transaction which later gets rolled back [optional] (since 1.28)
*/
- public function __construct( callable $callback, $fname = 'unknown', IDatabase $dbw = null ) {
+ public function __construct( callable $callback, $fname = 'unknown', $dbws = [] ) {
$this->callback = $callback;
$this->fname = $fname;
- if ( $dbw && $dbw->trxLevel() ) {
- $dbw->onTransactionResolution( [ $this, 'cancelOnRollback' ], $fname );
+ $dbws = is_array( $dbws ) ? $dbws : [ $dbws ];
+ foreach ( $dbws as $dbw ) {
+ if ( $dbw && $dbw->trxLevel() ) {
+ $dbw->onTransactionResolution( [ $this, 'cancelOnRollback' ], $fname );
+ }
}
}
}
}
+ /**
+ * @param WikiPage $page
+ * @param Revision $rev
+ *
+ * @return ParserOutput|bool False if the revision was not found
+ */
protected function getParserOutput( WikiPage $page, Revision $rev ) {
$parserOptions = $page->makeParserOptions( $this->getContext() );
global $wgLang;
foreach ( $this->getTrace() as $frame ) {
- if ( isset( $frame['class'] ) && $frame['class'] === 'LocalisationCache' ) {
+ if ( isset( $frame['class'] ) && $frame['class'] === LocalisationCache::class ) {
return false;
}
}
$logger = LoggerFactory::getInstance( 'fatal' );
$logger->error( $msg, [
'fatal_exception' => [
- 'class' => 'ErrorException',
+ 'class' => ErrorException::class,
'message' => "PHP Fatal Error: {$message}",
'code' => $level,
'file' => $file,
private static function useOutputPage( $e ) {
// Can the extension use the Message class/wfMessage to get i18n-ed messages?
foreach ( $e->getTrace() as $frame ) {
- if ( isset( $frame['class'] ) && $frame['class'] === 'LocalisationCache' ) {
+ if ( isset( $frame['class'] ) && $frame['class'] === LocalisationCache::class ) {
return false;
}
}
// Get the FS backend configuration
$autoBackends[] = [
'name' => $backendName,
- 'class' => 'FSFileBackend',
+ 'class' => FSFileBackend::class,
'lockManager' => 'fsLockManager',
'containerPaths' => [
"{$repoName}-public" => "{$directory}",
$config = $this->config( $name );
$class = $config['class'];
- if ( $class === 'FileBackendMultiWrite' ) {
+ if ( $class === FileBackendMultiWrite::class ) {
foreach ( $config['backends'] as $index => $beConfig ) {
if ( isset( $beConfig['template'] ) ) {
// Config is just a modified version of a registered backend's.
'wikiId' => wfWikiID(), // e.g. "my_wiki-en_"
'mimeCallback' => [ $this, 'guessMimeInternal' ],
'obResetFunc' => 'wfResetOutputBuffers',
- 'streamMimeFunc' => [ 'StreamFile', 'contentTypeFromPath' ],
+ 'streamMimeFunc' => [ StreamFile::class, 'contentTypeFromPath' ],
'tmpDirectory' => wfTempDir(),
- 'statusWrapper' => [ 'Status', 'wrap' ],
+ 'statusWrapper' => [ Status::class, 'wrap' ],
'wanCache' => MediaWikiServices::getInstance()->getMainWANObjectCache(),
'srvCache' => ObjectCache::getLocalServerInstance( 'hash' ),
'logger' => LoggerFactory::getInstance( 'FileOperation' ),
LockManagerGroup::singleton( $config['wikiId'] )->get( $config['lockManager'] );
$config['fileJournal'] = isset( $config['fileJournal'] )
? FileJournal::factory( $config['fileJournal'], $name )
- : FileJournal::factory( [ 'class' => 'NullFileJournal' ], $name );
+ : FileJournal::factory( [ 'class' => NullFileJournal::class ], $name );
return $config;
}
if ( !isset( $this->managers[$name]['instance'] ) ) {
$class = $this->managers[$name]['class'];
$config = $this->managers[$name]['config'];
- if ( $class === 'DBLockManager' ) {
+ if ( $class === DBLockManager::class ) {
$lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
$lb = $lbFactory->newMainLB( $config['domain'] );
$dbw = $lb->getLazyConnectionRef( DB_MASTER, [], $config['domain'] );
protected $isPrivate;
/** @var array callable Override these in the base class */
- protected $fileFactory = [ 'UnregisteredLocalFile', 'newFromTitle' ];
+ protected $fileFactory = [ UnregisteredLocalFile::class, 'newFromTitle' ];
/** @var array callable|bool Override these in the base class */
protected $oldFileFactory = false;
/** @var array callable|bool Override these in the base class */
/** @var array callable|bool Override these in the base class */
protected $oldFileFactoryKey = false;
+ /** @var string URL of where to proxy thumb.php requests to.
+ * Example: http://127.0.0.1:8888/wiki/dev/thumb/
+ */
+ protected $thumbProxyUrl;
+ /** @var string Secret key to pass as an X-Swift-Secret header to the proxied thumb service */
+ protected $thumbProxySecret;
+
/**
* @param array|null $info
* @throws MWException
$optionalSettings = [
'descBaseUrl', 'scriptDirUrl', 'articleUrl', 'fetchDescription',
'thumbScriptUrl', 'pathDisclosureProtection', 'descriptionCacheExpiry',
- 'scriptExtension', 'favicon'
+ 'scriptExtension', 'favicon', 'thumbProxyUrl', 'thumbProxySecret'
];
foreach ( $optionalSettings as $var ) {
if ( isset( $info[$var] ) ) {
return $this->thumbScriptUrl;
}
+ /**
+ * Get the URL thumb.php requests are being proxied to
+ *
+ * @return string
+ */
+ public function getThumbProxyUrl() {
+ return $this->thumbProxyUrl;
+ }
+
+ /**
+ * Get the secret key for the proxied thumb service
+ *
+ * @return string
+ */
+ public function getThumbProxySecret() {
+ return $this->thumbProxySecret;
+ }
+
/**
* Returns true if the repository can transform files via a 404 handler
*
* @return Status
*/
public function newFatal( $message /*, parameters...*/ ) {
- $status = call_user_func_array( [ 'Status', 'newFatal' ], func_get_args() );
+ $status = call_user_func_array( [ Status::class, 'newFatal' ], func_get_args() );
$status->cleanCallback = $this->getErrorCleanupFunction();
return $status;
* Example config:
*
* $wgForeignFileRepos[] = [
- * 'class' => 'ForeignAPIRepo',
+ * 'class' => ForeignAPIRepo::class,
* 'name' => 'shared',
* 'apibase' => 'https://en.wikipedia.org/w/api.php',
* 'fetchDescription' => true, // Optional
'timestamp',
];
- protected $fileFactory = [ 'ForeignAPIFile', 'newFromTitle' ];
+ protected $fileFactory = [ ForeignAPIFile::class, 'newFromTitle' ];
/** @var int Check back with Commons after this expiry */
protected $apiThumbCacheExpiry = 86400; // 1 day (24*3600)
protected $dbConn;
/** @var callable */
- protected $fileFactory = [ 'ForeignDBFile', 'newFromTitle' ];
+ protected $fileFactory = [ ForeignDBFile::class, 'newFromTitle' ];
/** @var callable */
- protected $fileFromRowFactory = [ 'ForeignDBFile', 'newFromRow' ];
+ protected $fileFromRowFactory = [ ForeignDBFile::class, 'newFromRow' ];
/**
* @param array|null $info
protected $tablePrefix;
/** @var array */
- protected $fileFactory = [ 'ForeignDBFile', 'newFromTitle' ];
+ protected $fileFactory = [ ForeignDBFile::class, 'newFromTitle' ];
/** @var array */
- protected $fileFromRowFactory = [ 'ForeignDBFile', 'newFromRow' ];
+ protected $fileFromRowFactory = [ ForeignDBFile::class, 'newFromRow' ];
/** @var bool */
protected $hasSharedCache;
*/
class LocalRepo extends FileRepo {
/** @var callable */
- protected $fileFactory = [ 'LocalFile', 'newFromTitle' ];
+ protected $fileFactory = [ LocalFile::class, 'newFromTitle' ];
/** @var callable */
- protected $fileFactoryKey = [ 'LocalFile', 'newFromKey' ];
+ protected $fileFactoryKey = [ LocalFile::class, 'newFromKey' ];
/** @var callable */
- protected $fileFromRowFactory = [ 'LocalFile', 'newFromRow' ];
+ protected $fileFromRowFactory = [ LocalFile::class, 'newFromRow' ];
/** @var callable */
- protected $oldFileFromRowFactory = [ 'OldLocalFile', 'newFromRow' ];
+ protected $oldFileFromRowFactory = [ OldLocalFile::class, 'newFromRow' ];
/** @var callable */
- protected $oldFileFactory = [ 'OldLocalFile', 'newFromTitle' ];
+ protected $oldFileFactory = [ OldLocalFile::class, 'newFromTitle' ];
/** @var callable */
- protected $oldFileFactoryKey = [ 'OldLocalFile', 'newFromKey' ];
+ protected $oldFileFactoryKey = [ OldLocalFile::class, 'newFromKey' ];
function __construct( array $info = null ) {
parent::__construct( $info );
protected $isSafeFile;
/** @var string Required Repository class type */
- protected $repoClass = 'FileRepo';
+ protected $repoClass = FileRepo::class;
/** @var array Cache of tmp filepaths pointing to generated bucket thumbnails, keyed by width */
protected $tmpBucketedThumbCache = [];
/** @var array */
private $mInfo = [];
- protected $repoClass = 'ForeignApiRepo';
+ protected $repoClass = ForeignApiRepo::class;
/**
* @param Title|string|bool $title
protected $deleted;
/** @var string */
- protected $repoClass = 'LocalRepo';
+ protected $repoClass = LocalRepo::class;
/** @var int Number of line to return by nextHistoryLine() (constructor) */
private $historyLine;
private static function loadModes() {
if ( self::$modeMapping === false ) {
self::$modeMapping = [
- 'traditional' => 'TraditionalImageGallery',
- 'nolines' => 'NolinesImageGallery',
- 'packed' => 'PackedImageGallery',
- 'packed-hover' => 'PackedHoverImageGallery',
- 'packed-overlay' => 'PackedOverlayImageGallery',
- 'slideshow' => 'SlideshowImageGallery',
+ 'traditional' => TraditionalImageGallery::class,
+ 'nolines' => NolinesImageGallery::class,
+ 'packed' => PackedImageGallery::class,
+ 'packed-hover' => PackedHoverImageGallery::class,
+ 'packed-overlay' => PackedOverlayImageGallery::class,
+ 'slideshow' => SlideshowImageGallery::class,
];
// Allow extensions to make a new gallery format.
Hooks::run( 'GalleryGetModes', [ &self::$modeMapping ] );
class HTMLForm extends ContextSource {
// A mapping of 'type' inputs onto standard HTMLFormField subclasses
public static $typeMappings = [
- 'api' => 'HTMLApiField',
- 'text' => 'HTMLTextField',
- 'textwithbutton' => 'HTMLTextFieldWithButton',
- 'textarea' => 'HTMLTextAreaField',
- 'select' => 'HTMLSelectField',
- 'combobox' => 'HTMLComboboxField',
- 'radio' => 'HTMLRadioField',
- 'multiselect' => 'HTMLMultiSelectField',
- 'limitselect' => 'HTMLSelectLimitField',
- 'check' => 'HTMLCheckField',
- 'toggle' => 'HTMLCheckField',
- 'int' => 'HTMLIntField',
- 'float' => 'HTMLFloatField',
- 'info' => 'HTMLInfoField',
- 'selectorother' => 'HTMLSelectOrOtherField',
- 'selectandother' => 'HTMLSelectAndOtherField',
- 'namespaceselect' => 'HTMLSelectNamespace',
- 'namespaceselectwithbutton' => 'HTMLSelectNamespaceWithButton',
- 'tagfilter' => 'HTMLTagFilter',
- 'sizefilter' => 'HTMLSizeFilterField',
- 'submit' => 'HTMLSubmitField',
- 'hidden' => 'HTMLHiddenField',
- 'edittools' => 'HTMLEditTools',
- 'checkmatrix' => 'HTMLCheckMatrix',
- 'cloner' => 'HTMLFormFieldCloner',
- 'autocompleteselect' => 'HTMLAutoCompleteSelectField',
- 'date' => 'HTMLDateTimeField',
- 'time' => 'HTMLDateTimeField',
- 'datetime' => 'HTMLDateTimeField',
+ 'api' => HTMLApiField::class,
+ 'text' => HTMLTextField::class,
+ 'textwithbutton' => HTMLTextFieldWithButton::class,
+ 'textarea' => HTMLTextAreaField::class,
+ 'select' => HTMLSelectField::class,
+ 'combobox' => HTMLComboboxField::class,
+ 'radio' => HTMLRadioField::class,
+ 'multiselect' => HTMLMultiSelectField::class,
+ 'limitselect' => HTMLSelectLimitField::class,
+ 'check' => HTMLCheckField::class,
+ 'toggle' => HTMLCheckField::class,
+ 'int' => HTMLIntField::class,
+ 'float' => HTMLFloatField::class,
+ 'info' => HTMLInfoField::class,
+ 'selectorother' => HTMLSelectOrOtherField::class,
+ 'selectandother' => HTMLSelectAndOtherField::class,
+ 'namespaceselect' => HTMLSelectNamespace::class,
+ 'namespaceselectwithbutton' => HTMLSelectNamespaceWithButton::class,
+ 'tagfilter' => HTMLTagFilter::class,
+ 'sizefilter' => HTMLSizeFilterField::class,
+ 'submit' => HTMLSubmitField::class,
+ 'hidden' => HTMLHiddenField::class,
+ 'edittools' => HTMLEditTools::class,
+ 'checkmatrix' => HTMLCheckMatrix::class,
+ 'cloner' => HTMLFormFieldCloner::class,
+ 'autocompleteselect' => HTMLAutoCompleteSelectField::class,
+ 'date' => HTMLDateTimeField::class,
+ 'time' => HTMLDateTimeField::class,
+ 'datetime' => HTMLDateTimeField::class,
// HTMLTextField will output the correct type="" attribute automagically.
// There are about four zillion other HTML5 input types, like range, but
// we don't use those at the moment, so no point in adding all of them.
- 'email' => 'HTMLTextField',
- 'password' => 'HTMLTextField',
- 'url' => 'HTMLTextField',
- 'title' => 'HTMLTitleTextField',
- 'user' => 'HTMLUserTextField',
- 'usersmultiselect' => 'HTMLUsersMultiselectField',
+ 'email' => HTMLTextField::class,
+ 'password' => HTMLTextField::class,
+ 'url' => HTMLTextField::class,
+ 'title' => HTMLTitleTextField::class,
+ 'user' => HTMLUserTextField::class,
+ 'usersmultiselect' => HTMLUsersMultiselectField::class,
];
public $mFieldData;
<?php
/**
- * Allows custom data specific to HTMLFormField to be set for OOjs UI forms. A matching JS widget
+ * Allows custom data specific to HTMLFormField to be set for OOUI forms. A matching JS widget
* (defined in htmlform.Element.js) picks up the extra config when constructed using OO.ui.infuse().
*
* Currently only supports passing 'hide-if' data.
$this->addClasses( [ 'mw-htmlform-hide-if' ] );
}
if ( $this->modules ) {
- // JS code must be able to read this before infusing (before OOjs UI is even loaded),
+ // JS code must be able to read this before infusing (before OOUI is even loaded),
// so we put this in a separate attribute (not with the rest of the config).
// And it's not needed anymore after infusing, so we don't put it in JS config at all.
$this->setAttributes( [ 'data-mw-modules' => implode( ',', $this->modules ) ] );
}
/**
- * Whether the field should be automatically infused. Note that all OOjs UI HTMLForm fields are
+ * Whether the field should be automatically infused. Note that all OOUI HTMLForm fields are
* infusable (you can call OO.ui.infuse() on them), but not all are infused by default, since
* there is no benefit in doing it e.g. for buttons and it's a small performance hit on page load.
*
/**
* Get the list of extra ResourceLoader modules which must be loaded client-side before it's
- * possible to infuse this field's OOjs UI widget.
+ * possible to infuse this field's OOUI widget.
*
* @return string[]
*/
if ( $this->mParent instanceof OOUIHTMLForm ) {
throw new MWException( 'HTMLMultiSelectField#getOneCheckbox() is not supported' );
} else {
- $elementFunc = [ 'Html', $this->mOptionsLabelsNotFromMessage ? 'rawElement' : 'element' ];
+ $elementFunc = [ Html::class, $this->mOptionsLabelsNotFromMessage ? 'rawElement' : 'element' ];
$checkbox =
Xml::check( "{$this->mName}[]", $checked, $attribs ) .
' ' .
$html = '';
$attribs = $this->getAttributes( [ 'disabled', 'tabindex' ] );
- $elementFunc = [ 'Html', $this->mOptionsLabelsNotFromMessage ? 'rawElement' : 'element' ];
+ $elementFunc = [ Html::class, $this->mOptionsLabelsNotFromMessage ? 'rawElement' : 'element' ];
# @todo Should this produce an unordered list perhaps?
foreach ( $options as $label => $info ) {
* @return MWHttpRequest
* @see MWHttpRequest::__construct
*/
- public static function factory( $url, $options = null, $caller = __METHOD__ ) {
+ public static function factory( $url, array $options = [], $caller = __METHOD__ ) {
return \MediaWiki\MediaWikiServices::getInstance()
->getHttpRequestFactory()
->create( $url, $options, $caller );
$this->config = $config;
if ( !in_array( 'uploadsource', stream_get_wrappers() ) ) {
- stream_wrapper_register( 'uploadsource', 'UploadSourceAdapter' );
+ stream_wrapper_register( 'uploadsource', UploadSourceAdapter::class );
}
$id = UploadSourceAdapter::registerSource( $source );
"maintenance/populateLogUsertext.php.\n"
);
- $task = $this->maintenance->runChild( 'PopulateLogUsertext' );
+ $task = $this->maintenance->runChild( PopulateLogUsertext::class );
$task->execute();
$this->output( "done.\n" );
}
"databases, you may want to hit Ctrl-C and do this manually with\n" .
"maintenance/populateLogSearch.php.\n" );
- $task = $this->maintenance->runChild( 'PopulateLogSearch' );
+ $task = $this->maintenance->runChild( PopulateLogSearch::class );
$task->execute();
$this->output( "done.\n" );
}
}
$this->output( "Updating category collations..." );
- $task = $this->maintenance->runChild( 'UpdateCollation' );
+ $task = $this->maintenance->runChild( UpdateCollation::class );
$task->execute();
$this->output( "...done.\n" );
}
*/
protected function doMigrateUserOptions() {
if ( $this->db->tableExists( 'user_properties' ) ) {
- $cl = $this->maintenance->runChild( 'ConvertUserOptions', 'convertUserOptions.php' );
+ $cl = $this->maintenance->runChild( ConvertUserOptions::class, 'convertUserOptions.php' );
$cl->execute();
$this->output( "done.\n" );
}
/**
* @var $cl RebuildLocalisationCache
*/
- $cl = $this->maintenance->runChild( 'RebuildLocalisationCache', 'rebuildLocalisationCache.php' );
+ $cl = $this->maintenance->runChild(
+ RebuildLocalisationCache::class, 'rebuildLocalisationCache.php'
+ );
$this->output( "Rebuilding localisation cache...\n" );
$cl->setForce();
$cl->execute();
"databases, you may want to hit Ctrl-C and do this manually with\n" .
"maintenance/migrateComments.php.\n"
);
- $task = $this->maintenance->runChild( 'MigrateComments', 'migrateComments.php' );
+ $task = $this->maintenance->runChild( MigrateComments::class, 'migrateComments.php' );
$task->execute();
$this->output( "done.\n" );
}
*/
protected function migrateArchiveText() {
$this->output( "Migrating archive ar_text to modern storage.\n" );
- $task = $this->maintenance->runChild( 'MigrateArchiveText', 'migrateArchiveText.php' );
+ $task = $this->maintenance->runChild( MigrateArchiveText::class, 'migrateArchiveText.php' );
$task->execute();
$this->output( "done.\n" );
}
// disable (problematic) object cache types explicitly, preserving all other (working) ones
// bug T113843
- $emptyCache = [ 'class' => 'EmptyBagOStuff' ];
+ $emptyCache = [ 'class' => EmptyBagOStuff::class ];
$objectCaches = [
CACHE_NONE => $emptyCache,
$this->parserTitle = Title::newFromText( 'Installer' );
$this->parserOptions = new ParserOptions( $wgUser ); // language will be wrong :(
$this->parserOptions->setEditSection( false );
- $this->parserOptions->setWrapOutputClass( false );
// Don't try to access DB before user language is initialised
$this->setParserLanguage( Language::factory( 'en' ) );
}
$out = $wgParser->parse( $text, $this->parserTitle, $this->parserOptions, $lineStart );
$html = $out->getText( [
'enableSectionEditLinks' => false,
+ 'unwrap' => true,
] );
} catch ( MediaWiki\Services\ServiceDisabledException $e ) {
$html = '<!--DB access attempted during parse--> ' . htmlspecialchars( $text );
// implementation that won't stomp on PHP's cookies.
$GLOBALS['wgSessionProviders'] = [
[
- 'class' => 'InstallerSessionProvider',
+ 'class' => InstallerSessionProvider::class,
'args' => [ [
'priority' => 1,
] ]
if ( !$overrides ) {
$overrides = [
- 'LocalSettingsGenerator' => 'LocalSettingsGenerator',
- 'WebInstaller' => 'WebInstaller',
- 'CliInstaller' => 'CliInstaller',
+ 'LocalSettingsGenerator' => LocalSettingsGenerator::class,
+ 'WebInstaller' => WebInstaller::class,
+ 'CliInstaller' => CliInstaller::class,
];
foreach ( glob( "$IP/mw-config/overrides/*.php" ) as $file ) {
require $file;
}
protected function doOldLinksUpdate() {
- $cl = $this->maintenance->runChild( 'ConvertLinks' );
+ $cl = $this->maintenance->runChild( ConvertLinks::class );
$cl->execute();
}
$this->output( "done.\n" );
$this->output( "Migrating old restrictions to new table...\n" );
- $task = $this->maintenance->runChild( 'UpdateRestrictions' );
+ $task = $this->maintenance->runChild( UpdateRestrictions::class );
$task->execute();
}
"may want to hit Ctrl-C and do this manually with maintenance/\n" .
"populateCategory.php.\n"
);
- $task = $this->maintenance->runChild( 'PopulateCategory' );
+ $task = $this->maintenance->runChild( PopulateCategory::class );
$task->execute();
$this->output( "Done populating category table.\n" );
}
"databases, you may want to hit Ctrl-C and do this manually with\n" .
"maintenance/populateParentId.php.\n" );
- $task = $this->maintenance->runChild( 'PopulateParentId' );
+ $task = $this->maintenance->runChild( PopulateParentId::class );
$task->execute();
}
}
return "# SQLite-specific settings
\$wgSQLiteDataDir = \"{$dir}\";
\$wgObjectCaches[CACHE_DB] = [
- 'class' => 'SqlBagOStuff',
+ 'class' => SqlBagOStuff::class,
'loggroup' => 'SQLBagOStuff',
'server' => [
'type' => 'sqlite',
"config-env-php": "O PHP $1 está instalado.",
"config-env-hhvm": "HHVM $1 está instalado.",
"config-unicode-using-intl": "A usar a [http://pecl.php.net/intl extensão intl PECL] para a normalização Unicode.",
- "config-unicode-pure-php-warning": "<strong>Aviso:</strong> A [http://pecl.php.net/intl extensão intl PECL] não está disponível para efetuar a normalização Unicode. Irá recorrer-se à implementação em PHP puro, que é mais lenta.\nSe o seu site tem alto volume de tráfego, devia informar-se um pouco sobre a [https://www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations/pt normalização Unicode].",
+ "config-unicode-pure-php-warning": "<strong>Aviso:</strong> A [http://pecl.php.net/intl extensão intl PECL] não está disponível para efetuar a normalização Unicode. Irá recorrer-se à implementação em PHP puro, que é mais lenta.\nSe o seu sítio tem alto volume de tráfego, devia informar-se um pouco sobre a [https://www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations/pt normalização Unicode].",
"config-unicode-update-warning": "<strong>Aviso:</strong> A versão instalada do wrapper de normalização Unicode usa uma versão mais antiga da biblioteca do [http://site.icu-project.org/ projeto ICU].\nDevia [https://www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations atualizá-la] se tem quaisquer preocupações sobre o uso do Unicode.",
"config-no-db": "Não foi possível encontrar um controlador apropriado da base de dados! Precisa de instalar um controlador da base de dados para o PHP. {{PLURAL:$2|É aceite o seguinte tipo|São aceites os seguintes tipos}} de base de dados: $1.\n\nSe fez a compilação do PHP, reconfigure-o com um cliente de base de dados ativado; por exemplo, usando <code>./configure --with-mysqli</code>.\nSe instalou o PHP a partir de um pacote Debian ou Ubuntu, então precisa de instalar também, por exemplo, o pacote <code>php5-mysql</code>.",
"config-outdated-sqlite": "<strong>Aviso:</strong> Tem a versão $1 do SQLite, que é anterior à versão mínima necessária, a $2. O SQLite não estará disponível.",
"config-mssql-windowsauth": "Autenticação do Windows",
"config-site-name": "Nome da wiki:",
"config-site-name-help": "Este nome aparecerá no título da janela do seu navegador e em vários outros sítios.",
- "config-site-name-blank": "Introduza o nome do site.",
+ "config-site-name-blank": "Introduza o nome do sítio.",
"config-project-namespace": "Espaço nominal do projeto:",
"config-ns-generic": "Projeto",
"config-ns-site-name": "O mesmo que o nome da wiki: $1",
"config-logo": "URL do logótipo:",
"config-logo-help": "O tema padrão do MediaWiki inclui espaço para um logótipo de 135x160 píxeis acima do menu da barra lateral.\nColoque na wiki uma imagem com estas dimensões e introduza aqui o URL dessa imagem.\n\nSe não pretende usar um logótipo, deixe este campo em branco.",
"config-instantcommons": "Ativar Instant Commons",
- "config-instantcommons-help": "O [https://www.mediawiki.org/wiki/InstantCommons Instant Commons] é uma funcionalidade que permite que as wikis usem imagens, áudio e outros ficheiros multimédia disponíveis no site [https://commons.wikimedia.org/ Wikimedia Commons].\nPara poder usá-los, o MediaWiki necessita de acesso à Internet.\n\nPara mais informações sobre esta funcionalidade, incluindo instruções sobre como configurá-la para usar outras wikis em vez da Wikimedia Commons, consulte o [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgForeignFileRepos Manual Técnico].",
+ "config-instantcommons-help": "O [https://www.mediawiki.org/wiki/InstantCommons Instant Commons] é uma funcionalidade que permite que as wikis usem imagens, áudio e outros ficheiros multimédia disponíveis no sítio [https://commons.wikimedia.org/ Wikimedia Commons].\nPara poder usá-los, o MediaWiki necessita de acesso à Internet.\n\nPara mais informações sobre esta funcionalidade, incluindo instruções sobre como configurá-la para usar outras wikis em vez da Wikimedia Commons, consulte o [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgForeignFileRepos Manual Técnico].",
"config-cc-error": "O auxiliar de escolha de licenças da Creative Commons não produziu resultados.\nIntroduza o nome da licença manualmente.",
"config-cc-again": "Escolha outra vez...",
"config-cc-not-chosen": "Escolha a licença da Creative Commons que pretende e clique \"proceed\".",
"config-advanced-settings": "Configuração avançada",
"config-cache-options": "Configuração da cache de objetos:",
- "config-cache-help": "A cache de objetos é usada para melhorar o desempenho do MediaWiki. Armazena dados usados com frequência.\nSites de tamanho médio ou grande são altamente encorajados a ativar esta funcionalidade e os sites pequenos também terão alguns benefícios em fazê-lo.",
+ "config-cache-help": "A cache de objetos é usada para melhorar o desempenho do MediaWiki. Armazena dados usados com frequência.\nSítios de tamanho médio ou grande são altamente encorajados a ativar esta funcionalidade e os sítios pequenos também terão alguns benefícios em fazê-lo.",
"config-cache-none": "Sem cache (não é removida nenhuma funcionalidade, mas a velocidade de operação pode ser afectada nas wikis grandes)",
"config-cache-accel": "Cache de objetos do PHP (APC, APCu, XCache ou WinCache)",
"config-cache-memcached": "Usar Memcached (requer instalação e configurações adicionais)",
"config-license-cc-by": "Creative Commons Ауторство (CC BY)",
"config-license-cc-by-nc-sa": "Creative Commons Ауторство-Некомерцијално-Делити под истим условима (CC BY-NC-SA)",
"config-license-cc-0": "Creative Commons Zero (јавно власништво)",
- "config-license-gfdl": "Ð\93Ð\9dУ-ова лиÑ\86енÑ\86а за Ñ\81лободнÑ\83 докÑ\83менÑ\82аÑ\86иÑ\98Ñ\83 веÑ\80зиÑ\98а 1.3 или новиÑ\98а веÑ\80зиÑ\98а",
+ "config-license-gfdl": "Ð\93Ð\9dУ-ова лиÑ\86енÑ\86а за Ñ\81лободнÑ\83 докÑ\83менÑ\82аÑ\86иÑ\98Ñ\83 издаÑ\9aе 1.3 или новиÑ\98е",
"config-license-pd": "Јавно власништво",
"config-email-settings": "Подешавања имејла",
"config-cc-not-chosen": "Одаберите која Кријејтив комонс лиценца вам одговара и потврдите.",
"config-skins-screenshots": "„$1” (снимци екрана: $2)",
"config-screenshot": "снимак екрана",
"mainpagetext": "<strong>Медијавики је успешно инсталиран.</strong>",
- "mainpagedocfooter": "Ð\9fогледаÑ\98Ñ\82е [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents коÑ\80иÑ\81ниÑ\87ки водиÑ\87] за коÑ\80иÑ\88Ñ\9bеÑ\9aе пÑ\80огÑ\80ама.\n\n== Увод ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Ð\9fомоÑ\9b Ñ\83 вези Ñ\81а подеÑ\88аваÑ\9aима]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ ЧеÑ\81Ñ\82о поÑ\81Ñ\82авÑ\99ена пиÑ\82аÑ\9aа]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Ð\94опиÑ\81на лиÑ\81Ñ\82а о издаÑ\9aима Ð\9cедиÑ\98авикиÑ\98а]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Ð\9dаÑ\83Ñ\87иÑ\82е како да Ñ\81е боÑ\80ете против спама на Вашој вики]"
+ "mainpagedocfooter": "Ð\9fогледаÑ\98Ñ\82е [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents коÑ\80иÑ\81ниÑ\87ки водиÑ\87] за коÑ\80иÑ\88Ñ\9bеÑ\9aе пÑ\80огÑ\80ама.\n\n== Увод ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Ð\9fомоÑ\9b Ñ\83 вези Ñ\81а подеÑ\88аваÑ\9aима]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ ЧеÑ\81Ñ\82о поÑ\81Ñ\82авÑ\99ена пиÑ\82аÑ\9aа]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Ð\94опиÑ\81ни Ñ\81пиÑ\81ак о издаÑ\9aима Ð\9cедиÑ\98авикиÑ\98а]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Ð\9dаÑ\83Ñ\87иÑ\82е како да Ñ\81е боÑ\80ите против спама на Вашој вики]"
}
"아라",
"Amire80",
"Piramidion",
- "Macofe"
+ "Macofe",
+ "Movses"
]
},
"config-desc": "Інсталятор MediaWiki",
"config-install-mainpage-failed": "Не вдається вставити головну сторінку: $1",
"config-install-done": "<strong>Вітаємо!</strong>\nВи успішно встановили MediaWiki.\n\nІнсталятор згенерував файл <code>LocalSettings.php</code>, який містить усі Ваші налаштування.\n\nВам необхідно завантажити його і помістити у кореневу папку Вашої вікі (туди ж, де index.php). Завантаження мало початись автоматично.\n\nЯкщо завантаження не почалось або Ви його скасували, можете заново його почати, натиснувши на посилання внизу:\n\n$3\n\n<strong>Примітка</strong>: Якщо Ви не зробите цього зараз, цей файл не буде доступним пізніше, коли Ви вийдете з встановлення, не скачавши його.\n\nПісля виконання дій, описаних вище, Ви зможете <strong>[$2 увійти у свою вікі]</strong>.",
"config-install-done-path": "<strong>Вітаємо!</strong>\nВи встановили Медіавікі.\n\nІнсталятор створив файл <code>LocalSettings.php</code>.\nУ ньому містяться всі Ваші налаштування.\n\nВам потрібно завантажити його й помістити в <code>$4</code>. Завантаження повинно було автоматично розпочатись.\n\nЯкщо завантаження не було запропоновано, або Ви його скасували, Ви можете перезапустити завантаження натиснувши на посилання нижче:\n\n$3\n\n<strong>Зверніть увагу:</strong> Якщо Ви не зробите це зараз, цей згенерований файл налаштувань не буде доступним для Вас пізніше якщо Ви вийдете зі встановлення не завантаживши його.\n\nКоли це було зроблено Ви можете <strong>[$2 зайти до своєї вікі]</strong>.",
+ "config-install-success": "Mediawiki успішно встановлено. Зараз ви можете перейти до <$1$2>, щоб переглянути свою вікі. Якщо у вас є питання, ознайомтеся з нашим FAQ: <https://www.mediawiki.org/wiki/Manual:FAQ> або використовуйте один з форумів підтримки, які вказано на цій сторінці.",
"config-download-localsettings": "Завантажити <code>LocalSettings.php</code>",
"config-help": "допомога",
"config-help-tooltip": "натисніть, щоб розгорнути",
/**
* @return resource
+ * @throws Exception
*/
protected function getCurlMulti() {
if ( !$this->multiHandle ) {
+ if ( !function_exists( 'curl_multi_init' ) ) {
+ throw new Exception( "PHP cURL extension missing. " .
+ "Check https://www.mediawiki.org/wiki/Manual:CURL" );
+ }
$cmh = curl_multi_init();
curl_multi_setopt( $cmh, CURLMOPT_PIPELINING, (int)$this->usePipelining );
curl_multi_setopt( $cmh, CURLMOPT_MAXCONNECTS, (int)$this->maxConnsPerHost );
: new NullLockManager( [] );
$this->fileJournal = isset( $config['fileJournal'] )
? $config['fileJournal']
- : FileJournal::factory( [ 'class' => 'NullFileJournal' ], $this->name );
+ : FileJournal::factory( [ 'class' => NullFileJournal::class ], $this->name );
$this->readOnly = isset( $config['readOnly'] )
? (string)$config['readOnly']
: '';
final protected function newStatus() {
$args = func_get_args();
if ( count( $args ) ) {
- $sv = call_user_func_array( [ 'StatusValue', 'newFatal' ], $args );
+ $sv = call_user_func_array( [ StatusValue::class, 'newFatal' ], $args );
} else {
$sv = StatusValue::newGood();
}
*/
final public function getOperationsInternal( array $ops ) {
$supportedOps = [
- 'store' => 'StoreFileOp',
- 'copy' => 'CopyFileOp',
- 'move' => 'MoveFileOp',
- 'delete' => 'DeleteFileOp',
- 'create' => 'CreateFileOp',
- 'describe' => 'DescribeFileOp',
- 'null' => 'NullFileOp'
+ 'store' => StoreFileOp::class,
+ 'copy' => CopyFileOp::class,
+ 'move' => MoveFileOp::class,
+ 'delete' => DeleteFileOp::class,
+ 'create' => CreateFileOp::class,
+ 'describe' => DescribeFileOp::class,
+ 'null' => NullFileOp::class
];
$performOps = []; // array of FileOp objects
$this->srvsByBucket = array_values( $this->srvsByBucket ); // consecutive
$memcConfig = isset( $config['memcConfig'] ) ? $config['memcConfig'] : [];
- $memcConfig += [ 'class' => 'MemcachedPhpBagOStuff' ]; // default
+ $memcConfig += [ 'class' => MemcachedPhpBagOStuff::class ]; // default
$class = $memcConfig['class'];
- if ( !is_subclass_of( $class, 'MemcachedBagOStuff' ) ) {
+ if ( !is_subclass_of( $class, MemcachedBagOStuff::class ) ) {
throw new InvalidArgumentException( "$class is not of type MemcachedBagOStuff." );
}
* There are three supported ways to handle broadcasted operations:
* - a) Configure the 'purge' EventRelayer to point to a valid PubSub endpoint
* that has subscribed listeners on the cache servers applying the cache updates.
- * - b) Ignore the 'purge' EventRelayer configuration (default is NullEventRelayer)
- * and set up mcrouter as the underlying cache backend, using one of the memcached
- * BagOStuff classes as 'cache'. Use OperationSelectorRoute in the mcrouter settings
- * to configure 'set' and 'delete' operations to go to all DCs via AllAsyncRoute and
- * configure other operations to go to the local DC via PoolRoute (for reference,
- * see https://github.com/facebook/mcrouter/wiki/List-of-Route-Handles).
- * - c) Ignore the 'purge' EventRelayer configuration (default is NullEventRelayer)
- * and set up dynomite as cache middleware between the web servers and either
- * memcached or redis. This will also broadcast all key setting operations, not just purges,
- * which can be useful for cache warming. Writes are eventually consistent via the
- * Dynamo replication model (see https://github.com/Netflix/dynomite).
+ * - b) Ommit the 'purge' EventRelayer parameter and set up mcrouter as the underlying cache
+ * backend, using a memcached BagOStuff class for the 'cache' parameter. The 'region'
+ * and 'cluster' parameters must be provided and 'mcrouterAware' must be set to 'true'.
+ * Configure mcrouter as follows:
+ * - 1) Use Route Prefixing based on region (datacenter) and cache cluster.
+ * See https://github.com/facebook/mcrouter/wiki/Routing-Prefix and
+ * https://github.com/facebook/mcrouter/wiki/Multi-cluster-broadcast-setup
+ * - 2) To increase the consistency of delete() and touchCheckKey() during cache
+ * server membership changes, you can use the OperationSelectorRoute to
+ * configure 'set' and 'delete' operations to go to all servers in the cache
+ * cluster, instead of just one server determined by hashing.
+ * See https://github.com/facebook/mcrouter/wiki/List-of-Route-Handles
+ * - c) Ommit the 'purge' EventRelayer parameter and set up dynomite as cache middleware
+ * between the web servers and either memcached or redis. This will also broadcast all
+ * key setting operations, not just purges, which can be useful for cache warming.
+ * Writes are eventually consistent via the Dynamo replication model.
+ * See https://github.com/Netflix/dynomite
*
* Broadcasted operations like delete() and touchCheckKey() are done asynchronously
* in all datacenters this way, though the local one should likely be near immediate.
protected $purgeChannel;
/** @var EventRelayer Bus that handles purge broadcasts */
protected $purgeRelayer;
+ /** @bar bool Whether to use mcrouter key prefixing for routing */
+ protected $mcrouterAware;
+ /** @var string Physical region for mcrouter use */
+ protected $region;
+ /** @var string Cache cluster name for mcrouter use */
+ protected $cluster;
/** @var LoggerInterface */
protected $logger;
/** @var StatsdDataFactoryInterface */
* callback supplied by the getWithSetCallback() caller. The result will be saved
* as normal. The handler is expected to call the WAN cache callback at an opportune
* time (e.g. HTTP post-send), though generally within a few 100ms. [optional]
+ * - region: the current physical region. This is required when using mcrouter as the
+ * backing store proxy. [optional]
+ * - cluster: name of the cache cluster used by this WAN cache. The name must be the
+ * same in all datacenters; the ("region","cluster") tuple is what distinguishes
+ * the counterpart cache clusters among all the datacenter. The contents of
+ * https://github.com/facebook/mcrouter/wiki/Config-Files give background on this.
+ * This is required when using mcrouter as the backing store proxy. [optional]
+ * - mcrouterAware: set as true if mcrouter is the backing store proxy and mcrouter
+ * is configured to interpret /<region>/<cluster>/ key prefixes as routes. This
+ * requires that "region" and "cluster" are both set above. [optional]
*/
public function __construct( array $params ) {
$this->cache = $params['cache'];
$this->purgeRelayer = isset( $params['relayers']['purge'] )
? $params['relayers']['purge']
: new EventRelayerNull( [] );
+ $this->region = isset( $params['region'] ) ? $params['region'] : 'main';
+ $this->cluster = isset( $params['cluster'] ) ? $params['cluster'] : 'wan-main';
+ $this->mcrouterAware = !empty( $params['mcrouterAware'] );
+
$this->setLogger( isset( $params['logger'] ) ? $params['logger'] : new NullLogger() );
$this->stats = isset( $params['stats'] ) ? $params['stats'] : new NullStatsdDataFactory();
$this->asyncHandler = isset( $params['asyncHandler'] ) ? $params['asyncHandler'] : null;
*
* Setting 'lag' and 'since' help avoids keys getting stuck in stale states.
*
+ * Be aware that this does not update the process cache for getWithSetCallback()
+ * callers. Keys accessed via that method are not generally meant to also be set
+ * using this primitive method.
+ *
+ * Do not use this method on versioned keys accessed via getWithSetCallback().
+ *
* Example usage:
* @code
* $dbr = wfGetDB( DB_REPLICA );
*
* Note that set() can also be lag-aware and lower the TTL if it's high.
*
+ * Be aware that this does not clear the process cache. Even if it did, callbacks
+ * used by getWithSetCallback() might still return stale data in the case of either
+ * uncommitted or not-yet-replicated changes (callback generally use replica DBs).
+ *
* When using potentially long-running ACID transactions, a good pattern is
* to use a pre-commit hook to issue the delete. This means that immediately
* after commit, callers will see the tombstone in cache upon purge relay.
* @return bool Success
*/
protected function relayPurge( $key, $ttl, $holdoff ) {
- if ( $this->purgeRelayer instanceof EventRelayerNull ) {
+ if ( $this->mcrouterAware ) {
+ // See https://github.com/facebook/mcrouter/wiki/Multi-cluster-broadcast-setup
+ // Wildcards select all matching routes, e.g. the WAN cluster on all DCs
+ $ok = $this->cache->set(
+ "/*/{$this->cluster}/{$key}",
+ $this->makePurgeValue( $this->getCurrentTime(), self::HOLDOFF_NONE ),
+ $ttl
+ );
+ } elseif ( $this->purgeRelayer instanceof EventRelayerNull ) {
// This handles the mcrouter and the single-DC case
- $ok = $this->cache->set( $key,
+ $ok = $this->cache->set(
+ $key,
$this->makePurgeValue( $this->getCurrentTime(), self::HOLDOFF_NONE ),
$ttl
);
* @return bool Success
*/
protected function relayDelete( $key ) {
- if ( $this->purgeRelayer instanceof EventRelayerNull ) {
- // This handles the mcrouter and the single-DC case
+ if ( $this->mcrouterAware ) {
+ // See https://github.com/facebook/mcrouter/wiki/Multi-cluster-broadcast-setup
+ // Wildcards select all matching routes, e.g. the WAN cluster on all DCs
+ $ok = $this->cache->delete( "/*/{$this->cluster}/{$key}" );
+ } elseif ( $this->purgeRelayer instanceof EventRelayerNull ) {
+ // Some other proxy handles broadcasting or there is only one datacenter
$ok = $this->cache->delete( $key );
} else {
$event = $this->cache->modifySimpleRelayEvent( [
public function transactionWritingIn( $server, $db, $id ) {
$name = "{$server} ({$db}) (TRX#$id)";
if ( isset( $this->dbTrxHoldingLocks[$name] ) ) {
- $this->logger->info( "Nested transaction for '$name' - out of sync." );
+ $this->logger->warning( "Nested transaction for '$name' - out of sync." );
}
$this->dbTrxHoldingLocks[$name] = [
'start' => microtime( true ),
$elapsed = ( $eTime - $sTime );
if ( $isWrite && $n > $this->expect['maxAffected'] ) {
- $this->logger->info(
+ $this->logger->warning(
"Query affected $n row(s):\n" . $query . "\n" .
( new RuntimeException() )->getTraceAsString() );
}
public function transactionWritingOut( $server, $db, $id, $writeTime = 0.0, $affected = 0 ) {
$name = "{$server} ({$db}) (TRX#$id)";
if ( !isset( $this->dbTrxMethodTimes[$name] ) ) {
- $this->logger->info( "Detected no transaction for '$name' - out of sync." );
+ $this->logger->warning( "Detected no transaction for '$name' - out of sync." );
return;
}
list( $query, $sTime, $end ) = $info;
$trace .= sprintf( "%d\t%.6f\t%s\n", $i, ( $end - $sTime ), $query );
}
- $this->logger->info( "Sub-optimal transaction on DB(s) [{dbs}]: \n{trace}", [
+ $this->logger->warning( "Sub-optimal transaction on DB(s) [{dbs}]: \n{trace}", [
'dbs' => implode( ', ', array_keys( $this->dbTrxHoldingLocks[$name]['conns'] ) ),
'trace' => $trace
] );
return;
}
- $this->logger->info(
+ $this->logger->warning(
"Expectation ({measure} <= {max}) by {by} not met (actual: {actual}):\n{query}\n" .
( new RuntimeException() )->getTraceAsString(),
[
protected $delimiter = ';';
/** @var DatabaseDomain */
protected $currentDomain;
+ /** @var integer|null Rows affected by the last query to query() or its CRUD wrappers */
+ protected $affectedRowCount;
/**
* Either 1 if a transaction is active or 0 otherwise.
}
/**
- * Helper method for query() that handles profiling and logging and sends
- * the query to doQuery()
+ * Wrapper for query() that also handles profiling, logging, and affected row count updates
*
* @param string $sql Original SQL query
* @param string $commentedSql SQL query with debugging/trace comment
if ( $this->profiler ) {
call_user_func( [ $this->profiler, 'profileIn' ], $queryProf );
}
+ $this->affectedRowCount = null;
$ret = $this->doQuery( $commentedSql );
+ $this->affectedRowCount = $this->affectedRows();
if ( $this->profiler ) {
call_user_func( [ $this->profiler, 'profileOut' ], $queryProf );
}
}
public function replace( $table, $uniqueIndexes, $rows, $fname = __METHOD__ ) {
- $quotedTable = $this->tableName( $table );
-
if ( count( $rows ) == 0 ) {
return;
}
- # Single row case
+ // Single row case
if ( !is_array( reset( $rows ) ) ) {
$rows = [ $rows ];
}
- // @FXIME: this is not atomic, but a trx would break affectedRows()
+ $affectedRowCount = 0;
foreach ( $rows as $row ) {
- # Delete rows which collide
- if ( $uniqueIndexes ) {
- $sql = "DELETE FROM $quotedTable WHERE ";
- $first = true;
- foreach ( $uniqueIndexes as $index ) {
- if ( $first ) {
- $first = false;
- $sql .= '( ';
- } else {
- $sql .= ' ) OR ( ';
- }
- if ( is_array( $index ) ) {
- $first2 = true;
- foreach ( $index as $col ) {
- if ( $first2 ) {
- $first2 = false;
- } else {
- $sql .= ' AND ';
- }
- $sql .= $col . '=' . $this->addQuotes( $row[$col] );
- }
- } else {
- $sql .= $index . '=' . $this->addQuotes( $row[$index] );
- }
+ // Delete rows which collide with this one
+ $indexWhereClauses = [];
+ foreach ( $uniqueIndexes as $index ) {
+ $indexColumns = (array)$index;
+ $indexRowValues = array_intersect_key( $row, array_flip( $indexColumns ) );
+ if ( count( $indexRowValues ) != count( $indexColumns ) ) {
+ throw new DBUnexpectedError(
+ $this,
+ 'New record does not provide all values for unique key (' .
+ implode( ', ', $indexColumns ) . ')'
+ );
+ } elseif ( in_array( null, $indexRowValues, true ) ) {
+ throw new DBUnexpectedError(
+ $this,
+ 'New record has a null value for unique key (' .
+ implode( ', ', $indexColumns ) . ')'
+ );
}
- $sql .= ' )';
- $this->query( $sql, $fname );
+ $indexWhereClauses[] = $this->makeList( $indexRowValues, LIST_AND );
+ }
+
+ if ( $indexWhereClauses ) {
+ $this->delete( $table, $this->makeList( $indexWhereClauses, LIST_OR ), $fname );
+ $affectedRowCount += $this->affectedRows();
}
- # Now insert the row
+ // Now insert the row
$this->insert( $table, $row, $fname );
+ $affectedRowCount += $this->affectedRows();
}
+
+ $this->affectedRowCount = $affectedRowCount;
}
/**
$where = false;
}
+ $affectedRowCount = 0;
$useTrx = !$this->mTrxLevel;
if ( $useTrx ) {
$this->begin( $fname, self::TRANSACTION_INTERNAL );
# Update any existing conflicting row(s)
if ( $where !== false ) {
$ok = $this->update( $table, $set, $where, $fname );
+ $affectedRowCount += $this->affectedRows();
} else {
$ok = true;
}
# Now insert any non-conflicting row(s)
$ok = $this->insert( $table, $rows, $fname, [ 'IGNORE' ] ) && $ok;
+ $affectedRowCount += $this->affectedRows();
} catch ( Exception $e ) {
if ( $useTrx ) {
$this->rollback( $fname, self::FLUSHING_INTERNAL );
if ( $useTrx ) {
$this->commit( $fname, self::FLUSHING_INTERNAL );
}
+ $this->affectedRowCount = $affectedRowCount;
return $ok;
}
}
}
+ public function affectedRows() {
+ return ( $this->affectedRowCount === null )
+ ? $this->fetchAffectedRowCount() // default to driver value
+ : $this->affectedRowCount;
+ }
+
+ /**
+ * @return int Number of retrieved rows according to the driver
+ */
+ abstract protected function fetchAffectedRowCount();
+
/**
* Take the result from a query, and wrap it in a ResultWrapper if
* necessary. Boolean values are passed through as is, to indicate success
/**
* @return int
*/
- public function affectedRows() {
+ protected function fetchAffectedRowCount() {
return $this->mAffectedRows;
}
/** @var string|null */
private $serverVersion = null;
+ /** @var bool|null */
+ private $insertSelectIsSafe = null;
/**
* Additional $params include:
* ID of this server's master will be used. Set the "conds" field to
* override the query conditions, e.g. ['shard' => 's1'].
* - useGTIDs : use GTID methods like MASTER_GTID_WAIT() when possible.
+ * - insertSelectIsSafe : force that native INSERT SELECT is or is not safe [default: null]
* - sslKeyPath : path to key file [default: null]
* - sslCertPath : path to certificate file [default: null]
* - sslCAFile: path to a single certificate authority PEM file [default: null]
}
$this->sqlMode = isset( $params['sqlMode'] ) ? $params['sqlMode'] : '';
$this->utf8Mode = !empty( $params['utf8Mode'] );
+ $this->insertSelectIsSafe = isset( $params['insertSelectIsSafe'] )
+ ? (bool)$params['insertSelectIsSafe'] : null;
parent::__construct( $params );
}
return $this->nativeReplace( $table, $rows, $fname );
}
+ protected function nativeInsertSelect(
+ $destTable, $srcTable, $varMap, $conds,
+ $fname = __METHOD__, $insertOptions = [], $selectOptions = [], $selectJoinConds = []
+ ) {
+ if ( $this->insertSelectIsSafe === null ) {
+ // In MySQL, an INSERT SELECT is only replication safe with row-based
+ // replication or if innodb_autoinc_lock_mode is 0. When those
+ // conditions aren't met, use non-native mode.
+ // While we could try to determine if the insert is safe anyway by
+ // checking if the target table has an auto-increment column that
+ // isn't set in $varMap, that seems unlikely to be worth the extra
+ // complexity.
+ $row = $this->selectRow(
+ false,
+ [
+ 'innodb_autoinc_lock_mode' => '@@innodb_autoinc_lock_mode',
+ 'binlog_format' => '@@binlog_format',
+ ],
+ [],
+ __METHOD__
+ );
+ $this->insertSelectIsSafe = $row->binlog_format === 'ROW' ||
+ (int)$row->innodb_autoinc_lock_mode === 0;
+ }
+
+ if ( !$this->insertSelectIsSafe ) {
+ return $this->nonNativeInsertSelect(
+ $destTable,
+ $srcTable,
+ $varMap,
+ $conds,
+ $fname,
+ $insertOptions,
+ $selectOptions,
+ $selectJoinConds
+ );
+ } else {
+ return parent::nativeInsertSelect(
+ $destTable,
+ $srcTable,
+ $varMap,
+ $conds,
+ $fname,
+ $insertOptions,
+ $selectOptions,
+ $selectJoinConds
+ );
+ }
+ }
+
/**
* Estimate rows in dataset
* Returns estimated count, based on EXPLAIN output
return 0; // already reached this point for sure
}
+ $useGTID = ( $this->useGTIDs && $pos->gtids );
+
// Call doQuery() directly, to avoid opening a transaction if DBO_TRX is set
- if ( $this->useGTIDs && $pos->gtids ) {
+ if ( $useGTID ) {
// Wait on the GTID set (MariaDB only)
$gtidArg = $this->addQuotes( implode( ',', $pos->gtids ) );
$res = $this->doQuery( "SELECT MASTER_GTID_WAIT($gtidArg, $timeout)" );
// Result can be NULL (error), -1 (timeout), or 0+ per the MySQL manual
$status = ( $row[0] !== null ) ? intval( $row[0] ) : null;
if ( $status === null ) {
- // T126436: jobs programmed to wait on master positions might be referencing binlogs
- // with an old master hostname. Such calls make MASTER_POS_WAIT() return null. Try
- // to detect this and treat the replica DB as having reached the position; a proper master
- // switchover already requires that the new master be caught up before the switch.
- $replicationPos = $this->getReplicaPos();
- if ( $replicationPos && !$replicationPos->channelsMatch( $pos ) ) {
- $this->lastKnownReplicaPos = $replicationPos;
- $status = 0;
+ if ( !$useGTID ) {
+ // T126436: jobs programmed to wait on master positions might be referencing
+ // binlogs with an old master hostname; this makes MASTER_POS_WAIT() return null.
+ // Try to detect this case and treat the replica DB as having reached the given
+ // position (any master switchover already requires that the new master be caught
+ // up before the switch).
+ $replicationPos = $this->getReplicaPos();
+ if ( $replicationPos && !$replicationPos->channelsMatch( $pos ) ) {
+ $this->lastKnownReplicaPos = $replicationPos;
+ $status = 0;
+ }
}
} elseif ( $status >= 0 ) {
// Remember that this position was reached to save queries next time
/**
* @return int
*/
- function affectedRows() {
+ protected function fetchAffectedRowCount() {
$conn = $this->getBindingHandle();
return $conn->affected_rows;
}
}
- public function affectedRows() {
+ protected function fetchAffectedRowCount() {
if ( !is_null( $this->mAffectedRows ) ) {
// Forced result for simulated queries
return $this->mAffectedRows;
/** @var FSLockManager (hopefully on the same server as the DB) */
protected $lockMgr;
+ /** @var array List of shared database already attached to this connection */
+ private $alreadyAttached = [];
+
/**
* Additional params include:
* - dbDirectory : directory containing the DB and the lock file directory
parent::__construct( $p );
// Super doesn't open when $user is false, but we can work with $dbName
if ( $p['dbname'] && !$this->isOpen() ) {
- if ( $this->open( $p['host'], $p['user'], $p['password'], $p['dbname'] ) ) {
- $done = [];
- foreach ( $this->tableAliases as $params ) {
- if ( isset( $done[$params['dbname']] ) ) {
- continue;
- }
- $this->attachDatabase( $params['dbname'] );
- $done[$params['dbname']] = 1;
- }
- }
+ $this->open( $p['host'], $p['user'], $p['password'], $p['dbname'] );
}
}
return parent::isWriteQuery( $sql ) && !preg_match( '/^(ATTACH|PRAGMA)\b/i', $sql );
}
+ protected function isTransactableQuery( $sql ) {
+ return parent::isTransactableQuery( $sql ) && !in_array(
+ $this->getQueryVerb( $sql ),
+ [ 'ATTACH', 'PRAGMA' ],
+ true
+ );
+ }
+
/**
* SQLite doesn't allow buffered results or data seeking etc, so we'll use fetchAll as the result
*
/**
* @return int
*/
- function affectedRows() {
+ protected function fetchAffectedRowCount() {
return $this->mAffectedRows;
}
return $this->query( $sql, $fName );
}
+ public function setTableAliases( array $aliases ) {
+ parent::setTableAliases( $aliases );
+ foreach ( $this->tableAliases as $params ) {
+ if ( isset( $this->alreadyAttached[$params['dbname']] ) ) {
+ continue;
+ }
+ $this->attachDatabase( $params['dbname'] );
+ $this->alreadyAttached[$params['dbname']] = true;
+ }
+ }
+
protected function requiresDatabaseUser() {
return false; // just a file
}
* INSERT SELECT wrapper. Takes data from a SELECT query and inserts it
* into another table.
*
+ * @warning If the insert will use an auto-increment or sequence to
+ * determine the value of a column, this may break replication on
+ * databases using statement-based replication if the SELECT is not
+ * deterministically ordered.
+ *
* @param string $destTable The table name to insert into
* @param string|array $srcTable May be either a table name, or an array of table names
* to include in a join.
$res = $this->result;
if ( $this->mSeekTo !== null ) {
- $result = sqlsrv_fetch_object( $res, 'stdClass', [],
+ $result = sqlsrv_fetch_object( $res, stdClass::class, [],
SQLSRV_SCROLL_ABSOLUTE, $this->mSeekTo );
$this->mSeekTo = null;
} else {
* @param array $params
*/
public function forEachLB( $callback, array $params = [] ) {
- call_user_func_array( $callback, array_merge( [ $this->lb ], $params ) );
+ if ( isset( $this->lb ) ) { // may not be set during _destruct()
+ call_user_func_array( $callback, array_merge( [ $this->lb ], $params ) );
+ }
}
}
// Use the local domain table prefix if the local domain is specified
$server['tablePrefix'] = $this->localDomain->getTablePrefix();
}
- $conn = $this->reallyOpenConnection( $server, $this->localDomain->getDatabase() );
+ $conn = $this->reallyOpenConnection( $server, $this->localDomain );
$host = $this->getServerName( $i );
if ( $conn->isOpen() ) {
$this->connLogger->debug( "Connected to database $i at '$host'." );
$server['foreignPoolRefCount'] = 0;
$server['foreign'] = true;
$server['autoCommitOnly'] = $autoCommit;
- $conn = $this->reallyOpenConnection( $server, $dbName );
+ $conn = $this->reallyOpenConnection( $server, $domainInstance );
if ( !$conn->isOpen() ) {
$this->connLogger->warning( __METHOD__ . ": connection error for $i/$domain" );
$this->errorConnection = $conn;
* Returns a Database object whether or not the connection was successful.
*
* @param array $server
- * @param string|null $dbNameOverride Use "" to not select any database
+ * @param DatabaseDomain $domainOverride Use an unspecified domain to not select any database
* @return Database
* @throws DBAccessError
* @throws InvalidArgumentException
*/
- protected function reallyOpenConnection( array $server, $dbNameOverride ) {
+ protected function reallyOpenConnection( array $server, DatabaseDomain $domainOverride ) {
if ( $this->disabled ) {
throw new DBAccessError();
}
- if ( $dbNameOverride !== null ) {
- $server['dbname'] = $dbNameOverride;
+ if ( $domainOverride->getDatabase() !== null ) {
+ $server['dbname'] = $domainOverride->getDatabase();
+ $server['schema'] = $domainOverride->getSchema();
}
// Let the handle know what the cluster master is (e.g. "db1052")
$oldDomain = $this->localDomain->getId();
$this->setLocalDomain( new DatabaseDomain(
$this->localDomain->getDatabase(),
- null,
+ $this->localDomain->getSchema(),
$prefix
) );
return new static( [ 'connection' => $db ] + $params );
}
- protected function reallyOpenConnection( array $server, $dbNameOverride ) {
+ protected function reallyOpenConnection( array $server, DatabaseDomain $domainOverride ) {
return $this->db;
}
}
-class_alias( 'Wikimedia\Rdbms\LoadBalancerSingle', 'LoadBalancerSingle' );
+class_alias( LoadBalancerSingle::class, 'LoadBalancerSingle' );
*/
class CategoryPage extends Article {
# Subclasses can change this to override the viewer class.
- protected $mCategoryViewerClass = 'CategoryViewer';
+ protected $mCategoryViewerClass = CategoryViewer::class;
/**
* @var WikiCategoryPage
$this->mPreprocessorClass = $conf['preprocessorClass'];
} elseif ( defined( 'HPHP_VERSION' ) ) {
# Preprocessor_Hash is much faster than Preprocessor_DOM under HipHop
- $this->mPreprocessorClass = 'Preprocessor_Hash';
+ $this->mPreprocessorClass = Preprocessor_Hash::class;
} elseif ( extension_loaded( 'domxml' ) ) {
# PECL extension that conflicts with the core DOM extension (T15770)
wfDebug( "Warning: you have the obsolete domxml extension for PHP. Please remove it!\n" );
- $this->mPreprocessorClass = 'Preprocessor_Hash';
+ $this->mPreprocessorClass = Preprocessor_Hash::class;
} elseif ( extension_loaded( 'dom' ) ) {
- $this->mPreprocessorClass = 'Preprocessor_DOM';
+ $this->mPreprocessorClass = Preprocessor_DOM::class;
} else {
- $this->mPreprocessorClass = 'Preprocessor_Hash';
+ $this->mPreprocessorClass = Preprocessor_Hash::class;
}
wfDebug( __CLASS__ . ": using preprocessor: {$this->mPreprocessorClass}\n" );
}
'stubthreshold' => true,
'printable' => true,
'userlang' => true,
- 'wrapclass' => true,
];
/**
/**
* CSS class to use to wrap output from Parser::parse()
* @since 1.30
- * @param string|bool $className Set false to disable wrapping.
+ * @param string $className Class name to use for wrapping.
+ * Passing false to indicate "no wrapping" was deprecated in MediaWiki 1.31.
* @return string|bool Current value
*/
public function setWrapOutputClass( $className ) {
if ( $className === true ) { // DWIM, they probably want the default class name
$className = 'mw-parser-output';
}
+ if ( $className === false ) {
+ wfDeprecated( __METHOD__ . '( false )', '1.31' );
+ }
return $this->setOption( 'wrapclass', $className );
}
'printable' => false,
'allowUnsafeRawHtml' => true,
'wrapclass' => 'mw-parser-output',
- 'currentRevisionCallback' => [ 'Parser', 'statelessFetchRevision' ],
- 'templateCallback' => [ 'Parser', 'statelessFetchTemplate' ],
+ 'currentRevisionCallback' => [ Parser::class, 'statelessFetchRevision' ],
+ 'templateCallback' => [ Parser::class, 'statelessFetchTemplate' ],
'speculativeRevIdCallback' => null,
];
*/
class ParserOutput extends CacheTime {
/**
- * Feature flag to indicate to extensions that MediaWiki core supports and
+ * Feature flags to indicate to extensions that MediaWiki core supports and
* uses getText() stateless transforms.
*/
const SUPPORTS_STATELESS_TRANSFORMS = 1;
+ const SUPPORTS_UNWRAP_TRANSFORM = 1;
/**
* @var string $mText The output text
* to generate one and `__NOTOC__` wasn't used. Default is true,
* but might be statefully overridden.
* - enableSectionEditLinks: (bool) Include section edit links, assuming
- * section edit link tokens are present in the HTML. Default is true,
+ * section edit link tokens are present in the HTML. Default is true,
* but might be statefully overridden.
+ * - unwrap: (bool) Remove a wrapping mw-parser-output div. Default is false.
* @return string HTML
*/
public function getText( $options = [] ) {
- // @todo Warn if !array_key_exists( 'allowTOC', $options ) && empty( $this->mTOCEnabled )
+ if ( !array_key_exists( 'allowTOC', $options ) && empty( $this->mTOCEnabled ) ) {
+ wfDeprecated( 'ParserOutput stateful allowTOC', '1.31' );
+ }
- // @todo Warn if !array_key_exists( 'enableSectionEditLinks', $options )
- // && !$this->mEditSectionTokens
// Note that while $this->mEditSectionTokens formerly defaulted to false,
// ParserOptions->getEditSection() defaults to true and Parser copies
// that to us so true makes more sense as the stateless default.
+ if ( !array_key_exists( 'enableSectionEditLinks', $options ) && !$this->mEditSectionTokens ) {
+ wfDeprecated( 'ParserOutput stateful enableSectionEditLinks', '1.31' );
+ }
$options += [
// empty() here because old cached versions might lack the field somehow.
// In that situation, the historical behavior (possibly buggy) is to remove the TOC.
'allowTOC' => !empty( $this->mTOCEnabled ),
'enableSectionEditLinks' => $this->mEditSectionTokens,
+ 'unwrap' => false,
];
$text = $this->mText;
Hooks::runWithoutAbort( 'ParserOutputPostCacheTransform', [ $this, &$text, &$options ] );
+ if ( $options['unwrap'] !== false ) {
+ $start = Html::openElement( 'div', [
+ 'class' => 'mw-parser-output'
+ ] );
+ $startLen = strlen( $start );
+ $end = Html::closeElement( 'div' );
+ $endLen = strlen( $end );
+
+ if ( substr( $text, 0, $startLen ) === $start && substr( $text, -$endLen ) === $end ) {
+ $text = substr( $text, $startLen, -$endLen );
+ }
+ }
+
if ( $options['enableSectionEditLinks'] ) {
$text = preg_replace_callback(
self::EDITSECTION_REGEX,
*/
public $top;
public $out;
- public $elementClass = 'PPDStackElement';
+ public $elementClass = PPDStackElement::class;
public static $false = false;
*/
public $lineStart;
- public $partClass = 'PPDPart';
+ public $partClass = PPDPart::class;
public function __construct( $data = [] ) {
$class = $this->partClass;
class PPDStack_Hash extends PPDStack {
public function __construct() {
- $this->elementClass = 'PPDStackElement_Hash';
+ $this->elementClass = PPDStackElement_Hash::class;
parent::__construct();
$this->rootAccum = [];
}
class PPDStackElement_Hash extends PPDStackElement {
public function __construct( $data = [] ) {
- $this->partClass = 'PPDPart_Hash';
+ $this->partClass = PPDPart_Hash::class;
parent::__construct( $data );
}
$descriptor = $store[$index];
if ( is_string( $descriptor ) ) {
- $class = 'PPNode_Hash_Text';
+ $class = PPNode_Hash_Text::class;
} elseif ( is_array( $descriptor ) ) {
if ( $descriptor[self::NAME][0] === '@' ) {
- $class = 'PPNode_Hash_Attr';
+ $class = PPNode_Hash_Attr::class;
} else {
- $class = 'PPNode_Hash_Tree';
+ $class = self::class;
}
} else {
throw new MWException( __METHOD__.': invalid node descriptor' );
# Stupid hack
$encValue = preg_replace_callback(
'/((?i)' . wfUrlProtocols() . ')/',
- [ 'Sanitizer', 'armorLinksCallback' ],
+ function ( $matches ) {
+ return str_replace( ':', ':', $matches[1] );
+ },
$encValue );
return $encValue;
}
return $html;
}
- /**
- * Regex replace callback for armoring links against further processing.
- * @param array $matches
- * @return string
- */
- private static function armorLinksCallback( $matches ) {
- return str_replace( ':', ':', $matches[1] );
- }
-
/**
* Return an associative array of attribute names and values from
* a partial tag string. Attribute names are forced to lowercase,
static function normalizeCharReferences( $text ) {
return preg_replace_callback(
self::CHAR_REFS_REGEX,
- [ 'Sanitizer', 'normalizeCharReferencesCallback' ],
+ [ self::class, 'normalizeCharReferencesCallback' ],
$text );
}
public static function decodeCharReferences( $text ) {
return preg_replace_callback(
self::CHAR_REFS_REGEX,
- [ 'Sanitizer', 'decodeCharReferencesCallback' ],
+ [ self::class, 'decodeCharReferencesCallback' ],
$text );
}
global $wgContLang;
$text = preg_replace_callback(
self::CHAR_REFS_REGEX,
- [ 'Sanitizer', 'decodeCharReferencesCallback' ],
+ [ self::class, 'decodeCharReferencesCallback' ],
$text,
-1, //limit
$count
* @see Setup.php
*/
private $types = [
- '' => [ 'type' => '', 'class' => 'InvalidPassword' ],
+ '' => [ 'type' => '', 'class' => InvalidPassword::class ],
];
/**
// Handling for multiselect preferences
if ( ( isset( $info['type'] ) && $info['type'] == 'multiselect' ) ||
- ( isset( $info['class'] ) && $info['class'] == 'HTMLMultiSelectField' ) ) {
+ ( isset( $info['class'] ) && $info['class'] == \HTMLMultiSelectField::class ) ) {
$options = HTMLFormField::flattenOptions( $info['options'] );
$prefix = isset( $info['prefix'] ) ? $info['prefix'] : $name;
$val = [];
// Handling for checkmatrix preferences
if ( ( isset( $info['type'] ) && $info['type'] == 'checkmatrix' ) ||
- ( isset( $info['class'] ) && $info['class'] == 'HTMLCheckMatrix' ) ) {
+ ( isset( $info['class'] ) && $info['class'] == \HTMLCheckMatrix::class ) ) {
$columns = HTMLFormField::flattenOptions( $info['columns'] );
$rows = HTMLFormField::flattenOptions( $info['rows'] );
$prefix = isset( $info['prefix'] ) ? $info['prefix'] : $name;
}
$defaultPreferences['timecorrection'] = [
- 'class' => 'HTMLSelectOrOtherField',
+ 'class' => \HTMLSelectOrOtherField::class,
'label-message' => 'timezonelegend',
'options' => $tzOptions,
'default' => $tzSetting,
public function getForm(
User $user,
IContextSource $context,
- $formClass = 'PreferencesForm',
+ $formClass = PreferencesForm::class,
array $remove = []
) {
$formDescriptor = $this->getFormDescriptor( $user, $context );
public function getForm(
User $user,
IContextSource $contextSource,
- $formClass = 'PreferencesForm',
+ $formClass = \PreferencesForm::class,
array $remove = []
);
global $wgProfiler, $wgProfileLimit;
$params = [
- 'class' => 'ProfilerStub',
+ 'class' => ProfilerStub::class,
'sampling' => 1,
'threshold' => $wgProfileLimit,
'output' => [],
$inSample = mt_rand( 0, $params['sampling'] - 1 ) === 0;
// wfIsCLI() is not available yet
if ( PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg' || !$inSample ) {
- $params['class'] = 'ProfilerStub';
+ $params['class'] = ProfilerStub::class;
}
if ( !is_array( $params['output'] ) ) {
* Profiler that only tracks explicit profiling sections
*
* @code
- * $wgProfiler['class'] = 'ProfilerSectionOnly';
+ * $wgProfiler['class'] = ProfilerSectionOnly::class;
* $wgProfiler['output'] = 'text';
* $wgProfiler['visible'] = true;
* @endcode
* Profiler wrapper for XHProf extension.
*
* @code
- * $wgProfiler['class'] = 'ProfilerXhprof';
+ * $wgProfiler['class'] = ProfilerXhprof::class;
* $wgProfiler['flags'] = XHPROF_FLAGS_NO_BUILTINS;
* $wgProfiler['output'] = 'text';
* $wgProfiler['visible'] = true;
* @endcode
*
* @code
- * $wgProfiler['class'] = 'ProfilerXhprof';
+ * $wgProfiler['class'] = ProfilerXhprof::class;
* $wgProfiler['flags'] = XHPROF_FLAGS_CPU | XHPROF_FLAGS_MEMORY | XHPROF_FLAGS_NO_BUILTINS;
* $wgProfiler['output'] = 'udp';
* @endcode
$object->setLogger( $this->logger );
} else {
if ( !isset( $info['class'] ) ) {
- $class = 'ResourceLoaderFileModule';
+ $class = ResourceLoaderFileModule::class;
} else {
$class = $info['class'];
}
}
if (
isset( $info['class'] ) &&
- $info['class'] !== 'ResourceLoaderFileModule' &&
- !is_subclass_of( $info['class'], 'ResourceLoaderFileModule' )
+ $info['class'] !== ResourceLoaderFileModule::class &&
+ !is_subclass_of( $info['class'], ResourceLoaderFileModule::class )
) {
return false;
}
$name, $scripts, $styles, $messages, $templates
) {
if ( $scripts instanceof XmlJsCode ) {
- $scripts = new XmlJsCode( "function ( $, jQuery, require, module ) {\n{$scripts->value}\n}" );
+ if ( self::inDebugMode() ) {
+ $scripts = new XmlJsCode( "function ( $, jQuery, require, module ) {\n{$scripts->value}\n}" );
+ } else {
+ $scripts = new XmlJsCode( 'function($,jQuery,require,module){'. $scripts->value . '}' );
+ }
} elseif ( !is_string( $scripts ) && !is_array( $scripts ) ) {
throw new MWException( 'Invalid scripts error. Array of URLs or string of code expected.' );
}
* @return string JavaScript code
*/
public function getScript( ResourceLoaderContext $context ) {
- return Xml::encodeJsCall( 'mw.user.options.set',
+ // Use FILTER_NOMIN annotation to prevent needless minification and caching (T84960).
+ return ResourceLoader::FILTER_NOMIN . Xml::encodeJsCall(
+ 'mw.user.options.set',
[ $context->getUserObj()->getOptions( User::GETOPTIONS_EXCLUDE_DEFAULTS ) ],
ResourceLoader::inDebugMode()
);
}
/**
- * Generate the JavaScript content of this module.
- *
- * Add FILTER_NOMIN annotation to prevent needless minification and caching (T84960).
- *
* @param ResourceLoaderContext $context
* @return string JavaScript code
*/
public function getScript( ResourceLoaderContext $context ) {
- return Xml::encodeJsCall(
+ // Use FILTER_NOMIN annotation to prevent needless minification and caching (T84960).
+ return ResourceLoader::FILTER_NOMIN . Xml::encodeJsCall(
'mw.user.tokens.set',
[ $this->contextUserTokens( $context ) ],
ResourceLoader::inDebugMode()
- ) . ResourceLoader::FILTER_NOMIN;
+ );
}
/**
class RevisionDeleter {
/** List of known revdel types, with their corresponding list classes */
private static $allowedTypes = [
- 'revision' => 'RevDelRevisionList',
- 'archive' => 'RevDelArchiveList',
- 'oldimage' => 'RevDelFileList',
- 'filearchive' => 'RevDelArchivedFileList',
- 'logging' => 'RevDelLogList',
+ 'revision' => RevDelRevisionList::class,
+ 'archive' => RevDelArchiveList::class,
+ 'oldimage' => RevDelFileList::class,
+ 'filearchive' => RevDelArchivedFileList::class,
+ 'logging' => RevDelLogList::class,
];
/** Type map to support old log entries */
public static function getSearchEngineClass( IDatabase $db ) {
switch ( $db->getType() ) {
case 'sqlite':
- return 'SearchSqlite';
+ return SearchSqlite::class;
case 'mysql':
- return 'SearchMySQL';
+ return SearchMySQL::class;
case 'postgres':
- return 'SearchPostgres';
+ return SearchPostgres::class;
case 'mssql':
- return 'SearchMssql';
+ return SearchMssql::class;
case 'oracle':
- return 'SearchOracle';
+ return SearchOracle::class;
default:
- return 'SearchEngineDummy';
+ return SearchEngineDummy::class;
}
}
}
$eintr = defined( 'SOCKET_EINTR' ) ? SOCKET_EINTR : 4;
$eintrMessage = "stream_select(): unable to select [$eintr]";
+ /* The select(2) system call only guarantees a "sufficiently small write"
+ * can be made without blocking. And on Linux the read might block too
+ * in certain cases, although I don't know if any of them can occur here.
+ * Regardless, set all the pipes to non-blocking to avoid T184171.
+ */
+ foreach ( $pipes as $pipe ) {
+ stream_set_blocking( $pipe, false );
+ }
+
$running = true;
$timeout = null;
$numReadyPipes = 0;
- while ( $running === true || $numReadyPipes !== 0 ) {
+ while ( $pipes && ( $running === true || $numReadyPipes !== 0 ) ) {
if ( $running ) {
$status = proc_get_status( $proc );
// If the process has terminated, switch to nonblocking selects
}
if ( $res === '' || $res === 0 ) {
- // End of file
- fclose( $pipes[$fd] );
- unset( $pipes[$fd] );
- if ( !$pipes ) {
- break 2;
+ // End of file?
+ if ( feof( $pipe ) ) {
+ fclose( $pipes[$fd] );
+ unset( $pipes[$fd] );
}
} elseif ( $isWrite ) {
- $buffers[$fd] = substr( $buffers[$fd], $res );
+ $buffers[$fd] = (string)substr( $buffers[$fd], $res );
+ if ( $buffers[$fd] === '' ) {
+ fclose( $pipes[$fd] );
+ unset( $pipes[$fd] );
+ }
} else {
$buffers[$fd] .= $res;
if ( $fd === 3 && strpos( $res, "\n" ) !== false ) {
* @return string
*/
public function getObjectType() {
- return 'Site';
+ return Site::class;
}
/**
}
/**
+ * @deprecated since 1.31 This function is a now-redundant optimisation intended
+ * for very old versions of PHP. The use of references here makes the code
+ * more fragile and is incompatible with plans like T140664. Use set() instead.
* @param string $name
* @param mixed &$value
*/
public function setRef( $name, &$value ) {
+ wfDeprecated( __METHOD__, '1.31' );
$this->data[$name] =& $value;
}
*/
class SkinApi extends SkinTemplate {
public $skinname = 'apioutput';
- public $template = 'SkinApiTemplate';
+ public $template = SkinApiTemplate::class;
public function setupSkinUserCss( OutputPage $out ) {
parent::setupSkinUserCss( $out );
class SkinFallback extends SkinTemplate {
public $skinname = 'fallback';
- public $template = 'SkinFallbackTemplate';
+ public $template = SkinFallbackTemplate::class;
/**
* Add CSS via ResourceLoader
* @var string For QuickTemplate, the name of the subclass which will
* actually fill the template. Child classes should override the default.
*/
- public $template = 'QuickTemplate';
+ public $template = QuickTemplate::class;
public $thispage;
public $titletxt;
} elseif ( array_key_exists( 'type', $definition ) ) {
$class = HTMLForm::$typeMappings[$definition['type']];
}
- if ( $class !== 'HTMLInfoField' ) {
+ if ( $class !== HTMLInfoField::class ) {
$definition['tabindex'] = $i;
$i++;
}
if ( $qp === null ) {
// QueryPage subclass, Special page name
$qp = [
- [ 'AncientPagesPage', 'Ancientpages' ],
- [ 'BrokenRedirectsPage', 'BrokenRedirects' ],
- [ 'DeadendPagesPage', 'Deadendpages' ],
- [ 'DoubleRedirectsPage', 'DoubleRedirects' ],
- [ 'FileDuplicateSearchPage', 'FileDuplicateSearch' ],
- [ 'ListDuplicatedFilesPage', 'ListDuplicatedFiles' ],
- [ 'LinkSearchPage', 'LinkSearch' ],
- [ 'ListredirectsPage', 'Listredirects' ],
- [ 'LonelyPagesPage', 'Lonelypages' ],
- [ 'LongPagesPage', 'Longpages' ],
- [ 'MediaStatisticsPage', 'MediaStatistics' ],
- [ 'MIMEsearchPage', 'MIMEsearch' ],
- [ 'MostcategoriesPage', 'Mostcategories' ],
- [ 'MostimagesPage', 'Mostimages' ],
- [ 'MostinterwikisPage', 'Mostinterwikis' ],
- [ 'MostlinkedCategoriesPage', 'Mostlinkedcategories' ],
- [ 'MostlinkedTemplatesPage', 'Mostlinkedtemplates' ],
- [ 'MostlinkedPage', 'Mostlinked' ],
- [ 'MostrevisionsPage', 'Mostrevisions' ],
- [ 'FewestrevisionsPage', 'Fewestrevisions' ],
- [ 'ShortPagesPage', 'Shortpages' ],
- [ 'UncategorizedCategoriesPage', 'Uncategorizedcategories' ],
- [ 'UncategorizedPagesPage', 'Uncategorizedpages' ],
- [ 'UncategorizedImagesPage', 'Uncategorizedimages' ],
- [ 'UncategorizedTemplatesPage', 'Uncategorizedtemplates' ],
- [ 'UnusedCategoriesPage', 'Unusedcategories' ],
- [ 'UnusedimagesPage', 'Unusedimages' ],
- [ 'WantedCategoriesPage', 'Wantedcategories' ],
- [ 'WantedFilesPage', 'Wantedfiles' ],
- [ 'WantedPagesPage', 'Wantedpages' ],
- [ 'WantedTemplatesPage', 'Wantedtemplates' ],
- [ 'UnwatchedpagesPage', 'Unwatchedpages' ],
- [ 'UnusedtemplatesPage', 'Unusedtemplates' ],
- [ 'WithoutInterwikiPage', 'Withoutinterwiki' ],
+ [ AncientPagesPage::class, 'Ancientpages' ],
+ [ BrokenRedirectsPage::class, 'BrokenRedirects' ],
+ [ DeadendPagesPage::class, 'Deadendpages' ],
+ [ DoubleRedirectsPage::class, 'DoubleRedirects' ],
+ [ FileDuplicateSearchPage::class, 'FileDuplicateSearch' ],
+ [ ListDuplicatedFilesPage::class, 'ListDuplicatedFiles' ],
+ [ LinkSearchPage::class, 'LinkSearch' ],
+ [ ListredirectsPage::class, 'Listredirects' ],
+ [ LonelyPagesPage::class, 'Lonelypages' ],
+ [ LongPagesPage::class, 'Longpages' ],
+ [ MediaStatisticsPage::class, 'MediaStatistics' ],
+ [ MIMEsearchPage::class, 'MIMEsearch' ],
+ [ MostcategoriesPage::class, 'Mostcategories' ],
+ [ MostimagesPage::class, 'Mostimages' ],
+ [ MostinterwikisPage::class, 'Mostinterwikis' ],
+ [ MostlinkedCategoriesPage::class, 'Mostlinkedcategories' ],
+ [ MostlinkedTemplatesPage::class, 'Mostlinkedtemplates' ],
+ [ MostlinkedPage::class, 'Mostlinked' ],
+ [ MostrevisionsPage::class, 'Mostrevisions' ],
+ [ FewestrevisionsPage::class, 'Fewestrevisions' ],
+ [ ShortPagesPage::class, 'Shortpages' ],
+ [ UncategorizedCategoriesPage::class, 'Uncategorizedcategories' ],
+ [ UncategorizedPagesPage::class, 'Uncategorizedpages' ],
+ [ UncategorizedImagesPage::class, 'Uncategorizedimages' ],
+ [ UncategorizedTemplatesPage::class, 'Uncategorizedtemplates' ],
+ [ UnusedCategoriesPage::class, 'Unusedcategories' ],
+ [ UnusedimagesPage::class, 'Unusedimages' ],
+ [ WantedCategoriesPage::class, 'Wantedcategories' ],
+ [ WantedFilesPage::class, 'Wantedfiles' ],
+ [ WantedPagesPage::class, 'Wantedpages' ],
+ [ WantedTemplatesPage::class, 'Wantedtemplates' ],
+ [ UnwatchedpagesPage::class, 'Unwatchedpages' ],
+ [ UnusedtemplatesPage::class, 'Unusedtemplates' ],
+ [ WithoutInterwikiPage::class, 'Withoutinterwiki' ],
];
Hooks::run( 'wgQueryPages', [ &$qp ] );
}
*/
private static $coreList = [
// Maintenance Reports
- 'BrokenRedirects' => 'BrokenRedirectsPage',
- 'Deadendpages' => 'DeadendPagesPage',
- 'DoubleRedirects' => 'DoubleRedirectsPage',
- 'Longpages' => 'LongPagesPage',
- 'Ancientpages' => 'AncientPagesPage',
- 'Lonelypages' => 'LonelyPagesPage',
- 'Fewestrevisions' => 'FewestrevisionsPage',
- 'Withoutinterwiki' => 'WithoutInterwikiPage',
- 'Protectedpages' => 'SpecialProtectedpages',
- 'Protectedtitles' => 'SpecialProtectedtitles',
- 'Shortpages' => 'ShortPagesPage',
- 'Uncategorizedcategories' => 'UncategorizedCategoriesPage',
- 'Uncategorizedimages' => 'UncategorizedImagesPage',
- 'Uncategorizedpages' => 'UncategorizedPagesPage',
- 'Uncategorizedtemplates' => 'UncategorizedTemplatesPage',
- 'Unusedcategories' => 'UnusedCategoriesPage',
- 'Unusedimages' => 'UnusedimagesPage',
- 'Unusedtemplates' => 'UnusedtemplatesPage',
- 'Unwatchedpages' => 'UnwatchedpagesPage',
- 'Wantedcategories' => 'WantedCategoriesPage',
- 'Wantedfiles' => 'WantedFilesPage',
- 'Wantedpages' => 'WantedPagesPage',
- 'Wantedtemplates' => 'WantedTemplatesPage',
+ 'BrokenRedirects' => BrokenRedirectsPage::class,
+ 'Deadendpages' => DeadendPagesPage::class,
+ 'DoubleRedirects' => DoubleRedirectsPage::class,
+ 'Longpages' => LongPagesPage::class,
+ 'Ancientpages' => AncientPagesPage::class,
+ 'Lonelypages' => LonelyPagesPage::class,
+ 'Fewestrevisions' => FewestrevisionsPage::class,
+ 'Withoutinterwiki' => WithoutInterwikiPage::class,
+ 'Protectedpages' => SpecialProtectedpages::class,
+ 'Protectedtitles' => SpecialProtectedtitles::class,
+ 'Shortpages' => ShortPagesPage::class,
+ 'Uncategorizedcategories' => UncategorizedCategoriesPage::class,
+ 'Uncategorizedimages' => UncategorizedImagesPage::class,
+ 'Uncategorizedpages' => UncategorizedPagesPage::class,
+ 'Uncategorizedtemplates' => UncategorizedTemplatesPage::class,
+ 'Unusedcategories' => UnusedCategoriesPage::class,
+ 'Unusedimages' => UnusedimagesPage::class,
+ 'Unusedtemplates' => UnusedtemplatesPage::class,
+ 'Unwatchedpages' => UnwatchedpagesPage::class,
+ 'Wantedcategories' => WantedCategoriesPage::class,
+ 'Wantedfiles' => WantedFilesPage::class,
+ 'Wantedpages' => WantedPagesPage::class,
+ 'Wantedtemplates' => WantedTemplatesPage::class,
// List of pages
- 'Allpages' => 'SpecialAllPages',
- 'Prefixindex' => 'SpecialPrefixindex',
- 'Categories' => 'SpecialCategories',
- 'Listredirects' => 'ListredirectsPage',
- 'PagesWithProp' => 'SpecialPagesWithProp',
- 'TrackingCategories' => 'SpecialTrackingCategories',
+ 'Allpages' => SpecialAllPages::class,
+ 'Prefixindex' => SpecialPrefixindex::class,
+ 'Categories' => SpecialCategories::class,
+ 'Listredirects' => ListredirectsPage::class,
+ 'PagesWithProp' => SpecialPagesWithProp::class,
+ 'TrackingCategories' => SpecialTrackingCategories::class,
// Authentication
- 'Userlogin' => 'SpecialUserLogin',
- 'Userlogout' => 'SpecialUserLogout',
- 'CreateAccount' => 'SpecialCreateAccount',
- 'LinkAccounts' => 'SpecialLinkAccounts',
- 'UnlinkAccounts' => 'SpecialUnlinkAccounts',
- 'ChangeCredentials' => 'SpecialChangeCredentials',
- 'RemoveCredentials' => 'SpecialRemoveCredentials',
+ 'Userlogin' => SpecialUserLogin::class,
+ 'Userlogout' => SpecialUserLogout::class,
+ 'CreateAccount' => SpecialCreateAccount::class,
+ 'LinkAccounts' => SpecialLinkAccounts::class,
+ 'UnlinkAccounts' => SpecialUnlinkAccounts::class,
+ 'ChangeCredentials' => SpecialChangeCredentials::class,
+ 'RemoveCredentials' => SpecialRemoveCredentials::class,
// Users and rights
- 'Activeusers' => 'SpecialActiveUsers',
- 'Block' => 'SpecialBlock',
- 'Unblock' => 'SpecialUnblock',
- 'BlockList' => 'SpecialBlockList',
- 'AutoblockList' => 'SpecialAutoblockList',
- 'ChangePassword' => 'SpecialChangePassword',
- 'BotPasswords' => 'SpecialBotPasswords',
- 'PasswordReset' => 'SpecialPasswordReset',
- 'DeletedContributions' => 'DeletedContributionsPage',
- 'Preferences' => 'SpecialPreferences',
- 'ResetTokens' => 'SpecialResetTokens',
- 'Contributions' => 'SpecialContributions',
- 'Listgrouprights' => 'SpecialListGroupRights',
- 'Listgrants' => 'SpecialListGrants',
- 'Listusers' => 'SpecialListUsers',
- 'Listadmins' => 'SpecialListAdmins',
- 'Listbots' => 'SpecialListBots',
- 'Userrights' => 'UserrightsPage',
- 'EditWatchlist' => 'SpecialEditWatchlist',
+ 'Activeusers' => SpecialActiveUsers::class,
+ 'Block' => SpecialBlock::class,
+ 'Unblock' => SpecialUnblock::class,
+ 'BlockList' => SpecialBlockList::class,
+ 'AutoblockList' => SpecialAutoblockList::class,
+ 'ChangePassword' => SpecialChangePassword::class,
+ 'BotPasswords' => SpecialBotPasswords::class,
+ 'PasswordReset' => SpecialPasswordReset::class,
+ 'DeletedContributions' => DeletedContributionsPage::class,
+ 'Preferences' => SpecialPreferences::class,
+ 'ResetTokens' => SpecialResetTokens::class,
+ 'Contributions' => SpecialContributions::class,
+ 'Listgrouprights' => SpecialListGroupRights::class,
+ 'Listgrants' => SpecialListGrants::class,
+ 'Listusers' => SpecialListUsers::class,
+ 'Listadmins' => SpecialListAdmins::class,
+ 'Listbots' => SpecialListBots::class,
+ 'Userrights' => UserrightsPage::class,
+ 'EditWatchlist' => SpecialEditWatchlist::class,
// Recent changes and logs
- 'Newimages' => 'SpecialNewFiles',
- 'Log' => 'SpecialLog',
- 'Watchlist' => 'SpecialWatchlist',
- 'Newpages' => 'SpecialNewpages',
- 'Recentchanges' => 'SpecialRecentChanges',
- 'Recentchangeslinked' => 'SpecialRecentChangesLinked',
- 'Tags' => 'SpecialTags',
+ 'Newimages' => SpecialNewFiles::class,
+ 'Log' => SpecialLog::class,
+ 'Watchlist' => SpecialWatchlist::class,
+ 'Newpages' => SpecialNewpages::class,
+ 'Recentchanges' => SpecialRecentChanges::class,
+ 'Recentchangeslinked' => SpecialRecentChangesLinked::class,
+ 'Tags' => SpecialTags::class,
// Media reports and uploads
- 'Listfiles' => 'SpecialListFiles',
- 'Filepath' => 'SpecialFilepath',
- 'MediaStatistics' => 'MediaStatisticsPage',
- 'MIMEsearch' => 'MIMEsearchPage',
- 'FileDuplicateSearch' => 'FileDuplicateSearchPage',
- 'Upload' => 'SpecialUpload',
- 'UploadStash' => 'SpecialUploadStash',
- 'ListDuplicatedFiles' => 'ListDuplicatedFilesPage',
+ 'Listfiles' => SpecialListFiles::class,
+ 'Filepath' => SpecialFilepath::class,
+ 'MediaStatistics' => MediaStatisticsPage::class,
+ 'MIMEsearch' => MIMEsearchPage::class,
+ 'FileDuplicateSearch' => FileDuplicateSearchPage::class,
+ 'Upload' => SpecialUpload::class,
+ 'UploadStash' => SpecialUploadStash::class,
+ 'ListDuplicatedFiles' => ListDuplicatedFilesPage::class,
// Data and tools
- 'ApiSandbox' => 'SpecialApiSandbox',
- 'Statistics' => 'SpecialStatistics',
- 'Allmessages' => 'SpecialAllMessages',
- 'Version' => 'SpecialVersion',
- 'Lockdb' => 'SpecialLockdb',
- 'Unlockdb' => 'SpecialUnlockdb',
+ 'ApiSandbox' => SpecialApiSandbox::class,
+ 'Statistics' => SpecialStatistics::class,
+ 'Allmessages' => SpecialAllMessages::class,
+ 'Version' => SpecialVersion::class,
+ 'Lockdb' => SpecialLockdb::class,
+ 'Unlockdb' => SpecialUnlockdb::class,
// Redirecting special pages
- 'LinkSearch' => 'LinkSearchPage',
- 'Randompage' => 'RandomPage',
- 'RandomInCategory' => 'SpecialRandomInCategory',
- 'Randomredirect' => 'SpecialRandomredirect',
- 'Randomrootpage' => 'SpecialRandomrootpage',
- 'GoToInterwiki' => 'SpecialGoToInterwiki',
+ 'LinkSearch' => LinkSearchPage::class,
+ 'Randompage' => RandomPage::class,
+ 'RandomInCategory' => SpecialRandomInCategory::class,
+ 'Randomredirect' => SpecialRandomredirect::class,
+ 'Randomrootpage' => SpecialRandomrootpage::class,
+ 'GoToInterwiki' => SpecialGoToInterwiki::class,
// High use pages
- 'Mostlinkedcategories' => 'MostlinkedCategoriesPage',
- 'Mostimages' => 'MostimagesPage',
- 'Mostinterwikis' => 'MostinterwikisPage',
- 'Mostlinked' => 'MostlinkedPage',
- 'Mostlinkedtemplates' => 'MostlinkedTemplatesPage',
- 'Mostcategories' => 'MostcategoriesPage',
- 'Mostrevisions' => 'MostrevisionsPage',
+ 'Mostlinkedcategories' => MostlinkedCategoriesPage::class,
+ 'Mostimages' => MostimagesPage::class,
+ 'Mostinterwikis' => MostinterwikisPage::class,
+ 'Mostlinked' => MostlinkedPage::class,
+ 'Mostlinkedtemplates' => MostlinkedTemplatesPage::class,
+ 'Mostcategories' => MostcategoriesPage::class,
+ 'Mostrevisions' => MostrevisionsPage::class,
// Page tools
- 'ComparePages' => 'SpecialComparePages',
- 'Export' => 'SpecialExport',
- 'Import' => 'SpecialImport',
- 'Undelete' => 'SpecialUndelete',
- 'Whatlinkshere' => 'SpecialWhatLinksHere',
- 'MergeHistory' => 'SpecialMergeHistory',
- 'ExpandTemplates' => 'SpecialExpandTemplates',
+ 'ComparePages' => SpecialComparePages::class,
+ 'Export' => SpecialExport::class,
+ 'Import' => SpecialImport::class,
+ 'Undelete' => SpecialUndelete::class,
+ 'Whatlinkshere' => SpecialWhatLinksHere::class,
+ 'MergeHistory' => SpecialMergeHistory::class,
+ 'ExpandTemplates' => SpecialExpandTemplates::class,
// Other
- 'Booksources' => 'SpecialBookSources',
+ 'Booksources' => SpecialBookSources::class,
// Unlisted / redirects
- 'ApiHelp' => 'SpecialApiHelp',
- 'Blankpage' => 'SpecialBlankpage',
- 'Diff' => 'SpecialDiff',
- 'EditTags' => 'SpecialEditTags',
- 'Emailuser' => 'SpecialEmailUser',
- 'Movepage' => 'MovePageForm',
- 'Mycontributions' => 'SpecialMycontributions',
- 'MyLanguage' => 'SpecialMyLanguage',
- 'Mypage' => 'SpecialMypage',
- 'Mytalk' => 'SpecialMytalk',
- 'Myuploads' => 'SpecialMyuploads',
- 'AllMyUploads' => 'SpecialAllMyUploads',
- 'PermanentLink' => 'SpecialPermanentLink',
- 'Redirect' => 'SpecialRedirect',
- 'Revisiondelete' => 'SpecialRevisionDelete',
- 'RunJobs' => 'SpecialRunJobs',
- 'Specialpages' => 'SpecialSpecialpages',
- 'PageData' => 'SpecialPageData'
+ 'ApiHelp' => SpecialApiHelp::class,
+ 'Blankpage' => SpecialBlankpage::class,
+ 'Diff' => SpecialDiff::class,
+ 'EditTags' => SpecialEditTags::class,
+ 'Emailuser' => SpecialEmailUser::class,
+ 'Movepage' => MovePageForm::class,
+ 'Mycontributions' => SpecialMycontributions::class,
+ 'MyLanguage' => SpecialMyLanguage::class,
+ 'Mypage' => SpecialMypage::class,
+ 'Mytalk' => SpecialMytalk::class,
+ 'Myuploads' => SpecialMyuploads::class,
+ 'AllMyUploads' => SpecialAllMyUploads::class,
+ 'PermanentLink' => SpecialPermanentLink::class,
+ 'Redirect' => SpecialRedirect::class,
+ 'Revisiondelete' => SpecialRevisionDelete::class,
+ 'RunJobs' => SpecialRunJobs::class,
+ 'Specialpages' => SpecialSpecialpages::class,
+ 'PageData' => SpecialPageData::class,
];
private static $list;
self::$list = self::$coreList;
if ( !$wgDisableInternalSearch ) {
- self::$list['Search'] = 'SpecialSearch';
+ self::$list['Search'] = SpecialSearch::class;
}
if ( $wgEmailAuthentication ) {
- self::$list['Confirmemail'] = 'EmailConfirmation';
- self::$list['Invalidateemail'] = 'EmailInvalidation';
+ self::$list['Confirmemail'] = EmailConfirmation::class;
+ self::$list['Invalidateemail'] = EmailInvalidation::class;
}
if ( $wgEnableEmail ) {
- self::$list['ChangeEmail'] = 'SpecialChangeEmail';
+ self::$list['ChangeEmail'] = SpecialChangeEmail::class;
}
if ( $wgEnableJavaScriptTest ) {
- self::$list['JavaScriptTest'] = 'SpecialJavaScriptTest';
+ self::$list['JavaScriptTest'] = SpecialJavaScriptTest::class;
}
if ( $wgPageLanguageUseDB ) {
- self::$list['PageLanguage'] = 'SpecialPageLanguage';
+ self::$list['PageLanguage'] = SpecialPageLanguage::class;
}
if ( $wgContentHandlerUseDB ) {
- self::$list['ChangeContentModel'] = 'SpecialChangeContentModel';
+ self::$list['ChangeContentModel'] = SpecialChangeContentModel::class;
}
// Add extension special pages
];
$fields['restrictions'] = [
- 'class' => 'HTMLRestrictionsField',
+ 'class' => HTMLRestrictionsField::class,
'required' => true,
'default' => $this->botPassword->getRestrictions(),
];
],
'diff' => [
'name' => 'diff',
- 'class' => 'HTMLTextField',
+ 'class' => HTMLTextField::class,
'label-message' => 'diff-form-revid',
],
], $this->getContext(), 'diff-form' );
// checkTitle can filter some options out, avoid empty sections
if ( count( $options ) > 0 ) {
$fields['TitlesNs' . $namespace] = [
- 'class' => 'EditWatchlistCheckboxSeriesField',
+ 'class' => EditWatchlistCheckboxSeriesField::class,
'options' => $options,
'section' => "ns$namespace",
];
'size' => 60,
'default' => $title,
'autofocus' => true,
- 'cssclass' => 'mw-ui-input-inline',
],
'input' => [
'type' => 'textarea',
$formDescriptor += [
'textarea' => [
- 'class' => 'HTMLTextAreaField',
+ 'class' => HTMLTextAreaField::class,
'name' => 'pages',
'label-message' => 'export-manual',
'nodata' => true,
) {
$formDescriptor = [
'namespace' => [
- 'class' => 'HTMLSelectNamespace',
+ 'class' => HTMLSelectNamespace::class,
'name' => 'namespace',
'id' => 'namespace',
'cssclass' => 'namespaceselector',
'id' => 'noredirect',
],
'sizelimit' => [
- 'class' => 'HTMLSizeFilterField',
+ 'class' => HTMLSizeFilterField::class,
'name' => 'size',
]
];
$out = $context->getOutput();
$tag = $data['HiddenTag'];
- $status = call_user_func( [ 'ChangeTags', "{$form->tagAction}TagWithChecks" ],
+ $status = call_user_func( [ ChangeTags::class, "{$form->tagAction}TagWithChecks" ],
$tag, $data['Reason'], $context->getUser(), true );
if ( $status->isGood() ) {
} else {
$expiryHtml = $this->msg( 'userrights-expiry-none' )->text();
}
+ // T171345: Add a hidden form element so that other groups can still be manipulated,
+ // otherwise saving errors out with an invalid expiry time for this group.
+ $expiryHtml .= Html::Hidden( "wpExpiry-$group",
+ $currentExpiry ? 'existing' : 'infinite' );
$expiryHtml .= "<br />\n";
} else {
$expiryHtml = Xml::element( 'span', null,
}
$descriptor['UploadFile'] = [
- 'class' => 'UploadSourceField',
+ 'class' => UploadSourceField::class,
'section' => 'source',
'type' => 'file',
'id' => 'wpUploadFile',
if ( $canUploadByUrl ) {
$this->mMaxUploadSize['url'] = UploadBase::getMaxUploadSize( 'url' );
$descriptor['UploadFileURL'] = [
- 'class' => 'UploadSourceField',
+ 'class' => UploadSourceField::class,
'section' => 'source',
'id' => 'wpUploadFileURL',
'radio-id' => 'wpSourceTypeurl',
} else {
$descriptor['License'] = [
'type' => 'select',
- 'class' => 'Licenses',
+ 'class' => Licenses::class,
'section' => 'description',
'id' => 'wpLicense',
'label-message' => 'license',
$formDescriptor = [
'user' => [
- 'class' => 'HTMLUserTextField',
+ 'class' => HTMLUserTextField::class,
'label' => $this->msg( 'listusersfrom' )->text(),
'name' => 'username',
'default' => $this->requestedUser,
'label' => $this->msg( 'group' )->text(),
'name' => 'group',
'default' => $this->requestedGroup,
- 'class' => 'HTMLSelectField',
+ 'class' => HTMLSelectField::class,
'options' => $groupOptions,
],
'editsOnly' => [
'default' => $this->mDefaultDirection
],
'limithiddenfield' => [
- 'class' => 'HTMLHiddenField',
+ 'class' => HTMLHiddenField::class,
'name' => 'limit',
'default' => $this->mLimit
]
if ( $beforeSubmitButtonHookOut !== '' ) {
$formDescriptior[ 'beforeSubmitButtonHookOut' ] = [
- 'class' => 'HTMLInfoField',
+ 'class' => HTMLInfoField::class,
'raw' => true,
'default' => $beforeSubmitButtonHookOut
];
}
$formDescriptor[ 'submit' ] = [
- 'class' => 'HTMLSubmitField',
+ 'class' => HTMLSubmitField::class,
'buttonlabel-message' => 'listusers-submit',
];
if ( $beforeClosingFieldsetHookOut !== '' ) {
$formDescriptior[ 'beforeClosingFieldsetHookOut' ] = [
- 'class' => 'HTMLInfoField',
+ 'class' => HTMLInfoField::class,
'raw' => true,
'default' => $beforeClosingFieldsetHookOut
];
$multiselectOptions = [];
foreach ( $prefs as $name => $info ) {
if ( ( isset( $info['type'] ) && $info['type'] == 'multiselect' ) ||
- ( isset( $info['class'] ) && $info['class'] == 'HTMLMultiSelectField' ) ) {
+ ( isset( $info['class'] ) && $info['class'] == HTMLMultiSelectField::class ) ) {
$opts = HTMLFormField::flattenOptions( $info['options'] );
$prefix = isset( $info['prefix'] ) ? $info['prefix'] : $name;
$checkmatrixOptions = [];
foreach ( $prefs as $name => $info ) {
if ( ( isset( $info['type'] ) && $info['type'] == 'checkmatrix' ) ||
- ( isset( $info['class'] ) && $info['class'] == 'HTMLCheckMatrix' ) ) {
+ ( isset( $info['class'] ) && $info['class'] == HTMLCheckMatrix::class ) ) {
$columns = HTMLFormField::flattenOptions( $info['columns'] );
$rows = HTMLFormField::flattenOptions( $info['rows'] );
$prefix = isset( $info['prefix'] ) ? $info['prefix'] : $name;
$this->cache = $cache;
$this->readOnlyMode = $readOnlyMode;
$this->stats = new NullStatsdDataFactory();
- $this->deferredUpdatesAddCallableUpdateCallback = [ 'DeferredUpdates', 'addCallableUpdate' ];
- $this->revisionGetTimestampFromIdCallback = [ 'Revision', 'getTimestampFromId' ];
+ $this->deferredUpdatesAddCallableUpdateCallback = [ DeferredUpdates::class, 'addCallableUpdate' ];
+ $this->revisionGetTimestampFromIdCallback = [ Revision::class, 'getTimestampFromId' ];
}
/**
"filereadonlyerror": "Nun pudo camudase'l ficheru «$1» porque l'estoyu de ficheros «$2» ta en mou de sólo llectura.\n\nL'alministrador del sistema que lu bloquió dio esti motivu: «$3».",
"invalidtitle-knownnamespace": "Títulu inválidu col espaciu de nomes «$2» ya'l testu «$3»",
"invalidtitle-unknownnamespace": "Títulu inválidu col númberu $1 d'espaciu de nomes desconocíu ya'l testu «$2»",
- "exception-nologin": "Nun anició sesión",
+ "exception-nologin": "Nun aniciasti sesión",
"exception-nologin-text": "Por favor, anicia sesión pa tener accesu a esta páxina o aición.",
"exception-nologin-text-manual": "Por favor, $1 pa tener accesu a esta páxina o aición.",
"virus-badscanner": "Fallu de configuración: Escáner de virus desconocíu: ''$1''",
"nav-login-createaccount": "Entrar / crear cuenta",
"logout": "Salir",
"userlogout": "Salir",
- "notloggedin": "Nun anició sesión",
+ "notloggedin": "Nun aniciasti sesión",
"userlogin-noaccount": "¿Nun tien una cuenta?",
"userlogin-joinproject": "Xunise a {{SITENAME}}",
"createaccount": "Crear una cuenta",
"postedit-confirmation-created": "Creóse la páxina.",
"postedit-confirmation-restored": "Restauróse la páxina.",
"postedit-confirmation-saved": "Guardóse la edición.",
+ "postedit-confirmation-published": "Publicóse la to edición.",
"edit-already-exists": "Nun pudo crease una páxina nueva.\nEsta yá esiste.",
"defaultmessagetext": "Testu predetermináu",
"content-failed-to-parse": "Fallu al analizar el conteníu $2 pal modelu $1: $3",
"rcfilters-activefilters": "Filtros activos",
"rcfilters-advancedfilters": "Filtros avanzaos",
"rcfilters-limit-title": "Resultancies qu'amosar",
- "rcfilters-limit-and-date-label": "{{PLURAL:$1|cambiu|$1 cambios}}, $2",
+ "rcfilters-limit-and-date-label": "$1 {{PLURAL:$1|cambiu|$1 cambios}}, $2",
"rcfilters-date-popup-title": "Periodu de tiempu a buscar",
"rcfilters-days-title": "Últimos díes",
"rcfilters-hours-title": "Últimes hores",
"reuploaddesc": "Encaboxar la xubida y tornar al formulariu de xubíes",
"upload-tryagain": "Unviar descripción camudada del ficheru",
"upload-tryagain-nostash": "Unviar el ficheru vueltu a xubir y la descripción cambiada",
- "uploadnologin": "Nun anició sesión",
+ "uploadnologin": "Nun aniciasti sesión",
"uploadnologintext": "Tien d'$1 pa xubir ficheros.",
"upload_directory_missing": "El direutoriu de xubida ($1) nun esiste y nun pudo crease pol sirvidor web.",
"upload_directory_read_only": "El sirvidor web nun pue escribir nel direutoriu de xubíes ($1).",
"uploadwarning-text": "Por favor, camuda más abaxo la descripción del ficheru y vuelve a tentalo.",
"uploadwarning-text-nostash": "Vuelve a unviar el ficheru, cambia la descripción más abaxo y tenta otra vuelta.",
"savefile": "Guardar ficheru",
- "uploaddisabled": "Deshabilitaes les xubíes",
+ "uploaddisabled": "Desactivaes les xubíes.",
"copyuploaddisabled": "Xubir por URL ta desactivao.",
"uploaddisabledtext": "Les xubíes de ficheros tán desactivaes.",
"php-uploaddisabledtext": "Les xubíes de ficheros tan desactivaes en PHP.\nPor favor, comprueba la configuración de file_uploads.",
"lockmanager-fail-closelock": "Nun se pudo zarrar el ficheru de bloquéu pa \"$1\".",
"lockmanager-fail-deletelock": "Non se pudo desaniciar el ficheru de bloquéu pa \"$1\".",
"lockmanager-fail-acquirelock": "Nun se pudo adquirir el bloquéu pa \"$1\".",
- "lockmanager-fail-openlock": "Nun se pudo abrir el ficheru de bloquéu pa \"$1\".",
+ "lockmanager-fail-openlock": "Nun se pudo abrir el ficheru de bloquéu pa \"$1\". Por favor comprueba que'l direutoriu de xubíes ta configuráu correutamente y que'l to sirvidor web tien permisos d'escritura nesi direutoriu. Ver https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgUploadDirectory pa más información.",
"lockmanager-fail-releaselock": "Nun se pudo lliberar el bloquéu pa \"$1\".",
"lockmanager-fail-db-bucket": "Nun se pudo contautar con bloqueos de bases de datos bastantes nel conxuntu $1.",
"lockmanager-fail-db-release": "Nun se pudieron lliberar los bloqueos na base de datos $1.",
"doubleredirects": "Redireiciones dobles",
"doubleredirectstext": "Esta páxina llista páxines que redireicionen a otres páxines de redireición.\nCada filera contien enllaces a la primera y segunda redireición, asina como al oxetivu de la segunda redireición, que de vezu ye la páxina oxetivu \"real\", onde tendría d'empobinar la primera redireición.\nLes entraes <del>tachaes</del> tan resueltes.",
"double-redirect-fixed-move": "[[$1]] treslladóse.\nAnovóse automáticamente y agora redirixe haza [[$2]].",
- "double-redirect-fixed-maintenance": "Iguando automáticamente la doble redireición de [[$1]] a [[$2]] nuna xera de mantenimientu.",
+ "double-redirect-fixed-maintenance": "Iguando automáticamente la doble redireición de [[$1]] a [[$2]] nuna xera de mantenimientu",
"double-redirect-fixer": "Iguador de redireiciones",
"brokenredirects": "Redireiciones frañaes",
"brokenredirectstext": "Les redireiciones siguientes enllacien a páxines que nun esisten:",
"undelete-error": "Error al restaurar la páxina",
"undelete-error-short": "Error al restaurar l'archivu: $1",
"undelete-error-long": "Atopáronse errores al restaurar l'archivu:\n\n$1",
- "undelete-show-file-confirm": "¿Tas seguru de que quies ver una versión desaniciada del ficheru \"<nowiki>$1</nowiki>\" del $2 a les $3?",
+ "undelete-show-file-confirm": "¿Tas seguru de que quies ver la versión desaniciada del ficheru «<nowiki>$1</nowiki>» del $2 a les $3?",
"undelete-show-file-submit": "Sí",
"namespace": "Espaciu de nomes:",
"invert": "Invertir seleición",
"month": "Dende'l mes (y anteriores):",
"year": "Dende l'añu (y anteriores):",
"sp-contributions-newbies": "Amosar namái les contribuciones de cuentes nueves",
- "sp-contributions-newbies-sub": "Namái les cuentes nueves",
+ "sp-contributions-newbies-sub": "Pa cuentes nueves",
"sp-contributions-newbies-title": "Contribuciones d'usuariu pa cuentes nueves",
"sp-contributions-blocklog": "rexistru de bloqueos",
"sp-contributions-suppresslog": "collaboraciones {{GENDER:$1|del usuariu|de la usuaria}} suprimíes",
"whatlinkshere-page": "Páxina:",
"linkshere": "Les páxines siguientes enllacien a '''[[:$1]]''':",
"nolinkshere": "Nenguna páxina enllaza a '''[[:$1]]'''.",
- "nolinkshere-ns": "Nenguna páxina enllaza a '''[[:$1]]''' nel espaciu de nome conseñáu.",
+ "nolinkshere-ns": "Nenguna páxina enllaza con <strong>[[:$1]]</strong> nel espaciu de nomes escoyíu.",
"isredirect": "páxina de redireición",
"istemplate": "tresclusión",
"isimage": "enllaz al ficheru",
"whatlinkshere-hideredirs": "$1 les redireiciones",
"whatlinkshere-hidetrans": "$1 les tresclusiones",
"whatlinkshere-hidelinks": "$1 los enllaces",
- "whatlinkshere-hideimages": "$1 los enllaces al ficheru",
+ "whatlinkshere-hideimages": "$1 enllaces a ficheros",
"whatlinkshere-filters": "Peñeres",
"whatlinkshere-submit": "Dir",
"autoblockid": "Autobloquiar #$1",
"ipbreason": "Motivu:",
"ipbreason-dropdown": "*Motivos comunes de bloquéu\n** Enxertamientu d'información falso\n** Dexar les páxines en blanco\n** Enllaces spam a páxines esternes\n** Enxertamientu de babayaes/enguedeyos nes páxines\n** Comportamientu intimidatoriu o d'acosu\n** Abusu de cuentes múltiples\n** Nome d'usuariu inaceutable",
"ipb-hardblock": "Torgar que los usuarios coneutaos editen dende esta direición IP",
- "ipbcreateaccount": "Evitar creación de cuentes",
+ "ipbcreateaccount": "Torgar la creación de cuentes",
"ipbemailban": "Torgar al usuariu l'unviu de corréu electrónicu",
"ipbenableautoblock": "Bloquiar automáticamente la cabera direición IP usada por esti usuariu y toles IP posteriores dende les qu'intente editar",
"ipbsubmit": "Bloquiar esti usuariu",
"ipb-disableusertalk": "Torgar qu'esti usuariu edite la so páxina d'alderique mentanto tea bloquiáu",
"ipb-change-block": "Volver a bloquiar l'usuariu con estos parámetros",
"ipb-confirm": "Confirmar bloquéu",
- "badipaddress": "IP non válida",
+ "badipaddress": "Dirección IP inválida",
"blockipsuccesssub": "Bloquéu fechu correctamente",
"blockipsuccesstext": "[[Special:Contributions/$1|$1]] ta {{GENDER:$1|bloquiáu|bloquiada}}.<br />\nMira na [[Special:BlockList|llista de bloqueos]] pa revisar los bloqueos.",
"ipb-blockingself": "¡Tas a piques de bloquiate tú mesmu! ¿Tas seguru de que quies facer eso?",
"expiringblock": "caduca'l $1 a les $2",
"anononlyblock": "namái anón.",
"noautoblockblock": "bloquéu automáticu desactiváu",
- "createaccountblock": "bloquiada la creación de cuentes",
+ "createaccountblock": "creación de cuentes desactivada",
"emailblock": "corréu electrónicu desactiváu",
- "blocklist-nousertalk": "nun pue editar la so páxina d'alderique",
+ "blocklist-nousertalk": "nun puede editar la páxina d'alderique propia",
"ipblocklist-empty": "La llista de bloqueos ta vacia.",
"ipblocklist-no-results": "La direición IP o nome d'usuariu solicitáu nun ta bloquiáu.",
"blocklink": "bloquiar",
"blocklogentry": "bloquió [[$1]] con una caducidá de $2 $3",
"reblock-logentry": "camudó los parámetros de bloquéu de [[$1]] con una caducidá de $2 $3",
"blocklogtext": "Esti ye un rexistru de los bloqueos y desbloqueos d'usuarios.\nLes direcciones IP bloquiaes automáticamente nun salen equí.\nPa ver los bloqueos qu'hai agora mesmo, mira na [[Special:BlockList|llista de bloqueos]].",
- "unblocklogentry": "desbloquió $1",
+ "unblocklogentry": "desbloquió a $1",
"block-log-flags-anononly": "namái usuarios anónimos",
"block-log-flags-nocreate": "creación de cuentes desactivada",
- "block-log-flags-noautoblock": "bloquéu automáticu deshabilitáu",
+ "block-log-flags-noautoblock": "bloquéu automáticu desactiváu",
"block-log-flags-noemail": "corréu electrónicu desactiváu",
- "block-log-flags-nousertalk": "nun pue editar la páxina d'alderique propia",
+ "block-log-flags-nousertalk": "nun puede editar la páxina d'alderique propia",
"block-log-flags-angry-autoblock": "autobloquéu ameyoráu activáu",
"block-log-flags-hiddenname": "nome d'usuariu anubríu",
"range_block_disabled": "La capacidá d'alministrador pa crear bloqueos d'intervalos ta desactivada.",
- "ipb_expiry_invalid": "Tiempu incorrectu.",
+ "ipb_expiry_invalid": "El tiempu de caducidá nun ye válidu.",
"ipb_expiry_old": "La fecha de caducidá ta pasada.",
- "ipb_expiry_temp": "Los bloqueos de nome d'usuariu escondíos han ser permanentes.",
+ "ipb_expiry_temp": "Los bloqueos a nomes d'usuariu tapecíos tienen de ser permanentes.",
"ipb_hide_invalid": "Nun se pue desaniciar esta cuenta; tien más {{PLURAL:$1|d'una edición|de $1 ediciones}}.",
"ipb_already_blocked": "\"$1\" yá ta bloquiáu",
"ipb-needreblock": "$1 yá ta bloquiáu. ¿Quies camudar los parámetros?",
"ipb-otherblocks-header": "{{PLURAL:$1|Otru bloquéu|Otros bloqueos}}",
"unblock-hideuser": "Nun pues desbloquiar esti usuariu, porque tien el nome d'usuariu anubríu.",
"ipb_cant_unblock": "Error: Nun s'atopó'l bloquéu númberu $1. Seique yá fuera desbloquiáu.",
- "ipb_blocked_as_range": "Error: La IP $1 nun ta bloquiada direutamente, polo que nun pue ser desloquiada. Sicasí, foi bloquiada como parte del intervalu $2, que pue ser desbloquiáu.",
- "ip_range_invalid": "Rangu IP non válidu.",
+ "ipb_blocked_as_range": "Error: La IP $1 nun ta bloquiada direutamente y nun puede desbloquiase.\nSicasí, bloquióse como parte del intervalu $2, que puede desbloquiase.",
+ "ip_range_invalid": "Intervalu de direiciones IP non válidu.",
"ip_range_toolarge": "Nun se permiten bloqueos mayores de /$1.",
"ip_range_exceeded": "El rangu d'IP pasa del máximu. Rangu permitíu: /$1.",
"ip_range_toolow": "Nun se permitieron efeutivamente los rangos d'IP.",
"proxyblocker": "Bloquiador de proxys",
- "proxyblockreason": "La to direición IP foi bloquiada porque ye un proxy abiertu. Por favor contauta col to proveedor de serviciones d'Internet o col to servicio d'asistencia téunica y infórmalos d'esti seriu problema de seguridá.",
+ "proxyblockreason": "La to direición IP bloquióse porque ye un proxy abiertu.\nComunícate col to proveedor de serviciu d'Internet o col serviciu d'asistencia téunica de la to organización pa informa-yos d'esti grave problema de seguridá.",
"sorbsreason": "La to direición IP sal na llista de proxys abiertos en DNSBL usada por {{SITENAME}}.",
- "sorbs_create_account_reason": "La to direición IP sal na llista de proxys abiertos en DNSBL usada por {{SITENAME}}. Nun pues crear una cuenta",
+ "sorbs_create_account_reason": "La to direición IP sal na llista de proxys abiertos en DNSBL usada por {{SITENAME}}.\nNun puedes crear una cuenta",
"softblockrangesreason": "Nun se permiten les contribuciones anónimes dende la to dirección IP ($1). Por favor, anicia sesión.",
"xffblockreason": "Una direición IP presente na testera X-Forwarded-For, o suya o d'un sirvidor proxy que ta usando, ta bloquiada. El motivu orixinal del bloquéu foi: $1",
"cant-see-hidden-user": "L'usuariu que tentes bloquiar yá ta bloquiáu y anubríu.\nComo nun tienes permisos p'anubrir usuarios, nun pues ver o editar el bloquéu del usuariu.",
"ipbblocked": "Nun pues bloquiar o desbloquiar a otros usuarios, porque tas bloquiáu tu mesmu",
"ipbnounblockself": "Nun tienes permisu pa desbloquiate tu mesmu",
- "lockdb": "Protexer la base de datos",
- "unlockdb": "Desprotexer la base de datos",
+ "lockdb": "Bloquiar la base de datos",
+ "unlockdb": "Desbloquiar la base de datos",
"lockdbtext": "Al bloquiar la base de datos suspenderáse la capacidá de tolos usuarios pa editar páxines, camudar les sos preferencies, editar les llistes de siguimientu y otres aiciones que requieran cambios na base de datos. Por favor confirma que ye lo que quies facer, y que desbloquiarás la base de datos cuando fines col mantenimientu.",
"unlockdbtext": "Al desbloquiar la base de datos restauraráse la capacidá de tolos usuarios pa editar páxines, camudar les sos preferencies, editar les sos llistes de siguimientu y otres aiciones que requieren cambios na base de datos. Por favor confirma que ye lo quies facer.",
- "lockconfirm": "Si, quiero candar daveres la base de datos.",
- "unlockconfirm": "Sí, quiero descandar daveres la base de datos.",
- "lockbtn": "Protexer la base de datos",
- "unlockbtn": "Desprotexer la base de datos",
- "locknoconfirm": "Nun activasti la caxa de confirmación.",
- "lockdbsuccesssub": "Candáu de la base de datos efeutuáu correutamente",
- "unlockdbsuccesssub": "Candáu de la base de datos elimináu",
- "lockdbsuccesstext": "Candóse la base de datos.\n<br />Alcuérdate de [[Special:UnlockDB|descandala]] depués d'acabar el so mantenimientu.",
- "unlockdbsuccesstext": "La base de datos foi descandada.",
- "lockfilenotwritable": "L'archivu de candáu de la base de datos nun ye escribible. Pa candar o descandar la base de datos esti tien que poder ser modificáu pol sirvidor.",
+ "lockconfirm": "Sí, realmente quiero bloquiar la base de datos.",
+ "unlockconfirm": "Sí, realmente quiero desbloquiar la base de datos.",
+ "lockbtn": "Bloquiar la base de datos",
+ "unlockbtn": "Desbloquiar la base de datos",
+ "locknoconfirm": "Nun marcasti'l caxellu de confirmación.",
+ "lockdbsuccesssub": "Bloquióse correutamente la base de datos",
+ "unlockdbsuccesssub": "Quitóse'l bloquéu de la base de datos",
+ "lockdbsuccesstext": "Bloquióse la base de datos.<br />\nAlcuérdate de [[Special:UnlockDB|quitar el bloquéu]] depués d'acabar el mantenimientu.",
+ "unlockdbsuccesstext": "La base de datos ta desbloquiada.",
+ "lockfilenotwritable": "El ficheru de bloquéu de la base de datos nun puede escribise.\nPa bloquiar o desbloquiar la base de datos esti tien que poder escribise pol sirvidor web.",
"databaselocked": "La base de datos yá ta bloquiada.",
- "databasenotlocked": "La base de datos nun ta candada.",
+ "databasenotlocked": "La base de datos nun ta bloquiada.",
"lockedbyandtime": "(por $1 el $2 a les $3)",
"move-page": "Treslladar $1",
"move-page-legend": "Treslladar páxina",
"movepagetalktext": "Si marques esti cuadru, la páxina d'alderique asociada va treslladase automáticamente al títulu nuevu, a nun ser que yá esista una páxina d'alderique non vacia allí.\n\nNesti casu tendrás que treslladar o fusionar la páxina manualmente si lo desees.",
"moveuserpage-warning": "'''Atención:''' Tas a piques de mover una páxina d'usuariu. Atalanta que namái se va mover la páxina y que ''nun'' se va renomar l'usuariu.",
"movecategorypage-warning": "<strong>Avisu:</strong> Tas a piques de treslladar una páxina de categoría. Ten en cuenta que sólo se treslladará la páxina y que cualquier páxina que tuviera na categoría antigua <em>nun</em> se recategorizará na nueva.",
- "movenologintext": "Tienes que ser un usuariu rexistráu y tar [[Special:UserLogin|identificáu]] pa treslladar una páxina.",
- "movenotallowed": "Nun tienes permisu pa mover páxines.",
- "movenotallowedfile": "Nun tienes permisu pa mover ficheros.",
+ "movenologintext": "Tienes de ser un usuariu rexistráu y con [[Special:UserLogin|sesión aniciada]] pa treslladar una páxina.",
+ "movenotallowed": "Nun tienes permisu pa treslladar páxines.",
+ "movenotallowedfile": "Nun tienes permisu pa treslladar ficheros.",
"cant-move-user-page": "Nun tienes permisu pa treslladar páxines d'usuariu (independientemente de les subpáxines).",
"cant-move-to-user-page": "Nun tienes permisu pa treslladar una páxina a una páxina d'usuariu (sacante a una subpáxina d'usuariu).",
"cant-move-category-page": "Nun tienes permisu pa treslladar páxines de categoría.",
"cant-move-subpages": "Nun tienes permisu pa mover subpáxines.",
"namespace-nosubpages": "L'espaciu de nomes «$1» nun permite subpáxines.",
"newtitle": "Títulu nuevu:",
- "move-watch": "Vixilar esta páxina",
+ "move-watch": "Vixilar les páxines d'orixe y destín",
"movepagebtn": "Treslladar la páxina",
"pagemovedsub": "Treslláu correctu",
"movepage-moved": "<strong>«$1» treslladóse a «$2»</strong>",
"movepage-moved-redirect": "Creóse una redireición.",
"movepage-moved-noredirect": "Desaniciose la creación d'una redireición.",
"articleexists": "Yá hai una páxina con esi nome, o'l nome qu'escoyisti nun ye válidu. Por favor, escueyi otru nome.",
- "cantmove-titleprotected": "Nun pues mover una páxina a esti llugar porque'l nuevu títulu foi protexíu de la so creación",
+ "cantmove-titleprotected": "Nun puedes treslladar una páxina a esti llugar porque ta protexida la creación del títulu nuevu.",
"movetalk": "Mover la páxina d'alderique asociada",
"move-subpages": "Treslladar les subpáxines (hasta $1)",
"move-talk-subpages": "Treslladar les subpáxines de la páxina d'alderique (hasta $1)",
- "movepage-page-exists": "La páxina $1 yá esiste y nun se pue sobreescribir automáticamente.",
+ "movepage-page-exists": "La páxina $1 yá esiste y nun puede sustituise automáticamente.",
"movepage-page-moved": "Treslladóse la páxina $1 a $2.",
- "movepage-page-unmoved": "Nun se pudo treslladar la páxina $1 a $2.",
+ "movepage-page-unmoved": "Nun pudo treslladase la páxina $1 a $2.",
"movepage-max-pages": "Treslladóse'l máximu de $1 {{PLURAL:$1|páxina|páxinees}} y nun van treslladase más automáticamente.",
"movelogpage": "Rexistru de tresllaos",
"movelogpagetext": "Esta ye la llista de páxines treslladaes.",
"movereason": "Motivu:",
"revertmove": "revertir",
"delete_and_move_text": "==Necesítase esborrar==\n\nLa páxina de destín «[[:$1]]» yá esiste. ¿Quies desaniciala pa dexar sitiu pal treslláu?",
- "delete_and_move_confirm": "Sí, esborrar la páxina",
+ "delete_and_move_confirm": "Sí, desaniciar la páxina",
"delete_and_move_reason": "Desaniciada pa facer sitiu pa treslladar dende «[[$1]]»",
"selfmove": "El títulu ye'l mesmu;\nnun puede treslladase una páxina a ella mesma.",
- "immobile-source-namespace": "Nun se puen treslladar páxines nel espaciu de nomes \"$1\"",
- "immobile-target-namespace": "Nun se puen treslladar páxines al espaciu de nomes \"$1\"",
+ "immobile-source-namespace": "Nun pueden treslladase páxines nel espaciu de nomes «$1».",
+ "immobile-target-namespace": "Nun pueden treslladase páxines al espaciu de nomes «$1».",
"immobile-target-namespace-iw": "Nun puedes mover una páxina a un enllaz d'Interwiki.",
"immobile-source-page": "Esta páxina nun ye treslladable.",
- "immobile-target-page": "Nun se pue treslladar a esi títulu de destín.",
+ "immobile-target-page": "Nun puede treslladase a esi títulu de destín.",
"bad-target-model": "El destín deseáu utiliza un modelu de conteníu diferente. Nun se pue convertir de $1 a $2.",
- "imagenocrossnamespace": "Nun se pue treslladar una imaxe a nun espaciu de nomes que nun ye d'imáxenes",
+ "imagenocrossnamespace": "Nun puede treslladase un ficheru a un espaciu de nomes que nun ye de ficheros.",
"nonfile-cannot-move-to-file": "Nun se pue treslladar más que ficheros al espaciu de nomes de ficheros",
"imagetypemismatch": "La estensión nueva del archivu nun concueya cola so mena",
- "imageinvalidfilename": "El nome del archivu oxetivu nun ye válidu",
- "fix-double-redirects": "Actualizar cualesquier redireición que señale al títulu orixinal",
+ "imageinvalidfilename": "El nome de ficheru de destín nun ye válidu.",
+ "fix-double-redirects": "Actualizar toles redireiciones qu'apunten al títulu orixinal",
"move-leave-redirect": "Dexar una redireición detrás",
"protectedpagemovewarning": "'''Avisu: Esta páxina ta candada pa que sólo los alministradores puedan treslladala.'''\nLa cabera entrada del rexistru s'ufre darréu pa referencia:",
"semiprotectedpagemovewarning": "'''Nota:''' Esta páxina ta candada pa que namái los usuarios rexistraos puedan treslladala.\nLa cabera entrada del rexistru s'ufre darréu pa referencia:",
"export": "Esportar páxines",
"exporttext": "Pues esportar el testu y l'historial d'ediciones d'una páxina en particular o d'una\nriestra páxines endolcaes nun documentu XML. Esti se pue importar depués n'otra wiki\nqu'use MediaWiki al traviés de la páxina [[Special:Import|importar]].\n\nPa esportar páxines, pon los títulos na caxa de testu d'embaxo, un títulu por llinia,\ny seleiciona si quies la versión actual xunto con toles versiones antigües, xunto col\nso historial, o namái la versión actual cola información de la postrer edición.\n\nPor último, tamién pues usar un enllaz: p.e. [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] pa la páxina \"[[{{MediaWiki:Mainpage}}]]\".",
"exportall": "Esportar toles páxines",
- "exportcuronly": "Amestar namái la revisión actual, non tol historial",
- "exportnohistory": "----\n'''Nota:''' Desactivóse la esportación del historial completu de páxines al traviés d'esti formulariu por motivos de rendimientu.",
+ "exportcuronly": "Amestar namái la revisión actual, non l'historial completu",
+ "exportnohistory": "----\n<strong>Nota:</strong> Desactivóse la esportación del historial completu de páxines con esti formulariu por motivos de rindimientu.",
"exportlistauthors": "Incluir una llista completa de collaboradores pa cada páxina",
"export-submit": "Esportar",
- "export-addcattext": "Añader páxines dende la categoría:",
+ "export-addcattext": "Añadir páxines dende la categoría:",
"export-addcat": "Amestar",
"export-addnstext": "Amestar páxines del espaciu de nomes:",
"export-addns": "Amestar",
- "export-download": "Guardar como archivu",
- "export-templates": "Inxerir plantíes",
+ "export-download": "Guardar como ficheru",
+ "export-templates": "Incluir plantíes",
"export-pagelinks": "Incluyir páxines enllazaes fasta una profundidá de:",
"export-manual": "Amestar páxines a mano:",
- "allmessages": "Tolos mensaxes del sistema",
+ "allmessages": "Mensaxes del sistema",
"allmessagesname": "Nome",
"allmessagesdefault": "Testu predetermináu",
- "allmessagescurrent": "Testu actual",
+ "allmessagescurrent": "Testu actual del mensaxe",
"allmessagestext": "Esta ye una llista de los mensaxes de sistema disponibles nel espaciu de nomes de MediaWiki.\nPor favor visita [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation Llocalización de MediaWiki] y [https://translatewiki.net translatewiki.net] si quies contribuyer a la llocalización xenérica de MediaWiki.",
- "allmessagesnotsupportedDB": "Nun pue usase '''{{ns:special}}:Allmessages''' porque '''$wgUseDatabaseMessages''' ta deshabilitáu.",
+ "allmessagesnotsupportedDB": "Esta páxina nun puede usase porque ta desactivao <strong>$wgUseDatabaseMessages</strong>.",
"allmessages-filter-legend": "Peñerar",
"allmessages-filter": "Peñerar por estáu de personalización:",
"allmessages-filter-unmodified": "Ensin cambeos",
"allmessages-filter-submit": "Dir",
"allmessages-filter-translate": "Traducir",
"thumbnail-more": "Agrandar",
- "filemissing": "Falta archivu",
+ "filemissing": "Falta el ficheru",
"thumbnail_error": "Error al crear la miniatura: $1",
"thumbnail_error_remote": "Mensaxe d'error de $1:\n$2",
- "djvu_page_error": "Páxina DjVu fuera de llímites",
- "djvu_no_xml": "Nun se pudo obtener el XML pal archivu DjVu",
+ "djvu_page_error": "Páxina DjVu fuera de llendes",
+ "djvu_no_xml": "Nun pudo llograse'l XML pal ficheru DjVu",
"thumbnail-temp-create": "Nun se pudo crear el ficheru temporal de miniatura",
"thumbnail-dest-create": "Nun se pudo guardar la miniatura nel destín",
"thumbnail_invalid_params": "Parámetros de miniatura non válidos",
"thumbnail_toobigimagearea": "Ficheru con dimensiones mayores que $1",
- "thumbnail_dest_directory": "Nun se pue crear el direutoriu de destín",
+ "thumbnail_dest_directory": "Nun pudo crease'l direutoriu de destín",
"thumbnail_image-type": "Triba d'imaxe ensin sofitu",
"thumbnail_gd-library": "Configuración incompleta de la biblioteca GD: falta la función $1",
"thumbnail_image-missing": "Paez que falta'l ficheru: $1",
"import-revision-count": "$1 {{PLURAL:$1|revisión|revisiones}}",
"importnopages": "Nun hai páxines pa importar.",
"imported-log-entries": "Importao $1 {{PLURAL:$1|entrada del rexistru|entraes del rexistru}}.",
- "importfailed": "Falló la importación: $1",
+ "importfailed": "Falló la importación: <nowiki>$1</nowiki>",
"importunknownsource": "Triba d'orixe d'importación desconocida",
"importnoprefix": "Nun se dio nengún prefixu d'interwiki",
"importcantopen": "Nun se pudo abrir el ficheru d'importación",
"importbadinterwiki": "Enllaz interwiki incorreutu",
"importsuccess": "¡Importación finalizada!",
"importnosources": "Nun se definieron wikis de onde importar y les xubíes direutes del historial tán desactivaes.",
- "importnofile": "Nun se xubió nengún archivu d'importación.",
- "importuploaderrorsize": "Falló la xubida del archivu d'importación. L'archivu ye más grande que'l tamañu permitíu de xubida.",
- "importuploaderrorpartial": "Falló la xubida del archivu d'importación. L'archivu xubióse solo parcialmente.",
- "importuploaderrortemp": "Falló la xubida del archivu d'importación. Falta una carpeta temporal.",
- "import-parse-failure": "Fallu nel análisis d'importación XML",
+ "importnofile": "Nun se xubió nengún ficheru d'importación.",
+ "importuploaderrorsize": "Falló la xubida del ficheru d'importación.\nEl ficheru ye mayor que'l tamañu permitíu de xubida.",
+ "importuploaderrorpartial": "Falló la xubida del ficheru d'importación.\nEl ficheru xubióse sólo parcialmente.",
+ "importuploaderrortemp": "Falló la xubida del ficheru d'importación.\nFalta una carpeta temporal.",
+ "import-parse-failure": "Falló l'analís d'importación XML",
"import-noarticle": "¡Nun hai páxina pa importar!",
"import-nonewrevisions": "Nun s'importó denguna revision (o yá taben toes presentes, o se saltaron por errores).",
"xml-error-string": "$1 na llinia $2, col $3 (byte $4): $5",
"import-upload": "Xubir datos XML",
"import-token-mismatch": "Perda de datos de la sesión.\n\nSeique zarróse la sesión. '''Comprueba si tienes abierta la sesión y tenta nuevamente'''.\nSi entá nun funciona, tenta [[Special:UserLogout|colar]] y volver a aniciar sesión y comprueba que'l restolador permite les cookies d'esti sitiu.",
- "import-invalid-interwiki": "Nun se puede importar d'esi wiki.",
+ "import-invalid-interwiki": "Nun puede importase de la wiki especificada.",
"import-error-edit": "La páxina «$1» nun s'importó porque nun tienes permisu pa editala.",
"import-error-create": "La páxina «$1» nun s'importó porque nun tienes permisu pa creala.",
"import-error-interwiki": "La páxina «$1» nun s'importó porque'l so nome ta acutáu pa enllaces esternos (interwiki).",
"import-rootpage-invalid": "La páxina raíz dada ye un títulu inválidu.",
"import-rootpage-nosubpage": "L'espaciu de nomes \"$1\" de la páxina raíz nun permite subpáxines.",
"importlogpage": "Rexistru d'importaciones",
- "importlogpagetext": "Importaciones alministrativas de páxines con historial d'ediciones d'otres wikis.",
+ "importlogpagetext": "Importaciones alministratives de páxines con historial d'ediciones d'otres wikis.",
"import-logentry-upload-detail": "$1 {{PLURAL:$1|revisión importada|revisiones importaes}}",
"import-logentry-interwiki-detail": "$1 {{PLURAL:$1|revisión importada|revisiones importaes}} dende $2",
"javascripttest": "Prueba de JavaScript",
"javascripttest-pagetext-unknownaction": "Aición desconocida «$1».",
"javascripttest-qunit-intro": "Ver la [$1 documentación de les pruebes] en mediawiki.org.",
"tooltip-pt-userpage": "La to páxina d'{{GENDER:|usuariu|usuaria}}",
- "tooltip-pt-anonuserpage": "La páxina d'usuariu de la IP cola que tas editando",
+ "tooltip-pt-anonuserpage": "La páxina d'usuariu de la direición IP cola que tas editando",
"tooltip-pt-mytalk": "La {{GENDER:|to}} páxina d'alderique",
"tooltip-pt-anontalk": "Alderique de les ediciones feches con esta direición IP",
"tooltip-pt-preferences": "Les {{GENDER:|tos}} preferencies",
"tooltip-ca-protect": "Protexer esta páxina",
"tooltip-ca-unprotect": "Camudar la proteición desta páxina",
"tooltip-ca-delete": "Desaniciar esta páxina",
- "tooltip-ca-undelete": "Restaura les ediciones feches nesta páxina enantes de que fuera esborrada",
+ "tooltip-ca-undelete": "Restaurar les ediciones feches nesta páxina enantes de que se desaniciara",
"tooltip-ca-move": "Tresllada esta páxina",
"tooltip-ca-watch": "Amiesta esta páxina a la to llista de siguimientu",
"tooltip-ca-unwatch": "Desaniciar esta páxina de la to llista de siguimientu",
"tooltip-t-permalink": "Enllaz permanente a esta revisión de la páxina",
"tooltip-ca-nstab-main": "Ver la páxina de conteníu",
"tooltip-ca-nstab-user": "Ver la páxina d'usuariu",
- "tooltip-ca-nstab-media": "Amuesa la páxina de multimedia",
+ "tooltip-ca-nstab-media": "Ver la páxina de multimedia",
"tooltip-ca-nstab-special": "Esta ye una páxina especial y nun pué editase",
"tooltip-ca-nstab-project": "Vera la páxina de proyeutu",
"tooltip-ca-nstab-image": "Ver la páxina del ficheru",
- "tooltip-ca-nstab-mediawiki": "Amuesa'l mensaxe de sistema",
+ "tooltip-ca-nstab-mediawiki": "Ver el mensaxe del sistema",
"tooltip-ca-nstab-template": "Amuesa la plantía",
"tooltip-ca-nstab-help": "Amuesa la páxina d'ayuda",
"tooltip-ca-nstab-category": "Ver la páxina de categoría",
"tooltip-watch": "Amiesta esta páxina a la to llista de siguimientu",
"tooltip-watchlistedit-normal-submit": "Desaniciar títulos",
"tooltip-watchlistedit-raw-submit": "Anovar llista de vixilancia",
- "tooltip-recreate": "Vuelve a crear la páxina magar que se tenga esborrao",
+ "tooltip-recreate": "Volver a crear la páxina anque se desaniciara",
"tooltip-upload": "Empecipiar la xubida",
"tooltip-rollback": "\"Revertir\" desfái nún clic la edición(es) d'esta páxina del postrer collaborador.",
"tooltip-undo": "\"Esfacer\" revierte esta edición y abre'l formulariu d'edición en mou de vista previa. Permite añader un motivu nel resume.",
"markedaspatrolledtext": "La revisión seleicionada de [[:$1]] se marcó como supervisada.",
"rcpatroldisabled": "Supervisión de cambios recientes desactivada",
"rcpatroldisabledtext": "La función de supervisión de cambios recientes ta desactivada nestos momentos.",
- "markedaspatrollederror": "Nun se pue marcar como supervisada",
+ "markedaspatrollederror": "Nun puede marcase como supervisada",
"markedaspatrollederrortext": "Necesites conseñar una revisión pa marcala como supervisada.",
"markedaspatrollederror-noautopatrol": "Nun tienes permisu pa marcar los cambios propios como supervisaos.",
"markedaspatrollednotify": "Esti cambiu en $1 marcóse como revisáu.",
"log-show-hide-tag": "$1 rexistru d'etiquetes",
"confirm-markpatrolled-button": "Aceutar",
"confirm-markpatrolled-top": "¿Marcar la revisión $3 de $2 como patrullada?",
- "deletedrevision": "Esborrada la reversión vieya $1",
- "filedeleteerror-short": "Error al esborrar l'archivu: $1",
- "filedeleteerror-long": "Atopáronse errores al esborrar l'archivu:\n\n$1",
- "filedelete-missing": "L'archivu \"$1\" nun pue esborrase porque nun esiste.",
- "filedelete-old-unregistered": "La revisión d'archivu \"$1\" nun ta na base de datos.",
- "filedelete-current-unregistered": "L'archivu especificáu \"$1\" nun ta na base de datos.",
- "filedelete-archive-read-only": "El direutoriu d'archivos \"$1\" nun pue ser modificáu pol sirvidor.",
+ "deletedrevision": "Desaniciada la revisión antigua $1",
+ "filedeleteerror-short": "Error al desaniciar el ficheru: $1",
+ "filedeleteerror-long": "Atopáronse errores al desaniciar el ficheru:\n\n$1",
+ "filedelete-missing": "El ficheru «$1» nun puede desaniciase porque nun esiste.",
+ "filedelete-old-unregistered": "La revisión especificada del ficheru «$1» nun ta na base de datos.",
+ "filedelete-current-unregistered": "El ficheru especificáu «$1» nun ta na base de datos.",
+ "filedelete-archive-read-only": "El sirvidor web nun puede escribir nel direutoriu d'archivos «$1».",
"previousdiff": "← Edición más antigua",
"nextdiff": "Edición más nueva →",
"mediawarning": "'''Avisu''': Esta triba de ficheru pue contener códigu maliciosu.\nAl executalu pues comprometer el to sistema.",
"file-info-png-frames": "$1 {{PLURAL:$1|cuadru|cuadros}}",
"file-no-thumb-animation": "'''Nota: pola mor de llímites téunicos, les miniatures d'esti ficheru nun tan animaes.'''",
"file-no-thumb-animation-gif": "'''Nota: pola mor de llímites téunicos, les miniatures d'imaxes GIF d'alta resolución como esta nun tan animaes.'''",
- "newimages": "Galería d'imáxenes nueves",
+ "newimages": "Galería de ficheros nuevos",
"imagelisttext": "Embaxo ta la llista {{PLURAL:$1|d'un archivu ordenáu|de '''$1''' archivos ordenaos}} $2.",
"newimages-summary": "Esta páxina especial amuesa los caberos archivos xubíos.",
"newimages-legend": "Peñera",
"postedit-confirmation-created": "Старонка была створаная.",
"postedit-confirmation-restored": "Старонка была адноўленая.",
"postedit-confirmation-saved": "Вашая праўка была захаваная.",
+ "postedit-confirmation-published": "Вашая праўка была апублікаваная.",
"edit-already-exists": "Немагчыма стварыць новую старонку.\nЯна ўжо існуе.",
"defaultmessagetext": "Перадвызначаны тэкст паведамленьня",
"content-failed-to-parse": "Зьмест «$2» не адпавядае мадэлі $1: $3.",
"right-createtalk": "Стварэньне старонак абмеркаваньня",
"right-createaccount": "Стварэньне новых рахункаў удзельнікаў",
"right-autocreateaccount": "Аўтаматычны ўваход з вонкавага рахунку ўдзельніка",
- "right-minoredit": "пазнаÑ\87Ñ\8dнÑ\8cне Ñ\80Ñ\8dдагаванÑ\8cнÑ\8fÑ\9e Ñ\8fк дÑ\80обнÑ\8bÑ\8f",
- "right-move": "перанос старонак",
- "right-move-subpages": "перанос старонак разам зь іх падстаронкамі",
+ "right-minoredit": "Ð\9fазнаÑ\87Ñ\8dнÑ\8cне Ñ\80Ñ\8dдагаванÑ\8cнÑ\8fÑ\9e Ñ\8fк дÑ\80обнÑ\8bÑ\85",
+ "right-move": "Ð\9fеранос старонак",
+ "right-move-subpages": "Ð\9fеранос старонак разам зь іх падстаронкамі",
"right-move-rootuserpages": "перанос карэнных старонак удзельнікаў",
"right-move-categorypages": "перанос старонак катэгорыяў",
"right-movefile": "перайменаваньне файлаў",
"zip-file-open-error": "Възникна грешка при отваряне на файла за проверка на ZIP.",
"zip-wrong-format": "Указаният файл не е ZIP файл.",
"zip-bad": "Файлът е повреден или е нечетим ZIP файл.\nСигурността му не може да бъде проверена.",
- "zip-unsupported": "Файлът е ZIP файл, който използва ZIP компоненти, които не се поддържат от МедияУики.\nСигурността му не може да бъде коректно проверена.",
+ "zip-unsupported": "Файлът е ZIP файл, който използва функционалност, която не се поддържа от МедияУики.\nСигурността му не може да бъде коректно проверена.",
"uploadstash": "Скрити качвания",
"uploadstash-summary": "Тази страница предоставя достъп до файловете, които са качени (или са в процес на качване), но все още не са публикувани в уикито. Тези файлове не са достъпни само за потребителя, който ги е качил.",
"uploadstash-clear": "Изчистване на скритите качвания",
"doubleredirects": "Двойни пренасочвания",
"doubleredirectstext": "Тази страница съдържа списък със страници, които пренасочват към друга пренасочваща страница.\nВсеки ред съдържа препратки към първото и второто пренасочване, както и целта на второто пренасочване, която обикновено е „истинската“ целева страница, към която първото пренасочване би трябвало да сочи.\n<del>Задрасканите</del> записи са коригирани.",
"double-redirect-fixed-move": "Страница [[$1]] беше преместена.\nБеше автоматично обновена и сега пренасочва към [[$2]].",
- "double-redirect-fixed-maintenance": "Автоматично коригиране на двойно пренасочване от [[$1]] към [[$2]] при извършване на техническо обслужване.",
+ "double-redirect-fixed-maintenance": "Автоматично коригиране на двойно пренасочване от [[$1]] към [[$2]] при извършване на техническо обслужване",
"double-redirect-fixer": "Коректор на пренасочвания",
"brokenredirects": "Невалидни пренасочвания",
"brokenredirectstext": "Следните пренасочващи страници сочат към несъществуващи страници:",
"expandtemplates": "Разгръщане на шаблони",
"expand_templates_intro": "Тази специална страница взима текст и рекурсивно разгръща всички шаблони в нея.\nТя разгръща и всички поддържани парсерни функции като\n<code><nowiki>{{</nowiki>#language:…}}</code> и променливи като\n<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.\nНа практика тя разгръща почти всичко в двойни скоби.",
"expand_templates_title": "Заглавие на страницата (напр. за {{FULLPAGENAME}}):",
- "expand_templates_input": "Входящ текст:",
+ "expand_templates_input": "Ð\92Ñ\85одÑ\8fÑ\89 Ñ\83икиÑ\82екÑ\81Ñ\82:",
"expand_templates_output": "Резултат",
"expand_templates_xml_output": "Изход на XML",
"expand_templates_ok": "ОК",
"category-empty": "<em>Ova kategorija trenutno ne sadrži članke ni medije.</em>",
"hidden-categories": "{{PLURAL:$1|Sakrivena kategorija|Sakrivene kategorije}}",
"hidden-category-category": "Skrivene kategorije",
- "category-subcat-count": "{{PLURAL:$2|1=Ova kategorija samo ima sljedeću potkategoriju.|Ova kategorija ima {{PLURAL:$1|sljedeću potkategoriju|sljedeće $1 potkategorije|sljedećih $1 potkategorija}}, od $2 ukupno.}}",
+ "category-subcat-count": "{{PLURAL:$2|1=Ova kategorija sadrži samo sljedeću potkategoriju.|{{PLURAL:$1|Prikazana je $1 potkategorija|Prikazane su $1 potkategorije|Prikazano je $1 potkategorija}}, od ukupno $2.}}",
"category-subcat-count-limited": "Ova kategorija sadrži {{PLURAL:$1|sljedeću $1 potkategoriju|sljedeće $1 potkategorije|sljedećih $1 potkategorija}}.",
- "category-article-count": "{{PLURAL:$2|1=Ova kategorija sadrži samo sljedeću stranicu.|{{PLURAL:$1|Sljedeća stranica je|Sljedeće $1 stranice su|Sljedećih $1 stranica je}} u ovoj kategoriji, od ukupno $2.}}",
+ "category-article-count": "{{PLURAL:$2|1=Ova kategorija sadrži samo sljedeću stranicu.|{{PLURAL:$1|Prikazana je $1 stranica|Prikazane su $1 stranice|Prikazano je $1 stranica}}, od ukupno $2.}}",
"category-article-count-limited": "{{PLURAL:$1|Slijedeća $1 stranica je|Slijedeće $1 stranice su|Slijedećih $1 stranica je}} u ovoj kategoriji.",
"category-file-count": "{{PLURAL:$2|Ova kategorija ima slijedeću $1 datoteku.|{{PLURAL:$1|Prikazana je $1 datoteka|Prikazane su $1 datoteke|Prikazano je $1 datoteka}} u ovoj kategoriji, od ukupno $2.}}",
"category-file-count-limited": "{{PLURAL:$1|Slijedeća $1 datoteka je|Slijedeće $1 datoteke su|Slijedećih $1 datoteka je}} u ovoj kategoriji.",
"postedit-confirmation-created": "S'ha creat la pàgina.",
"postedit-confirmation-restored": "S'ha restaurat la pàgina.",
"postedit-confirmation-saved": "S'ha desat la modificació.",
+ "postedit-confirmation-published": "S’ha publicat la vostra modificació.",
"edit-already-exists": "No s'ha pogut crear una pàgina.\nJa existeix.",
"defaultmessagetext": "Missatge per defecte",
"content-failed-to-parse": "Ha fallat l'anàlisi del contingut de $2 per al model $1: $3",
"authprovider-confirmlink-failed": "L'enllaçament de comptes no ha funcionat satisfactòriament: $1",
"authprovider-resetpass-skip-label": "Omet",
"authprovider-resetpass-skip-help": "Omet el restabliment de contrasenya.",
+ "authform-nosession-login": "L’autenticació fou exitosa, però el vostre navegador no pot «recordar» haver iniciat la sessió.\n\n$1",
+ "authform-nosession-signup": "S’ha creat el compte, però el vostre navegador no pot «recordar» haver iniciat la sessió.\n\n$1",
"specialpage-securitylevel-not-allowed-title": "No permès",
"specialpage-securitylevel-not-allowed": "Ho sentim, no podeu utilitzar la pàgina perquè no es pot verificar la vostra identitat.",
"authpage-cannot-login": "No s'ha pogut iniciar la sessió.",
"edit-error-long": "Errors:\n\n$1",
"revid": "revisió $1",
"pageid": "ID de pàgina $1",
+ "rawhtml-notallowed": "No és possible fer servir les etiquetes <html> fora de les pàgines normals.",
"gotointerwiki": "A punt d’abandonar {{SITENAME}}",
"gotointerwiki-invalid": "El títol especificat no és vàlid.",
"gotointerwiki-external": "Esteu a punt d’abandonar {{SITENAME}} per a visitar [[$2]], un lloc web diferent.\n\n'''[$1 Continua a $1]'''",
"movepage-moved-noredirect": "ДӀасхьажорг кхоллар дохина.",
"articleexists": "ХӀарасанна цӀе йолу агӀо йолуш ю йа ахьа гойтуш йолу цӀе магош яц.\nДехар до, харжа кхин цӀе.",
"movetalk": "Цуьнца йогӀуш йолу дийцаре агӀон цӀе хийцар",
- "move-subpages": "ЦÓ\80еÑ\80Ñ\88 Ñ\85ийÑ\86а бÑ\83Ñ\85аÑ\80а агÓ\80онийн ($1 кхаччалц)",
+ "move-subpages": "Ð\91Ñ\83Ñ\85аÑ\80а агÓ\80онийн Ñ\86Ó\80еÑ\80Ñ\88 Ñ\85ийÑ\86а($1 кхаччалц)",
"move-talk-subpages": "ЦӀе хийца бухара агӀонийн а, агӀонийн дийцаре а ($1 кхаччалц)",
"movepage-page-exists": "Агӏо $1 йолуш ю цундела и ша юху дӏаязъян йиш яц.",
"movepage-page-moved": "АгӀона $1 цӀе хийцина → $2.",
"Martin Urbanec",
"Marek Pavlica",
"Asmen",
- "Meliganai"
+ "Meliganai",
+ "Ilimanaq29"
]
},
"tog-underline": "Podtrhávat odkazy:",
"postedit-confirmation-created": "Stránka byla založena.",
"postedit-confirmation-restored": "Stránka byla obnovena.",
"postedit-confirmation-saved": "Vaše změny byly uloženy.",
+ "postedit-confirmation-published": "Vaše editace byla uložena.",
"edit-already-exists": "Nepodařilo se vytvořit novou stránku, protože již existuje.",
"defaultmessagetext": "Výchozí text hlášení",
"content-failed-to-parse": "Nepodařilo se zpracovat data $2 do modelu $1: $3",
"lockmanager-fail-closelock": "Soubor se zámkem pro „$1“ nelze zavřít.",
"lockmanager-fail-deletelock": "Soubor se zámkem pro „$1“ nelze smazat.",
"lockmanager-fail-acquirelock": "Zámek pro „$1“ nelze získat.",
- "lockmanager-fail-openlock": "Soubor se zámkem pro „$1“ nelze otevřít.",
+ "lockmanager-fail-openlock": "Soubor se zámkem „$1“ nelze otevřít. Ujistěte se, že vámi nahraný adresář je správně nakonfigurován a že váš webový server má povolení k editaci tohoto adresáře. Pro další informace vizte https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgUploadDirectory.",
"lockmanager-fail-releaselock": "Zámek pro „$1“ nelze uvolnit.",
"lockmanager-fail-db-bucket": "Nelze navázat spojení s dostatečným počtem databází zámků v bloku $1.",
"lockmanager-fail-db-release": "Uzamčení databáze $1 nelze uvolnit.",
"postedit-confirmation-created": "Die Seite wurde erstellt.",
"postedit-confirmation-restored": "Die Seite wurde wiederhergestellt.",
"postedit-confirmation-saved": "Deine Bearbeitung wurde gespeichert.",
+ "postedit-confirmation-published": "Deine Bearbeitung wurde veröffentlicht.",
"edit-already-exists": "Die neue Seite konnte nicht erstellt werden, da sie bereits vorhanden ist.",
"defaultmessagetext": "Standardtext",
"content-failed-to-parse": "Parsen des Inhalts $2 für Modell $1 fehlgeschlagen: $3",
"seconds-ago": "Verê $1 {{PLURAL:$1|saniya|saniyeyan}}",
"monday-at": "Dışeme $1 de",
"tuesday-at": "Sêşeme $1 de",
- "wednesday-at": "Çarşeme $1 de",
+ "wednesday-at": "Çeharşeme $1 de",
"thursday-at": "Pancşeme $1 de",
"friday-at": "Êne $1 de",
"saturday-at": "Şeme $1 de",
"postedit-confirmation-created": "The page has been created.",
"postedit-confirmation-restored": "The page has been restored.",
"postedit-confirmation-saved": "Your edit was saved.",
+ "postedit-confirmation-published": "Your edit was published.",
"edit-already-exists": "Could not create a new page.\nIt already exists.",
"addsection-preload": "",
"addsection-editintro": "",
"postedit-confirmation-created": "Se ha creado la página.",
"postedit-confirmation-restored": "Se ha restaurado la página.",
"postedit-confirmation-saved": "Se ha guardado tu edición.",
+ "postedit-confirmation-published": "Se publicó tu edición.",
"edit-already-exists": "No se pudo crear una página nueva.\nYa existe.",
"defaultmessagetext": "Texto predeterminado",
"content-failed-to-parse": "No se ha podido procesar el contenido $2 del modelo de $1: $3",
"lockmanager-fail-closelock": "No se pudo cerrar la referencia para el archivo de bloqueo de \"$1\".",
"lockmanager-fail-deletelock": "No se pudo eliminar el archivo de bloqueo para \"$1\".",
"lockmanager-fail-acquirelock": "No pudo adquirir el bloqueo para \"$1\".",
- "lockmanager-fail-openlock": "No se pudo abrir el archivo de bloqueo para \"$1\". Por favor verifica que el directorio de subidas está configurado correctamente y que tu servidor web tiene permisos de escritura en ese directorio. Ver https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgUploadDirectory para más información.",
+ "lockmanager-fail-openlock": "No se pudo abrir el archivo de bloqueo de «$1». Revisa que el directorio de cargas esté configurado correctamente y que tu servidor web tenga permisos de escritura en ese directorio. Consulta https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgUploadDirectory para obtener más información.",
"lockmanager-fail-releaselock": "No se pudo liberar el bloqueo de \"$1\".",
"lockmanager-fail-db-bucket": "No se pudo contactar con las suficientes bases de datos del conjunto $1.",
"lockmanager-fail-db-release": "No se pudieron liberar los bloqueos registrados en la base de datos $1.",
"protect-otherreason": "Otra razón:",
"protect-otherreason-op": "Otro motivo",
"protect-dropdown": "*Razones de protección habituales\n**Vandalismo excesivo\n**Spam excesivo\n**Guerra de ediciones\n**Página muy visitada",
- "protect-edit-reasonlist": "Editar las razones de protección",
+ "protect-edit-reasonlist": "Editar motivos de protección",
"protect-expiry-options": "1 hora:1 hour,1 día:1 day,1 semana:1 week,2 semanas:2 weeks,1 mes:1 month,3 meses:3 months,6 meses:6 months,1 año:1 year,para siempre:infinite",
"restriction-type": "Permiso:",
"restriction-level": "Nivel de restricción:",
"authprovider-confirmlink-ok-help": "Continuar luego de mostrar los mensajes de error en la vinculación.",
"authprovider-resetpass-skip-label": "Omitir",
"authprovider-resetpass-skip-help": "Saltar el reestablecimiento de la contraseña.",
- "authform-nosession-login": "La autenticación fue exitosa, pero tu navegador no puede \"recordar\" haber iniciado sesión.\n\n$1",
- "authform-nosession-signup": "La cuenta ha sido creada, pero tu navegador no \"recuerda\" haber iniciado sesión.\n\n$1",
+ "authform-nosession-login": "La autenticación fue exitosa, pero tu navegador no «recuerda» haber accedido a la cuenta.\n\n$1",
+ "authform-nosession-signup": "Se ha creado la cuenta, pero tu navegador no «recuerda» haber accedido a ella.\n\n$1",
"authform-newtoken": "Falta token. $1",
"authform-notoken": "Falta token",
"authform-wrongtoken": "Token incorrecto",
"postedit-confirmation-created": "See lehekülg on alustatud.",
"postedit-confirmation-restored": "See lehekülg on taastatud.",
"postedit-confirmation-saved": "Sinu muudatus on salvestatud.",
+ "postedit-confirmation-published": "Sinu muudatus on avaldatud.",
"edit-already-exists": "Ei saanud alustada uut lehekülge.\nSee on juba olemas.",
"defaultmessagetext": "Sõnumi vaiketekst",
"content-failed-to-parse": "Ebaõnnestus $1i mudeli $2-tüüpi sisu liigendamine: $3",
"lockmanager-fail-closelock": "Raja \"$1\" lukustusfaili ei saa sulgeda.",
"lockmanager-fail-deletelock": "Raja \"$1\" lukustusfaili ei saa kustutada.",
"lockmanager-fail-acquirelock": "Ressursi \"$1\" luku hankimine ebaõnnestus.",
- "lockmanager-fail-openlock": "Raja \"$1\" lukustusfaili ei saa avada.",
+ "lockmanager-fail-openlock": "Raja \"$1\" lukustusfaili ei saa avada. Veendu, et üleslaadimise kataloog on õigesti häälestatud ja et sinu veebiserveril on õigus sellesse kataloogi kirjutada. Vaata lisateavet aadressil https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgUploadDirectory.",
"lockmanager-fail-releaselock": "Ressursi \"$1\" lukku ei õnnestunud vabastada.",
"lockmanager-fail-db-bucket": "Komplektis $1 ei õnnestunud saada ühendust piisavalt paljude lukustusandmebaasidega.",
"lockmanager-fail-db-release": "Andmebaasis $1 ei õnnestunud lukke vabastada.",
"pageinfo-category-subcats": "Alamkategooriaid",
"pageinfo-category-files": "Faile",
"pageinfo-user-id": "Kasutaja identifikaator",
+ "pageinfo-file-hash": "Räsiväärtus",
"markaspatrolleddiff": "Märgi kontrollituks",
"markaspatrolledtext": "Märgi see leht kontrollituks",
"markaspatrolledtext-file": "Märgi see failiversioon kontrollituks",
"lockmanager-fail-closelock": "Ezin izan da \"$1\" fitxategiaren giltza itxi.",
"lockmanager-fail-deletelock": "Ezin izan da \"$1\" fitxategia desblokeatu.",
"lockmanager-fail-acquirelock": "Ezin izan da \"$1\" blokeoa eskuratu.",
- "lockmanager-fail-openlock": "Ezin izan da \"$1\" blokeo fitxategia ireki.",
+ "lockmanager-fail-openlock": "Ezin izan da \"$1\"-rentzako blokeo fitxategia ireki. Ziurtatu igoera direktorioa behar bezala konfiguratuta dagoela eta zure web zerbitzariak baimena duela idazteko. Ikusi informazio gehiagorako https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgUploadDirectory.",
"lockmanager-fail-releaselock": "Ezin izan da \"$1\" blokeoa askatu.",
"lockmanager-fail-db-bucket": "Ezin izan dut $1 buketean datubase nahikoa ziurtatu.",
"lockmanager-fail-db-release": "Ezin izan da $1 datubasean giltzaraporik askatu.",
"restrictionsfield-badip": "Baliogabeko IP helbide edo eremua: $1",
"restrictionsfield-label": "Onartutako IP eremuak:",
"restrictionsfield-help": "Linea bakoitzeko IP helbide edo CIDR eremu bakarra. Guztia gaitzeko, erabili: \n<pre>0.0.0.0/0\n::/0</pre>",
+ "edit-error-short": "Akatsa: $1",
+ "edit-error-long": "Akatsak:\n\n$1",
"revid": "$1 berrikusi",
"pageid": "$1 orri IDa",
"rawhtml-notallowed": "<html> etiketak ezin dira orri arruntetatik kanpo erabili.",
"ipb-hardblock": "جلوگیری از ویرایش کردن کاربران ثبت نام کرده از طریق این نشانی آیپی",
"ipbcreateaccount": "جلوگیری از ایجاد حساب",
"ipbemailban": "جلوگیری از ارسال ایمیل",
- "ipbenableautoblock": "بستن خودکار آخرین نشانی آیپی استفاده شده توسط کاربر و نشانیهای دیگری که از آنها برای ویرایش تلاش میکند",
+ "ipbenableautoblock": "بستن خودکار آخرین نشانی آیپی استفاده شده توسط کاربر و نشانیهای دیگری که از آنها برای ویرایش تلاش میکند",
"ipbsubmit": "این کاربر بسته شود",
"ipbother": "زمانی دیگر",
"ipboptions": "۲ ساعت:2 hours,۱ روز:1 day,۳ روز:3 days,۱ هفته:1 week,۲ هفته:2 weeks,۱ ماه:1 month,۳ ماه:3 months,۶ ماه:6 months,۱ سال:1 year,بیپایان:infinite",
"postedit-confirmation-created": "La page a été créée.",
"postedit-confirmation-restored": "La page a été restaurée.",
"postedit-confirmation-saved": "Votre modification a été enregistrée.",
+ "postedit-confirmation-published": "Votre modification a été publiée.",
"edit-already-exists": "La nouvelle page n’a pas pu être créée.\nElle existe déjà.",
"defaultmessagetext": "Message par défaut",
"content-failed-to-parse": "Échec de l’analyse syntaxique du contenu de $2 pour le modèle $1 : $3",
"postedit-confirmation-created": "הדף נוצר.",
"postedit-confirmation-restored": "הדף שוחזר.",
"postedit-confirmation-saved": "העריכה שלך נשמרה.",
+ "postedit-confirmation-published": "העריכה שלך פורסמה.",
"edit-already-exists": "לא ניתן ליצור דף חדש.\nהוא כבר קיים.",
"defaultmessagetext": "טקסט ההודעה המקורי",
"content-failed-to-parse": "פענוח $2 כתוכן מסוג $1 נכשל: $3",
"lockmanager-fail-closelock": "לא הייתה אפשרות לסגור את קובץ הנעילה עבור \"$1\".",
"lockmanager-fail-deletelock": "לא הייתה אפשרות למחוק את קובץ הנעילה עבור \"$1\".",
"lockmanager-fail-acquirelock": "לא הייתה אפשרות לקבל נעילה עבור \"$1\".",
- "lockmanager-fail-openlock": "לא הייתה אפשרות לפתוח את קובץ הנעילה עבור \"$1\".",
+ "lockmanager-fail-openlock": "לא הייתה אפשרות לפתוח את קובץ הנעילה עבור \"$1\". יש לוודא שתיקיית ההעלאות מוגדרת בצורה תקינה ושלשרת האינטרנט יש הרשאות לכתוב לתיקייה זו. [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgUploadDirectory למידע נוסף].",
"lockmanager-fail-releaselock": "לא הייתה אפשרות לשחרר את הנעילה עבור \"$1\".",
"lockmanager-fail-db-bucket": "לא הייתה אפשרות לקבל מספיק מסדי נתונים של נעילות בדלי $1.",
"lockmanager-fail-db-release": "לא הייתה אפשרות לשחרר נעילות על מסד הנתונים $1.",
"watchlist": "Popis praćenja",
"mywatchlist": "Popis praćenja",
"watchlistfor2": "Za $1 $2",
- "nowatchlist": "Na Vašem popisu praćenja nema nijednog članka.",
+ "nowatchlist": "Na Vašem popisu praćenja nema ijedne stavke.",
"watchlistanontext": "Molimo Vas prijavite se kako biste mogli vidjeti ili uređivati Vaš popis praćenih stranica.",
"watchnologin": "Niste prijavljeni",
"addwatch": "Dodaj u popis praćenja",
"postedit-confirmation-created": "Az oldal létrehozva.",
"postedit-confirmation-restored": "Az oldal helyre lett állítva.",
"postedit-confirmation-saved": "A szerkesztésedet elmentettük.",
+ "postedit-confirmation-published": "A szerkesztésed közzé lett téve.",
"edit-already-exists": "Az új lap nem készíthető el.\nMár létezik.",
"defaultmessagetext": "Alapértelmezett szöveg",
"content-failed-to-parse": "Hiba történt a $2 tartalom $1 modellre történő konvertálása során: $3",
"search-external": "Külső kereső",
"searchdisabled": "Elnézésed kérjük, de a teljes szöveges keresés terhelési okok miatt átmenetileg nem használható. Ezidő alatt használhatod a lenti Google keresést, mely viszont lehetséges, hogy nem teljesen friss adatokkal dolgozik.",
"search-error": "A keresés közben hiba történt: $1",
- "search-warning": "$1 keresése közben hiba történt",
+ "search-warning": "Hiba történt a keresés közben: $1",
"preferences": "Beállítások",
"mypreferences": "Beállítások",
"prefs-edits": "Szerkesztéseid száma:",
"lockmanager-fail-closelock": "Nem sikerült a „$1” zárolási fájljának bezárása.",
"lockmanager-fail-deletelock": "Nem sikerült a(z) „$1” zárolási fájljának törlése.",
"lockmanager-fail-acquirelock": "Nem sikerült zárolást igényelni a „$1” fájlhoz.",
- "lockmanager-fail-openlock": "Nem sikerült a „$1” zárolási fájljának megnyitása.",
+ "lockmanager-fail-openlock": "Nem sikerült a „$1” zárolási fájljának megnyitása. Győződj meg róla, hogy a feltöltési könyvtárad jól van konfigurálva és a webszerverednek van engedélye írni a könyvtárat. Lásd még további információért: https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgUploadDirectory",
"lockmanager-fail-releaselock": "Nem sikerült a(z) „$1” fájl zárolásának feloldása.",
"lockmanager-fail-db-bucket": "Nem sikerült kapcsolatot létesíteni elég adatbázis zároláshoz a $1 vödörben.",
"lockmanager-fail-db-release": "Nem lehet a $1 adatbázis zárolását feloldani.",
"timezoneregion-indian": "Indlandshaf",
"timezoneregion-pacific": "Kyrrahaf",
"allowemail": "Leyfa öðrum notendum að senda mér tölvupóst",
+ "email-allow-new-users-label": "Leyfa tölvupóst frá nýskráðum notendum",
"prefs-searchoptions": "Leit",
"prefs-namespaces": "Nafnrými",
"default": "sjálfgefið",
"lockmanager-fail-closelock": "Gat ekki lokað lásaskrá vegna „$1“.",
"lockmanager-fail-deletelock": "Gat ekki eytt lásaskrá vegna „$1“.",
"lockmanager-fail-acquirelock": "Gat ekki nálgast lás vegna „$1“.",
- "lockmanager-fail-openlock": "Gat ekki opnað lásaskrá vegna „$1“.",
+ "lockmanager-fail-openlock": "Gat ekki opnað lásaskrá vegna „$1“. Gakkt úr skugga um að innsendingamappan þín sé rétt uppsett, og að vefþjónninn þinn hafi heimildir til að skrifa í þá möppu. Skoðaðu https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgUploadDirectory til að sjá nánari upplýsingar.",
"lockmanager-fail-releaselock": "Gat ekki opnað lás vegna „$1“.",
"lockmanager-fail-db-bucket": "Náði ekki sambandi við nógu marga lása í fötunni $1.",
"lockmanager-fail-db-release": "Gat ekki opnað lása á gagnagrunninum $1.",
"uploadstash-bad-path": "Slóðin er ekki til.",
"uploadstash-bad-path-invalid": "Slóðin er ógild.",
"uploadstash-bad-path-unknown-type": "Óþekkt gerð \"$1\".",
+ "uploadstash-bad-path-unrecognized-thumb-name": "Óþekkt heiti á smámynd.",
+ "uploadstash-file-not-found-no-thumb": "Gat ekki náð í smámynd.",
"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",
"doubleredirects": "Tvöfaldar tilvísanir",
"doubleredirectstext": "Þessi síða er listi yfir skrár sem eru tilvísanir á aðrar tilvísanir.\nHver lína inniheldur tengla á fyrstu og aðra tilvísun auk þeirrar síðu sem seinni tilvísunin beinist að, sem er oftast sú síða sem allar tilvísanirnar eiga að benda á.\n<del>Yfirstrikaðar</del> færslur hafa verið leiðréttar.",
"double-redirect-fixed-move": "[[$1]] hefur verið færð.\nHún var uppfærð sjálfkrafa og tilvísar núna á [[$2]].",
- "double-redirect-fixed-maintenance": "Laga sjálfvirkt tvöfalda tilvísun frá [[$1]] til [[$2]] í viðhalds aðgerð.",
+ "double-redirect-fixed-maintenance": "Laga sjálfvirkt tvöfalda endurbeiningu frá [[$1]] til [[$2]] í viðhaldsaðgerð",
"double-redirect-fixer": "Laga tilvísun",
"brokenredirects": "Rofnar endurbeiningar",
"brokenredirectstext": "Eftirfarandi tilvísanir vísa á síður sem ekki eru til:",
"newimages-hidepatrolled": "Fela yfirfarnar innsendingar",
"newimages-mediatype": "Skrátegund:",
"noimages": "Ekkert að sjá.",
+ "gallery-slideshow-toggle": "Víxla smámyndum af/á",
"ilsubmit": "Leita",
"bydate": "eftir dagsetningu",
"sp-newimages-showfrom": "Leita af nýjum skráum frá $2, $1",
"tog-enotifwatchlistpages": "Inviami una email quando viene modificata una pagina o un file presente tra gli osservati speciali",
"tog-enotifusertalkpages": "Inviami una email quando viene modificata la mia pagina di discussione",
"tog-enotifminoredits": "Inviami una email anche per le modifiche minori di pagine e file",
- "tog-enotifrevealaddr": "Mostra il mio indirizzo nelle e-mail di notifica",
+ "tog-enotifrevealaddr": "Mostra il mio indirizzo nelle email di notifica",
"tog-shownumberswatching": "Mostra il numero di utenti che hanno la pagina in osservazione",
"tog-oldsig": "La tua firma attuale:",
"tog-fancysig": "Gestisci la firma come wikitesto (senza collegamento automatico)",
"mailmypassword": "Reimposta password",
"passwordremindertitle": "Servizio Password Reminder di {{SITENAME}}",
"passwordremindertext": "Qualcuno (probabilmente tu, con indirizzo IP $1) ha richiesto l'invio di una nuova password di accesso a {{SITENAME}} ($4).\nUna password temporanea per l'utente \"$2\" è stata impostata a \"$3\".\nÈ opportuno eseguire un accesso quanto prima e cambiare la password immediatamente. La password temporanea scadrà dopo {{PLURAL:$5|un giorno|$5 giorni}}.\n\nSe non sei stato tu a fare la richiesta, oppure hai ritrovato la password e non desideri più cambiarla, puoi ignorare questo messaggio e continuare a usare la vecchia password.",
- "noemail": "Nessun indirizzo e-mail registrato per l'utente \"$1\".",
- "noemailcreate": "È necessario fornire un indirizzo e-mail valido",
+ "noemail": "Nessun indirizzo email registrato per l'utente \"$1\".",
+ "noemailcreate": "È necessario fornire un indirizzo email valido",
"passwordsent": "Una nuova password è stata inviata all'indirizzo e-mail registrato per l'utente \"$1\".\nPer favore, effettua un accesso non appena la ricevi.",
"blocked-mailpassword": "Il tuo indirizzo IP è bloccato alla modifica. Per prevenire abusi, non è consentito usare la funzione di recupero password da questo indirizzo IP.",
"eauthentsent": "Un messaggio email di conferma è stato spedito all'indirizzo indicato.\nPer abilitare l'invio di messaggi email per questo utente è necessario seguire le istruzioni che vi sono indicate, in modo da confermare che si è i legittimi proprietari dell'indirizzo.",
"acct_creation_throttle_hit": "{{PLURAL:$1|1 registrazione è già stata effettuata|$1 registrazioni sono già state effettuate}} da qualcuno con il tuo stesso indirizzo IP negli ultimi $2, che è il massimo consentito in questo periodo di tempo.\nPerciò, gli utenti che usano questo indirizzo IP non possono più registrarsi per il momento.",
"emailauthenticated": "L'indirizzo email è stato confermato il $2 alle $3.",
"emailnotauthenticated": "L'indirizzo di posta elettronica non è stato ancora confermato.\nNon verranno inviati messaggi email per le funzioni elencate di seguito.",
- "noemailprefs": "Indicare un indirizzo e-mail per attivare queste funzioni.",
+ "noemailprefs": "Indicare un indirizzo email per attivare queste funzioni.",
"emailconfirmlink": "Conferma il tuo indirizzo email",
"invalidemailaddress": "L'indirizzo e-mail indicato ha un formato non valido. Inserire un indirizzo valido o svuotare la casella.",
"cannotchangeemail": "Gli indirizzi e-mail non possono essere modificati in questo wiki.",
"pt-createaccount": "registrati",
"pt-userlogout": "esci",
"php-mail-error-unknown": "Errore sconosciuto nella funzione PHP mail()",
- "user-mail-no-addy": "Hai cercato di inviare una e-mail senza un indirizzo.",
+ "user-mail-no-addy": "Hai cercato di inviare una email senza un indirizzo.",
"user-mail-no-body": "Tentato di inviare una e-mail con un testo vuoto o estremamente breve.",
"changepassword": "Cambia password",
"resetpass_announce": "Per completare l'accesso, è necessario impostare una nuova password.",
"changeemail-password": "La password su {{SITENAME}}:",
"changeemail-submit": "Modifica email",
"changeemail-throttled": "Sono stati effettuati troppi tentativi di accesso.\nAttendi $1 e riprova in seguito.",
- "changeemail-nochange": "Per favore inserisci un nuovo indirizzo e-mail.",
+ "changeemail-nochange": "Per favore inserisci un nuovo indirizzo email.",
"resettokens": "Reimposta token",
"resettokens-text": "Qui puoi reimpostare le chiavi che permettono l'accesso a determinati dati privati associati alla tua utenza.\n\nDovresti farlo se le hai accidentalmente condivise con qualcuno o se la tua utenza è stato compromessa.",
"resettokens-no-tokens": "Non ci sono token da reimpostare.",
"postedit-confirmation-created": "La pagina è stata creata.",
"postedit-confirmation-restored": "La pagina è stata ripristinata.",
"postedit-confirmation-saved": "La modifica è stata salvata.",
+ "postedit-confirmation-published": "La tua modifica è stata pubblicata.",
"edit-already-exists": "Impossibile creare una nuova pagina.\nEsiste già.",
"defaultmessagetext": "Testo predefinito",
"content-failed-to-parse": "Impossibile analizzare $2 per il modello $1: $3",
"defemailsubject": "Messaggio da {{SITENAME}} dall'utente \"$1\"",
"usermaildisabled": "e-mail utente disabilitata",
"usermaildisabledtext": "Non è possibile inviare e-mail ad altri utenti su questo wiki",
- "noemailtitle": "Nessun indirizzo e-mail",
- "noemailtext": "Questo utente non ha indicato un indirizzo e-mail valido.",
+ "noemailtitle": "Nessun indirizzo email",
+ "noemailtext": "Questo utente non ha indicato un indirizzo email valido.",
"nowikiemailtext": "Questo utente ha scelto di non ricevere messaggi di posta elettronica dagli altri utenti.",
"emailnotarget": "Nome utente del destinatario inesistente o non valido.",
"emailtarget": "Inserisci il nome utente del destinatario",
"confirmemail_oncreate": "Un codice di conferma è stato spedito all'indirizzo\ndi posta elettronica indicato. Il codice non è necessario per accedere al sito,\nma è necessario fornirlo per poter abilitare tutte le funzioni del sito che fanno\nuso della posta elettronica.",
"confirmemail_sendfailed": "{{SITENAME}} non può inviare il messaggio e-mail di conferma. Verificare che il proprio indirizzo e-mail non contenga caratteri non validi.\n\nMessaggio di errore del mailer: $1",
"confirmemail_invalid": "Codice di conferma non valido. Il codice potrebbe essere scaduto.",
- "confirmemail_needlogin": "È necessario $1 per confermare il proprio indirizzo e-mail.",
+ "confirmemail_needlogin": "È necessario $1 per confermare il proprio indirizzo email.",
"confirmemail_success": "L'indirizzo e-mail è confermato. Ora è possibile [[Special:UserLogin|eseguire l'accesso]] e fare pieno uso del sito.",
"confirmemail_loggedin": "L'indirizzo email è stato confermato.",
"confirmemail_subject": "{{SITENAME}}: richiesta di conferma dell'indirizzo",
"confirmemail_body": "Qualcuno, probabilmente tu stesso dall'indirizzo IP $1, ha registrato l'account \"$2\" su {{SITENAME}} indicando questo indirizzo e-mail.\n\nPer confermare che l'account ti appartiene veramente e attivare le funzioni relative all'invio di e-mail su {{SITENAME}}, apri il collegamento seguente con il tuo browser:\n\n$3\n\nSe *non* hai registrato tu l'account, segui questo collegamento per annullare la conferma dell'indirizzo e-mail:\n\n$5\n\nQuesto codice di conferma scadrà automaticamente alle $4.",
"confirmemail_body_changed": "Qualcuno, probabilmente tu stesso dall'indirizzo IP $1,\nha modificato l'indirizzo e-mail dell'account \"$2\" su {{SITENAME}} indicando questo indirizzo e-mail.\n\nPer confermare che l'account ti appartiene veramente e riattivare le funzioni relative all'invio\ndi e-mail su {{SITENAME}}, apri il collegamento seguente con il tuo browser:\n\n$3\n\nSe l'account *non* ti appartiene, segui questo collegamento\nper annullare la conferma dell'indirizzo e-mail:\n\n$5\n\nQuesto codice di conferma scadrà automaticamente alle $4.",
"confirmemail_body_set": "Qualcuno, probabilmente tu stesso dall'indirizzo IP $1,\nha impostato l'indirizzo email dell'account \"$2\" su {{SITENAME}} indicando questo indirizzo email.\n\nPer confermare che l'account ti appartiene veramente e attivare le funzioni relative all'invio\ndi email su {{SITENAME}}, apri il collegamento seguente con il tuo browser:\n\n$3\n\nSe l'account *non* ti appartiene, segui questo collegamento\nper annullare la conferma dell'indirizzo email:\n\n$5\n\nQuesto codice di conferma scadrà automaticamente alle $4.",
- "confirmemail_invalidated": "Richiesta di conferma indirizzo e-mail annullata",
+ "confirmemail_invalidated": "Richiesta di conferma indirizzo email annullata",
"invalidateemail": "Annulla richiesta di conferma e-mail",
"notificationemail_subject_changed": "L'indirizzo di posta elettronica registrato su {{SITENAME}} è stato modificato",
"notificationemail_subject_removed": "L'indirizzo di posta elettronica registrato su {{SITENAME}} è stato rimosso",
"recentchangeslinked-feed": "関連ページの更新状況",
"recentchangeslinked-toolbox": "関連ページの更新状況",
"recentchangeslinked-title": "「$1」と関連する変更",
- "recentchangeslinked-summary": "ã\81\93ã\82\8cã\81¯æ\8c\87å®\9aã\81\97ã\81\9fã\83\9aã\83¼ã\82¸ã\81\8bã\82\89ã\83ªã\83³ã\82¯ã\81\95ã\82\8cã\81¦ã\81\84ã\82\8b (ã\81¾ã\81\9fã\81¯æ\8c\87å®\9aã\81\97ã\81\9fã\82«ã\83\86ã\82´ã\83ªã\81«å\90«ã\81¾ã\82\8cã\81¦ã\81\84ã\82\8b) ã\83\9aã\83¼ã\82¸ã\81®æ\9c\80è¿\91ã\81®å¤\89æ\9b´ã\81®ä¸\80覧ã\81§ã\81\99ã\80\82\n[[Special:Watchlist|è\87ªå\88\86ã\81®ã\82¦ã\82©ã\83\83ã\83\81ã\83ªã\82¹ã\83\88]]ã\81«ã\81\82ã\82\8bã\83\9aã\83¼ã\82¸は<strong>太字</strong>で表示されます。",
+ "recentchangeslinked-summary": "ã\83\9aã\83¼ã\82¸å\90\8dã\82\92å\85¥å\8a\9bã\81\99ã\82\8bã\81¨ã\80\81ã\83ªã\83³ã\82¯é\96¢ä¿\82 (ã\81\9dã\81®ã\83\9aã\83¼ã\82¸ã\81®ã\83ªã\83³ã\82¯å\85\88ã\82\82ã\81\97ã\81\8fã\81¯ä»\96ã\81®ã\83\9aã\83¼ã\82¸ã\81\8bã\82\89ã\81®ã\83ªã\83³ã\82¯) ã\81®æ\9c\80è¿\91ã\81®å¤\89æ\9b´ã\82\92調ã\81¹ã\82\8bã\81\93ã\81¨ã\81\8cã\81§ã\81\8dã\81¾ã\81\99ã\80\82 (ä¸\8bä½\8dã\82«ã\83\86ã\82´ã\83ªã\82\92å\8f\82ç\85§ã\81\99ã\82\8bã\81«ã\81¯ã\80\81ã\82«ã\83\86ã\82´ã\83ª:ã\82«ã\83\86ã\82´ã\83ªå\90\8d (Category:Name of category) ã\82\92å\85¥å\8a\9b)ã\80\82[[Special:Watchlist|è\87ªå\88\86ã\81®ã\82¦ã\82©ã\83\83ã\83\81ã\83ªã\82¹ã\83\88]]ã\81«ã\81\82ã\82\8bã\83\9aã\83¼ã\82¸ã\81®å¤\89æ\9b´は<strong>太字</strong>で表示されます。",
"recentchangeslinked-page": "ページ名:",
"recentchangeslinked-to": "このページへのリンク元での変更の表示に切り替え",
"recentchanges-page-added-to-category": "[[:$1]]をカテゴリに追加",
"uploaded-script-svg": "アップロードされたSVGファイルにスクリプト可能な要素「$1」が見つかりました。",
"uploaded-hostile-svg": "アップロードされたSVGファイルのスタイル要素に安全ではないCSSが見つかりました。",
"uploaded-event-handler-on-svg": "イベントハンドラをセットする属性 <code>$1=\"$2\"</code> は、SVGファイルを許可されていません。",
- "uploaded-href-attribute-svg": "SVG ファイルの href 属性が http:// または https:// のターゲットのみにリンクする <code><$1 $2=\"$3\"></code> が見つかりました。",
+ "uploaded-href-attribute-svg": "<a> 要素では、データ (埋め込みファイル)、http://、https://、フラグメント (#、ID 属性など) のターゲットにのみリンクできます。<image> などの他の要素では、データとフラグメントのみが使用できます。SVG をエクスポートする際は画像を埋め込むようにしてください。アップロードされたファイルには <code><$1 $2=\"$3\"></code> が含まれています。",
"uploaded-href-unsafe-target-svg": "アップロードされた SVG ファイルの、安全ではないデータ URI にターゲット <code><$1 $2=\"$3\"></code> の href が見つかりました。",
"uploaded-animate-svg": "アップロードされたSVGファイルに、「from」属性 <code><$1 $2=\"$3\"></code> を使用した、href を変更させる可能性がある「animate」タグが見つかりました。",
"uploaded-setting-event-handler-svg": "アップロードされたSVGファイルに、ブロックされているイベントハンドラ属性が設定された <code><$1 $2=\"$3\"></code> が見つかりました。",
"lockmanager-fail-closelock": "「$1」用のロックファイルを閉じることができませんでした。",
"lockmanager-fail-deletelock": "「$1」用のロックファイルを削除できませんでした。",
"lockmanager-fail-acquirelock": "「$1」用のロックを取得できませんでした。",
- "lockmanager-fail-openlock": "「$1」用のロックファイルを開くことができませんでした。",
+ "lockmanager-fail-openlock": "「$1」用のロックファイルを開くことができませんでした。アップロードディレクトリが正しく設定されており、ウェブサーバーによる書き込みの権限が許可されていることを確認してください。詳しくは https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgUploadDirectory をご覧ください。",
"lockmanager-fail-releaselock": "「$1」用のロックを解放できませんでした。",
"lockmanager-fail-db-bucket": "バケツ $1 で十分な数のロックデータベースに接触できませんでした。",
"lockmanager-fail-db-release": "データベース $1 上のロックを解放できませんでした。",
"uploadstash-refresh": "ファイルの一覧を更新",
"uploadstash-thumbnail": "サムネイルを表示",
"uploadstash-exception": "スタッシュにアップロードできませんでした ($1): \"$2\"",
+ "uploadstash-bad-path": "パスが存在しません。",
+ "uploadstash-bad-path-invalid": "パスが無効です。",
+ "uploadstash-bad-path-unknown-type": "「$1」は不明なタイプです。",
+ "uploadstash-bad-path-unrecognized-thumb-name": "サムネイル名が認識できません。",
+ "uploadstash-bad-path-no-handler": "ファイル $2 の MIME $1 に対するハンドラが見つかりません。",
+ "uploadstash-bad-path-bad-format": "キー「$1」は適切な形式ではありません。",
"uploadstash-zero-length": "ファイルのサイズがゼロです。",
"invalid-chunk-offset": "無効なチャンクオフセット",
"img-auth-accessdenied": "アクセスが拒否されました",
"import-mapping-namespace": "名前空間へインポート:",
"import-mapping-subpage": "次のページの下位ページとしてインポート:",
"import-upload-filename": "ファイル名:",
+ "import-upload-username-prefix": "インターウィキ接頭辞:",
"import-comment": "コメント:",
"importtext": "元のウィキで[[Special:Export|書き出し機能]]を使用してファイルに書き出してください。\nそれをコンピューターに保存した後、こちらへアップロードしてください。",
"importstart": "ページを取り込み中...",
"pageinfo-category-subcats": "下位カテゴリ数",
"pageinfo-category-files": "ファイル数",
"pageinfo-user-id": "利用者 ID",
+ "pageinfo-file-hash": "ハッシュ値",
"markaspatrolleddiff": "巡回済みにする",
"markaspatrolledtext": "このページを巡回済みにする",
"markaspatrolledtext-file": "このファイルの版を巡回済みにする",
"limitreport-expensivefunctioncount": "高負荷パーサー関数の数",
"limitreport-expensivefunctioncount-value": "$1/$2",
"expandtemplates": "テンプレートを展開",
- "expand_templates_intro": "この特別ページは、入力したテキストに含まれるすべてのテンプレートを再帰的に展開します。\n<code><nowiki>{{</nowiki>#language:…}}</code> のようなパーサー関数や、\n<code><nowiki>{{</nowiki>CURRENTDAY}}</code> のような変数も展開します。\nつまり、二重中括弧で囲まれたものほぼすべてを展開します。",
+ "expand_templates_intro": "ã\81\93ã\81®ç\89¹å\88¥ã\83\9aã\83¼ã\82¸ã\81¯ã\80\81å\85¥å\8a\9bã\81\97ã\81\9fã\82¦ã\82£ã\82ã\83\86ã\82ã\82¹ã\83\88ã\81«å\90«ã\81¾ã\82\8cã\82\8bã\81\99ã\81¹ã\81¦ã\81®ã\83\86ã\83³ã\83\97ã\83¬ã\83¼ã\83\88ã\82\92å\86\8d帰ç\9a\84ã\81«å±\95é\96\8bã\81\97ã\81¾ã\81\99ã\80\82\n<code><nowiki>{{</nowiki>#language:â\80¦}}</code> ã\81®ã\82\88ã\81\86ã\81ªã\83\91ã\83¼ã\82µã\83¼é\96¢æ\95°ã\82\84ã\80\81\n<code><nowiki>{{</nowiki>CURRENTDAY}}</code> ã\81®ã\82\88ã\81\86ã\81ªå¤\89æ\95°ã\82\82å±\95é\96\8bã\81\97ã\81¾ã\81\99ã\80\82\nã\81¤ã\81¾ã\82\8aã\80\81äº\8cé\87\8dä¸æ\8b¬å¼§ã\81§å\9b²ã\81¾ã\82\8cã\81\9fã\82\82ã\81®ã\81»ã\81¼ã\81\99ã\81¹ã\81¦ã\82\92å±\95é\96\8bã\81\97ã\81¾ã\81\99ã\80\82",
"expand_templates_title": "{{FULLPAGENAME}} などで使用するページ名:",
- "expand_templates_input": "展開するテキスト:",
+ "expand_templates_input": "å±\95é\96\8bã\81\99ã\82\8bã\82¦ã\82£ã\82ã\83\86ã\82ã\82¹ã\83\88:",
"expand_templates_output": "展開結果",
"expand_templates_xml_output": "XML 出力",
"expand_templates_html_output": "出力される HTML ソース",
"expand_templates_preview": "プレビュー",
"expand_templates_preview_fail_html": "<em>{{SITENAME}} ではHTMLソースが有効になっており、セッションデータの損失が生じているので、JavaScript の攻撃に対する予防措置としてプレビューは表示されません。</em>\n\n<strong>これが合法的なプレビューの試みである場合には、もう一度試してください。</strong>\nそれでも動作しない場合は、[[Special:UserLogout|ログアウト]]してからログインし直し、現在使用しているブラウザでこのサイトからのクッキーが許可されていることを確認してください。",
"expand_templates_preview_fail_html_anon": "<em>{{SITENAME}} ではHTMLソースが有効になっており、ログインしていないため、JavaScript の攻撃に対する予防措置としてプレビューは表示されません。</em>\n\n<strong>これが合法的なプレビューの試みである場合には、[[Special:UserLogin|ログイン]]してもう一度試してください。</strong>",
- "expand_templates_input_missing": "文章を入力してください。",
+ "expand_templates_input_missing": "ウィキテキストを入力してください。",
"pagelanguage": "ページ言語の変更",
"pagelang-name": "ページ",
"pagelang-language": "言語",
"restrictionsfield-label": "許可する IP の範囲:",
"restrictionsfield-help": "一行につき、単一の IP アドレス、もしくは CIDR による範囲。全帯域からの接続を許可する場合: <pre>0.0.0.0/0\n::/0</pre>",
"edit-error-short": "エラー: $1",
- "edit-error-long": "エラー:\n\n\n\n$1",
+ "edit-error-long": "エラー:\n\n\n\n$1",
"revid": "版 $1",
"pageid": "ページID $1",
"rawhtml-notallowed": "<html>タグは通常ページ以外では使用できません。",
"site-rss-feed": "$1 ''RSS Feed''",
"site-atom-feed": "Lebon atom $1",
"page-rss-feed": "\"$1\" ''RSS Feed''",
- "page-atom-feed": "\"$1\" ''Atom Feed''",
+ "page-atom-feed": "Pakan atom \"$1\"",
"red-link-title": "$1 (kaca ora ana)",
"sort-descending": "Urutaké medhun",
"sort-ascending": "Urutaké munggah",
"nosuchaction": "Ora ana tumindak mangkono",
"nosuchactiontext": "Tumindak sing dikarepaké déning URL ora trep.\nPanjenengan bokmanawa salah ngetik URL-é, utawa salah nurut pranala.\nIki bokmanawa uga nuduhaké yèn ana ama ing piranti alus sing dianggo déning {{SITENAME}}.",
"nosuchspecialpage": "Ora ana kaca mirunggan mangkono",
- "nospecialpagetext": "Panjenengan nyuwun kaca astaméwa sing ora sah. Daftar kaca astaméwa sing sah bisa dipirsani ing [[Special:SpecialPages|daftar kaca astaméwa]].",
+ "nospecialpagetext": "<strong>Panjenengan nyuwun kaca mirunggan sing ora sah.</strong>\n\nPratélan kaca mirunggan sing sah bisa tinemu ing [[Special:SpecialPages|{{int:specialpages}}]].",
"error": "Masalah",
"databaseerror": "Masalah sasana dhata",
"databaseerror-text": "Ana kerusakan ing basis data (query error).\n\nMungkin ana masalah ing software-e.",
"showingresults": "Ing ngisor iki dituduhaké {{PLURAL:$1|'''1''' kasil|'''$1''' kasil}}, wiwitané saking #<strong>$2</strong>.",
"showingresultsinrange": "Nuduhaké nganti {{PLURAL:$1|<strong>1</strong> kasil|<strong>$1</strong> kasil}} sajeroning penthangan #<strong>$2</strong> tekan #<strong>$3</strong>.",
"search-showingresults": "{{PLURAL:$4|Asil <strong>$1</strong> saka <strong>$3</strong>|Asil <strong>$1 – $2</strong> saka <strong>$3</strong>}}",
- "search-nonefound": "Ora ana kasil sing cocog karo pitakonan (''query'').",
+ "search-nonefound": "Ora ana kasil sing mathuk karo pitakoné.",
"search-nonefound-thiswiki": "Ora ana kasil sing jumbuh karo panjalukan ing situs iki.",
"powersearch-legend": "Panggolèkan sabanjuré (''advance search'')",
"powersearch-ns": "Golèk ing mandala aran:",
"recentchanges": "Owahan-owahan anyar",
"recentchanges-legend": "Opsi owah-owahan anyar",
"recentchanges-summary": "Lacak owah-owahan anyar wiki iki ing kaca iki.",
- "recentchanges-noresult": "Ora ana pangowahan ing periode sing diwiwiti kriteria iki.",
+ "recentchanges-noresult": "Ora ana owahan ing kalamangsa sing mathuk karo pranatan iki.",
"recentchanges-feed-description": "Urutna owah-owahan anyar ing wiki ing ''feed'' iki.",
"recentchanges-label-newpage": "Besutan iki nggawé kaca anyar",
"recentchanges-label-minor": "Iki besutan cilik",
"recentchangeslinked-title": "Owah-owahan sing magepokan \"$1\"",
"recentchangeslinked-summary": "Iki pratélaning owah-owahan sing mentas digawé tumrap ing kaca-kaca sing nggayut sawijining kaca (utawa kaca-kaca anggotaning sawijining kategori).\nKaca ing [[Special:Watchlist|pawawangané panjenegan]] <strong>dikandeli</strong>.",
"recentchangeslinked-page": "Jeneng kaca:",
- "recentchangeslinked-to": "Nuduhaké owah-owahan menyang kaca sing disambung menyang kaca-kaca iki",
+ "recentchangeslinked-to": "Nuduhaké owah-owahan kaca-kaca sing nggayut kaca iki",
"recentchanges-page-added-to-category": "[[:$1]] ditambahaké ing kategori",
"recentchanges-page-added-to-category-bundled": "[[:$1]] ditambahaké ing kategori, [[Special:WhatLinksHere/$1|kaca iki kalebu ing njeroné kaca liyané]]",
"recentchanges-page-removed-from-category": "[[:$1]] dibusak saka kategori",
"mywatchlist": "Pawawangan",
"watchlistfor2": "Kanggo $1 $2",
"nowatchlist": "Ora ana apa-apa ing pawawanganing sampéyan.",
- "watchlistanontext": "Mangga $1 kanggo mirsani utawa nyunting daftar pangawasan panjenengan.",
+ "watchlistanontext": "Sumangga mlebu log saperlu ndeleng utawa mbesut barang ing pawawangané panjenengan.",
"watchnologin": "Durung mlebu log",
"addwatch": "Tambah nèng daptar pangawasan",
"addedwatchtext": "Kaca \"[[:$1]]\" wis ditambahaké menyang [[Special:Watchlist|daftar pangawasan]].\nOwah-owahan sing dumadi ing tembé ing kaca iku lan kaca dhiskusi sing kagandhèng, bakal dipacak ing kéné.",
"import-upload": "Ngunggahaké data XML",
"import-token-mismatch": "Kélangan data sèsi. Mangga dijajal manèh.",
"import-invalid-interwiki": "Ora bisa ngimport saka wiki sing kapilih.",
- "import-error-edit": "Kaca \"$1\" ora diimpor amarga Sampéyan ora dililakaké nyunting kuwi.",
+ "import-error-edit": "Kaca \"$1\" ora kaimpor amarga panjenengan ora kawogan mbesut iku.",
"import-error-create": "Kaca \"$1\" ora diimpor amarga Sampéyan ora dililakaké nggawé kuwi.",
"import-error-interwiki": "Kaca \"$1\" ora diimpor amarga jenengé dicadhangaké kango pranala njaba (interwiki).",
"import-error-special": "Kaca \"$1\" ora diimpor amarga darbèké mandala aran mirunggan sing ora nglilakaké anané kaca.",
"tooltip-t-whatlinkshere": "Pratélané kabèh kaca wiki sing nggayut mréné",
"tooltip-t-recentchangeslinked": "Owah-owahan anyar saka kaca-kaca sing nggayut kaca iki",
"tooltip-feed-rss": "''RSS feed'' kanggo kaca iki",
- "tooltip-feed-atom": "''Atom feed'' kanggo kaca iki",
+ "tooltip-feed-atom": "Pakan atom tumrap kaca iki",
"tooltip-t-contributions": "Pratélaning pisumbanging {{GENDER:$1|panganggo iki}}",
"tooltip-t-emailuser": "Kirimi layang-èl nyang {{GENDER:$1|panganggo iki}}",
"tooltip-t-info": "Katerangan liyané ngenani kaca iki",
"exif-referenceblackwhite": "Wiji réferènsi pasangan ireng putih",
"exif-datetime": "Tanggal lan wektu owahé barkas",
"exif-imagedescription": "Sesirah gambar",
- "exif-make": "Produsèn kamera",
+ "exif-make": "Prodhusèn kodhak",
"exif-model": "Modhèl kaméra",
"exif-software": "Piranti alus sing dianggo",
"exif-artist": "Prodhusèn",
"scarytranscludetoolong": "[URL-é kedawan]",
"deletedwhileediting": "<strong>Pélik:</strong> Kaca iki wis dibusak kawit pisanan panjenengan mbesut!",
"confirmrecreate": "Panganggo [[User:$1|$1]] ([[User talk:$1|Wicara]]) wis mbusak kaca iki nalika panjenengan miwiti panyuntingan mawa alesan:\n: ''$2''\nMangga didhedhes (dikonfirmasi) menawa panjenengan kersa nggawé ulang kaca iki.",
- "confirmrecreate-noreason": "Panganggo [[User:$1|$1]] ([[User talk:$1|wicara]]) mbusak kaca iki sakbaré Sampéyan lekas nyunting. Mangga pesthèkaké yèn Sampéyan pancen pingin tenan nggawé manèh kaca iki.",
+ "confirmrecreate-noreason": "Panganggo [[User:$1|$1]] ([[User talk:$1|rembug]]) {{GENDER:$1|mbusak}} kaca iki sawisé panjenengan wiwit mbesut. Sumangga konfirmasi yèn panjenengan temen arep nggawé manèh kaca iki.",
"recreate": "Gawé ulang",
"confirm-purge-title": "Buwang kaca iki",
"confirm_purge_button": "OK",
"redirect": "Lih-lihan miturut barkas, panganggo, kaca, owahan, utawa cathetan",
"redirect-summary": "Kaca mirunggan iki ngener ing sawijining barkas (jeneng gambar diwenehi), kaca (ID revisi utama ID kaca diwenehi), utawa kaca panganggo (ID panganggo diwenehi). Cara nganggo: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], or [[{{#Special:Redirect}}/user/101]].",
"redirect-submit": "Menyang",
- "redirect-lookup": "Golek:",
+ "redirect-lookup": "Luru:",
"redirect-value": "Aji:",
"redirect-user": "ID panganggo",
"redirect-page": "ID kaca",
"logentry-patrol-patrol": "$1 {{GENDER:$2|nengeri}} révisi $4 saka kaca $3 sing diawasi",
"logentry-patrol-patrol-auto": "$1 otomatis {{GENDER:$2|nandhani}} benahan $4 saka kaca $3 kaawasake",
"logentry-newusers-newusers": "Akun panganggo $1 {{GENDER:$2|digawé}}",
- "logentry-newusers-create": "Akun panganggo $1 {{GENDER:$2|digawé}}",
+ "logentry-newusers-create": "Akun panganggo $1 wis {{GENDER:$2|kagawé}}",
"logentry-newusers-create2": "Akun panganggo $3 {{GENDER:$2|digawé}} déning $1",
"logentry-newusers-byemail": "Akun panganggo $3 {{GENDER:$2|digawé}} déning $1 lan tembung wadi dikirim lumantar layang-èl",
"logentry-newusers-autocreate": "Akun panganggo $1 otomatis {{GENDER:$2|digawé}}",
"postedit-confirmation-created": "D'Säit gouf ugeluecht.",
"postedit-confirmation-restored": "D'Säit gouf restauréiert.",
"postedit-confirmation-saved": "Är Ännerung gouf gespäichert.",
+ "postedit-confirmation-published": "Är Ännerung gouf verëffentlecht.",
"edit-already-exists": "Déi nei Säit konnt net ugeluecht ginn, well et se scho gëtt.",
"defaultmessagetext": "Standardtext",
"content-failed-to-parse": "Den $2-Inhalt fir den $1-Modell konnt net geparst ginn: $3",
"mediawikipage": "Vizualizza o messaggio",
"templatepage": "Vizualizza o modello",
"viewhelppage": "Móstra a pagina d'agiutto",
- "categorypage": "Veddi a pagina da categorîa",
+ "categorypage": "Amia a pagina da categoria",
"viewtalkpage": "Amîa a pagina de discusción",
"otherlanguages": "In âtre léngoe",
"redirectedfrom": "(Rendirissou da $1)",
"perfcached": "I dæti chì apreuvo son estræti da 'na coppia ''cache'' do database, e porrieivan no ese agiornæ. Un mascimo de {{PLURAL:$1|un risultou o l'è disponibbile|$1 risultæ son disponibbili}} into cache.",
"perfcachedts": "I dæti chì apreuvo son estræti da una coppia ''cache'' do database, o quæ urtimo agiornamento o remonta a-o $1. Un mascimo de {{PLURAL:$4|un risultou o l'è disponibbile|$4 risultæ son disponibili}} into cache.",
"querypage-no-updates": "I agiornamenti da pagina son temporaniamente sospeixi. I dæti in lé contegnui no saian aggiornæ.",
- "viewsource": "Veddi a fonte",
+ "viewsource": "Vixualizza wikitesto",
"viewsource-title": "Visualizza sorgente de $1",
"actionthrottled": "Assion ritardâ",
"actionthrottledtext": "Comme mesua de segueça contra o spam, l'esecuçion de çerte açioin a l'è limitâ a un nummero mascimo de votte inte 'n determinòu periodo de tempo, limmite che ti t'hæ superòu. Se prega de riprovâ tra quarche menuto.",
"publishpage": "Pubbrica a paggina",
"publishchanges": "Pubbrica e modiffiche",
"preview": "Anteprìmma",
- "showpreview": "Veddi l'anteprimma",
- "showdiff": "Veddi i cangiamenti",
+ "showpreview": "Amia l'anteprimma",
+ "showdiff": "Mostra modiffiche",
"blankarticle": "<strong>Atençión:</strong> a pàgina che ti çerchi a l'é vêua.\nClicando tórna in sce \"$1\", a pàgina a saiâ creâ sénsa contegnûi.",
"anoneditwarning": "<strong>Attension:</strong> No t'ê introu. Se ti fæ di cangi o teu adresso IP o saiâ vixibile pubbricamente. Se <strong>[$1 ti intri]</strong> ò <strong>[$2 ti crei un'utensa]</strong>, e teu modifiche saian attribuie a-o teu nomme utente, insemme a di atri benefiççi.",
"anonpreviewwarning": "No t'hæ fæto l'accesso. Se ti sarvi inta stoia da paggina ghe saiâ solo o to adresso IP",
"undo-summary-username-hidden": "Anullou a modiffica $1 de un utente ascoso",
"cantcreateaccount-text": "A registrassion da questo addresso IP (<b>$1</b>) a l'è stæta bloccâ da [[User:$3|$3]].\n\nA raxon dæta a l'è ''$2''",
"cantcreateaccount-range-text": "A registraçion da di addressi IP inte l'intervallo <strong>$1</strong>, ch'o l'includde o teu (<strong>$4</strong>), a l'è stæta bloccâ da [[User:$3|$3]].\n\nA raxon dæta da $3 a l'è <em>$2</em>",
- "viewpagelogs": "Veddi i log relativi a 'sta paggina.",
+ "viewpagelogs": "Amia i log relativi a 'sta paggina.",
"nohistory": "A stoia de verscioin de sta paggina a no gh'è.",
"currentrev": "Verscion attuâle",
"currentrev-asof": "Ùrtima revixón do $1",
"recentchanges-label-unpatrolled": "Sto cangiaménto o no l'é stæto ancón verificòu",
"recentchanges-label-plusminus": "Variassion da paggina in nummero de byte",
"recentchanges-legend-heading": "<strong>Legenda:</strong>",
- "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (veddi e [[Special:NewPages|neuve paggine]])",
+ "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (amia e [[Special:NewPages|noeuve paggine]])",
"recentchanges-submit": "Fanni vedde",
"rcfilters-activefilters": "Filtri attivi",
"rcfilters-advancedfilters": "Filtri avançæ",
"recentchanges-page-removed-from-category-bundled": "[[:$1]] rimossa da-a categoria, [[Special:WhatLinksHere/$1|questa pagina a l'è inclusa a l'interno di atre pagine]]",
"autochange-username": "Modiffica aotomattica MediaWiki",
"upload": "Carrega 'n file",
- "uploadbtn": "Carrega 'n file",
+ "uploadbtn": "Carreghilo",
"reuploaddesc": "Torna a-o moddulo pe-o caregamento.",
"upload-tryagain": "Invia a descrission do file modificou",
"uploadnologin": "No t'ê introu",
"upload-curl-error6-text": "Imposcibile razonze a URL specificâ. Verifica che a URL a sæ scrita correttamente e che o scito in question o sæ attivo.",
"upload-curl-error28": "Tempo descheito pe l'upload",
"upload-curl-error28-text": "O scito remoto o l'ha impiegou troppo tempo a risponde. Verifica che o sito o sæ attivo, attendi quarche menuto e proeuva torna, se mai inte 'n momento con meno traffego.",
- "license": "Licénsa:",
- "license-header": "Licénsa",
+ "license": "Liçençia:",
+ "license-header": "Liçençia",
"nolicense": "Nisciûnn-a liçensa indicâa",
"licenses-edit": "Modiffica opçioin de liçença",
"license-nopreview": "(Anteprimma non disponibbile)",
"modifiedarticleprotection-comment": "{{GENDER:$2|Cangiou o livello de proteçion}} pe \"[[$1]]\"",
"unprotectedarticle-comment": "{{GENDER:$2|Rimosso a proteçion}} da \"[[$1]]\"",
"protect-title": "Cangio do livello de proteçion pe \"$1\"",
- "protect-title-notallowed": "Veddi o livello de proteçion de \" $1 \"",
+ "protect-title-notallowed": "Amia o livello de proteçion de \" $1 \"",
"prot_1movedto2": "[[$1]] mesciòu a [[$2]]",
"protect-badnamespace-title": "Namespace non protezibbile",
"protect-badnamespace-text": "E pagine de questo namespace no poeuan ese protezue.",
"restriction-level-autoconfirmed": "semi-protezua",
"restriction-level-all": "Tutti i livelli",
"undelete": "Amîa e paggine scassæ",
- "undeletepage": "Veddi e recuppera e pagine scançellæ",
+ "undeletepage": "Amia e recuppera e paggine scassæ",
"undeletepagetitle": "'''Quanto segue o l'è composto da de revixoin scassæ de [[:$1|$1]]'''.",
- "viewdeletedpage": "Veddi e paggine scassæ",
+ "viewdeletedpage": "Amia e paggine scassæ",
"undeletepagetext": "{{PLURAL:$1|A seguente pagina a l'è stæta scassâ, ma a l'è ancon in archivio e pertanto a poeu ese recuperâ|E seguente pagine son stæte scassæ, ma son ancon in archivio e pertanto poeuan ese recuperæ}}. L'archivio o poeu ese vuou periodicamente.",
"undelete-fieldset-title": "Ripristina revixoin",
"undeleteextrahelp": "Pe recuperâ l'intrega cronologia da pagina, lascia tutte e caselle deseleçionæ e fanni clic insce '''''{{int:undeletebtn}}'''''.\nPe effettuâ un ripristino selettivo, seleçion-a e caselle corrispondente a-e verscioin da ripristinâ e fanni clic insce '''''{{int:undeletebtn}}'''''.",
"tooltip-t-permalink": "Colegaménto fisso a sta revixión da pàgina",
"tooltip-ca-nstab-main": "Véddi a vôxe",
"tooltip-ca-nstab-user": "Amîa a paggina utente",
- "tooltip-ca-nstab-media": "Veddi a paggina do file murtimediâ",
+ "tooltip-ca-nstab-media": "Amia a paggina do file murtimediâ",
"tooltip-ca-nstab-special": "Sta chi l'è 'na pàgina speciâle e a no peu êse cangiâ",
"tooltip-ca-nstab-project": "Véddi a pàgina de servìçio",
- "tooltip-ca-nstab-image": "Veddi a paggina do file",
- "tooltip-ca-nstab-mediawiki": "Veddi o messaggio de scistema",
- "tooltip-ca-nstab-template": "Veddi o template",
- "tooltip-ca-nstab-help": "Veddi a paggina d'agiûtto",
+ "tooltip-ca-nstab-image": "Amia a paggina do file",
+ "tooltip-ca-nstab-mediawiki": "Amia o messaggio de scistema",
+ "tooltip-ca-nstab-template": "Amia o template",
+ "tooltip-ca-nstab-help": "Amia a paggina d'agiutto",
"tooltip-ca-nstab-category": "Véddi a pàgina da categorîa",
"tooltip-minoredit": "Marchilo comme cangiaménto minô",
"tooltip-save": "Sarva i cangiaménti",
"watchlistedit-clear-removed": "L'è stæto eliminou {{PLURAL:$1|una paggina|$1 paggine}}:",
"watchlistedit-too-many": "Gh'è troppe paggine da visualizzâ chì.",
"watchlisttools-clear": "Svoeua a lista sott'öservaçion",
- "watchlisttools-view": "Veddi e modiffiche pertinenti",
- "watchlisttools-edit": "Veddi e modiffica a lista",
+ "watchlisttools-view": "amia e modiffiche pertinenti",
+ "watchlisttools-edit": "Amia e modiffica a lista",
"watchlisttools-raw": "Modiffica a lista in formato testo",
"signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|discuscioin]])",
"timezone-local": "Locale",
"postedit-confirmation-created": "Lapa ir izveidota.",
"postedit-confirmation-restored": "Lapa ir atjaunota.",
"postedit-confirmation-saved": "Jūsu labojums tika saglabāts.",
+ "postedit-confirmation-published": "Tavs labojums tika publicēts.",
"edit-already-exists": "Nevar izveidot jaunu lapu.\nTā jau eksistē.",
"defaultmessagetext": "Noklusētais ziņojuma teksts",
"invalid-content-data": "Nederīgi satura dati",
"right-writeapi": "Rakstīšanas API lietošana",
"right-delete": "Dzēst lapas",
"right-bigdelete": "Dzēst lapas ar lielām hronoloģijām",
+ "right-deletelogentry": "Dzēst un atjaunot konkrētus žurnāla ierakstus",
"right-deleterevision": "Dzēst un atjaunot lapu noteiktas versijas",
"right-deletedhistory": "Skatīt izdzēstos hronoloģijas ierakstus, bez tiem piesaistītā teksta",
"right-deletedtext": "Apskatīt izdzēsto tekstu un izmaiņas starp izdzēstām versijām",
"doubleredirects": "Divkāršas pāradresācijas lapas",
"doubleredirectstext": "Šajā lapā ir uzskaitītas pāradresācijas lapas, kuras pāradresē uz citām pāradresācijas lapām.\nKatrā rindiņā ir saites uz pirmo un otro pāradresācijas lapu, kā arī pirmā rindiņa no otrās pāradresācijas lapas teksta, kas parasti ir faktiskā \"gala\" lapa, uz kuru vajadzētu būt saitei pirmajā lapā.\n<del>Nosvītrotie</del> ieraksti jau ir tikuši salaboti.",
"double-redirect-fixed-move": "[[$1]] bija ticis pārvietots, tas tagad ir pāradresācija uz [[$2]]",
- "double-redirect-fixed-maintenance": "Labota dubultā pāradresācija no [[$1]] uz [[$2]].",
+ "double-redirect-fixed-maintenance": "Automātiski ar apkopes procesu labota dubultā pāradresācija no [[$1]] uz [[$2]].",
"double-redirect-fixer": "Pāradresāciju labotājs",
"brokenredirects": "Kļūdainas pāradresācijas",
"brokenredirectstext": "Šīs ir pāradresācijas lapas uz neesošām lapām:",
"postedit-confirmation-created": "Страницата е создадена.",
"postedit-confirmation-restored": "Страницата е повратена.",
"postedit-confirmation-saved": "Вашето уредување е зачувано.",
+ "postedit-confirmation-published": "Вашето уредување е објавено.",
"edit-already-exists": "Не може да се создаде нова страница.\nИстата веќе постои.",
"defaultmessagetext": "Текст на пораката по основно",
"content-failed-to-parse": "Не успеав да ја предадам содржината од типот $2 за моделот $1: $3",
"lockmanager-fail-closelock": "Не можев да ја затворам податотеката-катанец за „$1“.",
"lockmanager-fail-deletelock": "Не можев да ја избришам податотеката-катанец за „$1“.",
"lockmanager-fail-acquirelock": "Не можев да добијам катанец за „$1“.",
- "lockmanager-fail-openlock": "Ð\9dе можев да Ñ\98а оÑ\82воÑ\80ам подаÑ\82оÑ\82екаÑ\82а-каÑ\82анеÑ\86 за â\80\9e$1â\80\9c.",
+ "lockmanager-fail-openlock": "Ð\9dе можев да Ñ\98а оÑ\82воÑ\80ам заклÑ\83Ñ\87наÑ\82а подаÑ\82оÑ\82ека â\80\9e$1â\80\9c. Ð\9fÑ\80овеÑ\80еÑ\82е дали папкаÑ\82а за подигаÑ\9aа е пÑ\80авилно поÑ\81Ñ\82авена и ваÑ\88иоÑ\82 Ñ\81емÑ\80ежен опÑ\81лÑ\83жÑ\83ваÑ\87 има дозвола да Ñ\81нима во неа. Ð\9fовеÑ\9cе инÑ\84оÑ\80маÑ\86ии Ñ\9cÑ\87е наÑ\98деÑ\82е на https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgUploadDirectory.",
"lockmanager-fail-releaselock": "Не можев да го ослободам катанецот за „$1“.",
"lockmanager-fail-db-bucket": "Не можев да контактирам доволно податотеки-катанци во садот $1",
"lockmanager-fail-db-release": "Не можев да ги ослободам катанците на базата $1",
"postedit-confirmation-created": "De pagina is aangemaakt.",
"postedit-confirmation-restored": "De pagina is hersteld.",
"postedit-confirmation-saved": "Uw bewerking is opgeslagen.",
+ "postedit-confirmation-published": "Uw bewerking is opgeslagen.",
"edit-already-exists": "De pagina is niet aangemaakt.\nDeze bestaat al.",
"defaultmessagetext": "Standaardinhoud",
"content-failed-to-parse": "Het was niet mogelijk de inhoud van het MIME-type $2 voor het model $1 te verwerken: $3.",
"postedit-confirmation-created": "A página foi criada.",
"postedit-confirmation-restored": "Esta página foi restaurada.",
"postedit-confirmation-saved": "Sua edição foi salva",
+ "postedit-confirmation-published": "A sua edição foi publicada.",
"edit-already-exists": "Não foi possível criar uma nova página.\nEla já existia.",
"defaultmessagetext": "Texto da mensagem padrão",
"content-failed-to-parse": "Falha ao analisar o conteúdo $2 para o modelo $1: $3",
"emailconfirmlink": "Confirme o seu endereço de correio eletrónico",
"invalidemailaddress": "O endereço de correio eletrónico não pode ser aceite porque parece ter um formato inválido.\nIntroduza um endereço formatado corretamente ou deixe o campo vazio.",
"cannotchangeemail": "Os endereços de correio eletrónico das contas não podem ser alterados nesta wiki.",
- "emaildisabled": "Este site não consegue enviar mensagens de correio eletrónico.",
+ "emaildisabled": "Este sítio não consegue enviar mensagens de correio eletrónico.",
"accountcreated": "Conta criada",
"accountcreatedtext": "A conta de utilizador para [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|talk]]) foi criada.",
"createaccount-title": "Criação de conta na wiki {{SITENAME}}",
"previewnote": "<strong>Lembre-se de que esta é apenas uma antevisão do resultado.</strong>\nAs modificações ainda não foram gravadas!",
"continue-editing": "Ir para a área de edição",
"previewconflict": "Esta antevisão do resultado apresenta o texto da caixa de edição acima tal como este aparecerá se escolher gravá-lo.",
- "session_fail_preview": "Desculpe! Não foi possível processar a edição devido à perda dos dados da sua sessão.\n\nA sua sessão poderá ter sido encerrada. <strong>Verifique se ainda está autenticado e tente novamente, por favor</strong>. \nCaso continue a não funcionar, tente [[Special:UserLogout|sair]] e voltar a entrar na sua conta, e verifique se o seu navegador permite cookies deste site.",
- "session_fail_preview_html": "Desculpe! Não foi possível processar a edição devido à perda de dados da sua sessão.\n\n<em>Como a wiki {{SITENAME}} possibilita o uso de HTML puro, a antevisão está oculta por precaução contra ataques com JavaScript.</em>\n\n<strong>Se esta é uma tentativa legítima de edição tente novamente, por favor</strong>. \nCaso continue a não funcionar, tente [[Special:UserLogout|sair]] e voltar a entrar na sua conta, e verifique se o seu navegador permite <em>cookies</em> deste <em>site</em>.",
+ "session_fail_preview": "Desculpe! Não foi possível processar a edição devido à perda dos dados da sua sessão.\n\nA sua sessão poderá ter sido encerrada. <strong>Verifique se ainda está autenticado e tente novamente, por favor</strong>. \nCaso continue a não funcionar, tente [[Special:UserLogout|sair]] e voltar a entrar na sua conta, e verifique se o seu navegador permite cookies deste sítio.",
+ "session_fail_preview_html": "Desculpe! Não foi possível processar a edição devido à perda de dados da sua sessão.\n\n<em>Como a wiki {{SITENAME}} possibilita o uso de HTML puro, a antevisão está oculta por precaução contra ataques com JavaScript.</em>\n\n<strong>Se esta é uma tentativa legítima de edição tente novamente, por favor</strong>. \nCaso continue a não funcionar, tente [[Special:UserLogout|sair]] e voltar a entrar na sua conta, e verifique se o seu navegador permite <em>cookies</em> deste sítio.",
"token_suffix_mismatch": "<strong>A edição foi rejeitada porque o seu navegador alterou os sinais de pontuação no editor.</strong>\nA edição foi rejeitada para evitar perdas no texto da página.\nIsto acontece ocasionalmente quando se usa um serviço de proxy anonimizador mal configurado.",
"edit_form_incomplete": "<strong>Algumas partes do formulário de edição não chegaram ao servidor; verifique que a sua edição continua intacta e tente novamente, por favor.</strong>",
"editing": "A editar $1",
"postedit-confirmation-created": "A página foi criada.",
"postedit-confirmation-restored": "A página foi restaurada.",
"postedit-confirmation-saved": "A sua edição foi gravada.",
+ "postedit-confirmation-published": "A sua edição foi publicada.",
"edit-already-exists": "Não foi possível criar uma página nova.\nEla já existia.",
"defaultmessagetext": "Texto da mensagem padrão",
"content-failed-to-parse": "Falha ao analisar conteúdo $2 para modelo $1:$3",
"showingresultsinrange": "Apresenta-se abaixo {{PLURAL:$1|<strong>1</strong> resultado|até <strong>$1</strong> resultados}} no intervalo #<strong>$2</strong> a #<strong>$3</strong>.",
"search-showingresults": "{{PLURAL:$4|Resultado <strong>$1</strong> de <strong>$3</strong>|Resultados <strong>$1 - $2</strong> de <strong>$3</strong>}}",
"search-nonefound": "A pesquisa não produziu resultados.",
- "search-nonefound-thiswiki": "Não existem resultados que correspondam à consulta neste site.",
+ "search-nonefound-thiswiki": "Não existem resultados que correspondam à consulta neste sítio.",
"powersearch-legend": "Pesquisa avançada",
"powersearch-ns": "Pesquisar nos domínios:",
"powersearch-togglelabel": "Marcar:",
"prefs-custom-css": "CSS personalizado",
"prefs-custom-js": "JS personalizado",
"prefs-common-css-js": "CSS/JS partilhado por todos os temas:",
- "prefs-reset-intro": "Pode usar esta página para repor as configurações padrão das preferências.\nAs suas preferências serão modificadas para os valores predefinidos do site.\nEsta operação não pode ser desfeita.",
+ "prefs-reset-intro": "Pode usar esta página para repor as configurações padrão das preferências.\nAs suas preferências serão modificadas para os valores predefinidos do sítio.\nEsta operação não pode ser desfeita.",
"prefs-emailconfirm-label": "Confirmação do correio eletrónico:",
"youremail": "Correio eletrónico:",
"username": "Nome de {{GENDER:$1|utilizador|utilizadora|utilizador(a)}}:",
"lockmanager-fail-closelock": "Não foi possível encerrar a referência de bloqueio para \"$1\".",
"lockmanager-fail-deletelock": "Não foi possível eliminar a referência de bloqueio para \"$1\".",
"lockmanager-fail-acquirelock": "Não foi possível adquirir bloqueio para \"$1\".",
- "lockmanager-fail-openlock": "Não foi possível abrir o ficheiro de bloqueio de \"$1\".",
+ "lockmanager-fail-openlock": "Não foi possível abrir o ficheiro de bloqueio de \"$1\". Verifique que o seu diretório de carregamento está devidamente configurado e que o seu servidor de Internet tem permissão para escrever nesse diretório. Para mais informações, consulte https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgUploadDirectory.",
"lockmanager-fail-releaselock": "Não foi possível libertar o bloqueio de \"$1\".",
"lockmanager-fail-db-bucket": "Não foi possível contactar bases de dados de bloqueio suficientes no \"bucket\" $1.",
"lockmanager-fail-db-release": "Não foi possível libertar bloqueios na base de dados $1.",
"http-curl-error": "Ocorreu um erro ao aceder ao URL: $1",
"http-bad-status": "Ocorreu um problema durante o pedido HTTP: $1 $2",
"upload-curl-error6": "Não foi possível aceder ao URL",
- "upload-curl-error6-text": "Não foi possível aceder ao URL.\nVerifique se o endereço está correto e o site disponível, por favor.",
+ "upload-curl-error6-text": "Não foi possível aceder ao URL.\nVerifique se o endereço está correto e o sítio disponível, por favor.",
"upload-curl-error28": "Tempo limite para o envio do ficheiro excedido",
- "upload-curl-error28-text": "O site demorou demasiado tempo a responder. Verifique que o site está disponível, aguarde alguns momentos e tente novamente, por favor. Talvez queira voltar a tentar numa altura menos congestionada.",
+ "upload-curl-error28-text": "O sítio demorou demasiado tempo a responder. Verifique que o sítio está disponível, aguarde alguns momentos e tente novamente, por favor. Talvez queira voltar a tentar numa altura menos congestionada.",
"license": "Licença:",
"license-header": "Licenciamento",
"nolicense": "Nenhuma selecionada",
"apihelp-no-such-module": "Módulo \"$1\" não encontrado.",
"apisandbox": "Testes da API",
"apisandbox-jsonly": "Para usar a área de testes da API é necessário o JavaScript.",
- "apisandbox-api-disabled": "A API está desativada neste site.",
+ "apisandbox-api-disabled": "A API está desativada neste sítio.",
"apisandbox-intro": "Use esta página para fazer experiências com a <strong>API operacional do MediaWiki</strong>.\nConsulte a [[mw:API:Main page|documentação da API]] para informações sobre o seu uso. Exemplo: [https://www.mediawiki.org/wiki/API#A_simple_example obter o conteúdo da Página Principal]. Selecione uma operação para ver mais exemplos.\n\nNote que, embora esta seja uma área de testes, as operações que executar nesta página podem modificar a wiki.",
"apisandbox-fullscreen": "Expandir painel",
"apisandbox-fullscreen-tooltip": "Expandir o painel da página de testes para preencher a janela do navegador.",
"booksources-invalid-isbn": "O número ISBN fornecido não parece ser válido; verifique a existência de erros ao copiar da fonte original.",
"magiclink-tracking-rfc": "Páginas que usam hiperligações mágicas RFC",
"magiclink-tracking-rfc-desc": "Esta página usa hiperligações mágicas RFC. Consulte a [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] para saber como migrar.",
- "magiclink-tracking-pmid": "Páginas que usam links mágicos PMID",
+ "magiclink-tracking-pmid": "Páginas que usam hiperligações mágicas PMID",
"magiclink-tracking-pmid-desc": "Esta página usa hiperligações mágicas PMID. Consulte a [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] para saber como migrar.",
- "magiclink-tracking-isbn": "Páginas que usam links mágicos ISBN",
+ "magiclink-tracking-isbn": "Páginas que usam hiperligações mágicas ISBN",
"magiclink-tracking-isbn-desc": "Esta página usa hiperligações mágicas ISBN. Consulte a [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] para saber como migrar.",
"specialloguserlabel": "Executante:",
"speciallogtitlelabel": "Alvo (título ou página ou {{ns:user}}:nome de utilizador):",
"import-nonewrevisions": "Não foi importada nenhuma revisão (já estavam todas presentes ou foram ignoradas devido a erros).",
"xml-error-string": "$1 na linha $2, coluna $3 (byte $4): $5",
"import-upload": "Enviar dados em XML",
- "import-token-mismatch": "Perda de dados da sessão.\n\nA sua sessão pode ter sido encerrada. '''Verifique se ainda está autenticado e tente novamente, por favor'''. \nCaso continue a não funcionar, tente [[Special:UserLogout|sair]] e voltar a entrar na sua conta, e verifique se o seu navegador permite cookies deste site.",
+ "import-token-mismatch": "Perda de dados da sessão.\n\nA sua sessão pode ter sido encerrada. '''Verifique se ainda está autenticado e tente novamente, por favor'''. \nCaso continue a não funcionar, tente [[Special:UserLogout|sair]] e voltar a entrar na sua conta, e verifique se o seu navegador permite cookies deste sítio.",
"import-invalid-interwiki": "Não é possível importar da wiki especificada.",
"import-error-edit": "A página \"$1\" não foi importada porque não tem permissão para editá-la.",
"import-error-create": "A página \"$1\" não foi importada porque não tem permissão para criá-la.",
"creditspage": "Créditos da página",
"nocredits": "Não há informação disponível sobre os créditos desta página.",
"spamprotectiontitle": "Filtro de proteção contra spam",
- "spamprotectiontext": "O texto que pretendia gravar foi bloqueado pelo filtro de spam.\nEste bloqueio foi provavelmente causado por uma hiperligação para um ''site'' externo que está na lista negra.",
+ "spamprotectiontext": "O texto que pretendia gravar foi bloqueado pelo filtro de spam.\nEste bloqueio foi provavelmente causado por uma hiperligação para um sítio externo que está na lista negra.",
"spamprotectionmatch": "O seguinte texto ativou o filtro de <i>spam</i>: $1",
"spambot_username": "MediaWiki limpeza de spam",
"spam_reverting": "A reverter para a última revisão que não contém ligação para $1",
"invalidateemail": "Cancelar confirmação do correio eletrónico",
"notificationemail_subject_changed": "O endereço de correio eletrónico registado na wiki {{SITENAME}} foi alterado",
"notificationemail_subject_removed": "O endereço de correio eletrónico registado na wiki {{SITENAME}} foi removido",
- "notificationemail_body_changed": "Alguém, provavelmente você, a partir do endereço IP $1, alterou o endereço de correio eletrónico da conta \"$2\" para \"$3\" na wiki {{SITENAME}}.\n\nCaso não o tenha alterado, contacte imediatamente um administrador do site.",
- "notificationemail_body_removed": "Alguém, provavelmente você, a partir do endereço IP $1, eliminou o endereço de correio eletrónico da conta \"$2\" na wiki {{SITENAME}}.\n\nCaso não o tenha eliminado, contacte imediatamente um administrador do site.",
+ "notificationemail_body_changed": "Alguém, provavelmente você, a partir do endereço IP $1, alterou o endereço de correio eletrónico da conta \"$2\" para \"$3\" na wiki {{SITENAME}}.\n\nCaso não o tenha alterado, contacte imediatamente um administrador do sítio.",
+ "notificationemail_body_removed": "Alguém, provavelmente você, a partir do endereço IP $1, eliminou o endereço de correio eletrónico da conta \"$2\" na wiki {{SITENAME}}.\n\nCaso não o tenha eliminado, contacte imediatamente um administrador do sítio.",
"scarytranscludedisabled": "[Transclusão interwikis foi impossibilitada]",
"scarytranscludefailed": "[Não foi possível obter a predefinição a partir de $1]",
"scarytranscludefailed-httpstatus": "[Não foi possível obter a predefinição a partir de $1: HTTP $2]",
"permanentlink": "Hiperligação permanente",
"permanentlink-revid": "Identificador de revisão",
"permanentlink-submit": "Ir para a revisão",
- "dberr-problems": "Desculpe! Este site está com dificuldades técnicas.",
+ "dberr-problems": "Desculpe! Este sítio está com dificuldades técnicas.",
"dberr-again": "Experimente esperar alguns minutos e atualizar.",
"dberr-info": "(Não foi possível aceder ao servidor da base de dados: $1)",
"dberr-info-hidden": "(Não foi possível aceder ao servidor da base de dados)",
"expand_templates_generate_xml": "Mostrar a árvore de análise sintáctica do XML",
"expand_templates_generate_rawhtml": "Mostrar o HTML puro",
"expand_templates_preview": "Antevisão do resultado",
- "expand_templates_preview_fail_html": "<em>Porque a wiki {{SITENAME}} permite código HTML puro e ocorreu uma perda de dados da sessão, a antevisão ficará ocultada como precaução contra ataques por JavaScript.</em>\n\n<strong>Se esta é uma tentativa legítima de visionamento, por favor tente novamente.</strong>\nCaso continue a não funcionar, tente [[Special:UserLogout|sair]] e voltar a entrar na sua conta, e verifique se o seu navegador permite que este site crie ''cookies''.",
+ "expand_templates_preview_fail_html": "<em>Porque a wiki {{SITENAME}} permite código HTML puro e ocorreu uma perda de dados da sessão, a antevisão ficará ocultada como precaução contra ataques por JavaScript.</em>\n\n<strong>Se esta é uma tentativa legítima de visionamento, por favor tente novamente.</strong>\nCaso continue a não funcionar, tente [[Special:UserLogout|sair]] e voltar a entrar na sua conta, e verifique se o seu navegador permite que este sítio crie ''cookies''.",
"expand_templates_preview_fail_html_anon": "<em>Porque a wiki {{SITENAME}} permite código HTML puro e não iniciou uma sessão, a antevisão ficará ocultada como precaução contra ataques por JavaScript.</em>\n\n<strong>Se esta é uma tentativa legítima de visionamento, por favor [[Special:UserLogin|inicie uma sessão]] e tente novamente.</strong>",
"expand_templates_input_missing": "Necessita de fornecer pelo menos algum texto wiki de entrada.",
"pagelanguage": "Alterar a língua da página",
"rawhtml-notallowed": "As etiquetas <html> não podem ser utilizadas fora de páginas normais.",
"gotointerwiki": "A sair da wiki {{SITENAME}}",
"gotointerwiki-invalid": "O título especificado é inválido.",
- "gotointerwiki-external": "Está prestes a sair da wiki {{SITENAME}} para visitar [[$2]], que é um site externo.\n\n'''[$1 Continuar para $1]'''",
+ "gotointerwiki-external": "Está prestes a sair da wiki {{SITENAME}} para visitar [[$2]], que é um sítio externo.\n\n'''[$1 Continuar para $1]'''",
"undelete-cantedit": "Não pode restaurar esta página porque não tem privilégios para a editar.",
"undelete-cantcreate": "Não pode restaurar esta página porque não existe nenhuma página com este nome e não tem privilégios para criar esta página.",
"pagedata-title": "Dados de página",
"postedit-confirmation-created": "{{gender}}\nShown after a user creates a new page. Parameters:\n* $1 - the current user, for GENDER support",
"postedit-confirmation-restored": "{{gender}}\nShown after a user restores a page to a previous revision. Parameters:\n* $1 - the current user, for GENDER support",
"postedit-confirmation-saved": "{{gender}}\nShown after a user saves a page. Parameters:\n* $1 - the current user, for GENDER support",
+ "postedit-confirmation-published": "{{gender}}\nShown after a user publishes a page. Parameters:\n* $1 - the current user, for GENDER support",
"edit-already-exists": "Used as error message.\n\nSee also:\n* {{msg-mw|edit-hook-aborted}}\n* {{msg-mw|edit-gone-missing}}\n* {{msg-mw|edit-conflict}}\n* {{msg-mw|edit-no-change}}",
"addsection-preload": "{{notranslate}}",
"addsection-editintro": "{{notranslate}}",
"tog-hidepatrolled": "Скрывать патрулированные правки в списке свежих правок",
"tog-newpageshidepatrolled": "Скрывать отпатрулированные страницы в списке новых страниц",
"tog-hidecategorization": "Скрывать категоризацию страниц",
- "tog-extendwatchlist": "РаÑ\81Ñ\88иÑ\80иÑ\82Ñ\8c Ñ\81пиÑ\81ок наблÑ\8eдениÑ\8f, вклÑ\8eÑ\87аÑ\8eÑ\89аÑ\8f вÑ\81е изменениÑ\8f, а не Ñ\82олÑ\8cко поÑ\81ледние <small>(они могÑ\83Ñ\82 бÑ\8bÑ\82Ñ\8c Ñ\81гÑ\80Ñ\83ппиÑ\80ованÑ\8b наÑ\81Ñ\82Ñ\80ойкой на вкладке «[[СлÑ\83жебнаÑ\8f:Ð\9dаÑ\81Ñ\82Ñ\80ойки#mw-prefsection-rc|Свежие пÑ\80авки]]»)</small>",
+ "tog-extendwatchlist": "Расширить список наблюдения, включая все изменения, а не только последние <small>(они могут быть сгруппированы настройкой на вкладке «[[Служебная:Настройки#mw-prefsection-rc|Свежие правки]]»)</small>",
"tog-usenewrc": "Группировать изменения в свежих правках и списке наблюдения",
"tog-numberheadings": "Автоматически нумеровать заголовки",
"tog-showtoolbar": "Показывать панель инструментов при редактировании",
"postedit-confirmation-created": "Страница создана.",
"postedit-confirmation-restored": "Страница была восстановлена.",
"postedit-confirmation-saved": "Ваша правка сохранена.",
+ "postedit-confirmation-published": "Ваша правка была опубликована.",
"edit-already-exists": "Невозможно создать новую страницу.\nОна уже существует.",
"defaultmessagetext": "Текст по умолчанию",
"content-failed-to-parse": "Содержимое $2 не соответствует типу $1: $3.",
"lockmanager-fail-closelock": "Не удалось закрыть файл блокировки для «$1».",
"lockmanager-fail-deletelock": "Не удалось удалить файл блокировки для «$1».",
"lockmanager-fail-acquirelock": "Не удалось добиться блокировки «$1».",
- "lockmanager-fail-openlock": "Не удалось открыть файл блокировки для «$1».",
+ "lockmanager-fail-openlock": "Не удалось открыть файл блокировки для «$1». Убедитесь, что ваш каталог загрузки настроен правильно, а ваш веб-сервер имеет разрешение на запись в этот каталог. Дополнительную информацию см. на https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgUploadDirectory.",
"lockmanager-fail-releaselock": "Не удалось разблокировать «$1».",
"lockmanager-fail-db-bucket": "Не удалось связаться с достаточным количеством баз блокировок в сегменте $1.",
"lockmanager-fail-db-release": "Не удалось снять блокировку базы данных $1 .",
"postedit-confirmation-created": "Сирэй оҥоһулунна.",
"postedit-confirmation-restored": "Сирэй сөргүтүлүннэ.",
"postedit-confirmation-saved": "Көннөрүүҥ бигэргэннэ.",
+ "postedit-confirmation-published": "Уларытыыҥ олоххо киирдэ.",
"edit-already-exists": "Саҥа сирэйи оҥорор табыллыбат.\nМаннык сирэй баар эбит.",
"defaultmessagetext": "Туспа этиллибэтэҕинэ суруллар тиэкис",
"content-failed-to-parse": "$2 иһинээҕитэ $1 көрүҥэр сөп түбэспэт: $3.",
"search-showingresults": "{{PLURAL:$4|نتيجو <strong>$1</strong> of <strong>$3</strong>|نتيجا <strong>$1 - $2</strong> of <strong>$3</strong>}}",
"search-nonefound": "توھان جي ڳولا جي نتيجي ۾ ڪجھہ بہ نہ لڌو.",
"powersearch-legend": "اعليٰ ڳولا",
+ "powersearch-ns": "نالن لاءِ ڇڏين وڇوٽين ۾ ڳولھيو (سرچ اِن نيم اسپيسز)",
"powersearch-togglelabel": "چڪاسيو:",
"powersearch-toggleall": "سڀ",
"powersearch-togglenone": "ڪو بہ نہ",
"nrevisions": "$1 {{PLURAL:$1|مسودو|مسودا}}",
"nimagelinks": "$1 {{PLURAL:$1|صفحي|صفحن}} ۾ استعمال ٿيل",
"ntransclusions": "$1 {{PLURAL:$1|صفحي|صفحن}} ۾ استعمال ٿيل",
- "specialpage-empty": "ھن رپورٽ لاءِ ڪي-بہ نتيجا ناھن.",
+ "specialpage-empty": "ھن رپورٽ لاءِ ڪي بہ نتيجا ناھن.",
"lonelypages": "يتيم صفحا",
"uncategorizedpages": "اڻ زمريل صفحا",
"uncategorizedcategories": "اڻزمرايل زمرا",
"restriction-level-sysop": "مڪمل طور تحفظيل",
"restriction-level-autoconfirmed": "نيم تحفظيل",
"viewdeletedpage": "ڊاٺل صفحا ڏسو",
- "undelete-nodiff": "ڪوبہ پويون مسودو نہ لڌو",
+ "undelete-nodiff": "ڪوبہ اڳيون مسودو نہ لڌو",
"undeletebtn": "بحاليو",
"undeleteviewlink": "ڏسو",
"undeletecomment": "سبب:",
"version-libraries-description": "تشريح",
"version-libraries-authors": "ليکڪ",
"redirect-submit": "ھلو",
+ "redirect-lookup": "ڏسو:",
"redirect-value": "قدر:",
"redirect-user": "واپرائيندڙ آءِڊي",
"redirect-page": "صفحي جي آءِڊي",
"postedit-confirmation-created": "Stran je bila ustvarjena.",
"postedit-confirmation-restored": "Stran je bila obnovljena.",
"postedit-confirmation-saved": "Vaše urejanje smo shranili.",
+ "postedit-confirmation-published": "Vaše urejanje smo objavili.",
"edit-already-exists": "Ni bilo mogoče ustvariti nove strani, ker že obstaja.",
"defaultmessagetext": "Prednastavljeno besedilo",
"content-failed-to-parse": "Nisem mogel razčleniti vsebine $2 za obliko $1: $3",
"lockmanager-fail-closelock": "Ne morem zapreti zaklenitvene datoteke »$1«.",
"lockmanager-fail-deletelock": "Ne morem izbrisati zaklenitvene datoteke »$1«.",
"lockmanager-fail-acquirelock": "Ne morem pridobiti zaklenitvene datoteke »$1«.",
- "lockmanager-fail-openlock": "Ne morem odpreti zaklenitvene datoteke »$1«.",
+ "lockmanager-fail-openlock": "Ne morem odpreti zaklenitvene datoteke »$1«. Prepričajte se, da je mapa za nalaganje nastavljena pravilno in da ima vaš spletni strežnik pravice za pisanje v tej mapi. Oglejte si https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgUploadDirectory za več informacij.",
"lockmanager-fail-releaselock": "Ne morem sprostiti zaklepa »$1«.",
"lockmanager-fail-db-bucket": "Ne morem kontaktirati zadostnega števila zaklenitvenih zbirk podatkov v vedru $1.",
"lockmanager-fail-db-release": "Ne morem sprostiti zaklepov zbirke podatkov $1.",
"exception-nologin": "Нисте пријављени",
"exception-nologin-text": "Пријавите се да бисте приступили овој страници или радњи.",
"exception-nologin-text-manual": "Морате бити $1 да бисте приступили овој страници или радњи.",
- "virus-badscanner": "Ð\9dеиÑ\81пÑ\80авна поÑ\81Ñ\82авка: непознати скенер за вирусе: <em>$1</em>",
+ "virus-badscanner": "Ð\9dеиÑ\81пÑ\80авно подеÑ\88аваÑ\9aе: непознати скенер за вирусе: <em>$1</em>",
"virus-scanfailed": "неуспешно скенирање (код $1)",
"virus-unknownscanner": "непознати антивирус:",
"logouttext": "<strong>Одјављени сте.</strong>\n\nИмајте на уму да неке странице могу наставити да се приказују као да сте још пријављени, све док не очистите привремену меморију Вашег прегледача.",
"userpage-userdoesnotexist": "Кориснички налог „<nowiki>$1</nowiki>“ није отворен.\nРазмислите да ли заиста желите да направите/уредите ову страницу.",
"userpage-userdoesnotexist-view": "Кориснички налог „$1“ није отворен.",
"blocked-notice-logextract": "Овај корисник је тренутно блокиран.\nИзвештај о последњем блокирању можете погледати испод:",
- "clearyourcache": "<strong>Ð\9dапомена:</strong> након Ñ\87Ñ\83ваÑ\9aа, можда Ñ\9bеÑ\82е моÑ\80аÑ\82и да оÑ\87иÑ\81Ñ\82иÑ\82е кеÑ\88 пÑ\80егледаÑ\87а како биÑ\81Ñ\82е видели пÑ\80омене.\n* <strong>Фајерфокс / Сафари:</strong> држите <em>Shift</em> и кликните на <em>Освежи</em>, или притисните <em>Ctrl-F5</em> или <em>Ctrl-R</em> (<em>⌘-R</em> на Меку)\n* <strong>Гугл кроум:</strong> притисните <em>Ctrl-Shift-R</em> (<em>⌘-Shift-R</em> на Меку)\n* <strong>Интернет експлорер:</strong> држите <em>Ctrl</em> и кликните на <em>Освежи</em> или притисните <em>Ctrl-F5</em>\n* <strong>Опера:</strong> идите на <em>Алатке → Подешавања</em> (<em>Опера → Поставке</em> на Меку) и затим <em>Приватност и безбедност → Очистите податке о прегледима → Кеширане слике и датотеке</em>.",
- "usercssyoucanpreview": "'''Савет:''' кориситите дугме „{{int:showpreview}}“ да испробате свој нови CSS пре него што га сачувате.",
- "userjsyoucanpreview": "'''Савет:''' кориситите дугме „{{int:showpreview}}“ да испробате свој нови јаваскрипт пре него што га сачувате.",
- "usercsspreview": "'''Ово је само преглед CSS-а.'''\n'''Страница још није сачувана!'''",
- "userjspreview": "'''Ово је само преглед јаваскрипта.'''\n'''Страница још није сачувана!'''",
- "sitecsspreview": "'''Ово је само преглед CSS-а.'''\n'''Страница још није сачувана!'''",
- "sitejspreview": "'''Ово је само преглед јаваскрипта.'''\n'''Страница још није сачувана!'''",
+ "clearyourcache": "<strong>Ð\9dапомена:</strong> након Ñ\87Ñ\83ваÑ\9aа, можда Ñ\9bеÑ\82е моÑ\80аÑ\82и да оÑ\87иÑ\81Ñ\82иÑ\82е кеÑ\88 пÑ\80егледаÑ\87а како биÑ\81Ñ\82е видели измене.\n* <strong>Фајерфокс / Сафари:</strong> држите <em>Shift</em> и кликните на <em>Освежи</em>, или притисните <em>Ctrl-F5</em> или <em>Ctrl-R</em> (<em>⌘-R</em> на Меку)\n* <strong>Гугл кроум:</strong> притисните <em>Ctrl-Shift-R</em> (<em>⌘-Shift-R</em> на Меку)\n* <strong>Интернет експлорер:</strong> држите <em>Ctrl</em> и кликните на <em>Освежи</em> или притисните <em>Ctrl-F5</em>\n* <strong>Опера:</strong> идите на <em>Алатке → Подешавања</em> (<em>Опера → Поставке</em> на Меку) и затим <em>Приватност и безбедност → Очистите податке о прегледима → Кеширане слике и датотеке</em>.",
+ "usercssyoucanpreview": "<strong>Савет:<strong> кориситите дугме „{{int:showpreview}}“ да испробате свој нови CSS пре него што га сачувате.",
+ "userjsyoucanpreview": "<strong>Савет:</strong> кориситите дугме „{{int:showpreview}}“ да испробате свој нови јаваскрипт пре него што га сачувате.",
+ "usercsspreview": "<strong>Ово је само преглед CSS-а.\nСтраница још није сачувана!</strong>",
+ "userjspreview": "<strong>Ово је само преглед јаваскрипта.\nСтраница још није сачувана!</strong>",
+ "sitecsspreview": "<strong>Ово је само преглед CSS-а.\nСтраница још није сачувана!</strong>",
+ "sitejspreview": "<strong>Ово је само преглед јаваскрипта.\nСтраница још није сачувана!</strong>",
"userinvalidcssjstitle": "<strong>Упозорење:</strong> не постоји тема „$1“.\nПрилагођене странице CSS и јаваскрипт почињу малим словом, нпр. {{ns:user}}:Foo/vector.css, а не {{ns:user}}:Foo/Vector.css.",
"updated": "(ажурирано)",
"note": "<strong>Напомена:</strong>",
"previewnote": "<strong>Не заборавите да је ово само претпреглед.</strong>\nВаше измене још нису сачуване!",
"continue-editing": "Иди на уређивачки оквир",
- "previewconflict": "Овај преглед осликава како ће текст у текстуалном оквиру изгледати.",
- "session_fail_preview": "Ð\98звиÑ\9aавамо Ñ\81е! Ð\9dиÑ\81мо могли да обÑ\80адимо Ð\92аÑ\88Ñ\83 изменÑ\83 због гÑ\83биÑ\82ка подаÑ\82ака Ñ\81еÑ\81иÑ\98е.\n\nÐ\9cожда Ñ\81Ñ\82е одÑ\98авÑ\99ени. <strong>Ð\9fÑ\80овеÑ\80иÑ\82е да ли Ñ\81Ñ\82е пÑ\80иÑ\98авÑ\99ени и покÑ\83Ñ\88аÑ\98Ñ\82е поново</strong>.\nÐ\90ко и даÑ\99е не Ñ\80ади, покÑ\83Ñ\88аÑ\98Ñ\82е да Ñ\81е [[Special:UserLogout|одÑ\98авиÑ\82е]] и поново пÑ\80иÑ\98авиÑ\82е, Ñ\82е пÑ\80овеÑ\80иÑ\82е да ли Ñ\81Ñ\83 на Ð\92аÑ\88ем пÑ\80еÑ\82Ñ\80аживачу дозвољени колачићи са овог сајта.",
+ "previewconflict": "Овај преглед осликава како ће изгледати текст у текстуалном оквиру.",
+ "session_fail_preview": "Ð\9dиÑ\81мо могли да обÑ\80адимо Ð\92аÑ\88Ñ\83 изменÑ\83 због гÑ\83биÑ\82ка подаÑ\82ака Ñ\81еÑ\81иÑ\98е.\n\nÐ\9cожда Ñ\81Ñ\82е одÑ\98авÑ\99ени. <strong>Ð\9fÑ\80овеÑ\80иÑ\82е да ли Ñ\81Ñ\82е пÑ\80иÑ\98авÑ\99ени и покÑ\83Ñ\88аÑ\98Ñ\82е поново</strong>.\nÐ\90ко и даÑ\99е не Ñ\80ади, покÑ\83Ñ\88аÑ\98Ñ\82е да Ñ\81е [[Special:UserLogout|одÑ\98авиÑ\82е]] и поново пÑ\80иÑ\98авиÑ\82е, Ñ\82е пÑ\80овеÑ\80иÑ\82е да ли Ñ\81Ñ\83 на Ð\92аÑ\88ем пÑ\80егледачу дозвољени колачићи са овог сајта.",
"session_fail_preview_html": "Нисмо могли да обрадимо вашу измену због губитка података сесије.\n\n<em>Будући да је на овом викију омогућен унос HTML ознака, преглед је сакривен као мера предострожности против напада преко јаваскрипта.</em>\n\n<strong>Ако сте покушали да направите праву измену, покушајте поново.<strong>\nАко и даље не ради, покушајте да се [[Special:UserLogout|одјавите]] и поново пријавите и проверите да ли Ваш прегледач дозвољава колачиће са овог сајта.",
- "token_suffix_mismatch": "'''Ваша измена је одбачена јер је ваш прегледач убацио знакове интерпункције у новчић уређивања.\nТо се понекад догађа када се користи неисправан посредник.'''",
+ "token_suffix_mismatch": "<strong>Ваша измена је одбачена јер је ваш прегледач убацио знакове интерпункције у новчић уређивања.</strong>\nТо се понекад догађа када се користи неисправан посредник.",
"edit_form_incomplete": "<strong>Неки делови обрасца за уређивање нису стигли до сервера. Проверите да ли су ваше измене непромењене и покушајте поново.</strong>",
"editing": "Уређујете $1",
"creating": "Прављење странице $1",
"editingsection": "Уређујете $1 (одељак)",
"editingcomment": "Уређујете $1 (нови одељак)",
"editconflict": "Сукобљене измене: $1",
- "explainconflict": "Ð\9dеко дÑ\80Ñ\83ги Ñ\98е Ñ\83 меÑ\92Ñ\83вÑ\80еменÑ\83 пÑ\80оменио овÑ\83 Ñ\81Ñ\82Ñ\80аниÑ\86Ñ\83.\nÐ\93оÑ\80Ñ\9aи оквиÑ\80 Ñ\81адÑ\80жи Ñ\81адаÑ\88Ñ\9aи Ñ\82екÑ\81Ñ\82 Ñ\81Ñ\82Ñ\80аниÑ\86е.\nÐ\92аÑ\88е измене Ñ\81Ñ\83 пÑ\80иказане Ñ\83 доÑ\9aем оквиÑ\80Ñ\83.\nÐ\9cоÑ\80аÑ\9bеÑ\82е да Ñ\83неÑ\81еÑ\82е Ñ\81воÑ\98е пÑ\80омене у садашњи текст странице.\n<strong>Само</strong> ће текст у горњем оквиру за уређивање бити сачуван када кликнете на „$1”.",
+ "explainconflict": "Ð\9dеко дÑ\80Ñ\83ги Ñ\98е Ñ\83 меÑ\92Ñ\83вÑ\80еменÑ\83 пÑ\80оменио овÑ\83 Ñ\81Ñ\82Ñ\80аниÑ\86Ñ\83.\nÐ\93оÑ\80Ñ\9aи оквиÑ\80 Ñ\81адÑ\80жи Ñ\81адаÑ\88Ñ\9aи Ñ\82екÑ\81Ñ\82 Ñ\81Ñ\82Ñ\80аниÑ\86е.\nÐ\92аÑ\88е измене Ñ\81Ñ\83 пÑ\80иказане Ñ\83 доÑ\9aем оквиÑ\80Ñ\83.\nÐ\9cоÑ\80аÑ\9bеÑ\82е да Ñ\83неÑ\81еÑ\82е Ñ\81воÑ\98е измене у садашњи текст странице.\n<strong>Само</strong> ће текст у горњем оквиру за уређивање бити сачуван када кликнете на „$1”.",
"yourtext": "Ваш текст",
"storedversion": "Ускладиштена измена",
"editingold": "<strong>Упозорење: уређујете застарелу измену ове странице.</strong>\nАко је сачувате, све новије измене ће бити изгубљене.",
"yourdiff": "Разлике",
- "copyrightwarning": "Ð\98маÑ\98Ñ\82е на Ñ\83мÑ\83 да Ñ\81е Ñ\81ви допÑ\80иноÑ\81и на овом викиÑ\98Ñ\83 Ñ\81маÑ\82Ñ\80аÑ\98Ñ\83 као обÑ\98авÑ\99ени под лиÑ\86енÑ\86ом $2 (виÑ\88е на $1).\nÐ\90ко не желиÑ\82е да Ñ\81е ваÑ\88и Ñ\82екÑ\81Ñ\82ови меÑ\9aаÑ\98Ñ\83 и Ñ\80азмеÑ\9aÑ\83Ñ\98Ñ\83 без огÑ\80аниÑ\87еÑ\9aа, онда иÑ\85 не Ñ\88аÑ\99иÑ\82е овде.<br />\nÐ\98Ñ\81Ñ\82о Ñ\82ако обеÑ\9bаваÑ\82е да Ñ\81Ñ\82е ви аутор текста, или да сте га умножили с извора који је у јавном власништву.\n<strong>Не шаљите радове заштићене ауторским правима без дозволе!</strong>",
+ "copyrightwarning": "Ð\98маÑ\98Ñ\82е на Ñ\83мÑ\83 да Ñ\81е Ñ\81ви допÑ\80иноÑ\81и на овом викиÑ\98Ñ\83 Ñ\81маÑ\82Ñ\80аÑ\98Ñ\83 као обÑ\98авÑ\99ени под лиÑ\86енÑ\86ом $2 (виÑ\88е на $1).\nÐ\90ко не желиÑ\82е да Ñ\81е ваÑ\88и Ñ\82екÑ\81Ñ\82ови меÑ\9aаÑ\98Ñ\83 и Ñ\80азмеÑ\9aÑ\83Ñ\98Ñ\83 без огÑ\80аниÑ\87еÑ\9aа, онда иÑ\85 не Ñ\88аÑ\99иÑ\82е овде.<br />\nÐ\98Ñ\81Ñ\82о Ñ\82ако обеÑ\9bаваÑ\82е да Ñ\81Ñ\82е Ð\92и аутор текста, или да сте га умножили с извора који је у јавном власништву.\n<strong>Не шаљите радове заштићене ауторским правима без дозволе!</strong>",
"copyrightwarning2": "Имајте на уму да се сви доприноси на овом викију могу мењати, враћати или брисати од других корисника.\nАко не желите да се ваши текстови слободно мењају и расподељују, не шаљите их овде.<br />\nИсто тако обећавате да сте ви аутор текста, или да сте га умножили с извора који је у јавном власништву (више на $1).\n<strong>Не шаљите радове заштићене ауторским правима без дозволе!</strong>",
"editpage-cannot-use-custom-model": "Модел садржаја ове странице се не може променити.",
- "longpageerror": "'''Грешка: текст који сте унели је величине {{PLURAL:$1|један килобајт|$1 килобајта|$1 килобајта}}, што је веће од {{PLURAL:$2|дозвољеног једног килобајта|дозвољена $2 килобајта|дозвољених $2 килобајта}}.'''\nСтраница не може бити сачувана.",
+ "longpageerror": "<strong>Грешка: текст који сте унели је величине {{PLURAL:$1|један килобајт|$1 килобајта}}, што је веће од {{PLURAL:$2|дозвољеног једног килобајта|дозвољена $2 килобајта|дозвољених $2 килобајта}}.</strong>\nСтраница не може бити сачувана.",
"readonlywarning": "<strong>Упозорење: база података је закључана ради одржавања, тако да тренутно нећете моћи да сачувате измене.</strong>\nМожда бисте желели сачувати текст за касније у некој текстуалној датотеци.\n\nСистемски администратор је навео следеће објашњење: $1",
"protectedpagewarning": "<strong>Упозорење: ова страница је заштићена, тако да само администратори могу да је мењају.</strong>\nПоследњи запис у дневнику је приказан испод:",
- "semiprotectedpagewarning": "<strong>Напомена:</strong> Ова страница је заштићена, тако да само регистровани корисници могу да је уређују.\nПоследњи запис у дневнику приказан је испод као референца:",
+ "semiprotectedpagewarning": "<strong>Напомена:</strong> Ова страница је заштићена, тако да само регистровани корисници могу да је уређују.\nПоследњи запис у дневнику је приказан испод:",
"cascadeprotectedwarning": "<strong>Упозорење:</strong> Ова страница је заштићена тако да је могу уређивати само корисници са [[Special:ListGroupRights|одређеним правима]] (администратори), јер је иста укључена у {{PLURAL:$1|следећу страницу која је заштићена|следеће странице које су заштићене}} „преносивом” заштитом:",
- "titleprotectedwarning": "<strong>УпозоÑ\80еÑ\9aе: овÑ\83 Ñ\81Ñ\82Ñ\80аниÑ\86Ñ\83 могÑ\83 напÑ\80авиÑ\82и Ñ\81амо коÑ\80иÑ\81ниÑ\86и [[Special:ListGroupRights|Ñ\81 одÑ\80еÑ\92еним пÑ\80авима]].</strong>\nÐ\98Ñ\81под Ñ\81Ñ\83 наведени поÑ\81ледÑ\9aи запиÑ\81и Ñ\83 дневникÑ\83:",
+ "titleprotectedwarning": "<strong>УпозоÑ\80еÑ\9aе: овÑ\83 Ñ\81Ñ\82Ñ\80аниÑ\86Ñ\83 могÑ\83 напÑ\80авиÑ\82и Ñ\81амо коÑ\80иÑ\81ниÑ\86и [[Special:ListGroupRights|Ñ\81 одÑ\80еÑ\92еним пÑ\80авима]].</strong>\nÐ\9fоÑ\81ледÑ\9aи запиÑ\81 Ñ\83 дневникÑ\83 Ñ\98е пÑ\80иказан иÑ\81под:",
"templatesused": "{{PLURAL:$1|Шаблон|Шаблони}} на овој страници:",
"templatesusedpreview": "{{PLURAL:$1|Шаблон|Шаблони}} у овом претпрегледу:",
"templatesusedsection": "{{PLURAL:$1|Шаблон|Шаблони}} у овом одељку:",
"permissionserrorstext-withaction": "Немате дозволу за $2 из {{PLURAL:$1|следећег|следећих}} разлога:",
"recreate-moveddeleted-warn": "<strong>Упозорење: поново правите страницу која је претходно обрисана.</strong>\n\nРазмотрите да ли је прикладно да наставите с уређивањем ове странице.\nОвде је наведена историја брисања и премештања с образложењем:",
"moveddeleted-notice": "Ова страница је обрисана.\nИсторија њеног брисања, заштите и премештања налази се испод:",
- "moveddeleted-notice-recent": "Ð\96ао нам Ñ\98е, ова Ñ\81Ñ\82Ñ\80аниÑ\86а Ñ\98е недавно обÑ\80иÑ\81ана (Ñ\83 поÑ\81ледÑ\9aиÑ\85 24 Ñ\81аÑ\82а).\nÐ\9eвде Ñ\98е наведена иÑ\81Ñ\82оÑ\80иÑ\98а бÑ\80иÑ\81аÑ\9aа и пÑ\80емеÑ\88Ñ\82аÑ\9aа Ñ\81 обÑ\80азложеÑ\9aем.",
+ "moveddeleted-notice-recent": "Ð\96ао нам Ñ\98е, ова Ñ\81Ñ\82Ñ\80аниÑ\86а Ñ\98е недавно обÑ\80иÑ\81ана (Ñ\83 поÑ\81ледÑ\9aиÑ\85 24 Ñ\81аÑ\82а).\nÐ\98Ñ\81Ñ\82оÑ\80иÑ\98а Ñ\9aеног бÑ\80иÑ\81аÑ\9aа, заÑ\88Ñ\82иÑ\82е и пÑ\80емеÑ\88Ñ\82аÑ\9aа налази Ñ\81е иÑ\81под:",
"log-fulllog": "Погледај целу историју",
"edit-hook-aborted": "Измену је прекинула кука.\nНије дато никакво образложење.",
"edit-gone-missing": "Не могу да ажурирам страницу.\nИзгледа да је обрисана.",
"duplicate-args-warning": "<strong>Упозорење:</strong> [[:$1]] позива [[:$2]] са више од једне вредности за параметар „$3“. Само последња наведена вредност ће бити коришћена.",
"duplicate-args-category": "Странице с дуплираним аргументима код позива шаблона",
"duplicate-args-category-desc": "Страница садржи позиве шаблона који користе двоструке аргументе, као што су <code><nowiki>{{foo|bar=1|bar=2}}</nowiki></code> или <code><nowiki>{{foo|bar|1=baz}}</nowiki></code>.",
- "expensive-parserfunction-warning": "'''Упозорење:''' ова страница садржи превише позива за рашчлањивање.\n\nТребало би да има мање од $2 {{PLURAL:$2|позив|позива|позива}}, а сада има $1.",
+ "expensive-parserfunction-warning": "<strong>Упозорење:</strong> ова страница садржи превише позива за рашчлањивање.\n\nТребало би да има мање од $2 {{PLURAL:$2|позив|позива}}, а сада има $1.",
"expensive-parserfunction-category": "Странице с превише позива за рашчлањивање",
- "post-expand-template-inclusion-warning": "'''Упозорење:''' величина укљученог шаблона је превелика.\nНеки шаблони неће бити укључени.",
- "post-expand-template-inclusion-category": "Странице где су укључени шаблони превелики",
+ "post-expand-template-inclusion-warning": "<strong>Упозорење:</strong> величина обухваћеног шаблона је превелика.\nНеки шаблони неће бити обухваћени.",
+ "post-expand-template-inclusion-category": "Странице где су обухваћени превелики шаблони",
"post-expand-template-argument-warning": "'''Упозорење:''' ова страница садржи најмање један аргумент у шаблону који има превелику величину.\nОвакве аргументе би требало избегавати.",
"post-expand-template-argument-category": "Странице које садрже изостављене аргументе у шаблону",
"parser-template-loop-warning": "Откривена је петља шаблона: [[$1]]",
"recentchangesdays-max": "Највише $1 {{PLURAL:$1|дан|дана}}",
"recentchangescount": "Број измена за приказ:",
"prefs-help-recentchangescount": "Подразумева скорашње измене, историје страница и дневнике.",
- "prefs-help-watchlist-token2": "Ово је тајни кључ за веб-довод Вашег списка надгледања. \nСвако ко зна овај кључ биће у могућности да види Ваша надгледања; стога, кључ немојте одавати никоме. \nАко је потребно, кључ можете [[Special:ResetTokens|ресетовати]].",
+ "prefs-help-watchlist-token2": "Ово је тајни кључ за веб-довод Вашег списка надгледања. \nСвако ко зна овај кључ биће у могућности да види Ваша списак надгледања, зато кључ немојте одавати никоме. \nАко је потребно, кључ [[Special:ResetTokens|можете ресетовати]].",
"savedprefs": "Ваша подешавања су сачувана.",
"savedrights": "Корисничке групе за {{GENDER:$1|$1}} су сачуване.",
"timezonelegend": "Временска зона:",
"prefs-custom-css": "Прилагођени CSS",
"prefs-custom-js": "Прилагођени јаваскрипт",
"prefs-common-css-js": "Дељени CSS/Јаваскрипт за све теме:",
- "prefs-reset-intro": "Ð\9cожеÑ\82е коÑ\80иÑ\81Ñ\82иÑ\82и овÑ\83 Ñ\81Ñ\82Ñ\80аниÑ\86Ñ\83 да пониÑ\88Ñ\82иÑ\82е Ñ\81воÑ\98е поÑ\81Ñ\82авке на подразумеване вредности.\nОва радња се не може вратити.",
+ "prefs-reset-intro": "Ð\9cожеÑ\82е коÑ\80иÑ\81Ñ\82иÑ\82и овÑ\83 Ñ\81Ñ\82Ñ\80аниÑ\86Ñ\83 да пониÑ\88Ñ\82иÑ\82е Ñ\81воÑ\98а подеÑ\88аваÑ\9aа на подразумеване вредности.\nОва радња се не може вратити.",
"prefs-emailconfirm-label": "Потврда имејла:",
"youremail": "Имејл:",
"username": "{{GENDER:$1|Корисничко име}}:",
"rcfilters-savedqueries-apply-label": "Направи филтер",
"rcfilters-savedqueries-apply-and-setdefault-label": "Направи подразумевани филтер",
"rcfilters-savedqueries-cancel-label": "Откажи",
- "rcfilters-savedqueries-add-new-title": "СаÑ\87Ñ\83ваÑ\98 Ñ\82Ñ\80енÑ\83Ñ\82не поÑ\81Ñ\82авке филтера",
+ "rcfilters-savedqueries-add-new-title": "СаÑ\87Ñ\83ваÑ\98 Ñ\82Ñ\80енÑ\83Ñ\82на подеÑ\88аваÑ\9aа филтера",
"rcfilters-savedqueries-already-saved": "Ови филтери су већ упамћени. Измените Ваша подешавања како бисте направили нове сачуване филтере.",
"rcfilters-restore-default-filters": "Враћање подразумеваних филтера",
"rcfilters-clear-all-filters": "Уклони све филтере",
"filerevert-submit": "Врати",
"filerevert-success": "Датотека '''[[Media:$1|$1]]''' је враћена на [$4 издање од $2; $3].",
"filerevert-badversion": "Не постоји раније локално издање датотеке с наведеним временским подацима.",
- "filerevert-identical": "ТÑ\80енÑ\83Ñ\82на веÑ\80зиÑ\98а датотеке индентична је изабраној.",
+ "filerevert-identical": "ТÑ\80енÑ\83Ñ\82на измена датотеке индентична је изабраној.",
"filedelete": "Обриши $1",
"filedelete-legend": "Обриши датотеку",
"filedelete-intro": "Бришете датотеку '''[[Media:$1|$1]]''' заједно с њеном историјом.",
"doubleredirects": "Двострука преусмерења",
"doubleredirectstext": "Ова страница приказује странице које преусмеравају на друга преусмерења.\nСваки ред садржи везе према првом и другом преусмерењу, као и одредишну страницу другог преусмерења која је обично „прави“ чланак на кога прво преусмерење треба да упућује.\n<del>Прецртани</del> уноси су већ решени.",
"double-redirect-fixed-move": "[[$1]] је премештен.\nАутоматски је ажурирано и сада преусмерава на [[$2]].",
- "double-redirect-fixed-maintenance": "Аутоматски исправља двострука преусмерења из [[$1]] у [[$2]]. Као део одржавања.",
+ "double-redirect-fixed-maintenance": "Аутоматски исправља двострука преусмерења из [[$1]] у [[$2]] као део одржавања",
"double-redirect-fixer": "Исправљач преусмерења",
"brokenredirects": "Покварена преусмерења",
"brokenredirectstext": "Следећа преусмерења упућују на непостојеће странице:",
"wlshowhidepatr": "патролиране измене",
"wlshowhidemine": "моје измене",
"wlshowhidecategorization": "категоризацију страница",
- "watchlist-options": "Поставке списка надгледања",
+ "watchlist-options": "Подешавања списка надгледања",
"watching": "Надгледање…",
"unwatching": "Уклањање са списка надгледања...",
"watcherrortext": "Дошло је до грешке при промени поставки вашег списка надгледања за „$1“.",
"protect-badnamespace-text": "Странице у овом именском простору се не могу заштитити.",
"protect-norestrictiontypes-text": "Ова страница се не може заштитити јер нема доступних врста ограничења.",
"protect-norestrictiontypes-title": "Незаштитљива страна",
- "protect-legend": "Поставке заштите",
+ "protect-legend": "Подешавања заштите",
"protectcomment": "Разлог:",
"protectexpiry": "Истиче:",
"protect_expiry_invalid": "Време истека је неисправно.",
"protect_expiry_old": "Време истека је старије од тренутног времена.",
- "protect-unchain-permissions": "Ð\9eÑ\82кÑ\99Ñ\83Ñ\87аÑ\98 даÑ\99Ñ\9aе поÑ\81Ñ\82авке заштите",
+ "protect-unchain-permissions": "Ð\9eÑ\82кÑ\99Ñ\83Ñ\87аÑ\98 даÑ\99Ñ\9aа подеÑ\88аваÑ\9aа заштите",
"protect-text": "Овде можете да погледате и промените степен заштите за страницу '''$1'''.",
- "protect-locked-blocked": "Ð\9dе можеÑ\82е меÑ\9aаÑ\82и Ñ\81Ñ\82епене заÑ\88Ñ\82иÑ\82е док Ñ\81Ñ\82е блокиÑ\80ани.\nÐ\9eво Ñ\81Ñ\83 Ñ\82Ñ\80енÑ\83Ñ\82не поÑ\81Ñ\82авке странице '''$1''':",
- "protect-locked-dblock": "Степени заштите се не могу мењати јер је активна база података закључана.\nОво су поставке странице '''$1''':",
- "protect-locked-access": "Ð\9dемаÑ\82е овлаÑ\88Ñ\9bеÑ\9aа за меÑ\9aаÑ\9aе Ñ\81Ñ\82епена заÑ\88Ñ\82иÑ\82е Ñ\81Ñ\82Ñ\80аниÑ\86е.\nÐ\9eво Ñ\81Ñ\83 Ñ\82Ñ\80енÑ\83Ñ\82не поÑ\81Ñ\82авке странице '''$1''':",
+ "protect-locked-blocked": "Ð\9dе можеÑ\82е меÑ\9aаÑ\82и Ñ\81Ñ\82епене заÑ\88Ñ\82иÑ\82е док Ñ\81Ñ\82е блокиÑ\80ани.\nÐ\9eво Ñ\81Ñ\83 Ñ\82Ñ\80енÑ\83Ñ\82на подеÑ\88аваÑ\9aа странице '''$1''':",
+ "protect-locked-dblock": "Степени заштите се не могу мењати јер је активна база података закључана.\nОво су подешавања странице '''$1''':",
+ "protect-locked-access": "Ð\9dемаÑ\82е овлаÑ\88Ñ\9bеÑ\9aа за меÑ\9aаÑ\9aе Ñ\81Ñ\82епена заÑ\88Ñ\82иÑ\82е Ñ\81Ñ\82Ñ\80аниÑ\86е.\nÐ\9eво Ñ\81Ñ\83 Ñ\82Ñ\80енÑ\83Ñ\82на подеÑ\88аваÑ\9aа странице '''$1''':",
"protect-cascadeon": "Ова страница је тренутно заштићена јер се налази на {{PLURAL:$1|страници која има|страницама које имају}} преносиву заштиту.\nМожете да промените степен заштите, али то неће утицати на преносиву заштиту.",
"protect-default": "Допуштено свим корисницима",
"protect-fallback": "Дозвољено само корисницима са дозволом „$1“",
"thumbnail_invalid_params": "Неисправни параметри за минијатуру",
"thumbnail_dest_directory": "Не могу да направим одредишну фасциклу",
"thumbnail_image-type": "Врста слике није подржана",
- "thumbnail_gd-library": "Ð\9dедовÑ\80Ñ\88ене поÑ\81Ñ\82авке графичке библиотеке: недостаје функција $1",
+ "thumbnail_gd-library": "Ð\9dедовÑ\80Ñ\88ена подеÑ\88аваÑ\9aа графичке библиотеке: недостаје функција $1",
"thumbnail_image-missing": "Датотека недостаје: $1",
"import": "Увоз страница",
"importinterwiki": "Увоз са другог викија",
"tooltip-upload": "Започните отпремање",
"tooltip-rollback": "„Врати“ враћа измене последњег корисника једним кликом",
"tooltip-undo": "Опција „поништи” враћа ову измену и отвара образац за уређивање у претпрегледном моду. Омогућава додавање разлога у опису измене.",
- "tooltip-preferences-save": "Сачувај поставке",
+ "tooltip-preferences-save": "Сачувај подешавања",
"tooltip-summary": "Унесите кратак опис",
"interlanguage-link-title": "$1 — $2",
"interlanguage-link-title-nonlang": "$1 — $2",
"duplicate-defaultsort": "<strong>Упозорење:</strong> Подразумевани кључ сврставања „$2“ мења ранији подразумевани кључ сврставања „$1“.",
"duplicate-displaytitle": "<strong>Упозорење:</strong> наслов за приказ „$2“ замениће постојећи „$1“.",
"restricted-displaytitle": "<strong>Упозорење:</strong> Наслов за приказ „$1” је игнорисан пошто није еквивалентан стварном наслову странице.",
- "version": "Ð\92еÑ\80зиÑ\98а",
+ "version": "Ð\98здаÑ\9aе",
"version-extensions": "Инсталирана проширења",
"version-skins": "Инсталиране теме",
"version-specialpages": "Посебне странице",
"version-ext-license": "Лиценца",
"version-ext-colheader-name": "Екстензија",
"version-skin-colheader-name": "Тема",
- "version-ext-colheader-version": "Ð\92еÑ\80зиÑ\98а",
+ "version-ext-colheader-version": "Ð\98здаÑ\9aе",
"version-ext-colheader-license": "Лиценца",
"version-ext-colheader-description": "Опис",
"version-ext-colheader-credits": "Аутори",
"version-license-info": "Медијавики је слободан софтвер можете га редистрибуирати и/или модификовати под условима ГНУ-ове опште јавне лиценце верзија 2 или сваке следеће коју објави Задужбина за слободан софтвер.\n\nМедијавики се редистрибуира у нади да ће бити од користи, али <em>БЕЗ ИКАКВЕ ГАРАНЦИЈЕ</em> чак и без <strong>ПОДРАЗУМЕВАНЕ ГАРАНЦИЈЕ ФУНКЦИОНАЛНОСТИ</strong> или <strong>ПРИКЛАДНОСТИ ЗА ОДРЕЂЕНЕУ НАМЕНУ</strong>. Погледајте ГНУ-ову општу јавну лиценцу за више информација.\n\nТребало би да сте добили [{{SERVER}}{{SCRIPTPATH}}/COPYING примерак ГНУ-ове опште јавне лиценце] заједно са овим програмом. Ако нисте, пишите на Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA или [//www.gnu.org/licenses/old-licenses/gpl-2.0.html прочитајте овде].",
"version-software": "Инсталирани софтвер",
"version-software-product": "Производ",
- "version-software-version": "Ð\92еÑ\80зиÑ\98а",
+ "version-software-version": "Ð\98здаÑ\9aе",
"version-entrypoints": "Адресе улазне тачке",
"version-entrypoints-header-entrypoint": "Улазна тачка",
"version-entrypoints-header-url": "Адреса",
"version-libraries": "Инсталиране библиотеке",
"version-libraries-library": "Библиотека",
- "version-libraries-version": "Ð\92еÑ\80зиÑ\98а",
+ "version-libraries-version": "Ð\98здаÑ\9aе",
"version-libraries-license": "Лиценца",
"version-libraries-description": "Опис",
"version-libraries-authors": "Аутори",
"redirect-value": "Вредност:",
"redirect-user": "Кориснички ID",
"redirect-page": "ID странице",
- "redirect-revision": "Ð\92еÑ\80зиÑ\98а странице",
+ "redirect-revision": "Ð\98змена странице",
"redirect-file": "Назив датотеке",
"redirect-not-exists": "Вредност није пронађена",
"fileduplicatesearch": "Претрага дупликата",
"compare-title-not-exists": "Наведени наслов не постоји.",
"compare-revision-not-exists": "Наведена измена не постоји.",
"diff-form": "Разлике",
+ "diff-form-submit": "Прикажи разлике",
"permanentlink": "Стална веза",
"dberr-problems": "Дошло је до техничких проблема.",
"dberr-again": "Сачекајте неколико минута и поново учитајте страницу.",
"expandtemplates": "Замена шаблона",
"expand_templates_intro": "Ова посебна страница узима викитекст и мења све шаблоне у њему рекурзивно.\nТакође мења функције парсера као што је <code><nowiki>{{</nowiki>#language:…}}</code> и променљиве као што је <code><nowiki>{{</nowiki>CURRENTDAY}}</code>. \nЗаправо практично све што се налази између витичастих заграда.",
"expand_templates_title": "Назив контекста; за {{СТРАНИЦА}} итд.:",
- "expand_templates_input": "Унос:",
+ "expand_templates_input": "Унос викитекста:",
"expand_templates_output": "Резултат",
"expand_templates_xml_output": "XML излаз",
"expand_templates_html_output": "Сиров HTML излаз",
"mw-widgets-mediasearch-noresults": "Нема резултата.",
"mw-widgets-titleinput-description-new-page": "страница још увек не постоји",
"mw-widgets-titleinput-description-redirect": "преусмерава на $1",
+ "mw-widgets-categoryselector-add-category-placeholder": "Додај категорију...",
"mw-widgets-usersmultiselect-placeholder": "Додај још...",
"date-range-from": "Од датума:",
"date-range-to": "До датума:",
"log-action-filter-rights-autopromote": "аутоматски",
"log-action-filter-upload-upload": "Ново отпремање",
"log-action-filter-upload-overwrite": "промена постојећег",
+ "authmanager-authplugin-setpass-failed-title": "Неуспешна промена лозинке",
"authmanager-email-label": "Имејл",
"authmanager-email-help": "Имејл адреса",
+ "authmanager-realname-label": "Право име",
+ "authmanager-realname-help": "Право име корисника",
"authprovider-resetpass-skip-label": "Прескочи",
+ "cannotauth-not-allowed-title": "Приступ је одбијен",
"changecredentials": "Промјена акредитива",
"changecredentials-submit": "Промени",
"removecredentials": "Уклањање акредитива",
"credentialsform-account": "Назив налога:",
"userjsispublic": "Напомена: JavaScript подстранице не би требале садржавати поверљиве информације будући да су видљиве другим корисницима.",
"usercssispublic": "Напомена: CSS подстранице не би требале садржавати поверљиве информације будући да су видљиве другим корисницима.",
+ "edit-error-short": "Грешка: $1",
+ "edit-error-long": "Грешке:\n\n$1",
+ "revid": "измена $1",
"rawhtml-notallowed": "<html> тагови не могу да се користе ван нормалних страница.",
"gotointerwiki": "Напуштам пројекат {{SITENAME}}",
"gotointerwiki-invalid": "Одабрани наслов је неисправан.",
--- /dev/null
+{
+ "@metadata": {
+ "authors": [
+ "Khanmarat",
+ "Sorbat",
+ "Stephanecbisson",
+ "Рустам Нурыев"
+ ]
+ },
+ "sunday": "Йәкшәмпе",
+ "monday": "Түшәмпе",
+ "tuesday": "Сишәмпе",
+ "wednesday": "Царшампы",
+ "thursday": "Пәйшәмпе",
+ "friday": "Йома",
+ "saturday": "Шәмпе",
+ "sun": "Йәк",
+ "mon": "Түш",
+ "tue": "Сиш",
+ "wed": "Цар",
+ "thu": "Пәй",
+ "fri": "Йом",
+ "sat": "Шәм",
+ "january": "январь",
+ "february": "февраль",
+ "march": "март",
+ "april": "апрель",
+ "may_long": "май",
+ "june": "июнь",
+ "july": "июль",
+ "august": "август",
+ "september": "сентябрь",
+ "october": "октябрь",
+ "november": "ноябрь",
+ "december": "декабрь",
+ "january-gen": "январь",
+ "february-gen": "февраль",
+ "march-gen": "март",
+ "april-gen": "апрель",
+ "may-gen": "май",
+ "june-gen": "июнь",
+ "july-gen": "июль",
+ "august-gen": "август",
+ "september-gen": "сентябрь",
+ "october-gen": "октябрь",
+ "november-gen": "ноябрь",
+ "december-gen": "декабрь",
+ "jan": "янв",
+ "feb": "фев",
+ "mar": "мар",
+ "apr": "апр",
+ "may": "май",
+ "jun": "июн",
+ "jul": "июл",
+ "aug": "авг",
+ "sep": "сен",
+ "oct": "окт",
+ "nov": "ноя",
+ "dec": "дек",
+ "pagecategories": "{{PLURAL:$1|1=Категория|Категориялар}}",
+ "category_header": "«$1» категориятағы питләр",
+ "subcategories": "Эцке категориялар",
+ "category-media-header": "«$1» категориясынтағы файллар",
+ "category-empty": "Пы категория ҡәсерге уаҡытта пуш.",
+ "hidden-categories": "{{PLURAL:$1|Йәшерен категория|Йәшерен категориялар}}",
+ "category-subcat-count": "{{PLURAL:$2|1=Пы төргөнтә түмәнтәге астөргөн кенә пар. |Пы төргөнтә пулған $2-тән {{PLURAL:$1|астөргөн|астөргөннәр}} $1 ҡына күрсәтеләте.}}",
+ "category-article-count": "{{PLURAL:$2|1=Пы төргөнтә пер генә пит пар. Пы категориятан пулған {{PLURAL:$2|пулған|пулғаннар}}}} $2 -тән {{PLURAL:$1|$1 пит күрсәтелгән|$1 питләр күрсәтелгәннәр}}.",
+ "category-file-count": "{{PLURAL:$2|Пы категорията пер генә файл пар.|Категориятағы $2 файлныңҡы {{PLURAL:$1|$1 файлы күргәселгән}}.}}",
+ "listingcontinuesabbrev": "ҡушлау",
+ "noindex-category": "Индексланмайтығын питләр",
+ "broken-file-category": "Файлға эшләмәйтеген ссылкалары пулған питләр",
+ "about": "Сүрәтләмә",
+ "newwindow": "(йаңа тәрәсәтә)",
+ "cancel": "Пулмайын иткәле",
+ "mytalk": "Уйлашыу",
+ "navigation": "Навигация",
+ "and": " әм",
+ "namespaces": "Исемнәрнең киңнеге",
+ "variants": "Вариантлар",
+ "navigation-heading": "Навигация",
+ "returnto": "$1 питкә ҡайтыу.",
+ "tagline": "{{SITENAME}} проекттан",
+ "help": "Пелешмә",
+ "search": "Эстәү",
+ "searchbutton": "Тапҡалы",
+ "searcharticle": "Күцкәле",
+ "history": "Тариҡ",
+ "history_short": "Тариҡ",
+ "printableversion": "Пастырыр өцөн версия",
+ "permalink": "Келәң ссылка",
+ "view": "Ҡарау",
+ "view-foreign": "$1 сайтта ҡарағалы",
+ "edit": "Төсәткәле",
+ "create": "Пултырғалы",
+ "create-local": "Локаль сүрәтләмәне өстәгәле",
+ "delete": "Йуҡ иткәле",
+ "newpage": "Йаңа пит",
+ "talkpagelinktext": "уйлашыу",
+ "personaltools": "Персональ ҡораллар",
+ "talk": "Уйлап ҡарау",
+ "views": "Ҡараулар",
+ "toolbox": "Ҡораллар",
+ "otherlanguages": "Пашҡа телләртә",
+ "redirectedfrom": "($1 питтән йебәрелгән)",
+ "redirectpagesub": "Йусыҡлау пит",
+ "redirectto": "Йусыҡлағалы",
+ "lastmodifiedat": "Пы пит $1гә, $2 пуйта суңҡа төсәйтелгән.",
+ "jumpto": "Анта күцкәле:",
+ "jumptonavigation": "навигация",
+ "jumptosearch": "эстәү",
+ "aboutsite": "{{SITENAME}} турлы",
+ "aboutpage": "Project:Сүрәтләмә",
+ "copyright": "Эцтәлеге $1 лицензия пелән кенә ацыҡ (пашҡа исем күргәселмәсә).",
+ "copyrightpage": "{{ns:project}}:Авторның ҡаҡы",
+ "currentevents": "Ҡәсерге пулған ҡәлләр",
+ "currentevents-url": "Project:Ҡәсерге пулған ҡәлләр",
+ "disclaimers": "Пелеклелектән паш тартыу",
+ "disclaimerpage": "Project:Пелеклелектән паш тартыу",
+ "edithelp": "Төсәтеүгә йәртәм",
+ "mainpage": "Паш пит",
+ "mainpage-description": "Паш пит",
+ "portal": "Перләшмә",
+ "portal-url": "Project:Порталның перләшмәсе",
+ "privacy": "Серне саҡлау сәйәсәт",
+ "privacypage": "Project:Серне саҡлайтығын сәйәсәт",
+ "retrievedfrom": "Аҡма — «$1»",
+ "youhavenewmessages": "{{PLURAL:$3|Сестә}} $1 ($2) пар.",
+ "youhavenewmessagesfromusers": "{{PLURAL:$4|Сескә}} {{PLURAL:$3|$3 ҡатнашыуцытан}} $1 килте ($2).",
+ "newmessageslinkplural": "{{PLURAL:$1|1=йаңа ҡәбәр|999=йаңа ҡәбәрләр}}",
+ "newmessagesdifflinkplural": "{{PLURAL:$1|1=суңҡы пашҡартыу|999=суңҡы пашҡартыулар}}",
+ "editsection": "төсәткәле",
+ "editold": "төсәткәле",
+ "viewsourceold": "пашлапҡы кодны ҡарағалы",
+ "editlink": "төсәткәле",
+ "viewsourcelink": "паш кодны ҡарағалы",
+ "editsectionhint": "$1 пүлекне төсәткәле",
+ "toc": "Эцтәлек",
+ "site-atom-feed": "$1 — Atom тасма",
+ "page-atom-feed": "«$1» — Atom-тасма",
+ "red-link-title": "$1 (пы пит йуҡ)",
+ "nstab-main": "Мәҡәлә",
+ "nstab-user": "Ҡатнашыуцы",
+ "nstab-special": "Ҡесмәт пит",
+ "nstab-project": "Проетның пите",
+ "nstab-image": "Файл",
+ "nstab-mediawiki": "Пелтереү",
+ "nstab-template": "Ҡалып",
+ "nstab-category": "Категория",
+ "mainpage-nstab": "Паш пит",
+ "nosuchspecialpage": "Мынтайын ҡесмәт пит йуҡ",
+ "nospecialpagetext": "<strong>Сес сураған ҡесмәт пит йуҡ.</strong>\n* Ҡесмәт питләр күцермәлекне ҡараң: [[Special:SpecialPages|{{int:specialpages}}]].",
+ "badtitle": "Йарамаған исем",
+ "badtitletext": "Питнең суралған исеме төрөс түгел, пуш йә интервикиныңҡы исеме төрөс күрсәтелмәгән. Пәйәкпәр, исемтә йарамаған символлар пар ты.",
+ "viewsource": "Вики-текстны ҡарау",
+ "viewsource-title": "$1 питнең паш текстын ҡарау",
+ "viewsourcetext": "Сес пы питнеңке паш текстын ҡарап күцерә аласыс.",
+ "userlogin-yourname": "Ҡулланыуцыныңҡы исеме",
+ "userlogin-yourname-ph": "Исәп йасмағысныңҡы исемен кергесең",
+ "userlogin-yourpassword": "Пароль",
+ "userlogin-yourpassword-ph": "Үсегеснең парольны йасың",
+ "createacct-yourpassword-ph": "Парольны йасың",
+ "createacct-yourpasswordagain": "Парольны төрөс тигәле",
+ "createacct-yourpasswordagain-ph": "Парольны тағын та йасың",
+ "userlogin-remembermypassword": "Системата ҡалғалы",
+ "login": "Кергәле",
+ "userlogin-noaccount": "Исәп йасмағыс йуҡ ма?",
+ "userlogin-joinproject": "{{SITENAME}} проектҡа ҡушылғалы",
+ "createaccount": "Йаңа ҡатнашыуцыны теркәү",
+ "userlogin-resetpassword-link": "Паролеғысны оноттоғос ма?",
+ "userlogin-helplink2": "Керер өцөн йәртәм",
+ "createacct-emailoptional": "Электрон почтағысның адресы (тейешлецә түгел)",
+ "createacct-email-ph": "Электрон почтағысның адресын йасың",
+ "createacct-submit": "Исәп йасманы пултырғалы",
+ "createacct-benefit-heading": "{{SITENAME}} — сеснең шигелле кешеләрнең эше.",
+ "createacct-benefit-body1": "{{PLURAL:$1|төсәтеү}}",
+ "createacct-benefit-body2": "{{PLURAL:$1|мәҡәлә|мәҡәләнең}}",
+ "createacct-benefit-body3": "Суңҡы уаҡыттағы {{PLURAL:$1|ҡатнашыуцы}}",
+ "loginlanguagelabel": "Тел: $1",
+ "pt-login": "Кергәле",
+ "pt-login-button": "Кергәле",
+ "pt-createaccount": "Йаңа аккаунт пултырғалы",
+ "pt-userlogout": "Цыҡҡалы",
+ "passwordreset": "Парольны пөтөрөү",
+ "bold_sample": "Ҡалын пелән йасыу",
+ "bold_tip": "Ҡалын пелән йасыу",
+ "italic_sample": "Курсив пелән йасыу",
+ "italic_tip": "Курсив пелән йасыу",
+ "link_sample": "Ссылканыңҡы төп исеме",
+ "link_tip": "Эцке ссылка",
+ "extlink_sample": "http://www.example.com ссылканың төп исеме",
+ "extlink_tip": "Тышҡы ссылка (http:// префиксны онотмаң)",
+ "headline_sample": "Төп исем",
+ "headline_tip": "2-нце ҡат төп исем",
+ "nowiki_sample": "Мынта форматлау кәрәкмәйтеген текстны өстәң",
+ "nowiki_tip": "Вики-форматлауға ҡолаҡ салмау",
+ "image_tip": "Кергеселгән файл",
+ "media_tip": "Файлға ссылка",
+ "sig_tip": "Ҡул ҡуйыуығыс пелән уаҡыт",
+ "hr_tip": "Горизонталь цыйыҡ (кел ҡулланмаң)",
+ "summary": "Пашҡартыуларны аңнатыу:",
+ "minoredit": "Кецкенә пашҡартыу",
+ "watchthis": "Пы питне көсәткәле",
+ "savearticle": "Питне йасып ҡуйғалы",
+ "preview": "Алттан ҡарау",
+ "showpreview": "Алттан ҡарап цығыу",
+ "showdiff": "Кергеселгән пашҡартыулар",
+ "anoneditwarning": "<strong>Саҡлыҡ!</strong> Сес сайтта теркәлмәтегес. Әгәр тә сес төрлө төсәтеүләр ҡылсағыс, сеснеңке IP-адресығыс пашҡаларға күренеп торор. Әгәр тә Сес <strong>[$1 керсәгез]</strong> йә <strong>[$2 ҡулланыуцы йасманы пултырсағыс]</strong>, сеснең төсәтеүләр ҡулланыуцы йасмағысҡа пәйле пулыр, шалай уҡ пашҡа өстөннөкләр тыуыр.",
+ "blockedtext": "<strong>Сеснең исәп йасмағыс йә IP адресығыс тыйылған.</strong>\n* Тыйған администратор: $1.\nКүргәселгән сәбәп: <em>$2.</em>\n\n* Тыйыу пашланҡан уаҡыт: $8\n* Тыйыуның пөтөү уаҡыты: $6\n* Тыйыуның кәрәге: $7\n\nСес $1 йә пүтән [[{{MediaWiki:Grouppage-sysop}}|администраторға]] тыйыу турлы сурауларығысны йебәрә аласыз.\nОнотмаң: әгәр сес үсегеснеңке ҡоролошоғоста электрон почта адресығысны пирмәгән пулсағыс ([[Special:Preferences|йә аны төрөс күргәсмәгән пулсағыс]]), администраторға ҡат йебәрә алмайсыс. Шалай уҡ тыйыу уаҡытны сес ҡат йебәрә алмаған пуласыс.\nСеснең IP адрес — $3, тыйыу идентификатор — #$5.\nҠатларта пы ҡәбәр-пелемнәрне күргәскәле онотмаң.",
+ "loginreqlink": "кергәле",
+ "newarticletext": "Сес ссылка пелән әле йасылмаған питкә күцтегес. Йаңа пит ҡылыр өцөн астытағы тәрәсәгә текст йасың (тулыраҡ өцөн [$1 пелешмәлек питне] ҡараң). Әгәр мынта йалғыш кереп киткән пулсағыс, браузерығысныңҡы \"сыртҡа\" кнопкаға пасың.",
+ "anontalkpagetext": "----\n<em>Пы уйлап ҡарау пит исәп йасыуны ҡылтырмаған йә аны ҡулланмайтығын аноним ҡатнашыуцыныңҡы пите.</em> Ҡулланыуцыны таныу өцөн аныңҡы IP-адресы ҡулланылаты. Әгәр сес аноним ҡулланыуцы пулсағыс, сескә йебәрелмәгән ҡатлар алтым тисәгес (пер IP-адрес кән ҡулланыуцыларта пулғалы мөмкин), пашҡа мынтайын аңнашылмауцылыҡлар килеп цыҡмасын өцөн, системаға керең йә теркәлең.",
+ "noarticletext": "Ҡәсерге уаҡытта пы питтә текст йуҡ. Сес [[Special:Search/{{PAGENAME}}|пы исем кергән пашҡа мәҡәләләрне]], <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} туры килгән йасмаларны] таба йә '''[{{fullurl:{{FULLPAGENAME}}|action=edit}} шантайын уҡ исемле йаңа питне ҡыла]'''</span> аласыс.",
+ "noarticletext-nopermission": "Ҡәсерге уаҡытта пы питтә текст йуҡ. Сес пашҡа питләртә [[Special:Search/{{PAGENAME}}|пы исемне]] йә <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} журналтағы йасмаларны] эстәй аласыс. Сескә пит йасағалы рөҡсәт пирелмәгән.</span>",
+ "userpage-userdoesnotexist-view": "«$1» исемле исәп йасма йуҡ.",
+ "clearyourcache": "<strong>Искәрмә:</strong> Питне саҡлағаннан суң пашҡартыуларығыс күренер өцөн, браузерығысныңҡы кэшын тасартҡалы кәрәк пулыр.\n* <strong>Firefox / Safari:</strong> <em>Shift</em> төймәгә пасып, йебәрмәйен, <em>Йаңартҡалы</em> төймәгә пасың, йә <em>Ctrl-F5</em> йә <em>Ctrl-R</em> (Mac-та <em>⌘-R</em>) төймәләргә пасың\n* <strong>Google Chrome:</strong> <em>Ctrl-Shift-R </em>төймәгә пасың (Mac-та <em>⌘-Shift-R</em>)\n* <strong>Internet Explorer:</strong> <em>Ctrl </em>төймәгә пасып, йебәрмәйен, <em>Йаңартҡалы</em>төймәгә пасың, йә <em>Ctrl-F5 </em>төймәгә пасың\n* <strong>Opera:</strong> <em>Ҡораллар → Ҡоролошлар</em> (Mac-та <em>Opera → Ҡоролошлар</em>) пүлеккә күцең, суңынан <em>Ҡауапсыслыҡ → Кереүләр тариҡны тасартыу → Рәсемнәр кэшлау</em> менюта кэш тасартыуны сайлаң",
+ "previewnote": "<strong>Онотмаң, пы алттан ҡарап цығыу ғына.</strong>\nПашҡартыуларығыс әле саҡланмаған!",
+ "continue-editing": "Төсәтеүне ҡушлағалы",
+ "editing": "«$1» битне төсәтеү",
+ "creating": "«$1» питне пултырыу",
+ "editingsection": "«$1» питтә төсәтеү",
+ "templatesused": "Пы питтә ҡулланылған {{PLURAL:$1|1=ҡалып|ҡалыплар}}:",
+ "templatesusedpreview": "Алттан ҡарау режимта ҡулланылған {{PLURAL:$1|1=ҡалып|ҡалыплар}}:",
+ "template-protected": "(саҡланҡан)",
+ "template-semiprotected": "(өлөшө пелән саҡланҡан)",
+ "hiddencategories": "Пы пит $1 {{PLURAL:$1|йәшерен төргөнкә|$1 йәшерен төргөннәргә}} керәте:",
+ "permissionserrors": "Кереүнең ҡаҡ ҡатасы",
+ "permissionserrorstext-withaction": "$2 әмәлен ҡыла алмайсыс. {{PLURAL:$1|1=сәбәбе пуйынца|сәбәпләре пуйынца}}:",
+ "recreate-moveddeleted-warn": "Саҡлыҡ: Сес элек йуҡ ителгән питне йаңатан ҡылмаҡцы пуласыс.\n\n* Сескә пы питне йаңатан ҡылыу кәрәклекне йаңатан уйлап ҡараң.\nТүмәнтә питнең йуҡ итеү пелән исемен пашҡартыу журнал пар.",
+ "moveddeleted-notice": "Пы пит уйылған. Пелешмә өцөн астыта пөтөрөү пелән исем алмаштырыу журналларның йасылғаннары күргәселгән.",
+ "content-model-wikitext": "вики-текст",
+ "undo-failure": "Аралыҡ пашҡартыулар туры килмәгәнкә, төсәтеүне кире алып пулмайты.",
+ "viewpagelogs": "Пы питнең журналын ҡарағалы",
+ "currentrev-asof": "$1, ҡәсерге версия",
+ "revisionasof": "$1 версия",
+ "revision-info": "$1 аңышы; {{GENDER:$6|$2}}$7",
+ "previousrevision": "← Алттағы",
+ "nextrevision": "Мынан суңҡысы →",
+ "currentrevisionlink": "Ҡәсерге версия",
+ "cur": "ҡәсерге",
+ "last": "алттағы",
+ "histlegend": "Аңышларны сайлау: сес туры килтергәле теләгән питләрнең аңышларын сайлап алың та {{int:compare-submit}}.<br /> -ға пасың. Аңнатмалар: ({{int:cur}}) — ҡәсерге аңыштан айырмалар; ({{int:last}}) — алтта пулған аңыштан айырмалар; {{int:minoreditletter}} — сур пулмаған айырмалар.",
+ "history-fieldset-title": "Төсәтеүләрне эстәү",
+ "histfirst": "иң элекеләре",
+ "histlast": "иң суңҡылары",
+ "history-feed-title": "Пашҡартыулар тариғы",
+ "history-feed-description": "Пы питнең викитағы пашҡартыулар тариғы",
+ "history-feed-item-nocomment": "$2-та $1",
+ "rev-delundel": "күргәскәле/йәшергәле",
+ "mergelog": "Перләштереүләр журнал",
+ "history-title": "$1 питенең пашҡартыу тариғы",
+ "difference-title": "$1 — версиялар арасынтағы айырмалар",
+ "lineno": "$1 йул:",
+ "compareselectedversions": "Сайланҡан аңышларны туры килтергәле",
+ "editundo": "пулмайын иткәле",
+ "diff-empty": "(айырмалар йуҡ)",
+ "diff-multi-sameuser": "(пы ҡулланыуцының {{PLURAL:$1|аралыҡ версия $1|аралыҡ версиялары $1}} күргәселмәгән)",
+ "diff-multi-otherusers": "({{PLURAL:$2|ҡатнашыуцының|$2 ҡатнашыуцыларның}} {{PLURAL:$1|ара аңышы|$1 арадаш аңышлары}} күргәселмәгән)",
+ "searchresults": "Эстәүнең йомҡаҡлары",
+ "searchresults-title": "«$1»ны эстәгәле",
+ "prevn": "алттағы {{PLURAL:$1|$1}}",
+ "nextn": "киләсе {{PLURAL:$1|$1}}",
+ "prevn-title": "Алттағы $1 {{PLURAL:$1|1=йасма|йасмалар}}",
+ "nextn-title": "{{PLURAL:$1|Киләсе $1 йасма}}",
+ "shown-title": "$1 пер питтә {{PLURAL:$1|йасыу|йасыулар}} күргәскәле",
+ "viewprevnext": "($1 {{int:pipe-separator}} $2) ($3) ҡарап паҡҡалы",
+ "searchmenu-exists": "Пы викита [[:$1]] тигән пит пар",
+ "searchmenu-new": "<strong>«[[:$1]]» Вики-проектта пит йасағалы!</strong> {{PLURAL:$2|0=|Шалай уҡ, эстәгән арағыстағы табылған питне караң.|Шалай уҡ, эстәгәнегестә табылған питләрне караң.}}",
+ "searchprofile-articles": "Төп питләр",
+ "searchprofile-images": "Мультимедиа",
+ "searchprofile-everything": "Пөтөн йертә",
+ "searchprofile-advanced": "Киңәйтелгән",
+ "searchprofile-articles-tooltip": "$1 тә эстәү",
+ "searchprofile-images-tooltip": "Файлларны эстәү",
+ "searchprofile-everything-tooltip": "Пөтөн питләртә (уйлашыу питләртә тә) эстәү",
+ "searchprofile-advanced-tooltip": "Пирелгән исемнәр киңнектә эстәгәгәле",
+ "search-result-size": "$1 ({{PLURAL:$2|1=$2 сүс|$2 сүс}})",
+ "search-result-category-size": "$1 {{PLURAL:$1|аса}} ($2 {{PLURAL:$2|астөргөн}}, $3 {{PLURAL:$3|файл}})",
+ "search-redirect": "($1 питтән йусыҡлау)",
+ "search-section": "($1 пүлек)",
+ "search-file-match": "(файлның эцтәлеге пелән туры киләте)",
+ "search-suggest": "Пәйәкпәр, ошоно эстәйсес пулыр: $1",
+ "searchall": "пөтөннәйе",
+ "search-showingresults": "{{PLURAL:$4|<strong>$3</strong> нәтижәтән <strong>$1</strong>| <strong>$3</strong> нәтижәләртән <strong>$1 — $2</strong>}}",
+ "search-nonefound": "Сурауға туры килгән йауаплар табылматы.",
+ "mypreferences": "Ҡороулар",
+ "group-bot": "Ботлар",
+ "group-sysop": "Администраторлар",
+ "grouppage-bot": "{{ns:project}}:Ботлар",
+ "grouppage-sysop": "{{ns:project}}:Администраторлар",
+ "right-writeapi": "Йасыр өцөн API-ны ҡулланыу",
+ "newuserlogpage": "Йаңа ҡулланыуцыларны теркәү журналы",
+ "rightslog": "Ҡатнашыуцының ҡаҡлары журналы",
+ "action-edit": "пы питне төсәткәле",
+ "action-createaccount": "Пы исәп йасманы ҡылыу",
+ "enhancedrc-history": "тариҡ",
+ "recentchanges": "Йаңа төсәтеүләр",
+ "recentchanges-legend": "Суңҡы төсәтеүлернең ҡоролошо",
+ "recentchanges-summary": "Төрлө питләртә эшләнкән суңҡы пашҡартыуларның күцермәлеге",
+ "recentchanges-noresult": "Күрсәтелгән уаҡытта тейешле шартларға туры килгән пашҡартыулар йуҡ.",
+ "recentchanges-feed-description": "Викита суңҡы пашҡартыуларны көсәтеү.",
+ "recentchanges-label-newpage": "Пы төсәтеү йаңа пит ҡылтырты",
+ "recentchanges-label-minor": "Пы сур пулмаған төсәтеү",
+ "recentchanges-label-bot": "Пы төсәтеүне бот ҡылған",
+ "recentchanges-label-unpatrolled": "Пы төсәтеүне әле иц кем тикшермәте",
+ "recentchanges-label-plusminus": "Питнең сурлығы ошо ҡәтәр байтҡа алмашынты",
+ "recentchanges-legend-heading": "<strong>Аңнатма:</strong>",
+ "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (шалай уҡ [[Special:NewPages|йаңа питләр күцермәлеген]] ҡараң)",
+ "rcfilters-filterlist-title": "Фильтрлар",
+ "rcfilters-filterlist-noresults": "Иц фильтр табылматы",
+ "rcnotefrom": "Астта <strong>$3, $4</strong> -ға туры килгән {{PLURAL:$5|пашҡартыулар күргәселгән}} (<strong>$1</strong> артыҡ түгел).",
+ "rclistfrom": "$3 $2 алып йаңа пашҡартыуларны күргәскәле",
+ "rcshowhideminor": "кецкенә төсәтеүләр $1",
+ "rcshowhideminor-show": "Күргәскәле",
+ "rcshowhideminor-hide": "Йәшергәле",
+ "rcshowhidebots": "ботларны $1",
+ "rcshowhidebots-show": "Күргәскәле",
+ "rcshowhidebots-hide": "Йәшергәле",
+ "rcshowhideliu": "$1 танылған ҡулланыуцылар",
+ "rcshowhideliu-show": "Күргәскәле",
+ "rcshowhideliu-hide": "Йәшергәле",
+ "rcshowhideanons": "танылмаған ҡулланыуцылар $1",
+ "rcshowhideanons-show": "Күргәскәле",
+ "rcshowhideanons-hide": "Йәшергәле",
+ "rcshowhidepatr": "$1 ҡараған төсәтеүләр",
+ "rcshowhidemine": "үс төсәтеүләр $1",
+ "rcshowhidemine-show": "Күргәскәле",
+ "rcshowhidemine-hide": "Йәшергәле",
+ "rclinks": "Суңҡы $2 көн арата йасалған $1 пашҡартыуларны күргәскәле",
+ "diff": "Төрлө",
+ "hist": "тариҡ",
+ "hide": "Йәшергәле",
+ "show": "Күргәскәле",
+ "minoreditletter": "м",
+ "newpageletter": "Й",
+ "boteditletter": "б",
+ "rc-change-size-new": "Төсәткәннән суңҡы сурлыҡ: $1 {{PLURAL:$1|1=байт|байт}}",
+ "rc-old-title": "\"$1\" итеп пашта ҡылынҡан",
+ "recentchangeslinked": "Пәйләнкән төсәтеүләр",
+ "recentchangeslinked-feed": "Пәйле пулған пашҡартыулар",
+ "recentchangeslinked-toolbox": "Пәйле төсәтеүләр",
+ "recentchangeslinked-title": "\"$1\" өцөн пәйләнкән төсәтеүләр",
+ "recentchangeslinked-summary": "Пы, күрсәтелгән пит йебәрәтеген (йә күрсәтелгән төргөнкә керәтегән), питләртә суңҡы пашҡартыуларның күцермәлеге. [[Special:Watchlist|көсәтеү күцермәлегегескә]] керәтеген питләр '''ҡалын''' итеп күрсәтелгән.",
+ "recentchangeslinked-page": "Питнең төп исеме:",
+ "recentchangeslinked-to": "Кирецә, пы питкә пәйләнкән питләртәге пашҡартыуларны күргәскәле",
+ "upload": "Файлны төйәгәлә",
+ "uploadlogpage": "Төйәүләр журнал",
+ "filedesc": "Ҡысҡа аңнатыу",
+ "license": "Лицензиясы:",
+ "license-header": "Лицензирование",
+ "imgfile": "файл",
+ "listfiles": "Файлларның күцермәлеге",
+ "file-anchor-link": "Файл",
+ "filehist": "Файлның тарығы",
+ "filehist-help": "Үткән уаҡытта файлныңҡы нинтәйен пулғанын күргегес килсә, көнө/уаҡытына пасың.",
+ "filehist-revert": "ҡайтарғалы",
+ "filehist-current": "ҡәсерге",
+ "filehist-datetime": "Көнө/уаҡыты",
+ "filehist-thumb": "Уаҡ рәсем",
+ "filehist-thumbtext": "$1 версиятан пулған сүрәт",
+ "filehist-nothumb": "Миниатюрасы йуҡ",
+ "filehist-user": "Ҡатнашыуцы",
+ "filehist-dimensions": "Сурлығы",
+ "filehist-comment": "Искәрмә",
+ "imagelinks": "Файлны ҡулланыу",
+ "linkstoimage": "Пы файлға {{PLURAL:$1|1=пит|$1 пит}} йебәрәте:",
+ "linkstoimage-more": "Пы файлға $1-на пашҡа та {{PLURAL:$1|пит}} ссылка ҡылатылар.\nТүмәнтәге күцермәлектә пы файлға $1 {{PLURAL:$1|ссылка}} ғына күргәселгән.\nШалай уҡ тулы күцермәлекне ҡарап пулаты.",
+ "nolinkstoimage": "Пы файлға йебәргән питләр йуҡ.",
+ "linkstoimage-redirect": "$1 (файл йусыҡлау) $2",
+ "sharedupload-desc-here": "Пы файл $1-нан, ул пашҡа проектларта ҡулланыла алаты. Файл турлы [$2 сүрәтләү пите] тулыраҡ пелешмә түмәнтәрәк пирелгән.",
+ "filepage-nofile": "Мынтайын исемле файл йуҡ.",
+ "upload-disallowed-here": "Сес пы файлны йаңатан йастыра алмайсыс.",
+ "randompage": "Уйланмаған мәҡәлә",
+ "statistics": "Статистика",
+ "double-redirect-fixer": "Йаңа йусыҡлауның төсәтеүцесе",
+ "nbytes": "$1 {{PLURAL:$1|байт}}",
+ "nmembers": "$1 {{PLURAL:$1|объект}}",
+ "prefixindex": "Питләрнең исемнәренең пашы пуйынца күстәргец",
+ "listusers": "Ҡатнашыуцыларның күцермәлеге",
+ "newpages": "Йаңа питләр",
+ "move": "Йаңа исем ататҡалы",
+ "pager-newer-n": "{{PLURAL:$1|$1 йаңараҡ}}",
+ "pager-older-n": "$1 {{PLURAL:$1|искерәк}}",
+ "booksources": "Китапларның аҡмалары",
+ "booksources-search-legend": "Китап турлы информация эстәү",
+ "booksources-search": "Эстәгәле",
+ "specialloguserlabel": "Ҡылыуцы:",
+ "speciallogtitlelabel": "Морат (исеме йә {{ns:user}}:ҡулланыуцының исеме):",
+ "log": "Журналлар",
+ "all-logs-page": "Пөтөн ацыҡ журналлар",
+ "alllogstext": "{{SITENAME}} сайтыныңҡы журналларының тула күцермәлеге.\nСес йомҡаҡларны журнал төрөнә, ҡатаншыуцының исеменә ҡарап (сур йә кецкенә ҡәрептән йасылыуына ҡарап ) йә күргәселгән питнең исеменә ҡарап (шулай уҡ сур йә кецкенә ҡәрептән йасылыуына ҡарап) сайлап ала аласыс.",
+ "logempty": "Журналта йарығытайын асмалар йуҡ.",
+ "allpages": "Пөтөн питләр",
+ "allarticles": "Пөтөн питләр",
+ "allpagessubmit": "Ҡылғалы",
+ "allpages-hide-redirects": "Йусыҡлауларны йәшергәле",
+ "categories": "Төргөннәр",
+ "listgrouprights-members": "(ҡатнашыуцыларның күцермәлеге)",
+ "emailuser": "Ҡатнашыуцыға ҡат",
+ "usermessage-editor": "Системалыҡ тапшырыу",
+ "watchlist": "Көсәтеү күцермәлек",
+ "mywatchlist": "Көсәтеү күцермәлек",
+ "watchlistfor2": "$1 $2-ға тип",
+ "watch": "Көсәткәле",
+ "unwatch": "Көсәтмәгәле",
+ "watchlist-details": "Көсәтеү күцермәлегегестә, уйлап ҡарау питләрне исәпләмәйен, {{PLURAL:$1|$1 пит}} пар.",
+ "wlheader-showupdated": "Сеснең суңҡы пашҡартыулартан суң пашҡарған питләр <strong>ҡалын</strong> шрифт пелән күргәселгән.",
+ "wlnote": "Түмәнтә $3 $4 уаҡытта суңҡы {{PLURAL:$2|1=сәғәт|$2 сәғәт}} эцтә эшләнкән {{PLURAL:$1|1=пашҡартыу|$1пашҡартыулар}} күргәселгән.",
+ "wlshowlast": "Суңҡы $1 сәғәт $2 көн эцентәгесен күргәскәле",
+ "watchlist-options": "Көсәтеү күцермәлекнең ҡоролошлары",
+ "enotif_reset": "Пөтөн питләрне ҡаралған тип пилгеләгәле",
+ "dellogpage": "Уйыуларның журналы",
+ "rollbacklink": "кире ҡайтарғалы",
+ "rollbacklinkcount": "$1 {{PLURAL:$1|1=төсәтеүне|төсәтеүне}} кире алғалы",
+ "protectlogpage": "Саҡлау журнал",
+ "protectedarticle": "[[$1]] питен йаҡлаған",
+ "modifiedarticleprotection": "[[$1]]-ныңҡы питенең йаҡлау ҡаты пашҡартылты",
+ "protect-default": "Пөтөн ҡулланыуцыларға ацыҡ",
+ "restriction-edit": "Төсәткәле",
+ "restriction-move": "Йаңа исем ҡушыу",
+ "namespace": "Исемнәрнең киңнеге:",
+ "invert": "Сайланҡанны әйләнтергәле",
+ "tooltip-invert": "Сайланҡан исемнәр арасынта (күрсәтелгән пулса, исемнәрнең пәйле киңнегентә тә) питләртәге пашҡартыуларны йәшерер өцөн пы пилгене ҡороң",
+ "namespace_association": "Пәйле киңнек",
+ "tooltip-namespace_association": "Сайланҡан исемнәр киңнек пелән пәйле пулған уйлап ҡаралған исемнәрнең киңнеген кергесер өцөн пы пилгене ҡороң",
+ "blanknamespace": "(Төп)",
+ "contributions": "{{GENDER:$1|ҡатнашыуцының}} ҡылған эше",
+ "contributions-title": "$1 исемле ҡатнашыуцының ҡылған эше",
+ "mycontris": "Кергескән эшләр",
+ "anoncontribs": "Кергескән эшләр",
+ "contribsub2": "{{GENDER:$3|$1}}-ның ҡылған эше ($2)",
+ "nocontribs": "Күргәселгән шартларға туры килгән пашҡартыулар табылматы.",
+ "uctop": "(ҡәсерге)",
+ "month": "Айтан пашлап (анан алттараҡ та):",
+ "year": "Йылтан пашлап (анан алттараҡ та):",
+ "sp-contributions-newbies": "Йаңа исәп йасмалартан ҡылынҡан эшне генә күргәскәле",
+ "sp-contributions-blocklog": "тыйыулар",
+ "sp-contributions-uploads": "төйәүләр",
+ "sp-contributions-logs": "журналлар",
+ "sp-contributions-talk": "уйлап ҡарау",
+ "sp-contributions-search": "Ҡылынҡан эшне эстәү",
+ "sp-contributions-username": "Ҡатнашыуцының IP-адресы йә исеме:",
+ "sp-contributions-toponly": "Иң суңҡы аңышлар пулған төсәтеүләрне генә күргәскәле",
+ "sp-contributions-newonly": "Йаңа пит ацатығын төсәтеүләрне генә күргәскәле",
+ "sp-contributions-submit": "Тапҡалы",
+ "whatlinkshere": "Мынта ссылкалар",
+ "whatlinkshere-title": "«$1» питкә йебәргән питләр",
+ "whatlinkshere-page": "Пит:",
+ "linkshere": "''[[:$1]]''' питкә киләсе питләр тайанатылар:",
+ "nolinkshere": "[[:$1]] питкә пер питтән тә ссылка йуҡ.",
+ "isredirect": "йусыҡлау пит",
+ "istemplate": "ҡушылыу",
+ "isimage": "файллы ссылка",
+ "whatlinkshere-prev": "{{PLURAL:$1|1=алттағы}} $1",
+ "whatlinkshere-next": "{{PLURAL:$1|1=киләсе}} $1",
+ "whatlinkshere-links": "← ссылкалар",
+ "whatlinkshere-hideredirs": "$1 йусыҡлаулар",
+ "whatlinkshere-hidetrans": "Кергесеүләр $1",
+ "whatlinkshere-hidelinks": "$1 ссылкалар",
+ "whatlinkshere-hideimages": "$1 файлның ссылкалары",
+ "whatlinkshere-filters": "Фильтрлар",
+ "ipboptions": "2 сәғәт:2 hours,1 көн:1 day,3 көн:3 days,1 атна:1 week,2 атна:2 weeks,1 ай:1 month,3ай:3 months,6 ай:6 months,1 йыл:1 year,уаҡытсыс:infinite",
+ "infiniteblock": "пилгеле пер уаҡытсыс",
+ "blocklink": "тыйғалы",
+ "contribslink": "өлөш",
+ "blocklogpage": "Тыйыулар журнал",
+ "blocklogentry": "[[$1]] $2 $3-ҡа пикләте",
+ "reblock-logentry": "[[$1]] ҡатнашыуцының тыйыуын пашҡартҡан, пөтөү уаҡыты — $2 $3",
+ "block-log-flags-nocreate": "исәп йасманың теркелеүе тыйылған",
+ "proxyblocker": "Проксины пикләү",
+ "movelogpage": "Исем алмаштырыуның журналы",
+ "export": "Питләрне цығарыу",
+ "thumbnail-more": "Сурайтҡалы",
+ "importlogpage": "Кергесеү журнал",
+ "tooltip-pt-userpage": "{{GENDER:|Сеснең}} ҡатнашыуцының пите",
+ "tooltip-pt-mytalk": "{{GENDER:|Сеснең}} уйлашыу питегес",
+ "tooltip-pt-preferences": "{{GENDER:|Сеснең}} ҡоролошларығыс",
+ "tooltip-pt-watchlist": "Сес көсәтеп парған питләрнең күцермәлеге",
+ "tooltip-pt-mycontris": "{{GENDER:|Сеснең}} төсәтеүләрнең күцермәлеге",
+ "tooltip-pt-login": "Мынта регистрация үткәле пулаты, әммә ул тейешлецә түгел",
+ "tooltip-pt-logout": "Цыҡҡалы",
+ "tooltip-pt-createaccount": "Тейешлецә пулмаса та, аккаунт ҡылып системаға кергәле киңәш итәбес",
+ "tooltip-ca-talk": "Төп пит турлы уйлап ҡарашыу",
+ "tooltip-ca-edit": "Пы питне төсәткәле",
+ "tooltip-ca-addsection": "Йаңа пүлек ҡылғалы",
+ "tooltip-ca-viewsource": "Пы пит пашҡартыулартан йаҡланҡан, әммә сес аның төп текстын ҡарай аласыс, копиясын ала аласыс",
+ "tooltip-ca-history": "Питне пашҡартыу күцермәлеге",
+ "tooltip-ca-protect": "Питне пашҡартыулартан саҡлағалы",
+ "tooltip-ca-delete": "Пы питне йуҡ иткәле",
+ "tooltip-ca-move": "Питкә йаңа исем пиргәле",
+ "tooltip-ca-watch": "Пы питне сеснең көсәтеү күцермәлеккә өстәгәле",
+ "tooltip-ca-unwatch": "Пы питне көсәтеү күцермәлегемнән алып ташлағалы",
+ "tooltip-search": "{{SITENAME}} эцтә эстәгәле",
+ "tooltip-search-go": "Шалай уҡ аталған питкә күцкәле",
+ "tooltip-search-fulltext": "Ошонтайын эцтәлекле питләрне тапҡалы",
+ "tooltip-p-logo": "Паш питкә күцкәле",
+ "tooltip-n-mainpage": "Паш питкә күцкәле",
+ "tooltip-n-mainpage-description": "Паш питкә күцкәле",
+ "tooltip-n-portal": "Проект турлы, мынта нимә ҡылғалы йарағаны турлы, ҡайта нимә урнашҡан турлы",
+ "tooltip-n-currentevents": "Ҡәсер пулып йатҡан пулған ҡәлләр турлы пелешмә",
+ "tooltip-n-recentchanges": "Суңҡы төсәтеүләрнең күцермәлеге",
+ "tooltip-n-randompage": "Көтөлмәгән питне ҡарап паҡҡалы",
+ "tooltip-n-help": "Пелешмәне алырлыҡ урын",
+ "tooltip-t-whatlinkshere": "Пы питкә тапшырған пөтөн питләрнең күцермәлеге",
+ "tooltip-t-recentchangeslinked": "Пы питтән тапшырылған питләрнең суңҡы пашҡартыулары",
+ "tooltip-feed-atom": "Пы пит өцөн Atom-ҡа трансляция",
+ "tooltip-t-contributions": "{{GENDER:$1|Пы ҡулланыуцы ҡылған}} пашҡартыуларның күцермәлеге",
+ "tooltip-t-emailuser": "{{GENDER:$1|пы ҡулланыуцыға}} ҡат йебәргәле",
+ "tooltip-t-upload": "Файлларны төйәгәле",
+ "tooltip-t-specialpages": "Ҡесмәт питләрнең күцермәлеге",
+ "tooltip-t-print": "Пы питнең пасма аңышы",
+ "tooltip-t-permalink": "Пы питнең версиясына тапшырған келәң ссылка",
+ "tooltip-ca-nstab-main": "Мәҡәләнеңке эцтәлеге",
+ "tooltip-ca-nstab-user": "Ҡулланыуцыныңҡы үсенең пите",
+ "tooltip-ca-nstab-special": "Пы ҡесмәт пит, аны төсәткәле пулмайты",
+ "tooltip-ca-nstab-project": "Проектның пите",
+ "tooltip-ca-nstab-image": "Файлның пите",
+ "tooltip-ca-nstab-mediawiki": "MediaWiki-ның ҡәбәрләре пите",
+ "tooltip-ca-nstab-template": "Ҡалыпның пите",
+ "tooltip-ca-nstab-category": "Категорияның пите",
+ "tooltip-minoredit": "Пы пашҡартыуны пайтаҡ түгел итеп пилгеләгәле",
+ "tooltip-save": "Пашҡартыуларығысны ҡалтырғалы",
+ "tooltip-preview": "Питне алттан ҡарап цығыу; төсәтеүләрегесне ҡалтырыр алттан ҡулланың!",
+ "tooltip-diff": "Текстта эшләнкән үсегеснең пашҡартыуларығысны генә күргәскәле",
+ "tooltip-compareselectedversions": "Пы питнең ике сайланҡан аңышылары арасынтағы айырманы ҡарағалы.",
+ "tooltip-watch": "Пы питне көсәтеү күцермәлегемә өстәгәле",
+ "tooltip-rollback": "Пер пасыу пелән суңҡы пашҡартыуларны алып уйғалы",
+ "tooltip-undo": "Пулмайын итеүнең сәбәбен күргәсә алыу мөмкинцелеге пелән кергеселгән төсәтеүне уйып ташлағалы.",
+ "tooltip-summary": "Ҡысҡаца сүрәтләмә кергесең",
+ "simpleantispam-label": "Спамҡа ҡаршы тикшереү. Мыны <strong>ТУЛТЫРМАҢ</strong>!",
+ "pageinfo-title": "«$1» турлы ҡәбәр-пелем",
+ "pageinfo-header-basic": "Төп ҡәбәр-пелемнәр",
+ "pageinfo-header-edits": "Төсәтеүләр тариғы",
+ "pageinfo-header-restrictions": "Питне саҡлау",
+ "pageinfo-header-properties": "Питнең үслекләре",
+ "pageinfo-display-title": "Күренкән исем",
+ "pageinfo-default-sort": "Тик сайлау ацҡыц",
+ "pageinfo-length": "Питнеңке оссонноғо (байтларта)",
+ "pageinfo-article-id": "Питнең аңныштырғыцы",
+ "pageinfo-language": "Пы питнең теле",
+ "pageinfo-content-model": "Пит эцтәлекнең моделе",
+ "pageinfo-robot-policy": "Эстәйтеген роботлар индексацялағанннар",
+ "pageinfo-robot-index": "Рөҡсәт ителгән",
+ "pageinfo-robot-noindex": "Рөҡсәт ителмәгән",
+ "pageinfo-watchers": "Көсәткәннәрнең исәбе",
+ "pageinfo-few-watchers": "$1 асыраҡ {{PLURAL:$1|көсәтеүце}}",
+ "pageinfo-redirects-name": "Пы питкә йусыҡлауларның исәбе",
+ "pageinfo-subpages-name": "Пы питнең эцке питләре",
+ "pageinfo-subpages-value": "$1 ($2 {{PLURAL:$2|йусыҡлау}}; $3 {{PLURAL:$3|тик}})",
+ "pageinfo-firstuser": "Питне ҡылыуцы",
+ "pageinfo-firsttime": "Пит ҡылыуның датасы",
+ "pageinfo-lastuser": "Суңҡы төсәткер",
+ "pageinfo-lasttime": "Суңҡы төсәтеүнең датасы",
+ "pageinfo-edits": "Пөттөрә төсәтеүләр исәбе",
+ "pageinfo-authors": "Төрлө авторларның тулы исәбе",
+ "pageinfo-recent-edits": "Суңҡы уаҡыттағы төсәтеүләр ($1 уаҡытны)",
+ "pageinfo-recent-authors": "Суңҡы уаҡыттағы авторлар",
+ "pageinfo-magic-words": "{{PLURAL:$1|1=Сиғерле сүс|Сиғерле сүсләр}} ($1)",
+ "pageinfo-hidden-categories": "{{PLURAL:$1|1=Йәшерен категория|Йәшерен категориялар}} ($1)",
+ "pageinfo-templates": "{{PLURAL:$1|1=Ҡалып|Ҡалыплар}} ($1)",
+ "pageinfo-toolboxlink": "\tПит турлы ҡәбәр-пелемнәр",
+ "pageinfo-contentpage": "Эцтәлекле пит тип исәпләнәте",
+ "pageinfo-contentpage-yes": "Әйә",
+ "patrol-log-page": "Тикшереү журнал",
+ "previousdiff": "← Алттағы төсәтеү",
+ "nextdiff": "Мынан суңҡы төсәтеү →",
+ "widthheightpage": "$1 × $2, $3 {{PLURAL:$3 пит}}",
+ "file-info-size": "$1 × $2 {{PLURAL:$2|пиксель}}, файлның сурлығы: $3, MIME төр: $4",
+ "file-info-size-pages": "$1 × $2 пиксель, файл үлцәме: $3, MIME-тибы: $4, $5 {{PLURAL:$5|пит|питләр}}",
+ "file-nohires": "Йуғары ацыҡлыҡлы аңыш йуҡ",
+ "svg-long-desc": "SVG-файл, номиналь $1 × $2 {{PLURAL:$2|пиксель|}}, файлның сурлығы: $3",
+ "show-big-image": "Пашлапҡы файл",
+ "show-big-image-preview": "Алттан ҡарау уаҡыттағы сурлыҡ: $1.",
+ "show-big-image-other": "{{PLURAL:$2|1=Пашҡа сурлыҡ|Пашҡа сурлыҡлар}}: $1.",
+ "show-big-image-size": "$1 × $2 пиксель",
+ "metadata": "Метапиремнәр",
+ "metadata-help": "Пы файлта тик цифралы камера йә сканер пелән өстәлгән мәғлүмәтләр пар. Әгәр пы файл ҡороу уаҡытынан суң алмашынҡан пулса, аныңҡы ҡәйбер параметрлары төрөс пулмасҡа мөмкин.",
+ "metadata-fields": "Пы күцермәлеккә кергән метапиремнәрнең ҡырлары сүрәт питтә күрсәтелер. Ҡалғаннары килешеү пуйынца йәшерелер. * make * model * datetimeoriginal * exposuretime * fnumber * isospeedratings * focallength * artist * copyright * imagedescription * gpslatitude * gpslongitude * gpsaltitude",
+ "exif-orientation": "Кадрныңҡы утысылыуы",
+ "exif-xresolution": "Горизонталь сурлыҡ",
+ "exif-yresolution": "Вертикаль сурлыҡ",
+ "exif-datetime": "Файлны пашҡартыу көнө пелән уаҡыты",
+ "exif-make": "Камераны йасауцы",
+ "exif-model": "Камераның төрө",
+ "exif-software": "Ҡулланҡан программа",
+ "exif-exifversion": "Exif-ныңҡы версиясы",
+ "exif-colorspace": "Төсләрнең киңнеге",
+ "exif-datetimeoriginal": "Цын көнө пелән уаҡыты",
+ "exif-datetimedigitized": "Саннаштырыуның көнө пелән уаҡыты",
+ "exif-orientation-1": "Нормаль",
+ "namespacesall": "парысы",
+ "monthsall": "пөттөрә",
+ "imgmultipagenext": "алттағы пит →",
+ "imgmultigo": "Күцкәле!",
+ "imgmultigoto": "$1 питкә күцкәле",
+ "watchlisttools-clear": "Төсәтеү күцермәлекне тасартҡалы",
+ "watchlisttools-view": "Күцермәлектәге питләртә пашҡарыулар",
+ "watchlisttools-edit": "Күцермәлекне ҡарағалы та төсәткәле",
+ "watchlisttools-raw": "Тик текст итеп төсәтеү",
+ "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|уйлап ҡарау]])",
+ "redirect": "Файлның аңныштырғыцынан, ҡатнашыуцытан, питтән, версиятан йә журналтан йусыҡлау",
+ "redirect-summary": "Пы ҡесмәт пит файлға (файлның исеменән), питкә (версияның аңныштырғыцынан йә питенән), ҡатнашыуцының питен (ҡатнашыуцының исәп аңныштырғыцынан) йә ҡатнашыуцының питенә (аңныштырғыцның журналынан) йебәрәте.",
+ "redirect-submit": "Күцкәле",
+ "redirect-lookup": "Эстәү:",
+ "redirect-value": "Мәғнә:",
+ "redirect-user": "Ҡатнашыуцының аңыштырғыцы",
+ "redirect-page": "Питнең аңныштырғыцы",
+ "redirect-revision": "Питнең аңышы",
+ "redirect-file": "Файлның исеме",
+ "specialpages": "Атайы питләр",
+ "tag-filter": "[[Special:Tags|Пилгеләр]] фильтры:",
+ "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|Тамғалар}}]]: $2)",
+ "tags-active-yes": "Әйә",
+ "tags-active-no": "Йуҡ",
+ "tags-hitcount": "$1 {{PLURAL:$1|1=пашҡартыу|пашҡартыулар|пашҡартыуларны}}",
+ "logentry-delete-delete": "$1 $3 питне {{GENDER:$2|пөтөрөп ҡуйты}}",
+ "logentry-delete-restore": "$1 $3 ($4) питен {{GENDER:$2|йаңатан торғосто}}",
+ "logentry-delete-revision": "Ҡатнашыуцы $1 $3: $4 питенең {{PLURAL:$5|$5 версиялары|$5 версияларының|1=версиялар}} күренешен {{GENDER:$2|пашҡартты|пашҡартты}}.",
+ "revdelete-content-hid": "эцтәлеге йәшерелшән",
+ "logentry-move-move": "$1 $3 питнең исемен {{GENDER:$2| алмаштырты}}. Йаңа исеме: $4",
+ "logentry-move-move-noredirect": "$1 йусыҡ ҡалтырмайын $3 питне $4 итеп йаңа исем пирте",
+ "logentry-move-move_redir": "$1 йусыҡлап $3 питне $4 итеп күцерте",
+ "logentry-patrol-patrol-auto": "$1 $3 питнең $4 версиясын автоматиклап {{GENDER:$2|тикшерте}}",
+ "logentry-newusers-create": "{{GENDER:$2|ҡатнашыуцы}} $1 исәп йасманы ҡылты.",
+ "logentry-newusers-autocreate": "Автоматик килеш {{GENDER:$2| ҡатнашыуцының}} $1 исәп йасмасы ҡылынты",
+ "logentry-upload-upload": "$1 $3 {{GENDER:$2|төйәте}}",
+ "logentry-upload-overwrite": "$1 йаңа аңыш{{GENDER:$2||тейәте}} $3",
+ "searchsuggest-search": "{{SITENAME}}та эстәгәле",
+ "duration-days": "$1 {{PLURAL:$1|көн}}",
+ "randomrootpage": "Көтөлмәгән тамыр пит"
+}
"cannotlogoutnow-title": "ఇప్పుడు లాగౌట్ అవలేరు",
"cannotlogoutnow-text": "$1 ను వాడుతూండగా లాగౌట్ అవలేరు.",
"welcomeuser": "స్వాగతం, $1!",
- "welcomecreation-msg": "మీ ఖాతాని సృష్టించాం.\nమీ [[Special:Preferences|{{SITENAME}} అభిరుచులను]] మార్చుకోవడం మరువకండి.\nతెలుగు వికీపీడియాలో తెలుగులోనే రాయాలి. వికీలో రచనలు చేసే ముందు, కింది సూచనలను గమనించండి.\nతెలుగు {{SITENAME}}లో తెలుగులోనే రాయాలి. వికీలో రచనలు చేసే ముందు, కింది సూచనలను గమనించండి.\n*వికీని త్వరగా అర్థం చేసుకునేందుకు [[వికీపీడియా:5 నిమిషాల్లో వికీ|5 నిమిషాల్లో వికీ]] పేజీని చూడండి.\n*తెలుగులో రాసేందుకు ఇంగ్లీషు అక్షరాల ఉచ్ఛారణతో తెలుగు టైపు చేసే [[వికీపీడియా:టైపింగు సహాయం| టైపింగ్ సహాయం]] వాడవచ్చు. మరిన్ని ఉపకరణాల కొరకు [[కీ బోర్డు]] మరియు తెరపై తెలుగు సరిగా లేకపోతే[[వికీపీడియా:Setting up your browser for Indic scripts|ఈ పేజీ]] చూడండి.",
+ "welcomecreation-msg": "మీ ఖాతాని సృష్టించాం.\nమీరు మీ {{SITENAME}} [[Special:Preferences|అభిరుచులను]] మార్చుకోవచ్చు.",
"yourname": "వాడుకరి పేరు:",
"userlogin-yourname": "వాడుకరి పేరు",
"userlogin-yourname-ph": "మీ వాడుకరి పేరును ఇవ్వండి",
"nosuchusershort": "\"$1\" adında bir kullanıcı bulunmamaktadır. Yazılışı kontrol edin.",
"nouserspecified": "Bir kullanıcı adı belirtmek zorundasınız.",
"login-userblocked": "Bu kullanıcı engellenmiş. Giriş yapmaya izin verilmiyor.",
- "wrongpassword": "Parolayı yanlış girdiniz. Lütfen tekrar deneyiniz.",
+ "wrongpassword": "Hatalı kullanıcı adı ya da parola girildi. Lütfen tekrar deneyin.",
"wrongpasswordempty": "Boş parola girdiniz. Lütfen tekrar deneyiniz.",
"passwordtooshort": "Parolalar en az {{PLURAL:$1|1 karakter|$1 karakter}} uzunluğunda olmalı.",
"passwordtoolong": "Parolalar $1 karakterden uzun olamaz.",
"grant-editmywatchlist": "İzleme listeni düzenle",
"grant-editprotected": "Korumalı sayfaları Düzenle",
"grant-patrol": "Sayfadaki değişiklikleri incele",
+ "grant-sendemail": "Diğer kullanıcılara e-posta gönder",
+ "grant-uploadeditmovefile": "Dosya yükle, yenisiyle değiştir ve taşı",
"grant-uploadfile": "Dosya yükle",
"grant-basic": "Basit haklar",
"grant-viewdeleted": "Silinen dosya ve sayfaları görüntüle",
"grant-viewmywatchlist": "İzleme listeni gör",
+ "grant-viewrestrictedlogs": "Kısıtlanmış günlük girdilerini görüntüle",
"newuserlogpage": "Kullanıcı oluşturma günlüğü",
"newuserlogpagetext": "Bu bir kullanıcı oluşturma günlüğüdür.",
"rightslog": "Kullanıcı hakları günlüğü",
"rightslogtext": "Bu, kullanıcı hakları değişiklikleri için bir günlüktür.",
"action-read": "bu sayfayı okumaya",
"action-edit": "bu sayfayı değiştirmeye",
- "action-createpage": "sayfa oluşturmaya",
- "action-createtalk": "tartışma sayfası oluşturmaya",
+ "action-createpage": "sayfayı oluştur",
+ "action-createtalk": "tartışma sayfasını oluştur",
"action-createaccount": "bu kullanıcı hesabını oluşturmaya",
+ "action-autocreateaccount": "bu harici kullanıcı hesabını otomatik olarak oluştur",
"action-history": "sayfa geçmişini görüntüle",
"action-minoredit": "bu değişikliği küçük olarak işaretlemeye",
"action-move": "bu sayfayı taşımaya",
"action-upload_by_url": "bir URL adresinden bu dosyayı yüklemeye",
"action-writeapi": "API yaz kullanmaya",
"action-delete": "bu sayfayı silmeye",
- "action-deleterevision": "bu revizyonu silmeye",
- "action-deletedhistory": "bu sayfanın silinme geçmişini görmeye",
+ "action-deleterevision": "revizyonları sil",
+ "action-deletelogentry": "günlük girdilerini sil",
+ "action-deletedhistory": "sayfanın silme geçmişini görüntüle",
+ "action-deletedtext": "silinmiş revizyon metnini görüntüle",
"action-browsearchive": "silinen sayfaları aramaya",
"action-undelete": "sayfaları geri getir",
"action-suppressrevision": "gizli sürümleri gözden geçir ve geri getir",
"rcfilters-activefilters": "Etkin süzgeçler",
"rcfilters-advancedfilters": "Gelişmiş süzgeçler",
"rcfilters-limit-title": "Gösterilecek sonuçlar",
+ "rcfilters-limit-and-date-label": "$1 değişiklik, $2",
"rcfilters-days-title": "Son günler",
"rcfilters-hours-title": "Son saatler",
+ "rcfilters-days-show-days": "$1 gün",
+ "rcfilters-days-show-hours": "$1 saat",
"rcfilters-quickfilters": "Kaydedilmiş süzgeçler",
"rcfilters-quickfilters-placeholder-title": "Henüz hiçbir süzgeç kaydedilmedi",
"rcfilters-quickfilters-placeholder-description": "Süzgeç ayarlarınızı kaydetmek ve sonrasında bunları kullanmak için, aşağıda Aktif Süzgeçler alanındaki yer imi simgesine tıklayın.",
"rcfilters-filtergroup-userExpLevel": "Deneyim düzeyi (yalnızca kayıtlı kullanıcılar için)",
"rcfilters-filter-user-experience-level-registered-label": "Kayıtlı",
"rcfilters-filter-user-experience-level-registered-description": "Oturum açmış editörler.",
- "rcfilters-filter-user-experience-level-unregistered-label": "Kayıtsız",
- "rcfilters-filter-user-experience-level-unregistered-description": "Oturum açmamış editörler.",
+ "rcfilters-filter-user-experience-level-unregistered-label": "Kayıtlı olmayan",
+ "rcfilters-filter-user-experience-level-unregistered-description": "Oturum açmamış kullanıcılar.",
"rcfilters-filter-user-experience-level-newcomer-label": "Yeni gelenler",
"rcfilters-filter-user-experience-level-newcomer-description": "10'dan az düzenlemesi veya 4 günden az etkinliği olan kayıtlı kullanıcılar.",
"rcfilters-filter-user-experience-level-learner-label": "Öğreniciler",
"rcfilters-filter-minor-description": "Yazarın küçük olarak etiketlediği düzenlemeler.",
"rcfilters-filter-major-label": "Küçük olmayan düzenlemeler",
"rcfilters-filter-major-description": "Küçük olarak etiketlenmemiş düzenlemeler.",
+ "rcfilters-filtergroup-watchlistactivity": "İzleme listesi faaliyetleri",
+ "rcfilters-filter-watchlistactivity-unseen-label": "Görülmemiş değişiklikler",
+ "rcfilters-filter-watchlistactivity-seen-label": "Görülmüş değişiklikler",
"rcfilters-filtergroup-changetype": "Değişiklik türü",
"rcfilters-filter-pageedits-label": "Sayfa düzenlemeleri",
"rcfilters-filter-pageedits-description": "Viki içeriği, tartışmalar, kategori açıklamalarındaki düzenlemeler...",
"tag-filter": "[[Special:Tags|מאַרקירונג]] פֿילטער:",
"tag-filter-submit": "פֿילטער",
"tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|טאַג|טאַגן}}]]: $2)",
+ "tag-mw-new-redirect": "נייע ווייטערפֿירונג",
+ "tag-mw-undo": "אַנולירן",
"tags-title": "טאַגן",
"tags-intro": "דער בלאַט ווײַזט די טאַגן מיט וואס דאס ווייכווארג קען צייכענען אַ רעדאַגירונג, און זייער באַטייַט.",
"tags-tag": "טאַג נאָמען",
"postedit-confirmation-created": "页面已创建。",
"postedit-confirmation-restored": "页面已恢复。",
"postedit-confirmation-saved": "您的编辑已保存。",
+ "postedit-confirmation-published": "您的编辑已发布。",
"edit-already-exists": "不可以建立一个新页面。\n它已经存在。",
"defaultmessagetext": "默认消息文本",
"content-failed-to-parse": "未能将 $2 内容转换为 $1:$3",
'name' => $name,
'count' => $stat->getCount(),
// Get rate per second from mean (in ms)
- 'rate' => 1.0 / ( $stat->getMean() / 1000.0 ),
+ 'rate' => $stat->getMean() == 0 ? INF : ( 1.0 / ( $stat->getMean() / 1000.0 ) ),
'total' => $stat->getMean() * $stat->getCount(),
'mean' => $stat->getMean(),
'max' => $stat->max,
<?php
/**
- * Remove hidden preferences from the database.
+ * Clean up user preferences from the database.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
*
* @file
* @author TyA <tya.wiki@gmail.com>
+ * @author Chad <chad@wikimedia.org>
* @see https://phabricator.wikimedia.org/T32976
* @ingroup Maintenance
*/
require_once __DIR__ . '/Maintenance.php';
/**
- * Maintenance script that removes hidden preferences from the database.
+ * Maintenance script that removes bogus preferences from the database.
*
* @ingroup Maintenance
*/
class CleanupPreferences extends Maintenance {
+ public function __construct() {
+ parent::__construct();
+ $this->mDescription = 'Clean up hidden preferences, removed preferences, and normalizes values';
+ $this->setBatchSize( 50 );
+ $this->addOption( 'dry-run', 'Print debug info instead of actually deleting' );
+ $this->addOption( 'hidden', 'Drop hidden preferences ($wgHiddenPrefs)' );
+ $this->addOption( 'unknown',
+ 'Drop unknown preferences (not in $wgDefaultUserOptions or a gadget or userjs)' );
+ // TODO: actually implement this
+ // $this->addOption( 'bogus', 'Drop preferences that have invalid/unaccepted values' );
+ }
+
+ /**
+ * We will do this in three passes
+ * 1) The easiest is to drop the hidden preferences from the database. We
+ * don't actually want them
+ * 2) Drop preference keys that we don't know about. They could've been
+ * removed from core, provided by a now-disabled extension, or the result
+ * of a bug. We don't want them.
+ * 3) TODO: Normalize accepted preference values. This is the biggest part of the work.
+ * For each preference we know about, iterate over it and if it's got a
+ * limited set of accepted values (so it's not text, basically), make sure
+ * all values are in that range. Drop ones that aren't.
+ */
public function execute() {
- global $wgHiddenPrefs;
+ global $wgHiddenPrefs, $wgDefaultUserOptions;
$dbw = $this->getDB( DB_MASTER );
- $this->beginTransaction( $dbw, __METHOD__ );
- foreach ( $wgHiddenPrefs as $item ) {
- $dbw->delete(
+ $didWork = false;
+ $hidden = $this->hasOption( 'hidden' );
+ $unknown = $this->hasOption( 'unknown' );
+ $bogus = $this->hasOption( 'bogus' );
+
+ if ( !$hidden && !$unknown && !$bogus ) {
+ $this->output( "Did not select one of --hidden, --unknown or --bogus, exiting\n" );
+ return;
+ }
+
+ // Remove hidden prefs. Iterate over them to avoid the IN on a large table
+ if ( $hidden ) {
+ if ( !$wgHiddenPrefs ) {
+ $this->output( "No hidden preferences, skipping\n" );
+ }
+ foreach ( $wgHiddenPrefs as $hiddenPref ) {
+ $this->deleteByWhere(
+ $dbw,
+ 'Dropping hidden preferences',
+ [ 'up_property' => $hiddenPref ]
+ );
+ }
+ }
+
+ // Remove unknown preferences. Special-case gadget- and userjs- as we can't
+ // control those names.
+ if ( $unknown ) {
+ $this->deleteByWhere(
+ $dbw,
+ 'Dropping unknown preferences',
+ [
+ 'up_property NOT' . $dbw->buildLike( 'gadget-', $dbw->anyString() ),
+ 'up_property NOT' . $dbw->buildLike( 'userjs-', $dbw->anyString() ),
+ 'up_property NOT IN (' . $dbw->makeList( array_keys( $wgDefaultUserOptions ) ) . ')',
+ ]
+ );
+ }
+
+ // Something something phase 3
+ if ( $bogus ) {
+ }
+ }
+
+ /**
+ *
+ */
+ private function deleteByWhere( $dbw, $startMessage, $where ) {
+ $this->output( $startMessage . "...\n" );
+ $total = 0;
+ while ( true ) {
+ $res = $dbw->select(
'user_properties',
- [ 'up_property' => $item ],
- __METHOD__
+ '*', // The table lacks a primary key, so select the whole row
+ $where,
+ __METHOD__,
+ [ 'LIMIT' => $this->mBatchSize ]
);
- };
- $this->commitTransaction( $dbw, __METHOD__ );
- $this->output( "Finished!\n" );
+
+ $numRows = $res->numRows();
+ $total += $numRows;
+ if ( $res->numRows() <= 0 ) {
+ // All done!
+ $this->output( "DONE! (handled $total entries)\n" );
+ break;
+ }
+
+ // Progress or something
+ $this->output( "..doing $numRows entries\n" );
+
+ // Delete our batch, then wait
+ foreach ( $res as $row ) {
+ if ( $this->hasOption( 'dry-run' ) ) {
+ $this->output(
+ " DRY RUN, would drop: " .
+ "[up_user] => '{$row->up_user}' " .
+ "[up_property] => '{$row->up_property}' " .
+ "[up_value] => '{$row->up_value}'\n"
+ );
+ continue;
+ }
+ $this->beginTransaction( $dbw, __METHOD__ );
+ $dbw->delete(
+ 'user_properties',
+ [
+ 'up_user' => $row->up_user,
+ 'up_property' => $row->up_property,
+ 'up_value' => $row->up_value,
+ ],
+ __METHOD__
+ );
+ $this->commitTransaction( $dbw, __METHOD__ );
+ }
+ }
}
}
|| $title->getInterwiki()
|| !$title->canExist()
) {
- if ( $title->getInterwiki() || !$title->canExist() ) {
+ $titleImpossible = $title->getInterwiki() || !$title->canExist();
+ if ( $titleImpossible ) {
$prior = $title->getPrefixedDBkey();
} else {
$prior = $title->getDBkey();
$ns = 0;
}
- $clean = 'Broken/' . $prior;
+ if ( !$titleImpossible && !$title->exists() ) {
+ // Looks like the current title, after cleaning it up, is valid and available
+ $clean = $prior;
+ } else {
+ $clean = 'Broken/' . $prior;
+ }
$verified = Title::makeTitleSafe( $ns, $clean );
if ( !$verified || $verified->exists() ) {
$blah = "Broken/id:" . $row->page_id;
#!/bin/bash -eu
-# This script generates a commit that updates our copy of OOjs UI
+# This script generates a commit that updates our copy of OOUI
if [ -n "${2:-}" ]
then
git reset -- $TARGET_DIR
git checkout -- $TARGET_DIR
git fetch origin
-git checkout -B upstream-oojs-ui origin/master
+git checkout -B upstream-ooui origin/master
# Fetch upstream version
cd $NPM_DIR
npm install oojs-ui
fi
-OOJSUI_VERSION=$(node -e 'console.log(require("./node_modules/oojs-ui/package.json").version);')
-if [ "$OOJSUI_VERSION" == "" ]
+OOUI_VERSION=$(node -e 'console.log(require("./node_modules/oojs-ui/package.json").version);')
+if [ "$OOUI_VERSION" == "" ]
then
- echo 'Could not find OOjs UI version'
+ echo 'Could not find OOUI version'
exit 1
fi
cd $REPO_DIR
COMMITMSG=$(cat <<END
-Update OOjs UI to v$OOJSUI_VERSION
+Update OOUI to v$OOUI_VERSION
Release notes:
- https://phabricator.wikimedia.org/diffusion/GOJU/browse/master/History.md;v$OOJSUI_VERSION
+ https://phabricator.wikimedia.org/diffusion/GOJU/browse/master/History.md;v$OOUI_VERSION
END
)
# Update composer.json as well
-composer require oojs/oojs-ui $OOJSUI_VERSION --no-update
+composer require oojs/oojs-ui $OOUI_VERSION --no-update
# Stage deletion, modification and creation of files. Then commit.
git add --update $TARGET_DIR
/**
* Special modules who have their own classes
*/
- 'startup' => [ 'class' => 'ResourceLoaderStartUpModule' ],
+ 'startup' => [ 'class' => ResourceLoaderStartUpModule::class ],
// Scripts managed by the local wiki (stored in the MediaWiki namespace)
- 'site' => [ 'class' => 'ResourceLoaderSiteModule' ],
- 'site.styles' => [ 'class' => 'ResourceLoaderSiteStylesModule' ],
+ 'site' => [ 'class' => ResourceLoaderSiteModule::class ],
+ 'site.styles' => [ 'class' => ResourceLoaderSiteStylesModule::class ],
'noscript' => [
- 'class' => 'ResourceLoaderWikiModule',
+ 'class' => ResourceLoaderWikiModule::class,
'styles' => [ 'MediaWiki:Noscript.css' ],
'group' => 'noscript',
],
'filepage' => [
- 'class' => 'ResourceLoaderWikiModule',
+ 'class' => ResourceLoaderWikiModule::class,
'styles' => [ 'MediaWiki:Filepage.css' ],
],
'user.groups' => [
],
// Scripts managed by the current user (stored in their user space)
- 'user' => [ 'class' => 'ResourceLoaderUserModule' ],
- 'user.styles' => [ 'class' => 'ResourceLoaderUserStylesModule' ],
+ 'user' => [ 'class' => ResourceLoaderUserModule::class ],
+ 'user.styles' => [ 'class' => ResourceLoaderUserStylesModule::class ],
// Populate mediawiki.user placeholders with information about the current user
- 'user.defaults' => [ 'class' => 'ResourceLoaderUserDefaultsModule' ],
- 'user.options' => [ 'class' => 'ResourceLoaderUserOptionsModule' ],
- 'user.tokens' => [ 'class' => 'ResourceLoaderUserTokensModule' ],
+ 'user.defaults' => [ 'class' => ResourceLoaderUserDefaultsModule::class ],
+ 'user.options' => [ 'class' => ResourceLoaderUserOptionsModule::class ],
+ 'user.tokens' => [ 'class' => ResourceLoaderUserTokensModule::class ],
// Scripts for the dynamic language specific data, like grammar forms.
- 'mediawiki.language.data' => [ 'class' => 'ResourceLoaderLanguageDataModule' ],
+ 'mediawiki.language.data' => [ 'class' => ResourceLoaderLanguageDataModule::class ],
/* MediaWiki base skinning modules */
],
// Used in the web installer. Test it after modifying this definition!
'mediawiki.skinning.interface' => [
- 'class' => 'ResourceLoaderSkinModule',
+ 'class' => ResourceLoaderSkinModule::class,
'styles' => [
'resources/src/mediawiki.skinning/elements.css' => [ 'media' => 'screen' ],
'resources/src/mediawiki.skinning/content.css' => [ 'media' => 'screen' ],
/* MediaWiki */
'mediawiki' => [
- 'class' => 'ResourceLoaderRawFileModule',
+ 'class' => ResourceLoaderRawFileModule::class,
// Keep in sync with maintenance/jsduck/eg-iframe.html
'scripts' => [
'resources/src/mediawiki/mediawiki.js',
],
'mediawiki.ForeignApi' => [
'targets' => [ 'desktop', 'mobile' ],
- 'class' => 'ResourceLoaderForeignApiModule',
+ 'class' => ResourceLoaderForeignApiModule::class,
// Additional dependencies generated dynamically
'dependencies' => 'mediawiki.ForeignApi.core',
],
]
],
'mediawiki.ForeignStructuredUpload.config' => [
- 'class' => 'ResourceLoaderUploadDialogModule',
+ 'class' => ResourceLoaderUploadDialogModule::class,
],
'mediawiki.ForeignStructuredUpload' => [
'scripts' => 'resources/src/mediawiki/mediawiki.ForeignStructuredUpload.js',
]
],
'mediawiki.util' => [
- 'class' => 'ResourceLoaderMediaWikiUtilModule',
+ 'class' => ResourceLoaderMediaWikiUtilModule::class,
'scripts' => 'resources/src/mediawiki/mediawiki.util.js',
'dependencies' => [
'jquery.accessKeyLabel',
'targets' => [ 'desktop', 'mobile' ],
],
'mediawiki.toolbar' => [
- 'class' => 'ResourceLoaderEditToolbarModule',
+ 'class' => ResourceLoaderEditToolbarModule::class,
'scripts' => 'resources/src/mediawiki.toolbar/toolbar.js',
'styles' => 'resources/src/mediawiki.toolbar/toolbar.less',
'dependencies' => 'jquery.textSelection',
'postedit-confirmation-created',
'postedit-confirmation-restored',
'postedit-confirmation-saved',
+ 'postedit-confirmation-published',
],
],
'mediawiki.action.view.redirect' => [
'mediawiki.jqueryMsg' => [
// Add data for mediawiki.jqueryMsg, such as allowed tags
- 'class' => 'ResourceLoaderJqueryMsgModule',
+ 'class' => ResourceLoaderJqueryMsgModule::class,
'scripts' => 'resources/src/mediawiki/mediawiki.jqueryMsg.js',
'dependencies' => [
'mediawiki.util',
)
],
- 'mediawiki.language.names' => [ 'class' => 'ResourceLoaderLanguageNamesModule' ],
+ 'mediawiki.language.names' => [ 'class' => ResourceLoaderLanguageNamesModule::class ],
'mediawiki.language.specialCharacters' => [
- 'class' => 'ResourceLoaderSpecialCharacterDataModule'
+ 'class' => ResourceLoaderSpecialCharacterDataModule::class
],
/* MediaWiki Libs */
// The core JavaScript library.
'oojs-ui-core' => [
- 'class' => 'ResourceLoaderOOUIFileModule',
+ 'class' => ResourceLoaderOOUIFileModule::class,
'scripts' => [
'resources/lib/oojs-ui/oojs-ui-core.js',
'resources/src/oojs-ui-local.js',
],
// This contains only the styles required by core widgets.
'oojs-ui-core.styles' => [
- 'class' => 'ResourceLoaderOOUIFileModule',
+ 'class' => ResourceLoaderOOUIFileModule::class,
'styles' => [
'resources/lib/oojs-ui/wikimedia-ui-base.less', // Providing Wikimedia UI LESS variables to all
'resources/src/oojs-ui-local.css', // HACK, see inside the file
],
// Additional widgets and layouts module.
'oojs-ui-widgets' => [
- 'class' => 'ResourceLoaderOOUIFileModule',
+ 'class' => ResourceLoaderOOUIFileModule::class,
'scripts' => 'resources/lib/oojs-ui/oojs-ui-widgets.js',
'themeStyles' => 'widgets',
'dependencies' => [
],
// Toolbar and tools module.
'oojs-ui-toolbars' => [
- 'class' => 'ResourceLoaderOOUIFileModule',
+ 'class' => ResourceLoaderOOUIFileModule::class,
'scripts' => 'resources/lib/oojs-ui/oojs-ui-toolbars.js',
'themeStyles' => 'toolbars',
'dependencies' => [
],
// Windows and dialogs module.
'oojs-ui-windows' => [
- 'class' => 'ResourceLoaderOOUIFileModule',
+ 'class' => ResourceLoaderOOUIFileModule::class,
'scripts' => 'resources/lib/oojs-ui/oojs-ui-windows.js',
'themeStyles' => 'windows',
'dependencies' => [
],
'oojs-ui.styles.indicators' => [
- 'class' => 'ResourceLoaderOOUIImageModule',
+ 'class' => ResourceLoaderOOUIImageModule::class,
'themeImages' => 'indicators',
],
'oojs-ui.styles.textures' => [
- 'class' => 'ResourceLoaderOOUIImageModule',
+ 'class' => ResourceLoaderOOUIImageModule::class,
'themeImages' => 'textures',
],
'oojs-ui.styles.icons-accessibility' => [
- 'class' => 'ResourceLoaderOOUIImageModule',
+ 'class' => ResourceLoaderOOUIImageModule::class,
'themeImages' => 'icons-accessibility',
],
'oojs-ui.styles.icons-alerts' => [
- 'class' => 'ResourceLoaderOOUIImageModule',
+ 'class' => ResourceLoaderOOUIImageModule::class,
'themeImages' => 'icons-alerts',
],
'oojs-ui.styles.icons-content' => [
- 'class' => 'ResourceLoaderOOUIImageModule',
+ 'class' => ResourceLoaderOOUIImageModule::class,
'themeImages' => 'icons-content',
],
'oojs-ui.styles.icons-editing-advanced' => [
- 'class' => 'ResourceLoaderOOUIImageModule',
+ 'class' => ResourceLoaderOOUIImageModule::class,
'themeImages' => 'icons-editing-advanced',
],
'oojs-ui.styles.icons-editing-core' => [
- 'class' => 'ResourceLoaderOOUIImageModule',
+ 'class' => ResourceLoaderOOUIImageModule::class,
'themeImages' => 'icons-editing-core',
],
'oojs-ui.styles.icons-editing-list' => [
- 'class' => 'ResourceLoaderOOUIImageModule',
+ 'class' => ResourceLoaderOOUIImageModule::class,
'themeImages' => 'icons-editing-list',
],
'oojs-ui.styles.icons-editing-styling' => [
- 'class' => 'ResourceLoaderOOUIImageModule',
+ 'class' => ResourceLoaderOOUIImageModule::class,
'themeImages' => 'icons-editing-styling',
],
'oojs-ui.styles.icons-interactions' => [
- 'class' => 'ResourceLoaderOOUIImageModule',
+ 'class' => ResourceLoaderOOUIImageModule::class,
'themeImages' => 'icons-interactions',
],
'oojs-ui.styles.icons-layout' => [
- 'class' => 'ResourceLoaderOOUIImageModule',
+ 'class' => ResourceLoaderOOUIImageModule::class,
'themeImages' => 'icons-layout',
],
'oojs-ui.styles.icons-location' => [
- 'class' => 'ResourceLoaderOOUIImageModule',
+ 'class' => ResourceLoaderOOUIImageModule::class,
'themeImages' => 'icons-location',
],
'oojs-ui.styles.icons-media' => [
- 'class' => 'ResourceLoaderOOUIImageModule',
+ 'class' => ResourceLoaderOOUIImageModule::class,
'themeImages' => 'icons-media',
],
'oojs-ui.styles.icons-moderation' => [
- 'class' => 'ResourceLoaderOOUIImageModule',
+ 'class' => ResourceLoaderOOUIImageModule::class,
'themeImages' => 'icons-moderation',
],
'oojs-ui.styles.icons-movement' => [
- 'class' => 'ResourceLoaderOOUIImageModule',
+ 'class' => ResourceLoaderOOUIImageModule::class,
'themeImages' => 'icons-movement',
],
'oojs-ui.styles.icons-user' => [
- 'class' => 'ResourceLoaderOOUIImageModule',
+ 'class' => ResourceLoaderOOUIImageModule::class,
'themeImages' => 'icons-user',
],
'oojs-ui.styles.icons-wikimedia' => [
- 'class' => 'ResourceLoaderOOUIImageModule',
+ 'class' => ResourceLoaderOOUIImageModule::class,
'themeImages' => 'icons-wikimedia',
],
];
* These plugins provide extra functionality for interaction with textareas.
*/
( function ( $ ) {
- if ( document.selection && document.selection.createRange ) {
- // On IE, patch the focus() method to restore the windows' scroll position
- // (T34241)
- $.fn.extend( {
- focus: ( function ( jqFocus ) {
- return function () {
- var $w, state, result;
- if ( arguments.length === 0 ) {
- $w = $( window );
- state = { top: $w.scrollTop(), left: $w.scrollLeft() };
- result = jqFocus.apply( this, arguments );
- window.scrollTo( state.top, state.left );
- return result;
- }
- return jqFocus.apply( this, arguments );
- };
- }( $.fn.focus ) )
- } );
- }
-
$.fn.textSelection = function ( command, options ) {
var fn,
alternateFn,
- context,
- hasWikiEditor,
- needSave,
retval;
- /**
- * Helper function to get an IE TextRange object for an element
- *
- * @param {HTMLElement} element
- * @return {TextRange}
- */
- function rangeForElementIE( element ) {
- var sel;
- if ( element.nodeName.toLowerCase() === 'input' ) {
- return element.createTextRange();
- } else {
- sel = document.body.createTextRange();
- sel.moveToElementText( element );
- return sel;
- }
- }
-
- /**
- * Helper function for IE for activating the textarea. Called only in the
- * IE-specific code paths below; makes use of IE-specific non-standard
- * function setActive() if possible to avoid screen flicker.
- *
- * @param {HTMLElement} element
- */
- function activateElementOnIE( element ) {
- if ( element.setActive ) {
- element.setActive(); // T34241: doesn't scroll
- } else {
- $( element ).focus(); // may scroll (but we patched it above)
- }
- }
-
fn = {
/**
* Get the contents of the textarea
this.val( content );
},
/**
- * Get the currently selected text in this textarea. Will focus the textarea
- * in some browsers (IE/Opera)
+ * Get the currently selected text in this textarea.
*
* @return {string}
*/
getSelection: function () {
- var retval, range,
+ var retval,
el = this.get( 0 );
if ( !el || $( el ).is( ':hidden' ) ) {
retval = '';
- } else if ( document.selection && document.selection.createRange ) {
- activateElementOnIE( el );
- range = document.selection.createRange();
- retval = range.text;
} else if ( el.selectionStart || el.selectionStart === 0 ) {
retval = el.value.substring( el.selectionStart, el.selectionEnd );
}
encapsulateSelection: function ( options ) {
return this.each( function () {
var selText, scrollTop, insertText,
- isSample, range, range2, range3, startPos, endPos,
+ isSample, startPos, endPos,
pre = options.pre,
post = options.post;
isSample = false;
// Do nothing if display none
if ( this.style.display !== 'none' ) {
- if ( document.selection && document.selection.createRange ) {
- // IE
-
- // Note that IE9 will trigger the next section unless we check this first.
- // See bug T37201.
-
- activateElementOnIE( this );
- if ( options.selectionStart !== undefined ) {
- $( this ).textSelection( 'setSelection', { start: options.selectionStart, end: options.selectionEnd } );
- }
-
- selText = $( this ).textSelection( 'getSelection' );
- scrollTop = this.scrollTop;
- range = document.selection.createRange();
-
- checkSelectedText();
- insertText = pre + selText + post;
- if ( options.splitlines ) {
- insertText = doSplitLines( selText, pre, post );
- }
- if ( options.ownline && range.moveStart ) {
- range2 = document.selection.createRange();
- range2.collapse();
- range2.moveStart( 'character', -1 );
- // FIXME: Which check is correct?
- if ( range2.text !== '\r' && range2.text !== '\n' && range2.text !== '' ) {
- insertText = '\n' + insertText;
- pre += '\n';
- }
- range3 = document.selection.createRange();
- range3.collapse( false );
- range3.moveEnd( 'character', 1 );
- if ( range3.text !== '\r' && range3.text !== '\n' && range3.text !== '' ) {
- insertText += '\n';
- post += '\n';
- }
- }
-
- range.text = insertText;
- if ( isSample && options.selectPeri && range.moveStart ) {
- range.moveStart( 'character', -post.length - selText.length );
- range.moveEnd( 'character', -post.length );
- }
- range.select();
- // Restore the scroll position
- this.scrollTop = scrollTop;
- } else if ( this.selectionStart || this.selectionStart === 0 ) {
- // Mozilla/Opera
-
+ if ( this.selectionStart || this.selectionStart === 0 ) {
$( this ).focus();
if ( options.selectionStart !== undefined ) {
$( this ).textSelection( 'setSelection', { start: options.selectionStart, end: options.selectionEnd } );
/**
* Ported from Wikia's LinkSuggest extension
* https://svn.wikia-code.com/wikia/trunk/extensions/wikia/LinkSuggest
- * Some code copied from
- * http://www.dedestruct.com/2008/03/22/howto-cross-browser-cursor-position-in-textareas/
*
* Get the position (in resolution of bytes not necessarily characters)
* in a textarea
*
- * Will focus the textarea in some browsers (IE/Opera)
- *
* @param {Object} options Options
* FIXME document the options parameters
* @return {number} Position
getCaretPosition: function ( options ) {
function getCaret( e ) {
var caretPos = 0,
- endPos = 0,
- preText, rawPreText, periText,
- rawPeriText, postText,
- // IE Support
- preFinished,
- periFinished,
- postFinished,
- // Range containing text in the selection
- periRange,
- // Range containing text before the selection
- preRange,
- // Range containing text after the selection
- postRange;
-
- if ( e && document.selection && document.selection.createRange ) {
- // IE doesn't properly report non-selected caret position through
- // the selection ranges when textarea isn't focused. This can
- // lead to saving a bogus empty selection, which then screws up
- // whatever we do later (T33847).
- activateElementOnIE( e );
-
- preFinished = false;
- periFinished = false;
- postFinished = false;
- periRange = document.selection.createRange().duplicate();
-
- preRange = rangeForElementIE( e );
- // Move the end where we need it
- preRange.setEndPoint( 'EndToStart', periRange );
-
- postRange = rangeForElementIE( e );
- // Move the start where we need it
- postRange.setEndPoint( 'StartToEnd', periRange );
+ endPos = 0;
- // Load the text values we need to compare
- preText = rawPreText = preRange.text;
- periText = rawPeriText = periRange.text;
- postText = postRange.text;
-
- /*
- * Check each range for trimmed newlines by shrinking the range by 1
- * character and seeing if the text property has changed. If it has
- * not changed then we know that IE has trimmed a \r\n from the end.
- */
- do {
- if ( !preFinished ) {
- if ( preRange.compareEndPoints( 'StartToEnd', preRange ) === 0 ) {
- preFinished = true;
- } else {
- preRange.moveEnd( 'character', -1 );
- if ( preRange.text === preText ) {
- rawPreText += '\r\n';
- } else {
- preFinished = true;
- }
- }
- }
- if ( !periFinished ) {
- if ( periRange.compareEndPoints( 'StartToEnd', periRange ) === 0 ) {
- periFinished = true;
- } else {
- periRange.moveEnd( 'character', -1 );
- if ( periRange.text === periText ) {
- rawPeriText += '\r\n';
- } else {
- periFinished = true;
- }
- }
- }
- if ( !postFinished ) {
- if ( postRange.compareEndPoints( 'StartToEnd', postRange ) === 0 ) {
- postFinished = true;
- } else {
- postRange.moveEnd( 'character', -1 );
- if ( postRange.text !== postText ) {
- postFinished = true;
- }
- }
- }
- } while ( ( !preFinished || !periFinished || !postFinished ) );
- caretPos = rawPreText.replace( /\r\n/g, '\n' ).length;
- endPos = caretPos + rawPeriText.replace( /\r\n/g, '\n' ).length;
- } else if ( e && ( e.selectionStart || e.selectionStart === 0 ) ) {
- // Firefox support
+ if ( e && ( e.selectionStart || e.selectionStart === 0 ) ) {
caretPos = e.selectionStart;
endPos = e.selectionEnd;
}
*/
setSelection: function ( options ) {
return this.each( function () {
- var selection, length, newLines;
// Do nothing if hidden
if ( !$( this ).is( ':hidden' ) ) {
if ( this.selectionStart || this.selectionStart === 0 ) {
this.selectionStart = options.start;
this.selectionEnd = options.end;
}
- } else if ( document.body.createTextRange ) {
- selection = rangeForElementIE( this );
- length = this.value.length;
- // IE doesn't count \n when computing the offset, so we won't either
- newLines = this.value.match( /\n/g );
- if ( newLines ) {
- length = length - newLines.length;
- }
- selection.moveStart( 'character', options.start );
- selection.moveEnd( 'character', -length + options.end );
-
- // This line can cause an error under certain circumstances (textarea empty, no selection)
- // Silence that error
- try {
- selection.select();
- } catch ( e ) { }
}
}
} );
return ( $.client.profile().platform === 'mac' ? 13 : ( $.client.profile().platform === 'linux' ? 15 : 16 ) ) * row;
}
return this.each( function () {
- var scroll, range, savedRange, pos, oldScrollTop;
+ var scroll;
// Do nothing if hidden
if ( !$( this ).is( ':hidden' ) ) {
if ( this.selectionStart || this.selectionStart === 0 ) {
- // Mozilla
scroll = getCaretScrollPosition( this );
if ( options.force || scroll < $( this ).scrollTop() ||
scroll > $( this ).scrollTop() + $( this ).height() ) {
$( this ).scrollTop( scroll );
}
- } else if ( document.selection && document.selection.createRange ) {
- // IE / Opera
- /*
- * IE automatically scrolls the selected text to the
- * bottom of the textarea at range.select() time, except
- * if it was already in view and the cursor position
- * wasn't changed, in which case it does nothing. To
- * cover that case, we'll force it to act by moving one
- * character back and forth.
- */
- range = document.body.createTextRange();
- savedRange = document.selection.createRange();
- pos = $( this ).textSelection( 'getCaretPosition' );
- oldScrollTop = this.scrollTop;
- range.moveToElementText( this );
- range.collapse();
- range.move( 'character', pos + 1 );
- range.select();
- if ( this.scrollTop !== oldScrollTop ) {
- this.scrollTop += range.offsetTop;
- } else if ( options.force ) {
- range.move( 'character', -1 );
- range.select();
- }
- savedRange.select();
}
}
$( this ).trigger( 'scrollToPosition' );
// Return [start, end] instead of just start
startAndEnd: false
}, options );
- // FIXME: We may not need character position-based functions if we insert markers in the right places
break;
case 'setSelection':
options = $.extend( {
if ( options.end === undefined ) {
options.end = options.start;
}
- // FIXME: We may not need character position-based functions if we insert markers in the right places
break;
case 'scrollToCaretPosition':
options = $.extend( {
return;
}
- context = $( this ).data( 'wikiEditor-context' );
- hasWikiEditor = ( context !== undefined && context.$iframe !== undefined );
-
- // IE selection restore voodoo
- needSave = false;
- if ( hasWikiEditor && context.savedSelection !== null ) {
- context.fn.restoreSelection();
- needSave = true;
- }
retval = ( alternateFn && alternateFn[ command ] || fn[ command ] ).call( this, options );
- if ( hasWikiEditor && needSave ) {
- context.fn.saveSelection();
- }
return retval;
};
data = data || {};
if ( data.message === undefined ) {
- data.message = $.parseHTML( mw.message( 'postedit-confirmation-saved', data.user || mw.user ).escaped() );
+ data.message = $.parseHTML( mw.message(
+ mw.config.get( 'wgEditSubmitButtonLabelPublish' ) ?
+ 'postedit-confirmation-published' :
+ 'postedit-confirmation-saved',
+ data.user || mw.user
+ ).escaped() );
}
$content = $( '<div>' ).addClass( 'postedit-icon postedit-icon-checkmark postedit-content' );
"Á", "á", "À", "à", "Â", "â", "Ä", "ä", "Ã", "ã", "Ǎ", "ǎ", "Ā", "ā", "Ă", "ă", "Ą", "ą", "Å", "å", "Ć", "ć", "Ĉ", "ĉ", "Ç", "ç", "Č", "č", "Ċ", "ċ", "Đ", "đ", "Ď", "ď", "É", "é", "È", "è", "Ê", "ê", "Ë", "ë", "Ě", "ě", "Ē", "ē", "Ĕ", "ĕ", "Ė", "ė", "Ę", "ę", "Ĝ", "ĝ", "Ģ", "ģ", "Ğ", "ğ", "Ġ", "ġ", "Ĥ", "ĥ", "Ħ", "ħ", "Í", "í", "Ì", "ì", "Î", "î", "Ï", "ï", "Ĩ", "ĩ", "Ǐ", "ǐ", "Ī", "ī", "Ĭ", "ĭ", "İ", "ı", "Į", "į", "Ĵ", "ĵ", "Ķ", "ķ", "Ĺ", "ĺ", "Ļ", "ļ", "Ľ", "ľ", "Ł", "ł", "Ń", "ń", "Ñ", "ñ", "Ņ", "ņ", "Ň", "ň", "Ó", "ó", "Ò", "ò", "Ô", "ô", "Ö", "ö", "Õ", "õ", "Ǒ", "ǒ", "Ō", "ō", "Ŏ", "ŏ", "Ǫ", "ǫ", "Ő", "ő", "Ŕ", "ŕ", "Ŗ", "ŗ", "Ř", "ř", "Ś", "ś", "Ŝ", "ŝ", "Ş", "ş", "Š", "š", "Ș", "ș", "Ț", "ț", "Ť", "ť", "Ú", "ú", "Ù", "ù", "Û", "û", "Ü", "ü", "Ũ", "ũ", "Ů", "ů", "Ǔ", "ǔ", "Ū", "ū", "ǖ", "ǘ", "ǚ", "ǜ", "Ŭ", "ŭ", "Ų", "ų", "Ű", "ű", "Ŵ", "ŵ", "Ý", "ý", "Ŷ", "ŷ", "Ÿ", "ÿ", "Ȳ", "ȳ", "Ź", "ź", "Ž", "ž", "Ż", "ż", "Æ", "æ", "Ǣ", "ǣ", "Ø", "ø", "Œ", "œ", "ß", "Ð", "ð", "Þ", "þ", "Ə", "ə"
],
"latinextended": [
- "Ḁ", "ḁ", "ẚ", "Ạ", "ạ", "Ả", "ả", "Ấ", "ấ", "Ầ", "ầ", "Ẩ", "ẩ", "Ẫ", "ẫ", "Ậ", "ậ", "Ắ", "ắ", "Ằ", "ằ", "Ẳ", "ẳ", "Ẵ", "ẵ", "Ặ", "ặ", "Ḃ", "ḃ", "Ḅ", "ḅ", "Ḇ", "ḇ", "Ḉ", "ḉ", "Ḋ", "ḋ", "Ḍ", "ḍ", "Ḏ", "ḏ", "Ḑ", "ḑ", "Ḓ", "ḓ", "Ḕ", "ḕ", "Ḗ", "ḗ", "Ḙ", "ḙ", "Ḛ", "ḛ", "Ḝ", "ḝ", "Ẹ", "ẹ", "Ẻ", "ẻ", "Ẽ", "ẽ", "Ế", "ế", "Ề", "ề", "Ể", "ể", "Ễ", "ễ", "Ệ", "ệ", "Ḟ", "ḟ", "Ḡ", "ḡ", "Ḣ", "ḣ", "Ḥ", "ḥ", "Ḧ", "ḧ", "Ḩ", "ḩ", "Ḫ", "ḫ", "ẖ", "Ḭ", "ḭ", "Ḯ", "ḯ", "Ỉ", "ỉ", "Ị", "ị", "Ḱ", "ḱ", "Ḳ", "ḳ", "Ḵ", "ḵ", "Ḷ", "ḷ", "Ḹ", "ḹ", "Ḻ", "ḻ", "Ḽ", "ḽ", "Ỻ", "ỻ", "Ḿ", "ḿ", "Ṁ", "ṁ", "Ṃ", "ṃ", "Ṅ", "ṅ", "Ṇ", "ṇ", "Ṉ", "ṉ", "Ṋ", "ṋ", "Ṍ", "ṍ", "Ṏ", "ṏ", "Ṑ", "ṑ", "Ṓ", "ṓ", "Ọ", "ọ", "Ỏ", "ỏ", "Ố", "ố", "Ồ", "ồ", "Ổ", "ổ", "Ỗ", "ỗ", "Ộ", "ộ", "Ớ", "ớ", "Ờ", "ờ", "Ở", "ở", "Ỡ", "ỡ", "Ợ", "ợ", "Ǿ", "ǿ", "Ơ", "ơ", "Ṕ", "ṕ", "Ṗ", "ṗ", "Ṙ", "ṙ", "Ṛ", "ṛ", "Ṝ", "ṝ", "Ṟ", "ṟ", "Ṡ", "ṡ", "ẛ", "Ṣ", "ṣ", "Ṥ", "ṥ", "Ṧ", "ṧ", "Ṩ", "ṩ", "ẜ", "ẝ", "Ṫ", "ṫ", "Ṭ", "ṭ", "Ṯ", "ṯ", "Ṱ", "ṱ", "ẗ", "Ṳ", "ṳ", "Ṵ", "ṵ", "Ṷ", "ṷ", "Ṹ", "ṹ", "Ṻ", "ṻ", "Ụ", "ụ", "Ủ", "ủ", "Ứ", "ứ", "Ừ", "ừ", "Ử", "ử", "Ữ", "ữ", "Ự", "ự", "Ư", "ư", "Ǖ", "Ǘ", "Ǚ", "Ǜ", "Ṽ", "ṽ", "Ṿ", "ṿ", "Ỽ", "ỽ", "Ẁ", "ẁ", "Ẃ", "ẃ", "Ẅ", "ẅ", "Ẇ", "ẇ", "Ẉ", "ẉ", "ẘ", "Ẋ", "ẋ", "Ẍ", "ẍ", "Ẏ", "ẏ", "ẙ", "Ỳ", "ỳ", "Ỵ", "ỵ", "Ỷ", "ỷ", "Ỹ", "ỹ", "Ỿ", "ỿ", "Ẑ", "ẑ", "Ẓ", "ẓ", "Ẕ", "ẕ", "Ǽ", "ǽ", "ẞ", "ẟ"
+ "Ḁ", "ḁ", "ẚ", "Ạ", "ạ", "Ả", "ả", "Ấ", "ấ", "Ầ", "ầ", "Ẩ", "ẩ", "Ẫ", "ẫ", "Ậ", "ậ", "Ắ", "ắ", "Ằ", "ằ", "Ẳ", "ẳ", "Ẵ", "ẵ", "Ặ", "ặ", "Ḃ", "ḃ", "Ḅ", "ḅ", "Ḇ", "ḇ", "Ḉ", "ḉ", "Ḋ", "ḋ", "Ḍ", "ḍ", "Ḏ", "ḏ", "Ḑ", "ḑ", "Ḓ", "ḓ", "Ḕ", "ḕ", "Ḗ", "ḗ", "Ḙ", "ḙ", "Ḛ", "ḛ", "Ḝ", "ḝ", "Ẹ", "ẹ", "Ẻ", "ẻ", "Ẽ", "ẽ", "Ế", "ế", "Ề", "ề", "Ể", "ể", "Ễ", "ễ", "Ệ", "ệ", "Ḟ", "ḟ", "Ḡ", "ḡ", "Ḣ", "ḣ", "Ḥ", "ḥ", "Ḧ", "ḧ", "Ḩ", "ḩ", "Ḫ", "ḫ", "ẖ", "Ḭ", "ḭ", "Ḯ", "ḯ", "Ỉ", "ỉ", "Ị", "ị", "Ḱ", "ḱ", "Ḳ", "ḳ", "Ḵ", "ḵ", "ĸ", "Ḷ", "ḷ", "Ḹ", "ḹ", "Ḻ", "ḻ", "Ḽ", "ḽ", "Ỻ", "ỻ", "Ḿ", "ḿ", "Ṁ", "ṁ", "Ṃ", "ṃ", "Ṅ", "ṅ", "Ṇ", "ṇ", "Ṉ", "ṉ", "Ṋ", "ṋ", "Ṍ", "ṍ", "Ṏ", "ṏ", "Ṑ", "ṑ", "Ṓ", "ṓ", "Ọ", "ọ", "Ỏ", "ỏ", "Ố", "ố", "Ồ", "ồ", "Ổ", "ổ", "Ỗ", "ỗ", "Ộ", "ộ", "Ớ", "ớ", "Ờ", "ờ", "Ở", "ở", "Ỡ", "ỡ", "Ợ", "ợ", "Ǿ", "ǿ", "Ơ", "ơ", "Ṕ", "ṕ", "Ṗ", "ṗ", "Ṙ", "ṙ", "Ṛ", "ṛ", "Ṝ", "ṝ", "Ṟ", "ṟ", "Ṡ", "ṡ", "ẛ", "Ṣ", "ṣ", "Ṥ", "ṥ", "Ṧ", "ṧ", "Ṩ", "ṩ", "ẜ", "ẝ", "Ṫ", "ṫ", "Ṭ", "ṭ", "Ṯ", "ṯ", "Ṱ", "ṱ", "ẗ", "Ṳ", "ṳ", "Ṵ", "ṵ", "Ṷ", "ṷ", "Ṹ", "ṹ", "Ṻ", "ṻ", "Ụ", "ụ", "Ủ", "ủ", "Ứ", "ứ", "Ừ", "ừ", "Ử", "ử", "Ữ", "ữ", "Ự", "ự", "Ư", "ư", "Ǖ", "Ǘ", "Ǚ", "Ǜ", "Ṽ", "ṽ", "Ṿ", "ṿ", "Ỽ", "ỽ", "Ẁ", "ẁ", "Ẃ", "ẃ", "Ẅ", "ẅ", "Ẇ", "ẇ", "Ẉ", "ẉ", "ẘ", "Ẋ", "ẋ", "Ẍ", "ẍ", "Ẏ", "ẏ", "ẙ", "Ỳ", "ỳ", "Ỵ", "ỵ", "Ỷ", "ỷ", "Ỹ", "ỹ", "Ỿ", "ỿ", "Ẑ", "ẑ", "Ẓ", "ẓ", "Ẕ", "ẕ", "Ǽ", "ǽ", "ẞ", "ẟ"
],
"ipa": [
"p", "t̪", "t", "ʈ", "c", "k", "q", "ʡ", "ʔ", "b", "d̪", "d", "ɖ", "ɟ", "ɡ", "ɢ", "ɓ", "ɗ", "ʄ", "ɠ", "ʛ", "t͡s", "t͡ʃ", "t͡ɕ", "d͡z", "d͡ʒ", "d͡ʑ", "ɸ", "f", "θ", "s", "ʃ", "ʅ", "ʆ", "ʂ", "ɕ", "ç", "ɧ", "x", "χ", "ħ", "ʜ", "h", "β", "v", "ʍ", "ð", "z", "ʒ", "ʓ", "ʐ", "ʑ", "ʝ", "ɣ", "ʁ", "ʕ", "ʖ", "ʢ", "ɦ", "ɬ", "ɮ", "m", "m̩", "ɱ", "ɱ̩", "ɱ̍", "n̪", "n̪̍", "n", "n̩", "ɳ", "ɳ̩", "ɲ", "ɲ̩", "ŋ", "ŋ̍", "ŋ̩", "ɴ", "ɴ̩", "ʙ", "ʙ̩", "r", "r̩", "ʀ", "ʀ̩", "ɾ", "ɽ", "ɿ", "ɺ", "l̪", "l̪̩", "l", "l̩", "ɫ", "ɫ̩", "ɭ", "ɭ̩", "ʎ", "ʎ̩", "ʟ", "ʟ̩", "w", "ɥ", "ʋ", "ɹ", "ɻ", "j", "ɰ", "ʘ", "ǂ", "ǀ", "!", "ǁ", "ʰ", "ʱ", "ʷ", "ʸ", "ʲ", "ʳ", "ⁿ", "ˡ", "ʴ", "ʵ", "ˢ", "ˣ", "ˠ", "ʶ", "ˤ", "ˁ", "ˀ", "ʼ", "i", "i̯", "ĩ", "y", "y̯", "ỹ", "ɪ", "ɪ̯", "ɪ̃", "ʏ", "ʏ̯", "ʏ̃", "ɨ", "ɨ̯", "ɨ̃", "ʉ", "ʉ̯", "ʉ̃", "ɯ", "ɯ̯", "ɯ̃", "u", "u̯", "ũ", "ʊ", "ʊ̯", "ʊ̃", "e", "e̯", "ẽ", "ø", "ø̯", "ø̃", "ɘ", "ɘ̯", "ɘ̃", "ɵ", "ɵ̯", "ɵ̃", "ɤ", "ɤ̯", "ɤ̃", "o", "o̯", "õ", "ɛ", "ɛ̯", "ɛ̃", "œ", "œ̯", "œ̃", "ɜ", "ɜ̯", "ɜ̃", "ə", "ə̯", "ə̃", "ɞ", "ɞ̯", "ɞ̃", "ʌ", "ʌ̯", "ʌ̃", "ɔ", "ɔ̯", "ɔ̃", "æ", "æ̯", "æ̃", "ɶ", "ɶ̯", "ɶ̃", "a", "a̯", "ã", "ɐ", "ɐ̯", "ɐ̃", "ɑ", "ɑ̯", "ɑ̃", "ɒ", "ɒ̯", "ɒ̃", "ˈ", "ˌ", "ː", "ˑ", "˘", ".", "‿", "|", "‖", "ɚ", "ɝ"
border: 1pt dashed #000;
padding: 1em 0;
font-size: 8pt;
- white-space: pre;
+ white-space: pre-wrap;
word-wrap: break-word;
- overflow: auto;
}
/* Prevent citations and subscripts from interfering with the line-height */
+/**
+ * Minimum available screen width at which a device can be considered a mobile device
+ * Many older feature phones have screens smaller than this value.
+ * Number is prone to change with new information.
+ * @since 1.31
+ */
+@width-breakpoint-mobile: 320px;
+
+/**
+ * Minimum available screen width at which a device can be considered a tablet
+ * The number is currently based on the device width of a Samsung Galaxy S5 mini and is low
+ * enough to cover iPad (768px). Number is prone to change with new information.
+ * @since 1.31
+ */
+@width-breakpoint-tablet: 720px;
+/**
+ * Minimum available screen width at which a device can be considered a desktop
+ * Number is prone to change with new information.
+ * @since 1.31
+ */
+@width-breakpoint-desktop: 1000px;
+
// Colors for use in mediawiki.ui and elsewhere
// Although this defines many shades, be parsimonious in your own use of grays.
display: none;
}
+ #jump-to-nav {
+ margin-top: -0.5em;
+ margin-bottom: 0.5em;
+ }
+
// Make the watchlist-details message display while loading, but make it not take up any
// space. This makes the min-height trick work better.
.watchlistDetails {
padding: 0.5em;
}
+#mw-apisandbox-ui .mw-apisandbox-link {
+ display: none;
+}
+
.mw-apisandbox-popup .oo-ui-popupWidget-body > .oo-ui-widget {
vertical-align: middle;
}
font-weight: bold;
}
-/* Login Button, following `ButtonWidget (progressive)` from OOjs UI */
+/* Login Button, following 'ButtonWidget (progressive)' from OOUI */
#mw-createaccount-join {
background-color: #f8f9fa;
color: #36c;
/**
* DateTimeInputWidgets can be used to input a date, a time, or a date and
* time, in either UTC or the user's local timezone.
- * Please see the [OOjs UI documentation on MediaWiki] [1] for more information and examples.
+ * Please see the [OOUI documentation on MediaWiki] [1] for more information and examples.
*
* This widget can be used inside a HTML form, such as a OO.ui.FormLayout.
*
* var dateTimeInput = new mw.widgets.datetime.DateTimeInputWidget( {} )
* $( 'body' ).append( dateTimeInput.$element );
*
- * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Inputs
+ * [1]: https://www.mediawiki.org/wiki/OOUI/Widgets/Inputs
*
* @class
* @extends OO.ui.InputWidget
/*!
- * OOJS-UI defines used by the existing CSS (will make it easier to put this
- * widget in OOJS-UI once OOJS-UI is capable of handling it)
+ * OOUI defines used by the existing CSS (will make it easier to put this
+ * widget in OOUI once OOUI is capable of handling it)
*/
.oo-ui-box-sizing( @type: border-box ) {
var apiPromise = this.get( {
formatversion: 2,
prop: 'categoryinfo',
- titles: String( title )
+ titles: [ String( title ) ]
} );
return apiPromise
.then( function ( data ) {
- return !!data.query.pages[ 0 ].categoryinfo;
+ return !!(
+ data.query && // query is missing on title=""
+ data.query.pages && // query.pages is missing on title="#" or title="mw:"
+ data.query.pages[ 0 ].categoryinfo
+ );
} )
.promise( { abort: apiPromise.abort } );
},
var apiPromise = this.get( {
formatversion: 2,
prop: 'categories',
- titles: String( title )
+ titles: [ String( title ) ]
} );
return apiPromise
.then( function ( data ) {
- var page = data.query.pages[ 0 ];
+ var page;
+ if ( !data.query || !data.query.pages ) {
+ return false;
+ }
+ page = data.query.pages[ 0 ];
if ( !page.categories ) {
return false;
}
/*
* HTMLForm enhancements:
- * Infuse some OOjs UI HTMLForm fields (those which benefit from always being infused).
+ * Infuse some OOUI HTMLForm fields (those which benefit from always being infused).
*/
( function ( mw, $ ) {
mw.htmlform = {};
/**
- * Allows custom data specific to HTMLFormField to be set for OOjs UI forms. This picks up the
+ * Allows custom data specific to HTMLFormField to be set for OOUI forms. This picks up the
* extra config from a matching PHP widget (defined in HTMLFormElement.php) when constructed using
* OO.ui.infuse().
*
this.feedbackPageTitle = config.title || new mw.Title( 'Feedback' );
this.messagePosterPromise = mw.messagePoster.factory.create( this.feedbackPageTitle, config.apiUrl );
+ this.foreignApi = config.apiUrl ? new mw.ForeignApi( config.apiUrl ) : null;
// Links
this.bugsTaskSubmissionLink = config.bugsLink || '//phabricator.wikimedia.org/maniphest/task/edit/form/1/';
* Respond to dialog submit event. If the information was
* submitted successfully, open a MessageDialog to thank the user.
*
- * @param {string} [status] A status of the end of operation
+ * @param {string} status A status of the end of operation
* of the main feedback dialog. Empty if the dialog was
* dismissed with no action or the user followed the button
* to the external task reporting site.
+ * @param {string} feedbackPageName
+ * @param {string} feedbackPageUrl
*/
- mw.Feedback.prototype.onDialogSubmit = function ( status ) {
+ mw.Feedback.prototype.onDialogSubmit = function ( status, feedbackPageName, feedbackPageUrl ) {
var dialogConfig;
if ( status !== 'submitted' ) {
title: mw.msg( 'feedback-thanks-title' ),
message: $( '<span>' ).msg(
'feedback-thanks',
- this.feedbackPageTitle.getNameText(),
+ feedbackPageName,
$( '<a>' ).attr( {
target: '_blank',
- href: this.feedbackPageTitle.getUrl()
+ href: feedbackPageUrl
} )
),
actions: [
this.constructor.static.dialog,
{
title: mw.msg( this.dialogTitleMessageKey ),
+ foreignApi: this.foreignApi,
settings: {
messagePosterPromise: this.messagePosterPromise,
title: this.feedbackPageTitle,
*/
mw.Feedback.Dialog.prototype.getSetupProcess = function ( data ) {
return mw.Feedback.Dialog.parent.prototype.getSetupProcess.call( this, data )
+ .next( function () {
+ // Get the URL of the target page, we want to use that in links in the intro
+ // and in the success dialog
+ var dialog = this;
+ if ( data.foreignApi ) {
+ return data.foreignApi.get( {
+ action: 'query',
+ prop: 'info',
+ inprop: 'url',
+ formatversion: 2,
+ titles: data.settings.title.getPrefixedText()
+ } ).then( function ( data ) {
+ dialog.feedbackPageUrl = OO.getProp( data, 'query', 'pages', 0, 'canonicalurl' );
+ } );
+ } else {
+ this.feedbackPageUrl = data.settings.title.getUrl();
+ }
+ }, this )
.next( function () {
var plainMsg, parsedMsg,
settings = data.settings;
this.setBugReportLink( settings.bugsTaskSubmissionLink );
this.feedbackPageTitle = settings.title;
this.feedbackPageName = settings.title.getNameText();
- this.feedbackPageUrl = settings.title.getUrl();
// Useragent checkbox
if ( settings.useragentCheckbox.show ) {
-/* HACK: Set sane font-size for OOjs UI dialogs (and menus/popups inside the default overlay), in
+/* HACK: Set sane font-size for OOUI dialogs (and menus/popups inside the default overlay), in
the most common case. This should be skin's responsibility, but alas our skins tend to have the
weirdest font-sizes on body. This shall be removed when we make the MediaWiki skins bundled with
tarball sane. (T91152) */
( function ( mw ) {
var isMobile;
- // Connect OOjs UI to MediaWiki's localisation system
+ // Connect OOUI to MediaWiki's localisation system
OO.ui.getUserLanguages = mw.language.getFallbackLanguageChain;
OO.ui.msg = mw.msg;
- // Connect OOjs UI's deprecation warnings to MediaWiki's logging system
+ // Connect OOUI's deprecation warnings to MediaWiki's logging system
OO.ui.warnDeprecation = function ( message ) {
mw.track( 'mw.deprecate', 'oojs-ui' );
mw.log.warn( message );
$this->assertSame( 401, $request->getStatus() );
}
+ public function testFactoryDefaults() {
+ $request = MWHttpRequest::factory( 'http://acme.test' );
+ $this->assertInstanceOf( MWHttpRequest::class, $request );
+ }
+
// --------------------
/**
$this->assertArrayNotHasKey( strtolower( $name ),
array_change_key_case( $cookieJar->cookie, CASE_LOWER ) );
}
+
}
$options = ParserOptions::newFromContext( $context );
$options->setTimestamp( $this->getFakeTimestamp() );
- if ( !isset( $opts['wrap'] ) ) {
- $options->setWrapOutputClass( false );
- }
-
if ( isset( $opts['tidy'] ) ) {
if ( !$this->tidySupport->isEnabled() ) {
$this->recorder->skipped( $test, 'tidy extension is not installed' );
} else {
$output = $parser->parse( $test['input'], $title, $options, true, true, 1337 );
$out = $output->getText( [
- 'allowTOC' => !isset( $opts['notoc'] )
+ 'allowTOC' => !isset( $opts['notoc'] ),
+ 'unwrap' => !isset( $opts['wrap'] ),
] );
if ( isset( $opts['tidy'] ) ) {
$out = preg_replace( '/\s+$/', '', $out );
}
}
+ SiteStatsInit::doPlaceholderInit();
+
User::resetIdByNameCache();
// Make sysop user
// FIXME: This test should pass without setting global content language
$this->options = ParserOptions::newFromUserAndLang( new User, $contLang );
$this->options->setTemplateCallback( [ __CLASS__, 'statelessFetchTemplate' ] );
- $this->options->setWrapOutputClass( false );
$this->parser = new Parser;
MagicWord::clearCache();
$title = Title::newFromText( 'Unit test' );
$options = ParserOptions::newFromUser( new User() );
- $options->setWrapOutputClass( false );
$this->assertEquals( "<p>$longLine</p>",
- $this->parser->parse( $longLine, $title, $options )->getText() );
+ $this->parser->parse( $longLine, $title, $options )->getText( [ 'unwrap' => true ] ) );
}
/**
$parserOutput = $this->parser->parse( "Test\n{{Foo}}\n{{Bar}}", $title, $this->options );
$this->assertEquals(
"<p>Test\nContent of <i>Template:Foo</i>\nContent of <i>Template:Bar</i>\n</p>",
- $parserOutput->getText()
+ $parserOutput->getText( [ 'unwrap' => true ] )
);
}
<?php
+/**
+ * @group GlobalFunctions
+ * @covers ::wfArrayFilter
+ * @covers ::wfArrayFilterByKey
+ */
class WfArrayFilterTest extends \PHPUnit_Framework_TestCase {
public function testWfArrayFilter() {
$arr = [ 'a' => 1, 'b' => 2, 'c' => 3 ];
/**
* @group Database
*/
-
class LinkerTest extends MediaWikiLangTestCase {
/**
*/
class RevisionStoreDbTest extends MediaWikiTestCase {
+ public function setUp() {
+ parent::setUp();
+ $this->tablesUsed[] = 'archive';
+ $this->tablesUsed[] = 'page';
+ $this->tablesUsed[] = 'revision';
+ $this->tablesUsed[] = 'comment';
+ }
+
/**
* @return LoadBalancer
*/
/**
* @covers WikiReference
*/
-
class WikiReferenceTest extends PHPUnit_Framework_TestCase {
use MediaWikiCoversValidator;
return false;
}
- function affectedRows() {
+ function fetchAffectedRowCount() {
return -1;
}
// Emulate rollback
$db->rollback( __METHOD__ );
+ $update->doUpdate();
+
+ // Ensure it was cancelled
+ $this->assertSame( 0, $ran );
+ }
+
+ public function testCancelSome() {
+ // Prepare update and DB
+ $db1 = new DatabaseTestHelper( __METHOD__ );
+ $db1->begin( __METHOD__ );
+ $db2 = new DatabaseTestHelper( __METHOD__ );
+ $db2->begin( __METHOD__ );
+ $ran = 0;
+ $update = new MWCallableUpdate( function () use ( &$ran ) {
+ $ran++;
+ }, __METHOD__, [ $db1, $db2 ] );
+
+ // Emulate rollback
+ $db1->rollback( __METHOD__ );
+
+ $update->doUpdate();
+
+ // Prevents: "Notice: DB transaction writes or callbacks still pending"
+ $db2->rollback( __METHOD__ );
+
// Ensure it was cancelled
+ $this->assertSame( 0, $ran );
+ }
+
+ public function testCancelAll() {
+ // Prepare update and DB
+ $db1 = new DatabaseTestHelper( __METHOD__ );
+ $db1->begin( __METHOD__ );
+ $db2 = new DatabaseTestHelper( __METHOD__ );
+ $db2->begin( __METHOD__ );
+ $ran = 0;
+ $update = new MWCallableUpdate( function () use ( &$ran ) {
+ $ran++;
+ }, __METHOD__, [ $db1, $db2 ] );
+
+ // Emulate rollbacks
+ $db1->rollback( __METHOD__ );
+ $db2->rollback( __METHOD__ );
+
$update->doUpdate();
+
+ // Ensure it was cancelled
$this->assertSame( 0, $ran );
}
+
}
* @group Database
* @group Installer
*/
-
class OracleInstallerTest extends MediaWikiTestCase {
/**
*
* @group Database
*/
-
class ArrayUtilsTest extends PHPUnit_Framework_TestCase {
use MediaWikiCoversValidator;
* @todo Test methods in this call should be split into a method and a
* dataprovider.
*/
-
class IPTest extends PHPUnit_Framework_TestCase {
use MediaWikiCoversValidator;
$wanCache = new WANObjectCache( [
'cache' => $localBag,
'pool' => 'testcache-hash',
- 'relayer' => new EventRelayerNull( [] )
+ 'relayer' => new EventRelayerNull( [] ),
+ 'mcrouterAware' => true,
+ 'region' => 'pmtpa',
+ 'cluster' => 'mw-wan'
] );
$valFunc = function () {
return 1;
$wanCache->reap( 'zzz', time() - 300 );
}
+ public function testMcRouterSupportBroadcastDelete() {
+ $localBag = $this->getMockBuilder( EmptyBagOStuff::class )
+ ->setMethods( [ 'set' ] )->getMock();
+ $wanCache = new WANObjectCache( [
+ 'cache' => $localBag,
+ 'pool' => 'testcache-hash',
+ 'relayer' => new EventRelayerNull( [] ),
+ 'mcrouterAware' => true,
+ 'region' => 'pmtpa',
+ 'cluster' => 'mw-wan'
+ ] );
+
+ $localBag->expects( $this->once() )->method( 'set' )
+ ->with( "/*/mw-wan/" . $wanCache::VALUE_KEY_PREFIX . "test" );
+
+ $wanCache->delete( 'test' );
+ }
+
+ public function testMcRouterSupportBroadcastTouchCK() {
+ $localBag = $this->getMockBuilder( EmptyBagOStuff::class )
+ ->setMethods( [ 'set' ] )->getMock();
+ $wanCache = new WANObjectCache( [
+ 'cache' => $localBag,
+ 'pool' => 'testcache-hash',
+ 'relayer' => new EventRelayerNull( [] ),
+ 'mcrouterAware' => true,
+ 'region' => 'pmtpa',
+ 'cluster' => 'mw-wan'
+ ] );
+
+ $localBag->expects( $this->once() )->method( 'set' )
+ ->with( "/*/mw-wan/" . $wanCache::TIME_KEY_PREFIX . "test" );
+
+ $wanCache->touchCheckKey( 'test' );
+ }
+
+ public function testMcRouterSupportBroadcastResetCK() {
+ $localBag = $this->getMockBuilder( EmptyBagOStuff::class )
+ ->setMethods( [ 'delete' ] )->getMock();
+ $wanCache = new WANObjectCache( [
+ 'cache' => $localBag,
+ 'pool' => 'testcache-hash',
+ 'relayer' => new EventRelayerNull( [] ),
+ 'mcrouterAware' => true,
+ 'region' => 'pmtpa',
+ 'cluster' => 'mw-wan'
+ ] );
+
+ $localBag->expects( $this->once() )->method( 'delete' )
+ ->with( "/*/mw-wan/" . $wanCache::TIME_KEY_PREFIX . "test" );
+
+ $wanCache->resetCheckKey( 'test' );
+ }
+
/**
* @dataProvider provideAdaptiveTTL
* @covers WANObjectCache::adaptiveTTL()
public function testAffected() {
$logger = $this->getMockBuilder( LoggerInterface::class )->getMock();
- $logger->expects( $this->exactly( 3 ) )->method( 'info' );
+ $logger->expects( $this->exactly( 3 ) )->method( 'warning' );
$tp = new TransactionProfiler();
$tp->setLogger( $logger );
public function testReadTime() {
$logger = $this->getMockBuilder( LoggerInterface::class )->getMock();
// 1 per query
- $logger->expects( $this->exactly( 2 ) )->method( 'info' );
+ $logger->expects( $this->exactly( 2 ) )->method( 'warning' );
$tp = new TransactionProfiler();
$tp->setLogger( $logger );
public function testWriteTime() {
$logger = $this->getMockBuilder( LoggerInterface::class )->getMock();
// 1 per query, 1 per trx, and one "sub-optimal trx" entry
- $logger->expects( $this->exactly( 4 ) )->method( 'info' );
+ $logger->expects( $this->exactly( 4 ) )->method( 'warning' );
$tp = new TransactionProfiler();
$tp->setLogger( $logger );
public function testAffectedTrx() {
$logger = $this->getMockBuilder( LoggerInterface::class )->getMock();
- $logger->expects( $this->exactly( 1 ) )->method( 'info' );
+ $logger->expects( $this->exactly( 1 ) )->method( 'warning' );
$tp = new TransactionProfiler();
$tp->setLogger( $logger );
public function testWriteTimeTrx() {
$logger = $this->getMockBuilder( LoggerInterface::class )->getMock();
// 1 per trx, and one "sub-optimal trx" entry
- $logger->expects( $this->exactly( 2 ) )->method( 'info' );
+ $logger->expects( $this->exactly( 2 ) )->method( 'warning' );
$tp = new TransactionProfiler();
$tp->setLogger( $logger );
public function testConns() {
$logger = $this->getMockBuilder( LoggerInterface::class )->getMock();
- $logger->expects( $this->exactly( 2 ) )->method( 'info' );
+ $logger->expects( $this->exactly( 2 ) )->method( 'warning' );
$tp = new TransactionProfiler();
$tp->setLogger( $logger );
public function testMasterConns() {
$logger = $this->getMockBuilder( LoggerInterface::class )->getMock();
- $logger->expects( $this->exactly( 2 ) )->method( 'info' );
+ $logger->expects( $this->exactly( 2 ) )->method( 'warning' );
$tp = new TransactionProfiler();
$tp->setLogger( $logger );
public function testReadQueryCount() {
$logger = $this->getMockBuilder( LoggerInterface::class )->getMock();
- $logger->expects( $this->exactly( 2 ) )->method( 'info' );
+ $logger->expects( $this->exactly( 2 ) )->method( 'warning' );
$tp = new TransactionProfiler();
$tp->setLogger( $logger );
public function testWriteQueryCount() {
$logger = $this->getMockBuilder( LoggerInterface::class )->getMock();
- $logger->expects( $this->exactly( 2 ) )->method( 'info' );
+ $logger->expects( $this->exactly( 2 ) )->method( 'warning' );
$tp = new TransactionProfiler();
$tp->setLogger( $logger );
protected function doQuery( $sql ) {
}
+ protected function fetchAffectedRowCount() {
+ }
+
// From DatabaseMysqli
protected function mysqlConnect( $realServer ) {
}
'rows' => [ 'field' => 'text', 'field2' => 'text2' ],
],
"DELETE FROM replace_table " .
- "WHERE ( field='text' ); " .
+ "WHERE (field = 'text'); " .
"INSERT INTO replace_table " .
"(field,field2) " .
"VALUES ('text','text2')"
],
],
"DELETE FROM module_deps " .
- "WHERE ( md_module='module' AND md_skin='skin' ); " .
+ "WHERE (md_module = 'module' AND md_skin = 'skin'); " .
"INSERT INTO module_deps " .
"(md_module,md_skin,md_deps) " .
"VALUES ('module','skin','deps')"
],
],
"DELETE FROM module_deps " .
- "WHERE ( md_module='module' AND md_skin='skin' ); " .
+ "WHERE (md_module = 'module' AND md_skin = 'skin'); " .
"INSERT INTO module_deps " .
"(md_module,md_skin,md_deps) " .
"VALUES ('module','skin','deps'); " .
"DELETE FROM module_deps " .
- "WHERE ( md_module='module2' AND md_skin='skin2' ); " .
+ "WHERE (md_module = 'module2' AND md_skin = 'skin2'); " .
"INSERT INTO module_deps " .
"(md_module,md_skin,md_deps) " .
"VALUES ('module2','skin2','deps2')"
],
],
"DELETE FROM module_deps " .
- "WHERE ( md_module='module' ) OR ( md_skin='skin' ); " .
+ "WHERE (md_module = 'module') OR (md_skin = 'skin'); " .
"INSERT INTO module_deps " .
"(md_module,md_skin,md_deps) " .
"VALUES ('module','skin','deps'); " .
"DELETE FROM module_deps " .
- "WHERE ( md_module='module2' ) OR ( md_skin='skin2' ); " .
+ "WHERE (md_module = 'module2') OR (md_skin = 'skin2'); " .
"INSERT INTO module_deps " .
"(md_module,md_skin,md_deps) " .
"VALUES ('module2','skin2','deps2')"
*/
private function getMockDB( $methods = [] ) {
static $abstractMethods = [
- 'affectedRows',
+ 'fetchAffectedRowCount',
'closeConnection',
'dataSeek',
'doQuery',
'stubthreshold' => true,
'printable' => true,
'userlang' => true,
- 'wrapclass' => true,
];
}
'No overrides' => [ true, [] ],
'In-key options are ok' => [ true, [
'thumbsize' => 1e100,
- 'wrapclass' => false,
+ 'printable' => false,
] ],
'Non-in-key options are not ok' => [ false, [
'removeComments' => false,
] ],
+ 'Non-in-key options are not ok (2)' => [ false, [
+ 'wrapclass' => 'foobar',
+ ] ],
'Canonical override, not default (1)' => [ true, [
'tidy' => true,
] ],
}
public static function provideOptionsHash() {
- $used = [ 'wrapclass', 'printable' ];
+ $used = [ 'thumbsize', 'printable' ];
$classWrapper = TestingAccessWrapper::newFromClass( ParserOptions::class );
$classWrapper->getDefaults();
'Canonical options, used some options' => [ $used, 'canonical', [] ],
'Used some options, non-default values' => [
$used,
- 'printable=1!wrapclass=foobar',
+ 'printable=1!thumbsize=200',
[
- 'wrapclass' => 'foobar',
+ 'thumbsize' => 200,
'printable' => true,
]
],
$wgHooks['ParserOptionsRegister'] = [];
$this->assertSame( [
'dateformat', 'numberheadings', 'printable', 'stubthreshold',
- 'thumbsize', 'userlang', 'wrapclass',
+ 'thumbsize', 'userlang'
], ParserOptions::allCacheVaryingOptions() );
self::clearCache();
};
$this->assertSame( [
'dateformat', 'foo', 'numberheadings', 'printable', 'stubthreshold',
- 'thumbsize', 'userlang', 'wrapclass',
+ 'thumbsize', 'userlang'
], ParserOptions::allCacheVaryingOptions() );
}
'wgScriptPath' => '/w',
'wgScript' => '/w/index.php',
] );
+ $this->hideDeprecated( 'ParserOutput stateful allowTOC' );
+ $this->hideDeprecated( 'ParserOutput stateful enableSectionEditLinks' );
$po = new ParserOutput( $text );
public static function provideGetText() {
// phpcs:disable Generic.Files.LineLength
$text = <<<EOF
-<p>Test document.
+<div class="mw-parser-output"><p>Test document.
</p>
<mw:toc><div id="toc" class="toc"><div class="toctitle"><h2>Contents</h2></div>
<ul>
</p>
<h2><span class="mw-headline" id="Section_3">Section 3</span><mw:editsection page="Test Page" section="4">Section 3</mw:editsection></h2>
<p>Three
-</p>
+</p></div>
EOF;
return [
'No stateless options, default state' => [
[], [], $text, <<<EOF
-<p>Test document.
+<div class="mw-parser-output"><p>Test document.
</p>
<div id="toc" class="toc"><div class="toctitle"><h2>Contents</h2></div>
<ul>
</p>
<h2><span class="mw-headline" id="Section_3">Section 3</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&action=edit&section=4" title="Edit section: Section 3">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
<p>Three
-</p>
+</p></div>
EOF
],
'No stateless options, TOC statefully disabled' => [
[], [ 'mTOCEnabled' => false ], $text, <<<EOF
-<p>Test document.
+<div class="mw-parser-output"><p>Test document.
</p>
<h2><span class="mw-headline" id="Section_1">Section 1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&action=edit&section=1" title="Edit section: Section 1">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
</p>
<h2><span class="mw-headline" id="Section_3">Section 3</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&action=edit&section=4" title="Edit section: Section 3">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
<p>Three
-</p>
+</p></div>
EOF
],
'No stateless options, section edits statefully disabled' => [
[], [ 'mEditSectionTokens' => false ], $text, <<<EOF
-<p>Test document.
+<div class="mw-parser-output"><p>Test document.
</p>
<div id="toc" class="toc"><div class="toctitle"><h2>Contents</h2></div>
<ul>
</p>
<h2><span class="mw-headline" id="Section_3">Section 3</span></h2>
<p>Three
-</p>
+</p></div>
EOF
],
'Stateless options override stateful settings' => [
[ 'allowTOC' => true, 'enableSectionEditLinks' => true ],
[ 'mTOCEnabled' => false, 'mEditSectionTokens' => false ],
$text, <<<EOF
-<p>Test document.
+<div class="mw-parser-output"><p>Test document.
</p>
<div id="toc" class="toc"><div class="toctitle"><h2>Contents</h2></div>
<ul>
</p>
<h2><span class="mw-headline" id="Section_3">Section 3</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&action=edit&section=4" title="Edit section: Section 3">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
<p>Three
-</p>
+</p></div>
EOF
],
'Statelessly disable section edit links' => [
[ 'enableSectionEditLinks' => false ], [], $text, <<<EOF
-<p>Test document.
+<div class="mw-parser-output"><p>Test document.
</p>
<div id="toc" class="toc"><div class="toctitle"><h2>Contents</h2></div>
<ul>
</p>
<h2><span class="mw-headline" id="Section_3">Section 3</span></h2>
<p>Three
-</p>
+</p></div>
EOF
],
'Statelessly disable TOC' => [
[ 'allowTOC' => false ], [], $text, <<<EOF
+<div class="mw-parser-output"><p>Test document.
+</p>
+
+<h2><span class="mw-headline" id="Section_1">Section 1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&action=edit&section=1" title="Edit section: Section 1">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<p>One
+</p>
+<h2><span class="mw-headline" id="Section_2">Section 2</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&action=edit&section=2" title="Edit section: Section 2">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<p>Two
+</p>
+<h3><span class="mw-headline" id="Section_2.1">Section 2.1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&action=edit&section=3" title="Edit section: Section 2.1">edit</a><span class="mw-editsection-bracket">]</span></span></h3>
+<p>Two point one
+</p>
+<h2><span class="mw-headline" id="Section_3">Section 3</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&action=edit&section=4" title="Edit section: Section 3">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<p>Three
+</p></div>
+EOF
+ ],
+ 'Statelessly unwrap text' => [
+ [ 'unwrap' => true ], [], $text, <<<EOF
<p>Test document.
</p>
+<div id="toc" class="toc"><div class="toctitle"><h2>Contents</h2></div>
+<ul>
+<li class="toclevel-1 tocsection-1"><a href="#Section_1"><span class="tocnumber">1</span> <span class="toctext">Section 1</span></a></li>
+<li class="toclevel-1 tocsection-2"><a href="#Section_2"><span class="tocnumber">2</span> <span class="toctext">Section 2</span></a>
+<ul>
+<li class="toclevel-2 tocsection-3"><a href="#Section_2.1"><span class="tocnumber">2.1</span> <span class="toctext">Section 2.1</span></a></li>
+</ul>
+</li>
+<li class="toclevel-1 tocsection-4"><a href="#Section_3"><span class="tocnumber">3</span> <span class="toctext">Section 3</span></a></li>
+</ul>
+</div>
<h2><span class="mw-headline" id="Section_1">Section 1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&action=edit&section=1" title="Edit section: Section 1">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
<p>One
</p>
EOF
],
+ 'Unwrap without a mw-parser-output wrapper' => [
+ [ 'unwrap' => true ], [], '<div class="foobar">Content</div>', '<div class="foobar">Content</div>'
+ ],
];
// phpcs:enable
}
private function getParserOptions() {
global $wgContLang;
$popt = ParserOptions::newFromUserAndLang( new User, $wgContLang );
- $popt->setWrapOutputClass( false );
return $popt;
}
Title::newFromText( 'Test' ),
$this->getParserOptions()
);
- $this->assertEquals( "<p>FooOneBaz\n</p>", $parserOutput->getText() );
+ $this->assertEquals( "<p>FooOneBaz\n</p>", $parserOutput->getText( [ 'unwrap' => true ] ) );
$parser->mPreprocessor = null; # Break the Parser <-> Preprocessor cycle
}
Title::newFromText( 'Test' ),
$this->getParserOptions()
);
- $this->assertEquals( "<p>FooOneBaz\n</p>", $parserOutput->getText() );
+ $this->assertEquals( "<p>FooOneBaz\n</p>", $parserOutput->getText( [ 'unwrap' => true ] ) );
$parser->mPreprocessor = null; # Break the Parser <-> Preprocessor cycle
}
namespace MediaWiki\Session;
+use Config;
use MediaWikiTestCase;
use User;
use Wikimedia\TestingAccessWrapper;
class SessionBackendTest extends MediaWikiTestCase {
const SESSIONID = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
+ /** @var SessionManager */
protected $manager;
+
+ /** @var Config */
protected $config;
+
+ /** @var SessionProvider */
protected $provider;
+
+ /** @var TestBagOStuff */
protected $store;
protected $onSessionMetadataCalled = false;
* Returns a non-persistent backend that thinks it has at least one session active
* @param User|null $user
* @param string $id
+ * @return SessionBackend
*/
protected function getBackend( User $user = null, $id = null ) {
if ( !$this->config ) {
$this->assertSame( $info->forceHTTPS(), $backend->shouldForceHTTPS() );
$expire = time() + 100;
- $this->store->setSessionMeta( self::SESSIONID, [ 'expires' => $expire ], 2 );
+ $this->store->setSessionMeta( self::SESSIONID, [ 'expires' => $expire ] );
$info = new SessionInfo( SessionInfo::MIN_PRIORITY, [
'provider' => $this->provider,
*/
class SessionManagerTest extends MediaWikiTestCase {
- protected $config, $logger, $store;
+ /** @var \HashConfig */
+ private $config;
+
+ /** @var \TestLogger */
+ private $logger;
+
+ /** @var TestBagOStuff */
+ private $store;
protected function getManager() {
\ObjectCache::$instances['testSessionStore'] = new TestBagOStuff();
/**
* @param string $id Session ID
* @param array $data Session data
- * @param int $expiry
- * @param User $user User for metadata
*/
- public function setSessionData( $id, array $data, $expiry = 0, User $user = null ) {
- $this->setSession( $id, [ 'data' => $data ], $expiry, $user );
+ public function setSessionData( $id, array $data ) {
+ $this->setSession( $id, [ 'data' => $data ] );
}
/**
* @param string $id Session ID
* @param array $metadata Session metadata
- * @param int $expiry
*/
- public function setSessionMeta( $id, array $metadata, $expiry = 0 ) {
- $this->setSession( $id, [ 'metadata' => $metadata ], $expiry );
+ public function setSessionMeta( $id, array $metadata ) {
+ $this->setSession( $id, [ 'metadata' => $metadata ] );
}
/**
* @param string $id Session ID
* @param array $blob Session metadata and data
- * @param int $expiry
- * @param User $user User for metadata
*/
- public function setSession( $id, array $blob, $expiry = 0, User $user = null ) {
+ public function setSession( $id, array $blob ) {
$blob += [
'data' => [],
'metadata' => [],
];
$blob['metadata'] += [
- 'userId' => $user ? $user->getId() : 0,
- 'userName' => $user ? $user->getName() : null,
- 'userToken' => $user ? $user->getToken( true ) : null,
+ 'userId' => 0,
+ 'userName' => null,
+ 'userToken' => null,
'provider' => 'DummySessionProvider',
];
- $this->setRawSession( $id, $blob, $expiry, $user );
+ $this->setRawSession( $id, $blob );
}
/**
* @param string $id Session ID
* @param array|mixed $blob Session metadata and data
- * @param int $expiry
*/
- public function setRawSession( $id, $blob, $expiry = 0 ) {
- if ( $expiry <= 0 ) {
- $expiry = \RequestContext::getMain()->getConfig()->get( 'ObjectCacheSessionExpiry' );
- }
-
+ public function setRawSession( $id, $blob ) {
+ $expiry = \RequestContext::getMain()->getConfig()->get( 'ObjectCacheSessionExpiry' );
$this->set( $this->makeKey( 'MWSession', $id ), $blob, $expiry );
}
*
* @author Bene* < benestar.wikimedia@gmail.com >
*/
-
class SkinTemplateTest extends MediaWikiTestCase {
/**
* @dataProvider makeListItemProvider
*
* @group Database
*/
-
class ImageListPagerTest extends MediaWikiTestCase {
/**
* @expectedException MWException
/**
* Make a safe copy of localEnv:
- * - Creates a copy so that when the same object reference to module hooks is
- * used by multipe test hooks, our QUnit.module extension will not wrap the
- * callbacks multiple times. Instead, they wrap using a new object.
- * - Normalise setup/teardown to avoid having to repeat this in each extension
+ * - Creates a new object that inherits, instead of modifying the original.
+ * This prevents recursion in the event that a test suite stores inherits
+ * hooks object statically and passes it to multiple QUnit.module() calls.
+ * - Supporting QUnit 1.x 'setup' and 'teardown' hooks
* (deprecated in QUnit 1.16, removed in QUnit 2).
- * - Strip any other properties.
*/
function makeSafeEnv( localEnv ) {
- return {
- beforeEach: localEnv.setup || localEnv.beforeEach,
- afterEach: localEnv.teardown || localEnv.afterEach
- };
+ var wrap = localEnv ? Object.create( localEnv ) : {};
+ if ( wrap.setup ) {
+ wrap.beforeEach = wrap.beforeEach || wrap.setup;
+ }
+ if ( wrap.teardown ) {
+ wrap.afterEach = wrap.afterEach || wrap.teardown;
+ }
+ return wrap;
}
/**
useFakeTimers: false,
useFakeServer: false
};
- // Extend QUnit.module to provide a Sinon sandbox.
+ // Extend QUnit.module with:
+ // - Add support for QUnit 1.x 'setup' and 'teardown' hooks
+ // - Add a Sinon sandbox to the test context.
+ // - Add a test fixture to the test context.
( function () {
var orgModule = QUnit.module;
QUnit.module = function ( name, localEnv, executeNow ) {
- var orgBeforeEach, orgAfterEach, orgExecute;
+ var orgExecute, orgBeforeEach, orgAfterEach;
if ( nested ) {
- // In a nested module, don't re-run our handlers.
+ // In a nested module, don't re-add our hooks, QUnit does that already.
return orgModule.apply( this, arguments );
}
if ( arguments.length === 2 && typeof localEnv === 'function' ) {
};
}
- localEnv = localEnv || {};
+ localEnv = makeSafeEnv( localEnv );
orgBeforeEach = localEnv.beforeEach;
orgAfterEach = localEnv.afterEach;
+
localEnv.beforeEach = function () {
+ // Sinon sandbox
var config = sinon.getConfig( sinon.config );
config.injectInto = this;
sinon.sandbox.create( config );
- if ( orgBeforeEach ) {
- return orgBeforeEach.apply( this, arguments );
- }
- };
- localEnv.afterEach = function () {
- var ret;
- if ( orgAfterEach ) {
- ret = orgAfterEach.apply( this, arguments );
- }
-
- this.sandbox.verifyAndRestore();
- return ret;
- };
- return orgModule( name, localEnv, executeNow );
- };
- }() );
-
- // Extend QUnit.module to provide a fixture element.
- ( function () {
- var orgModule = QUnit.module;
- QUnit.module = function ( name, localEnv, executeNow ) {
- var orgBeforeEach, orgAfterEach;
- if ( nested ) {
- // In a nested module, don't re-run our handlers.
- return orgModule.apply( this, arguments );
- }
- if ( arguments.length === 2 && typeof localEnv === 'function' ) {
- executeNow = localEnv;
- localEnv = undefined;
- }
-
- localEnv = localEnv || {};
- orgBeforeEach = localEnv.beforeEach;
- orgAfterEach = localEnv.afterEach;
- localEnv.beforeEach = function () {
+ // Fixture element
this.fixture = document.createElement( 'div' );
this.fixture.id = 'qunit-fixture';
document.body.appendChild( this.fixture );
if ( orgAfterEach ) {
ret = orgAfterEach.apply( this, arguments );
}
-
+ this.sandbox.verifyAndRestore();
this.fixture.parentNode.removeChild( this.fixture );
return ret;
};
- return orgModule( name, localEnv, executeNow );
- };
- }() );
- // Extend QUnit.module to normalise localEnv.
- // NOTE: This MUST be the last QUnit.module extension so that the above extensions
- // may safely modify the object and assume beforeEach/afterEach.
- ( function () {
- var orgModule = QUnit.module;
- QUnit.module = function ( name, localEnv, executeNow ) {
- if ( typeof localEnv === 'object' ) {
- localEnv = makeSafeEnv( localEnv );
- }
return orgModule( name, localEnv, executeNow );
};
}() );
}
return function ( orgEnv ) {
- var localEnv = orgEnv ? makeSafeEnv( orgEnv ) : {};
- // MediaWiki env testing
- localEnv.config = orgEnv && orgEnv.config || {};
- localEnv.messages = orgEnv && orgEnv.messages || {};
-
- return {
- beforeEach: function () {
- // Greetings, mock environment!
- mw.config = new MwMap();
- mw.config.set( freshConfigCopy( localEnv.config ) );
- mw.messages = new MwMap();
- mw.messages.set( freshMessagesCopy( localEnv.messages ) );
- // Update reference to mw.messages
- mw.jqueryMsg.setParserDefaults( {
- messages: mw.messages
- } );
-
- this.suppressWarnings = suppressWarnings;
- this.restoreWarnings = restoreWarnings;
+ var localEnv, orgBeforeEach, orgAfterEach;
- // Start tracking ajax requests
- $( document ).on( 'ajaxSend', trackAjax );
-
- if ( localEnv.beforeEach ) {
- return localEnv.beforeEach.apply( this, arguments );
- }
- },
+ localEnv = makeSafeEnv( orgEnv );
+ // MediaWiki env testing
+ localEnv.config = localEnv.config || {};
+ localEnv.messages = localEnv.messages || {};
- afterEach: function () {
- var timers, pending, $activeLen, ret;
+ orgBeforeEach = localEnv.beforeEach;
+ orgAfterEach = localEnv.afterEach;
- if ( localEnv.afterEach ) {
- ret = localEnv.afterEach.apply( this, arguments );
- }
+ localEnv.beforeEach = function () {
+ // Greetings, mock environment!
+ mw.config = new MwMap();
+ mw.config.set( freshConfigCopy( localEnv.config ) );
+ mw.messages = new MwMap();
+ mw.messages.set( freshMessagesCopy( localEnv.messages ) );
+ // Update reference to mw.messages
+ mw.jqueryMsg.setParserDefaults( {
+ messages: mw.messages
+ } );
+
+ this.suppressWarnings = suppressWarnings;
+ this.restoreWarnings = restoreWarnings;
+
+ // Start tracking ajax requests
+ $( document ).on( 'ajaxSend', trackAjax );
- // Stop tracking ajax requests
- $( document ).off( 'ajaxSend', trackAjax );
+ if ( orgBeforeEach ) {
+ return orgBeforeEach.apply( this, arguments );
+ }
+ };
+ localEnv.afterEach = function () {
+ var timers, pending, $activeLen, ret;
- // As a convenience feature, automatically restore warnings if they're
- // still suppressed by the end of the test.
- restoreWarnings();
+ if ( orgAfterEach ) {
+ ret = orgAfterEach.apply( this, arguments );
+ }
- // Farewell, mock environment!
- mw.config = liveConfig;
- mw.messages = liveMessages;
- // Restore reference to mw.messages
- mw.jqueryMsg.setParserDefaults( {
- messages: liveMessages
+ // Stop tracking ajax requests
+ $( document ).off( 'ajaxSend', trackAjax );
+
+ // As a convenience feature, automatically restore warnings if they're
+ // still suppressed by the end of the test.
+ restoreWarnings();
+
+ // Farewell, mock environment!
+ mw.config = liveConfig;
+ mw.messages = liveMessages;
+ // Restore reference to mw.messages
+ mw.jqueryMsg.setParserDefaults( {
+ messages: liveMessages
+ } );
+
+ // Tests should use fake timers or wait for animations to complete
+ // Check for incomplete animations/requests/etc and throw if there are any.
+ if ( $.timers && $.timers.length !== 0 ) {
+ timers = $.timers.length;
+ $.each( $.timers, function ( i, timer ) {
+ var node = timer.elem;
+ mw.log.warn( 'Unfinished animation #' + i + ' in ' + timer.queue + ' queue on ' +
+ mw.html.element( node.nodeName.toLowerCase(), $( node ).getAttrs() )
+ );
} );
+ // Force animations to stop to give the next test a clean start
+ $.timers = [];
+ $.fx.stop();
- // Tests should use fake timers or wait for animations to complete
- // Check for incomplete animations/requests/etc and throw if there are any.
- if ( $.timers && $.timers.length !== 0 ) {
- timers = $.timers.length;
- $.each( $.timers, function ( i, timer ) {
- var node = timer.elem;
- mw.log.warn( 'Unfinished animation #' + i + ' in ' + timer.queue + ' queue on ' +
- mw.html.element( node.nodeName.toLowerCase(), $( node ).getAttrs() )
- );
- } );
- // Force animations to stop to give the next test a clean start
- $.timers = [];
- $.fx.stop();
-
- throw new Error( 'Unfinished animations: ' + timers );
- }
+ throw new Error( 'Unfinished animations: ' + timers );
+ }
- // Test should use fake XHR, wait for requests, or call abort()
- $activeLen = $.active;
- if ( $activeLen !== undefined && $activeLen !== 0 ) {
- pending = ajaxRequests.filter( function ( ajax ) {
- return ajax.xhr.state() === 'pending';
- } );
- if ( pending.length !== $activeLen ) {
- mw.log.warn( 'Pending requests does not match jQuery.active count' );
- }
- // Force requests to stop to give the next test a clean start
- ajaxRequests.forEach( function ( ajax, i ) {
- mw.log.warn(
- 'AJAX request #' + i + ' (state: ' + ajax.xhr.state() + ')',
- ajax.options
- );
- ajax.xhr.abort();
- } );
- ajaxRequests = [];
-
- throw new Error( 'Pending AJAX requests: ' + pending.length + ' (active: ' + $activeLen + ')' );
+ // Test should use fake XHR, wait for requests, or call abort()
+ $activeLen = $.active;
+ if ( $activeLen !== undefined && $activeLen !== 0 ) {
+ pending = ajaxRequests.filter( function ( ajax ) {
+ return ajax.xhr.state() === 'pending';
+ } );
+ if ( pending.length !== $activeLen ) {
+ mw.log.warn( 'Pending requests does not match jQuery.active count' );
}
+ // Force requests to stop to give the next test a clean start
+ ajaxRequests.forEach( function ( ajax, i ) {
+ mw.log.warn(
+ 'AJAX request #' + i + ' (state: ' + ajax.xhr.state() + ')',
+ ajax.options
+ );
+ ajax.xhr.abort();
+ } );
+ ajaxRequests = [];
- return ret;
+ throw new Error( 'Pending AJAX requests: ' + pending.length + ' (active: ' + $activeLen + ')' );
}
+
+ return ret;
};
+ return localEnv;
};
}() );
} );
} );
+ QUnit.module( 'testrunner-hooks-outer', function () {
+ var beforeHookWasExecuted = false,
+ afterHookWasExecuted = false;
+ QUnit.module( 'testrunner-hooks', {
+ before: function () {
+ beforeHookWasExecuted = true;
+
+ // This way we can be sure that module `testrunner-hook-after` will always
+ // be executed after module `testrunner-hooks`
+ QUnit.module( 'testrunner-hooks-after' );
+ QUnit.test(
+ '`after` hook for module `testrunner-hooks` was executed',
+ function ( assert ) {
+ assert.ok( afterHookWasExecuted );
+ }
+ );
+ },
+ after: function () {
+ afterHookWasExecuted = true;
+ }
+ } );
+
+ QUnit.test( '`before` hook was executed', function ( assert ) {
+ assert.ok( beforeHookWasExecuted );
+ } );
+ } );
+
}( jQuery, mediaWiki, QUnit ) );
);
} );
} );
+
+ QUnit.test( '.isCategory("")', function ( assert ) {
+ this.server.respondWith( /titles=$/, [
+ 200,
+ { 'Content-Type': 'application/json' },
+ '{"batchcomplete":true}'
+ ] );
+ return new mw.Api().isCategory( '' ).then( function ( response ) {
+ assert.equal( response, false );
+ } );
+ } );
+
+ QUnit.test( '.isCategory("#")', function ( assert ) {
+ this.server.respondWith( /titles=%23$/, [
+ 200,
+ { 'Content-Type': 'application/json' },
+ '{"batchcomplete":true,"query":{"normalized":[{"fromencoded":false,"from":"#","to":""}]}}'
+ ] );
+ return new mw.Api().isCategory( '#' ).then( function ( response ) {
+ assert.equal( response, false );
+ } );
+ } );
+
+ QUnit.test( '.isCategory("mw:")', function ( assert ) {
+ this.server.respondWith( /titles=mw%3A$/, [
+ 200,
+ { 'Content-Type': 'application/json' },
+ '{"batchcomplete":true,"query":{"interwiki":[{"title":"mw:","iw":"mw"}]}}'
+ ] );
+ return new mw.Api().isCategory( 'mw:' ).then( function ( response ) {
+ assert.equal( response, false );
+ } );
+ } );
+
+ QUnit.test( '.isCategory("|")', function ( assert ) {
+ this.server.respondWith( /titles=%1F%7C$/, [
+ 200,
+ { 'Content-Type': 'application/json' },
+ '{"batchcomplete":true,"query":{"pages":[{"title":"|","invalidreason":"The requested page title contains invalid characters: \\"|\\".","invalid":true}]}}'
+ ] );
+ return new mw.Api().isCategory( '|' ).then( function ( response ) {
+ assert.equal( response, false );
+ } );
+ } );
+
+ QUnit.test( '.getCategories("")', function ( assert ) {
+ this.server.respondWith( /titles=$/, [
+ 200,
+ { 'Content-Type': 'application/json' },
+ '{"batchcomplete":true}'
+ ] );
+ return new mw.Api().getCategories( '' ).then( function ( response ) {
+ assert.equal( response, false );
+ } );
+ } );
+
+ QUnit.test( '.getCategories("#")', function ( assert ) {
+ this.server.respondWith( /titles=%23$/, [
+ 200,
+ { 'Content-Type': 'application/json' },
+ '{"batchcomplete":true,"query":{"normalized":[{"fromencoded":false,"from":"#","to":""}]}}'
+ ] );
+ return new mw.Api().getCategories( '#' ).then( function ( response ) {
+ assert.equal( response, false );
+ } );
+ } );
+
+ QUnit.test( '.getCategories("mw:")', function ( assert ) {
+ this.server.respondWith( /titles=mw%3A$/, [
+ 200,
+ { 'Content-Type': 'application/json' },
+ '{"batchcomplete":true,"query":{"interwiki":[{"title":"mw:","iw":"mw"}]}}'
+ ] );
+ return new mw.Api().getCategories( 'mw:' ).then( function ( response ) {
+ assert.equal( response, false );
+ } );
+ } );
+
+ QUnit.test( '.getCategories("|")', function ( assert ) {
+ this.server.respondWith( /titles=%1F%7C$/, [
+ 200,
+ { 'Content-Type': 'application/json' },
+ '{"batchcomplete":true,"query":{"pages":[{"title":"|","invalidreason":"The requested page title contains invalid characters: \\"|\\".","invalid":true}]}}'
+ ] );
+ return new mw.Api().getCategories( '|' ).then( function ( response ) {
+ assert.equal( response, false );
+ } );
+ } );
+
}( mediaWiki ) );
return;
}
- list( $thumb, $errorMsg ) = wfGenerateThumbnail( $img, $params, $thumbName, $thumbPath );
+ $thumbProxyUrl = $img->getRepo()->getThumbProxyUrl();
+
+ if ( strlen( $thumbProxyUrl ) ) {
+ wfProxyThumbnailRequest( $img, $thumbName );
+ // No local fallback when in proxy mode
+ return;
+ } else {
+ // Generate the thumbnail locally
+ list( $thumb, $errorMsg ) = wfGenerateThumbnail( $img, $params, $thumbName, $thumbPath );
+ }
/** @var MediaTransformOutput|MediaTransformError|bool $thumb */
}
}
+/**
+ * Proxies thumbnail request to a service that handles thumbnailing
+ *
+ * @param File $img
+ * @param string $thumbName
+ */
+function wfProxyThumbnailRequest( $img, $thumbName ) {
+ $thumbProxyUrl = $img->getRepo()->getThumbProxyUrl();
+
+ // Instead of generating the thumbnail ourselves, we proxy the request to another service
+ $thumbProxiedUrl = $thumbProxyUrl . $img->getThumbRel( $thumbName );
+
+ $req = MWHttpRequest::factory( $thumbProxiedUrl );
+ $secret = $img->getRepo()->getThumbProxySecret();
+
+ // Pass a secret key shared with the proxied service if any
+ if ( strlen( $secret ) ) {
+ $req->setHeader( 'X-Swift-Secret', $secret );
+ }
+
+ // Send request to proxied service
+ $status = $req->execute();
+
+ // Simply serve the response from the proxied service as-is
+ header( 'HTTP/1.1 ' . $req->getStatus() );
+
+ $headers = $req->getResponseHeaders();
+
+ foreach ( $headers as $key => $values ) {
+ foreach ( $values as $value ) {
+ header( $key . ': ' . $value, false );
+ }
+ }
+
+ echo $req->getContent();
+}
+
/**
* Actually try to generate a new thumbnail
*